4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
11 * @file tunnelbridge_cmd.cpp
12 * This file deals with tunnels and bridges (non-gui stuff)
13 * @todo separate this file into two
17 #include "newgrf_object.h"
18 #include "viewport_func.h"
19 #include "cmd_helper.h"
20 #include "command_func.h"
23 #include "pathfinder/yapf/yapf_cache.h"
24 #include "autoslope.h"
25 #include "map/tunnelbridge.h"
26 #include "map/water.h"
28 #include "strings_func.h"
29 #include "tunnelbridge.h"
31 #include "signal_func.h"
32 #include "cheat_type.h"
33 #include "company_base.h"
34 #include "object_base.h"
35 #include "company_gui.h"
37 #include "table/strings.h"
39 TileIndex _build_tunnel_endtile
; ///< The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
42 extern bool IsValidRoadBridgeBits(Slope tileh
, DiagDirection dir
, RoadBits bits
);
46 * @param tile_start Start tile
47 * @param tile_end End tile
48 * @param bridge_type Bridge type
49 * @param rts Road types
50 * @param town the town that is building the road (if applicable)
51 * @param flags type of operation
52 * @return the cost of this operation or an error
54 static CommandCost
BuildRoadBridge(TileIndex tile_start
, TileIndex tile_end
, BridgeType bridge_type
, RoadTypes rts
, TownID town
, DoCommandFlag flags
)
56 CompanyID company
= _current_company
;
58 if (!HasExactlyOneBit(rts
) || !HasRoadTypesAvail(_current_company
, rts
)) return CMD_ERROR
;
60 if (company
== OWNER_DEITY
) {
61 const Town
*t
= CalcClosestTownFromTile(tile_start
);
63 /* If we are not within a town, we are not owned by the town */
64 if (t
== NULL
|| DistanceSquare(tile_start
, t
->xy
) > t
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
70 } else if (company
== OWNER_TOWN
) {
71 if (!Town::IsValidID(town
)) return CMD_ERROR
;
77 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
78 if (ret
.Failed()) return ret
;
80 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
82 /* set and test bridge length, availability */
83 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
84 ret
= CheckBridgeAvailability(bridge_type
, bridge_len
, flags
);
85 if (ret
.Failed()) return ret
;
87 CommandCost
cost(EXPENSES_CONSTRUCTION
);
89 if (IsRoadBridgeTile(tile_start
) && IsRoadBridgeTile(tile_end
) &&
90 GetOtherBridgeEnd(tile_start
) == tile_end
) {
91 /* Replace a current bridge. */
93 /* Special owner check. */
94 Owner owner_road
= HasTileRoadType(tile_start
, ROADTYPE_ROAD
) ? GetRoadOwner(tile_start
, ROADTYPE_ROAD
) : INVALID_OWNER
;
95 Owner owner_tram
= HasTileRoadType(tile_start
, ROADTYPE_TRAM
) ? GetRoadOwner(tile_start
, ROADTYPE_TRAM
) : INVALID_OWNER
;
97 /* You must own one of the roadtypes, or one of the roadtypes must be unowned, or a town must own the road. */
98 if (owner_road
!= company
&& owner_road
!= OWNER_NONE
&& owner_road
!= OWNER_TOWN
&&
99 owner_tram
!= company
&& owner_tram
!= OWNER_NONE
) {
100 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
103 /* You must own all of the roadtypes if downgrading. */
104 if (!(flags
& DC_QUERY_COST
) &&
105 GetBridgeSpec(bridge_type
)->speed
< GetBridgeSpec(GetRoadBridgeType(tile_start
))->speed
&&
106 _game_mode
!= GM_EDITOR
) {
107 if (owner_road
== OWNER_TOWN
) {
108 Town
*t
= ClosestTownFromTile(tile_start
, UINT_MAX
);
110 if (t
== NULL
) return CMD_ERROR
;
112 SetDParam(0, t
->index
);
113 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS
);
115 if (owner_road
!= company
&& owner_road
!= OWNER_NONE
&& owner_road
!= INVALID_OWNER
) {
116 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
118 if (owner_tram
!= company
&& owner_tram
!= OWNER_NONE
&& owner_tram
!= INVALID_OWNER
) {
119 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
123 /* Do not remove road types when upgrading a bridge */
124 rts
|= GetRoadTypes(tile_start
);
126 /* Do not replace the bridge with the same bridge type. */
127 if (!(flags
& DC_QUERY_COST
) && (bridge_type
== GetRoadBridgeType(tile_start
)) && ((rts
& ~GetRoadTypes(tile_start
)) == 0)) {
128 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
131 cost
.AddCost((bridge_len
+ 1) * _price
[PR_CLEAR_BRIDGE
]); // The cost of clearing the current bridge.
134 if (flags
& DC_EXEC
) {
135 RoadTypes prev_roadtypes
= GetRoadTypes(tile_start
);
136 /* Also give unowned present roadtypes to new owner */
137 if (HasBit(prev_roadtypes
, ROADTYPE_ROAD
) && GetRoadOwner(tile_start
, ROADTYPE_ROAD
) == OWNER_NONE
) ClrBit(prev_roadtypes
, ROADTYPE_ROAD
);
138 if (HasBit(prev_roadtypes
, ROADTYPE_TRAM
) && GetRoadOwner(tile_start
, ROADTYPE_TRAM
) == OWNER_NONE
) ClrBit(prev_roadtypes
, ROADTYPE_TRAM
);
139 Company
*c
= Company::GetIfValid(company
);
141 /* Add all new road types to the company infrastructure counter. */
143 FOR_EACH_SET_ROADTYPE(new_rt
, rts
^ prev_roadtypes
) {
144 /* A full diagonal road tile has two road bits. */
145 c
->infrastructure
.road
[new_rt
] += (bridge_len
+ 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR
;
148 DirtyCompanyInfrastructureWindows(company
);
150 SetRoadBridgeType(tile_start
, bridge_type
);
151 SetRoadTypes(tile_start
, rts
);
152 SetRoadBridgeType(tile_end
, bridge_type
);
153 SetRoadTypes(tile_end
, rts
);
155 for (RoadType rt
= ROADTYPE_BEGIN
; rt
< ROADTYPE_END
; rt
++) {
156 if (!HasBit(prev_roadtypes
, rt
)) {
157 SetRoadOwner(tile_start
, rt
, company
);
158 SetRoadOwner(tile_end
, rt
, company
);
162 MarkBridgeTilesDirty(tile_start
, tile_end
, AxisToDiagDir(direction
));
165 DiagDirection dir
= AxisToDiagDir(direction
);
167 bool clear_start
= !IsNormalRoadTile(tile_start
) ||
168 GetDisallowedRoadDirections(tile_start
) != DRD_NONE
||
169 HasRoadWorks(tile_start
) ||
170 !IsValidRoadBridgeBits(GetTileSlope(tile_start
), dir
, GetAllRoadBits(tile_start
));
174 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile_start
) & rts
) {
175 if (GetRoadOwner(tile_start
, rt
) != company
) clear_start
= true;
179 bool clear_end
= !IsNormalRoadTile(tile_end
) ||
180 GetDisallowedRoadDirections(tile_end
) != DRD_NONE
||
181 HasRoadWorks(tile_end
) ||
182 !IsValidRoadBridgeBits(GetTileSlope(tile_end
), ReverseDiagDir(dir
), GetAllRoadBits(tile_end
));
186 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile_end
) & rts
) {
187 if (GetRoadOwner(tile_end
, rt
) != company
) clear_end
= true;
191 /* Build a new bridge. */
192 CommandCost ret
= CheckBridgeBuildable(tile_start
, tile_end
, flags
, clear_start
, clear_end
);
193 if (ret
.Failed()) return ret
;
197 if (flags
& DC_EXEC
) {
198 Company
*c
= Company::GetIfValid(company
);
199 uint num_pieces
= 2 * bridge_len
;
202 MakeRoadBridgeRamp(tile_start
, company
, company
, bridge_type
, dir
, rts
, town
!= INVALID_TOWN
? town
: CalcClosestTownIDFromTile(tile_start
));
205 MakeRoadBridgeFromRoad(tile_start
, bridge_type
, dir
);
206 SetRoadTypes(tile_start
, GetRoadTypes(tile_start
) | rts
);
208 RoadBits bits
= DiagDirToRoadBits(dir
);
210 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
211 RoadBits pieces
= GetRoadBits(tile_start
, new_rt
);
212 uint n
= CountBits(pieces
);
213 if (c
!= NULL
) c
->infrastructure
.road
[new_rt
] += (n
+ 1) * TUNNELBRIDGE_TRACKBIT_FACTOR
- n
;
214 SetRoadBits(tile_start
, pieces
| bits
, new_rt
);
219 MakeRoadBridgeRamp(tile_end
, company
, company
, bridge_type
, ReverseDiagDir(dir
), rts
, town
!= INVALID_TOWN
? town
: CalcClosestTownIDFromTile(tile_end
));
222 MakeRoadBridgeFromRoad(tile_end
, bridge_type
, ReverseDiagDir(dir
));
223 SetRoadTypes(tile_end
, GetRoadTypes(tile_end
) | rts
);
225 RoadBits bits
= DiagDirToRoadBits(ReverseDiagDir(dir
));
227 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
228 RoadBits pieces
= GetRoadBits(tile_end
, new_rt
);
229 uint n
= CountBits(pieces
);
230 if (c
!= NULL
) c
->infrastructure
.road
[new_rt
] += (n
+ 1) * TUNNELBRIDGE_TRACKBIT_FACTOR
- n
;
231 SetRoadBits(tile_end
, pieces
| bits
, new_rt
);
235 num_pieces
*= TUNNELBRIDGE_TRACKBIT_FACTOR
;
237 /* Add all new road types to the company infrastructure counter. */
239 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
240 /* A full diagonal road tile has two road bits. */
241 c
->infrastructure
.road
[new_rt
] += num_pieces
;
245 SetBridgeMiddleTiles(tile_start
, tile_end
, direction
);
246 DirtyCompanyInfrastructureWindows(company
);
250 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
251 * It's unnecessary to execute this command every time for every bridge. So it is done only
252 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
254 Company
*c
= Company::GetIfValid(company
);
255 if (!(flags
& DC_QUERY_COST
) || (c
!= NULL
&& c
->is_ai
)) {
256 bridge_len
+= 2; // begin and end tiles/ramps
258 cost
.AddCost(bridge_len
* _price
[PR_BUILD_ROAD
] * 2 * CountBits(rts
));
260 if (c
!= NULL
) bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
262 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_BRIDGE
] * GetBridgeSpec(bridge_type
)->price
>> 8);
270 * Trackbits to add to a rail tile if a bridge is built on it, or TRACK_BIT_NONE if tile must be cleared
271 * @param tile tile to check
272 * @param dir direction for bridge
273 * @param rt railtype for bridge
274 * @return trackbits to add, or TRACK_BIT_NONE if tile must be cleared
276 static TrackBits
RailBridgeAddBits(TileIndex tile
, DiagDirection dir
, RailType rt
)
278 if (!IsNormalRailTile(tile
) || !IsTileOwner(tile
, _current_company
)) return TRACK_BIT_NONE
;
280 Slope tileh
= GetTileSlope(tile
);
281 DiagDirDiff diff
= CheckExtendedBridgeHead(tileh
, dir
);
282 TrackBits present
= GetTrackBits(tile
);
285 case DIAGDIRDIFF_REVERSE
: return TRACK_BIT_NONE
;
287 case DIAGDIRDIFF_SAME
: {
288 TrackBits bridgebits
= DiagdirReachesTracks(ReverseDiagDir(dir
));
289 if ((present
& bridgebits
) != TRACK_BIT_NONE
) return TRACK_BIT_NONE
;
291 Track track
= FindFirstTrack(present
);
293 if (KillFirstBit(present
) != TRACK_BIT_NONE
) {
294 return (GetRailType(tile
, track
) == rt
) ? bridgebits
: TRACK_BIT_NONE
;
295 } else if (GetRailType(tile
, track
) == rt
&& !HasSignalOnTrack(tile
, track
)) {
296 return bridgebits
& ~TrackToTrackBits(TrackToOppositeTrack(track
));
297 } else if (IsDiagonalTrack(track
)) {
298 return TRACK_BIT_NONE
;
300 return bridgebits
& TrackToTrackBits(TrackToOppositeTrack(track
));
305 TrackBits allowed
= TRACK_BIT_ALL
& ~DiagdirReachesTracks(ReverseDiagDir(ChangeDiagDir(dir
, diff
)));
306 if (present
!= (allowed
& ~DiagdirReachesTracks(ReverseDiagDir(dir
)))) {
307 return TRACK_BIT_NONE
;
310 Track track
= FindFirstTrack(present
);
311 assert(present
== TrackToTrackBits(track
)); // present should have exactly one trackbit
313 if (HasSignalOnTrack(tile
, track
) || GetRailType(tile
, track
) != rt
) return TRACK_BIT_NONE
;
315 return allowed
^ present
;
321 * Build a rail bridge
322 * @param tile_start Start tile
323 * @param tile_end End tile
324 * @param bridge_type Bridge type
325 * @param railtype Rail type
326 * @param flags type of operation
327 * @return the cost of this operation or an error
329 static CommandCost
BuildRailBridge(TileIndex tile_start
, TileIndex tile_end
, BridgeType bridge_type
, RailType railtype
, DoCommandFlag flags
)
331 if (!ValParamRailtype(railtype
)) return CMD_ERROR
;
333 if (_current_company
== OWNER_DEITY
) return CMD_ERROR
;
336 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
337 if (ret
.Failed()) return ret
;
339 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
341 /* set and test bridge length, availability */
342 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
343 ret
= CheckBridgeAvailability(bridge_type
, bridge_len
, flags
);
344 if (ret
.Failed()) return ret
;
346 CommandCost
cost(EXPENSES_CONSTRUCTION
);
348 if (IsRailBridgeTile(tile_start
) && IsRailBridgeTile(tile_end
) &&
349 GetOtherBridgeEnd(tile_start
) == tile_end
) {
350 /* Replace a current bridge. */
352 /* Make sure the railtypes match. */
353 if (GetBridgeRailType(tile_start
) != railtype
) {
354 return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
357 /* Do not replace the bridge with the same bridge type. */
358 if (!(flags
& DC_QUERY_COST
) && bridge_type
== GetRailBridgeType(tile_start
)) {
359 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
362 /* Do not allow replacing another company's bridges. */
363 if (!IsTileOwner(tile_start
, _current_company
) && !IsTileOwner(tile_start
, OWNER_TOWN
)) {
364 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
367 cost
.AddCost((bridge_len
+ 1) * _price
[PR_CLEAR_BRIDGE
]); // The cost of clearing the current bridge.
370 if (flags
& DC_EXEC
) {
371 SetRailBridgeType(tile_start
, bridge_type
);
372 SetRailBridgeType(tile_end
, bridge_type
);
374 MarkBridgeTilesDirty(tile_start
, tile_end
, AxisToDiagDir(direction
));
377 DiagDirection dir
= AxisToDiagDir(direction
);
379 TrackBits add_start
= RailBridgeAddBits(tile_start
, dir
, railtype
);
380 TrackBits add_end
= RailBridgeAddBits(tile_end
, ReverseDiagDir(dir
), railtype
);
382 /* Build a new bridge. */
383 CommandCost ret
= CheckBridgeBuildable(tile_start
, tile_end
, flags
, add_start
== TRACK_BIT_NONE
, add_end
== TRACK_BIT_NONE
);
384 if (ret
.Failed()) return ret
;
388 if (flags
& DC_EXEC
) {
389 /* Add to company infrastructure count if building a new bridge. */
390 Company
*c
= Company::Get(_current_company
);
391 uint pieces
= bridge_len
;
393 if (add_start
== TRACK_BIT_NONE
) {
394 MakeRailBridgeRamp(tile_start
, _current_company
, bridge_type
, dir
, railtype
);
397 TrackBits bits
= GetTrackBits(tile_start
);
398 MakeRailBridgeFromRail(tile_start
, bridge_type
, dir
);
399 SetTrackBits(tile_start
, bits
| add_start
);
400 SetRailType(tile_start
, railtype
, FindFirstTrack(add_start
));
402 if (HasExactlyOneBit(add_start
)) {
405 uint n
= CountBits(bits
);
406 c
->infrastructure
.rail
[railtype
] -= n
* n
;
407 n
= CountBits(bits
| add_start
);
412 if (add_end
== TRACK_BIT_NONE
) {
413 MakeRailBridgeRamp(tile_end
, _current_company
, bridge_type
, ReverseDiagDir(dir
), railtype
);
416 TrackBits bits
= GetTrackBits(tile_end
);
417 MakeRailBridgeFromRail(tile_end
, bridge_type
, ReverseDiagDir(dir
));
418 SetTrackBits(tile_end
, bits
| add_end
);
419 SetRailType(tile_end
, railtype
, FindFirstTrack(add_end
));
421 if (HasExactlyOneBit(add_end
)) {
424 uint n
= CountBits(bits
);
425 c
->infrastructure
.rail
[railtype
] -= n
* n
;
426 n
= CountBits(bits
| add_end
);
431 c
->infrastructure
.rail
[railtype
] += pieces
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
432 DirtyCompanyInfrastructureWindows(_current_company
);
434 SetBridgeMiddleTiles(tile_start
, tile_end
, direction
);
435 DirtyCompanyInfrastructureWindows(_current_company
);
439 if (flags
& DC_EXEC
) {
440 Track track
= AxisToTrack(direction
);
441 AddBridgeToSignalBuffer(tile_start
, _current_company
);
442 YapfNotifyTrackLayoutChange(tile_start
, track
);
445 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
446 * It's unnecessary to execute this command every time for every bridge. So it is done only
447 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
449 Company
*c
= Company::Get(_current_company
);
450 if (!(flags
& DC_QUERY_COST
) || c
->is_ai
) {
451 bridge_len
+= 2; // begin and end tiles/ramps
453 cost
.AddCost(bridge_len
* RailBuildCost(railtype
));
455 bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
457 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_BRIDGE
] * GetBridgeSpec(bridge_type
)->price
>> 8);
466 * @param tile_start Start tile
467 * @param tile_end End tile
468 * @param flags type of operation
469 * @return the cost of this operation or an error
471 static CommandCost
BuildAqueduct(TileIndex tile_start
, TileIndex tile_end
, DoCommandFlag flags
)
473 if (_current_company
== OWNER_DEITY
) return CMD_ERROR
;
476 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
477 if (ret
.Failed()) return ret
;
479 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
481 /* set and test bridge length, availability */
482 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
483 if (bridge_len
> _settings_game
.construction
.max_bridge_length
) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG
);
485 CommandCost
cost(EXPENSES_CONSTRUCTION
);
487 if (IsAqueductTile(tile_start
) && IsAqueductTile(tile_end
) &&
488 GetOtherBridgeEnd(tile_start
) == tile_end
) {
489 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
492 /* Build a new bridge. */
493 ret
= CheckBridgeBuildable(tile_start
, tile_end
, flags
, true, true, true);
494 if (ret
.Failed()) return ret
;
498 if (flags
& DC_EXEC
) {
499 DiagDirection dir
= AxisToDiagDir(direction
);
501 Company
*c
= Company::GetIfValid(_current_company
);
502 if (c
!= NULL
) c
->infrastructure
.water
+= (bridge_len
+ 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
503 MakeAqueductBridgeRamp(tile_start
, _current_company
, dir
);
504 MakeAqueductBridgeRamp(tile_end
, _current_company
, ReverseDiagDir(dir
));
506 SetBridgeMiddleTiles(tile_start
, tile_end
, direction
);
507 DirtyCompanyInfrastructureWindows(_current_company
);
510 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
511 * It's unnecessary to execute this command every time for every bridge. So it is done only
512 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
514 Company
*c
= Company::GetIfValid(_current_company
);
515 if (!(flags
& DC_QUERY_COST
) || (c
!= NULL
&& c
->is_ai
)) {
516 bridge_len
+= 2; // begin and end tiles/ramps
518 if (c
!= NULL
) bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
520 /* Aqueducts use a separate base cost. */
521 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_AQUEDUCT
]);
530 * @param end_tile end tile
531 * @param flags type of operation
532 * @param p1 packed start tile coords (~ dx)
533 * @param p2 various bitstuffed elements
534 * - p2 = (bit 0- 7) - bridge type (hi bh)
535 * - p2 = (bit 8-11) - rail type or road types.
536 * - p2 = (bit 12-13) - transport type.
537 * - p2 = (bit 16-31) - the town that is building the road (if applicable)
539 * @return the cost of this operation or an error
541 CommandCost
CmdBuildBridge(TileIndex end_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
543 /* unpack parameters */
544 BridgeType bridge_type
= GB(p2
, 0, 8);
546 if (!IsValidTile(p1
)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER
);
549 switch (Extract
<TransportType
, 12, 2>(p2
)) {
551 return BuildRoadBridge(p1
, end_tile
, bridge_type
, Extract
<RoadTypes
, 8, 2>(p2
), GB(p2
, 16, 16), flags
);
554 return BuildRailBridge(p1
, end_tile
, bridge_type
, Extract
<RailType
, 8, 4>(p2
), flags
);
556 case TRANSPORT_WATER
:
557 return BuildAqueduct(p1
, end_tile
, flags
);
560 /* Airports don't have bridges. */
568 * @param start_tile start tile of tunnel
569 * @param flags type of operation
570 * @param p1 bit 0-3 railtype or roadtypes
571 * bit 8-9 transport type
574 * @return the cost of this operation or an error
576 CommandCost
CmdBuildTunnel(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
578 CompanyID company
= _current_company
;
580 TransportType transport_type
= Extract
<TransportType
, 8, 2>(p1
);
582 RailType railtype
= INVALID_RAILTYPE
;
583 RoadTypes rts
= ROADTYPES_NONE
;
584 _build_tunnel_endtile
= 0;
585 switch (transport_type
) {
587 railtype
= Extract
<RailType
, 0, 4>(p1
);
588 if (!ValParamRailtype(railtype
)) return CMD_ERROR
;
592 rts
= Extract
<RoadTypes
, 0, 2>(p1
);
593 if (!HasExactlyOneBit(rts
) || !HasRoadTypesAvail(company
, rts
)) return CMD_ERROR
;
596 default: return CMD_ERROR
;
599 if (company
== OWNER_DEITY
) {
600 if (transport_type
!= TRANSPORT_ROAD
) return CMD_ERROR
;
601 const Town
*town
= CalcClosestTownFromTile(start_tile
);
603 company
= OWNER_TOWN
;
605 /* If we are not within a town, we are not owned by the town */
606 if (town
== NULL
|| DistanceSquare(start_tile
, town
->xy
) > town
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
607 company
= OWNER_NONE
;
613 Slope start_tileh
= GetTileSlope(start_tile
, &start_z
);
614 DiagDirection direction
= GetInclinedSlopeDirection(start_tileh
);
615 if (direction
== INVALID_DIAGDIR
) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL
);
617 if (HasTileWaterGround(start_tile
)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER
);
619 CommandCost ret
= DoCommand(start_tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
620 if (ret
.Failed()) return ret
;
622 /* XXX - do NOT change 'ret' in the loop, as it is used as the price
623 * for the clearing of the entrance of the tunnel. Assigning it to
624 * cost before the loop will yield different costs depending on start-
625 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
627 TileIndexDiff delta
= TileOffsByDiagDir(direction
);
628 DiagDirection tunnel_in_way_dir
;
629 if (DiagDirToAxis(direction
) == AXIS_Y
) {
630 tunnel_in_way_dir
= (TileX(start_tile
) < (MapMaxX() / 2)) ? DIAGDIR_SW
: DIAGDIR_NE
;
632 tunnel_in_way_dir
= (TileY(start_tile
) < (MapMaxX() / 2)) ? DIAGDIR_SE
: DIAGDIR_NW
;
635 TileIndex end_tile
= start_tile
;
637 /* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
639 /* Number of tiles from start of tunnel */
641 /* Number of tiles at which the cost increase coefficient per tile is halved */
644 CommandCost
cost(EXPENSES_CONSTRUCTION
);
648 if (!IsValidTile(end_tile
)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER
);
649 end_tileh
= GetTileSlope(end_tile
, &end_z
);
651 if (start_z
== end_z
) break;
653 if (!_cheats
.crossing_tunnels
.value
&& IsTunnelInWayDir(end_tile
, start_z
, tunnel_in_way_dir
)) {
654 return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY
);
658 if (tiles
== tiles_bump
) {
663 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
664 cost
.AddCost(cost
.GetCost() >> tiles_coef
); // add a multiplier for longer tunnels
667 /* Add the cost of the entrance */
668 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
671 /* if the command fails from here on we want the end tile to be highlighted */
672 _build_tunnel_endtile
= end_tile
;
674 if (tiles
> _settings_game
.construction
.max_tunnel_length
) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG
);
676 if (HasTileWaterGround(end_tile
)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER
);
678 /* Clear the tile in any case */
679 ret
= DoCommand(end_tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
680 if (ret
.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND
);
683 /* slope of end tile must be complementary to the slope of the start tile */
684 if (end_tileh
!= ComplementSlope(start_tileh
)) {
685 /* Mark the tile as already cleared for the terraform command.
686 * Do this for all tiles (like trees), not only objects. */
687 ClearedObjectArea
*coa
= FindClearedObject(end_tile
);
689 coa
= _cleared_object_areas
.Append();
690 coa
->first_tile
= end_tile
;
691 coa
->area
= TileArea(end_tile
, 1, 1);
694 /* Hide the tile from the terraforming command */
695 TileIndex old_first_tile
= coa
->first_tile
;
696 coa
->first_tile
= INVALID_TILE
;
697 ret
= DoCommand(end_tile
, end_tileh
& start_tileh
, 0, flags
, CMD_TERRAFORM_LAND
);
698 coa
->first_tile
= old_first_tile
;
699 if (ret
.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND
);
702 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
704 /* Pay for the rail/road in the tunnel including entrances */
705 switch (transport_type
) {
706 case TRANSPORT_ROAD
: cost
.AddCost((tiles
+ 2) * _price
[PR_BUILD_ROAD
] * 2); break;
707 case TRANSPORT_RAIL
: cost
.AddCost((tiles
+ 2) * RailBuildCost(railtype
)); break;
708 default: NOT_REACHED();
711 if (flags
& DC_EXEC
) {
712 Company
*c
= Company::GetIfValid(company
);
713 uint num_pieces
= (tiles
+ 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
714 if (transport_type
== TRANSPORT_RAIL
) {
715 if (!IsTunnelTile(start_tile
) && c
!= NULL
) c
->infrastructure
.rail
[railtype
] += num_pieces
;
716 MakeRailTunnel(start_tile
, company
, direction
, railtype
);
717 MakeRailTunnel(end_tile
, company
, ReverseDiagDir(direction
), railtype
);
718 AddTunnelToSignalBuffer(start_tile
, company
);
719 YapfNotifyTrackLayoutChange(start_tile
, DiagDirToDiagTrack(direction
));
723 FOR_EACH_SET_ROADTYPE(rt
, rts
^ (IsTunnelTile(start_tile
) ? GetRoadTypes(start_tile
) : ROADTYPES_NONE
)) {
724 c
->infrastructure
.road
[rt
] += num_pieces
* 2; // A full diagonal road has two road bits.
727 MakeRoadTunnel(start_tile
, company
, direction
, rts
);
728 MakeRoadTunnel(end_tile
, company
, ReverseDiagDir(direction
), rts
);
730 DirtyCompanyInfrastructureWindows(company
);