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.h"
24 #include "autoslope.h"
25 #include "map/zoneheight.h"
26 #include "map/tunnelbridge.h"
27 #include "map/water.h"
29 #include "strings_func.h"
30 #include "tunnelbridge.h"
32 #include "signalbuffer.h"
33 #include "cheat_type.h"
34 #include "company_base.h"
35 #include "object_base.h"
36 #include "company_gui.h"
38 #include "table/strings.h"
40 TileIndex _build_tunnel_endtile
; ///< The end of a tunnel; as hidden return from the tunnel build command for GUI purposes.
43 extern bool IsValidRoadBridgeBits(Slope tileh
, DiagDirection dir
, RoadBits bits
);
47 * @param tile_start Start tile
48 * @param tile_end End tile
49 * @param bridge_type Bridge type
50 * @param rts Road types
51 * @param town the town that is building the road (if applicable)
52 * @param flags type of operation
53 * @return the cost of this operation or an error
55 static CommandCost
BuildRoadBridge(TileIndex tile_start
, TileIndex tile_end
, BridgeType bridge_type
, RoadTypes rts
, TownID town
, DoCommandFlag flags
)
57 CompanyID company
= _current_company
;
59 if (!HasExactlyOneBit(rts
) || !HasRoadTypesAvail(_current_company
, rts
)) return CMD_ERROR
;
61 if (company
== OWNER_DEITY
) {
62 const Town
*t
= CalcClosestTownFromTile(tile_start
);
64 /* If we are not within a town, we are not owned by the town */
65 if (t
== NULL
|| DistanceSquare(tile_start
, t
->xy
) > t
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
71 } else if (company
== OWNER_TOWN
) {
72 if (!Town::IsValidID(town
)) return CMD_ERROR
;
78 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
79 if (ret
.Failed()) return ret
;
81 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
83 /* set and test bridge length, availability */
84 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
85 ret
= CheckBridgeAvailability(bridge_type
, bridge_len
, flags
);
86 if (ret
.Failed()) return ret
;
88 CommandCost
cost(EXPENSES_CONSTRUCTION
);
90 if (IsRoadBridgeTile(tile_start
) && IsRoadBridgeTile(tile_end
) &&
91 GetOtherBridgeEnd(tile_start
) == tile_end
) {
92 /* Replace a current bridge. */
94 Owner owner
[ROADTYPE_END
][2];
95 RoadTypes bridge_rts
= ROADTYPES_NONE
;
96 RoadBits bridge_bit
= DiagDirToRoadBits (AxisToDiagDir (direction
));
97 RoadBits reverse_bit
= DiagDirToRoadBits (ReverseDiagDir (AxisToDiagDir (direction
)));
98 bool replace_allowed
= false;
100 for (RoadType rt
= ROADTYPE_BEGIN
; rt
< ROADTYPE_END
; rt
++) {
101 if (HasTileRoadType (tile_start
, rt
)) {
102 owner
[rt
][0] = GetRoadOwner (tile_start
, rt
);
103 if ((GetRoadBits (tile_start
, rt
) & bridge_bit
) != 0) {
104 assert (HasTileRoadType (tile_end
, rt
));
105 assert ((GetRoadBits (tile_end
, rt
) & reverse_bit
) != 0);
106 bridge_rts
|= RoadTypeToRoadTypes (rt
);
107 Owner o
= owner
[rt
][0];
108 assert (GetRoadOwner (tile_end
, rt
) == o
);
110 if (o
== company
|| o
== OWNER_NONE
|| o
== OWNER_TOWN
) {
111 replace_allowed
= true;
116 owner
[rt
][0] = INVALID_OWNER
;
119 if (HasTileRoadType (tile_end
, rt
)) {
120 assert ((GetRoadBits (tile_end
, rt
) & reverse_bit
) == 0);
121 owner
[rt
][1] = GetRoadOwner (tile_end
, rt
);
123 owner
[rt
][1] = INVALID_OWNER
;
127 assert (bridge_rts
!= ROADTYPES_NONE
);
129 /* You must own one of the roadtypes, or one of the roadtypes must be unowned, or a town must own the road. */
130 if (!replace_allowed
) {
131 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
134 /* You must own all of the roadtypes if downgrading. */
135 if (!(flags
& DC_QUERY_COST
) &&
136 GetBridgeSpec(bridge_type
)->speed
< GetBridgeSpec(GetRoadBridgeType(tile_start
))->speed
&&
137 _game_mode
!= GM_EDITOR
) {
138 if (owner
[ROADTYPE_ROAD
][0] == OWNER_TOWN
) {
139 Town
*t
= ClosestTownFromTile(tile_start
);
140 if (t
== NULL
) return CMD_ERROR
;
142 SetDParam(0, t
->index
);
143 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS
);
146 if (owner
[ROADTYPE_ROAD
][1] == OWNER_TOWN
) {
147 Town
*t
= ClosestTownFromTile(tile_end
);
148 if (t
== NULL
) return CMD_ERROR
;
150 SetDParam(0, t
->index
);
151 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS
);
154 for (RoadType rt
= ROADTYPE_BEGIN
; rt
< ROADTYPE_END
; rt
++) {
155 for (uint i
= 0; i
< 2; i
++) {
156 Owner o
= owner
[rt
][i
];
157 if (o
!= company
&& o
!= OWNER_NONE
&& o
!= OWNER_TOWN
&& o
!= INVALID_OWNER
) {
158 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
164 if ((rts
& ~bridge_rts
) != 0) {
165 /* Adding a new roadtype. */
166 RoadType new_rt
= (RoadType
) FindFirstBit (rts
);
167 for (uint i
= 0; i
< 2; i
++) {
168 Owner o
= owner
[new_rt
][i
];
169 if (o
!= company
&& o
!= OWNER_NONE
&& o
!= INVALID_OWNER
) {
173 } else if (!(flags
& DC_QUERY_COST
) && (bridge_type
== GetRoadBridgeType (tile_start
))) {
174 /* Do not replace the bridge with the same bridge type. */
175 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
178 cost
.AddCost((bridge_len
+ 1) * _price
[PR_CLEAR_BRIDGE
]); // The cost of clearing the current bridge.
181 if (flags
& DC_EXEC
) {
182 Company
*c
= Company::GetIfValid(company
);
184 /* Also give unowned present roadtypes to new owner */
186 FOR_EACH_SET_ROADTYPE(rt
, bridge_rts
) {
187 assert (owner
[rt
][0] == owner
[rt
][1]);
188 if (owner
[rt
][0] == OWNER_NONE
) {
189 SetRoadOwner (tile_start
, rt
, company
);
190 SetRoadOwner (tile_end
, rt
, company
);
192 uint bits_start
= CountBits (GetRoadBits (tile_start
, rt
));
193 uint bits_end
= CountBits (GetRoadBits (tile_end
, rt
));
194 c
->infrastructure
.road
[rt
] += (bits_start
+ bits_end
+ 2 * bridge_len
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
199 if ((rts
& ~bridge_rts
) != 0) {
200 /* Adding a new roadtype. */
201 assert ((rts
| bridge_rts
) == ROADTYPES_ALL
);
203 RoadType new_rt
= (RoadType
) FindFirstBit (rts
);
207 if (owner
[new_rt
][0] == INVALID_OWNER
) {
208 assert (GetRoadTypes (tile_start
) == bridge_rts
);
209 SetRoadTypes (tile_start
, ROADTYPES_ALL
);
210 RoadBits present
= GetAllRoadBits (tile_start
);
211 assert ((present
& bridge_bit
) != ROAD_NONE
);
212 if ((present
& reverse_bit
) != ROAD_NONE
) {
213 SetRoadBits (tile_start
, bridge_bit
| reverse_bit
, new_rt
);
216 SetRoadBits (tile_start
, bridge_bit
, new_rt
);
220 assert (GetRoadTypes (tile_start
) == ROADTYPES_ALL
);
221 RoadBits present
= GetRoadBits (tile_start
, new_rt
);
222 assert ((present
& bridge_bit
) == ROAD_NONE
);
223 SetRoadBits (tile_start
, present
| bridge_bit
, new_rt
);
224 if (owner
[new_rt
][0] == OWNER_NONE
) {
225 SetRoadOwner (tile_start
, new_rt
, company
);
226 count
+= CountBits (present
);
232 if (owner
[new_rt
][1] == INVALID_OWNER
) {
233 assert (GetRoadTypes (tile_end
) == bridge_rts
);
234 SetRoadTypes (tile_end
, ROADTYPES_ALL
);
235 RoadBits present
= GetAllRoadBits (tile_end
);
236 assert ((present
& reverse_bit
) != ROAD_NONE
);
237 if ((present
& bridge_bit
) != ROAD_NONE
) {
238 SetRoadBits (tile_end
, bridge_bit
| reverse_bit
, new_rt
);
241 SetRoadBits (tile_end
, reverse_bit
, new_rt
);
245 assert (GetRoadTypes (tile_end
) == ROADTYPES_ALL
);
246 RoadBits present
= GetRoadBits (tile_end
, new_rt
);
247 assert ((present
& reverse_bit
) == ROAD_NONE
);
248 SetRoadBits (tile_end
, present
| reverse_bit
, new_rt
);
249 if (owner
[new_rt
][1] == OWNER_NONE
) {
250 SetRoadOwner (tile_end
, new_rt
, company
);
251 count
+= CountBits (present
);
258 /* A full diagonal road tile has two road bits. */
259 c
->infrastructure
.road
[new_rt
] += (2 * bridge_len
+ count
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
263 DirtyCompanyInfrastructureWindows(company
);
265 SetRoadBridgeType(tile_start
, bridge_type
);
266 SetRoadBridgeType(tile_end
, bridge_type
);
268 MarkBridgeTilesDirty(tile_start
, tile_end
, AxisToDiagDir(direction
));
271 /* Count existing road types in cost computation. */
274 DiagDirection dir
= AxisToDiagDir(direction
);
276 bool clear_start
= !IsNormalRoadTile(tile_start
) ||
277 GetDisallowedRoadDirections(tile_start
) != DRD_NONE
||
278 HasRoadWorks(tile_start
) ||
279 !IsValidRoadBridgeBits(GetTileSlope(tile_start
), dir
, GetAllRoadBits(tile_start
));
283 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile_start
) & rts
) {
284 if (GetRoadOwner(tile_start
, rt
) != company
) clear_start
= true;
288 bool clear_end
= !IsNormalRoadTile(tile_end
) ||
289 GetDisallowedRoadDirections(tile_end
) != DRD_NONE
||
290 HasRoadWorks(tile_end
) ||
291 !IsValidRoadBridgeBits(GetTileSlope(tile_end
), ReverseDiagDir(dir
), GetAllRoadBits(tile_end
));
295 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile_end
) & rts
) {
296 if (GetRoadOwner(tile_end
, rt
) != company
) clear_end
= true;
300 /* Build a new bridge. */
302 CommandCost ret
= CheckBridgeBuildable (tile_start
, tile_end
,
303 flags
, clear_start
, clear_end
, &height
);
304 if (ret
.Failed()) return ret
;
308 if (flags
& DC_EXEC
) {
309 Company
*c
= Company::GetIfValid(company
);
310 uint num_pieces
= 2 * bridge_len
;
313 MakeRoadBridgeRamp(tile_start
, company
, company
, bridge_type
, dir
, rts
, town
!= INVALID_TOWN
? town
: CalcClosestTownIDFromTile(tile_start
));
316 MakeRoadBridgeFromRoad(tile_start
, bridge_type
, dir
);
317 SetRoadTypes(tile_start
, GetRoadTypes(tile_start
) | rts
);
319 RoadBits bits
= DiagDirToRoadBits(dir
);
321 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
322 RoadBits pieces
= GetRoadBits(tile_start
, new_rt
);
323 uint n
= CountBits(pieces
);
324 if (c
!= NULL
) c
->infrastructure
.road
[new_rt
] += (n
+ 1) * TUNNELBRIDGE_TRACKBIT_FACTOR
- n
;
325 SetRoadBits(tile_start
, pieces
| bits
, new_rt
);
330 MakeRoadBridgeRamp(tile_end
, company
, company
, bridge_type
, ReverseDiagDir(dir
), rts
, town
!= INVALID_TOWN
? town
: CalcClosestTownIDFromTile(tile_end
));
333 MakeRoadBridgeFromRoad(tile_end
, bridge_type
, ReverseDiagDir(dir
));
334 SetRoadTypes(tile_end
, GetRoadTypes(tile_end
) | rts
);
336 RoadBits bits
= DiagDirToRoadBits(ReverseDiagDir(dir
));
338 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
339 RoadBits pieces
= GetRoadBits(tile_end
, new_rt
);
340 uint n
= CountBits(pieces
);
341 if (c
!= NULL
) c
->infrastructure
.road
[new_rt
] += (n
+ 1) * TUNNELBRIDGE_TRACKBIT_FACTOR
- n
;
342 SetRoadBits(tile_end
, pieces
| bits
, new_rt
);
346 num_pieces
*= TUNNELBRIDGE_TRACKBIT_FACTOR
;
348 /* Add all new road types to the company infrastructure counter. */
350 FOR_EACH_SET_ROADTYPE(new_rt
, rts
) {
351 /* A full diagonal road tile has two road bits. */
352 c
->infrastructure
.road
[new_rt
] += num_pieces
;
356 SetBridgeMiddleTiles (tile_start
, tile_end
, direction
, height
);
357 DirtyCompanyInfrastructureWindows(company
);
361 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
362 * It's unnecessary to execute this command every time for every bridge. So it is done only
363 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
365 Company
*c
= Company::GetIfValid(company
);
366 if (!(flags
& DC_QUERY_COST
) || (c
!= NULL
&& c
->is_ai
)) {
367 bridge_len
+= 2; // begin and end tiles/ramps
369 cost
.AddCost(bridge_len
* _price
[PR_BUILD_ROAD
] * 2 * CountBits(rts
));
371 if (c
!= NULL
) bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
373 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_BRIDGE
] * GetBridgeSpec(bridge_type
)->price
>> 8);
381 * Trackbits to add to a rail tile if a bridge is built on it, or TRACK_BIT_NONE if tile must be cleared
382 * @param tile tile to check
383 * @param dir direction for bridge
384 * @param rt railtype for bridge
385 * @return trackbits to add, or TRACK_BIT_NONE if tile must be cleared
387 static TrackBits
RailBridgeAddBits(TileIndex tile
, DiagDirection dir
, RailType rt
)
389 if (!IsNormalRailTile(tile
) || !IsTileOwner(tile
, _current_company
)) return TRACK_BIT_NONE
;
391 Slope tileh
= GetTileSlope(tile
);
392 DiagDirDiff diff
= CheckExtendedBridgeHead(tileh
, dir
);
393 TrackBits present
= GetTrackBits(tile
);
396 case DIAGDIRDIFF_REVERSE
: return TRACK_BIT_NONE
;
398 case DIAGDIRDIFF_SAME
: {
399 TrackBits bridgebits
= DiagdirReachesTracks(ReverseDiagDir(dir
));
400 if ((present
& bridgebits
) != TRACK_BIT_NONE
) return TRACK_BIT_NONE
;
402 Track track
= FindFirstTrack(present
);
404 if (KillFirstBit(present
) != TRACK_BIT_NONE
) {
405 return (GetRailType(tile
, track
) == rt
) ? bridgebits
: TRACK_BIT_NONE
;
406 } else if (GetRailType(tile
, track
) == rt
&& !HasSignalOnTrack(tile
, track
)) {
407 return bridgebits
& ~TrackToTrackBits(TrackToOppositeTrack(track
));
408 } else if (IsDiagonalTrack(track
)) {
409 return TRACK_BIT_NONE
;
411 return bridgebits
& TrackToTrackBits(TrackToOppositeTrack(track
));
416 TrackBits allowed
= TRACK_BIT_ALL
& ~DiagdirReachesTracks(ReverseDiagDir(ChangeDiagDir(dir
, diff
)));
417 if (present
!= (allowed
& ~DiagdirReachesTracks(ReverseDiagDir(dir
)))) {
418 return TRACK_BIT_NONE
;
421 Track track
= FindFirstTrack(present
);
422 assert(present
== TrackToTrackBits(track
)); // present should have exactly one trackbit
424 if (HasSignalOnTrack(tile
, track
) || GetRailType(tile
, track
) != rt
) return TRACK_BIT_NONE
;
426 return allowed
^ present
;
432 * Build a rail bridge
433 * @param tile_start Start tile
434 * @param tile_end End tile
435 * @param bridge_type Bridge type
436 * @param railtype Rail type
437 * @param flags type of operation
438 * @return the cost of this operation or an error
440 static CommandCost
BuildRailBridge(TileIndex tile_start
, TileIndex tile_end
, BridgeType bridge_type
, RailType railtype
, DoCommandFlag flags
)
442 if (!ValParamRailtype(railtype
)) return CMD_ERROR
;
444 if (_current_company
== OWNER_DEITY
) return CMD_ERROR
;
447 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
448 if (ret
.Failed()) return ret
;
450 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
452 /* set and test bridge length, availability */
453 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
454 ret
= CheckBridgeAvailability(bridge_type
, bridge_len
, flags
);
455 if (ret
.Failed()) return ret
;
457 CommandCost
cost(EXPENSES_CONSTRUCTION
);
459 if (IsRailBridgeTile(tile_start
) && IsRailBridgeTile(tile_end
) &&
460 GetOtherBridgeEnd(tile_start
) == tile_end
) {
461 /* Replace a current bridge. */
463 /* Make sure the railtypes match. */
464 if (GetBridgeRailType(tile_start
) != railtype
) {
465 return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
468 /* Do not replace the bridge with the same bridge type. */
469 if (!(flags
& DC_QUERY_COST
) && bridge_type
== GetRailBridgeType(tile_start
)) {
470 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
473 /* Do not allow replacing another company's bridges. */
474 if (!IsTileOwner(tile_start
, _current_company
) && !IsTileOwner(tile_start
, OWNER_TOWN
)) {
475 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
478 cost
.AddCost((bridge_len
+ 1) * _price
[PR_CLEAR_BRIDGE
]); // The cost of clearing the current bridge.
481 if (flags
& DC_EXEC
) {
482 SetRailBridgeType(tile_start
, bridge_type
);
483 SetRailBridgeType(tile_end
, bridge_type
);
485 MarkBridgeTilesDirty(tile_start
, tile_end
, AxisToDiagDir(direction
));
488 DiagDirection dir
= AxisToDiagDir(direction
);
490 TrackBits add_start
= RailBridgeAddBits(tile_start
, dir
, railtype
);
491 TrackBits add_end
= RailBridgeAddBits(tile_end
, ReverseDiagDir(dir
), railtype
);
493 /* Build a new bridge. */
495 CommandCost ret
= CheckBridgeBuildable (tile_start
, tile_end
,
496 flags
, add_start
== TRACK_BIT_NONE
,
497 add_end
== TRACK_BIT_NONE
, &height
);
498 if (ret
.Failed()) return ret
;
502 if (flags
& DC_EXEC
) {
503 /* Add to company infrastructure count if building a new bridge. */
504 Company
*c
= Company::Get(_current_company
);
505 uint pieces
= bridge_len
;
507 if (add_start
== TRACK_BIT_NONE
) {
508 MakeRailBridgeRamp(tile_start
, _current_company
, bridge_type
, dir
, railtype
);
511 TrackBits bits
= GetTrackBits(tile_start
);
512 MakeRailBridgeFromRail(tile_start
, bridge_type
, dir
);
513 SetTrackBits(tile_start
, bits
| add_start
);
514 SetRailType(tile_start
, railtype
, FindFirstTrack(add_start
));
516 if (HasExactlyOneBit(add_start
)) {
519 uint n
= CountBits(bits
);
520 c
->infrastructure
.rail
[railtype
] -= n
* n
;
521 n
= CountBits(bits
| add_start
);
526 if (add_end
== TRACK_BIT_NONE
) {
527 MakeRailBridgeRamp(tile_end
, _current_company
, bridge_type
, ReverseDiagDir(dir
), railtype
);
530 TrackBits bits
= GetTrackBits(tile_end
);
531 MakeRailBridgeFromRail(tile_end
, bridge_type
, ReverseDiagDir(dir
));
532 SetTrackBits(tile_end
, bits
| add_end
);
533 SetRailType(tile_end
, railtype
, FindFirstTrack(add_end
));
535 if (HasExactlyOneBit(add_end
)) {
538 uint n
= CountBits(bits
);
539 c
->infrastructure
.rail
[railtype
] -= n
* n
;
540 n
= CountBits(bits
| add_end
);
545 c
->infrastructure
.rail
[railtype
] += pieces
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
546 DirtyCompanyInfrastructureWindows(_current_company
);
548 SetBridgeMiddleTiles (tile_start
, tile_end
, direction
, height
);
549 DirtyCompanyInfrastructureWindows(_current_company
);
553 if (flags
& DC_EXEC
) {
554 AddBridgeToSignalBuffer(tile_start
, _current_company
);
555 YapfNotifyTrackLayoutChange();
558 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
559 * It's unnecessary to execute this command every time for every bridge. So it is done only
560 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
562 Company
*c
= Company::Get(_current_company
);
563 if (!(flags
& DC_QUERY_COST
) || c
->is_ai
) {
564 bridge_len
+= 2; // begin and end tiles/ramps
566 cost
.AddCost(bridge_len
* RailBuildCost(railtype
));
568 bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
570 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_BRIDGE
] * GetBridgeSpec(bridge_type
)->price
>> 8);
579 * @param tile_start Start tile
580 * @param tile_end End tile
581 * @param flags type of operation
582 * @return the cost of this operation or an error
584 static CommandCost
BuildAqueduct(TileIndex tile_start
, TileIndex tile_end
, DoCommandFlag flags
)
586 if (_current_company
== OWNER_DEITY
) return CMD_ERROR
;
589 CommandCost ret
= CheckBridgeTiles(tile_start
, tile_end
, &direction
);
590 if (ret
.Failed()) return ret
;
592 if (tile_end
< tile_start
) Swap(tile_start
, tile_end
);
594 /* set and test bridge length, availability */
595 uint bridge_len
= GetTunnelBridgeLength(tile_start
, tile_end
);
596 if (bridge_len
> _settings_game
.construction
.max_bridge_length
) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG
);
598 CommandCost
cost(EXPENSES_CONSTRUCTION
);
600 if (IsAqueductTile(tile_start
) && IsAqueductTile(tile_end
) &&
601 GetOtherBridgeEnd(tile_start
) == tile_end
) {
602 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
605 /* Build a new bridge. */
607 ret
= CheckBridgeBuildable (tile_start
, tile_end
, flags
, true, true,
609 if (ret
.Failed()) return ret
;
612 assert ((uint
) height
== TileHeight (tile_start
));
615 if (flags
& DC_EXEC
) {
616 DiagDirection dir
= AxisToDiagDir(direction
);
618 Company
*c
= Company::GetIfValid(_current_company
);
619 if (c
!= NULL
) c
->infrastructure
.water
+= (bridge_len
+ 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
620 MakeAqueductBridgeRamp(tile_start
, _current_company
, dir
);
621 MakeAqueductBridgeRamp(tile_end
, _current_company
, ReverseDiagDir(dir
));
623 SetBridgeMiddleTiles (tile_start
, tile_end
, direction
, height
);
624 DirtyCompanyInfrastructureWindows(_current_company
);
627 /* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
628 * It's unnecessary to execute this command every time for every bridge. So it is done only
629 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
631 Company
*c
= Company::GetIfValid(_current_company
);
632 if (!(flags
& DC_QUERY_COST
) || (c
!= NULL
&& c
->is_ai
)) {
633 bridge_len
+= 2; // begin and end tiles/ramps
635 if (c
!= NULL
) bridge_len
= CalcBridgeLenCostFactor(bridge_len
);
637 /* Aqueducts use a separate base cost. */
638 cost
.AddCost((int64
)bridge_len
* _price
[PR_BUILD_AQUEDUCT
]);
647 * @param end_tile end tile
648 * @param flags type of operation
649 * @param p1 packed start tile coords (~ dx)
650 * @param p2 various bitstuffed elements
651 * - p2 = (bit 0- 7) - bridge type (hi bh)
652 * - p2 = (bit 8-11) - rail type or road types.
653 * - p2 = (bit 12-13) - transport type.
654 * - p2 = (bit 16-31) - the town that is building the road (if applicable)
656 * @return the cost of this operation or an error
658 CommandCost
CmdBuildBridge(TileIndex end_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
660 /* unpack parameters */
661 BridgeType bridge_type
= GB(p2
, 0, 8);
663 if (!IsValidTile(p1
)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER
);
666 switch (Extract
<TransportType
, 12, 2>(p2
)) {
668 return BuildRoadBridge(p1
, end_tile
, bridge_type
, Extract
<RoadTypes
, 8, 2>(p2
), GB(p2
, 16, 16), flags
);
671 return BuildRailBridge(p1
, end_tile
, bridge_type
, Extract
<RailType
, 8, 4>(p2
), flags
);
673 case TRANSPORT_WATER
:
674 return BuildAqueduct(p1
, end_tile
, flags
);
677 /* Airports don't have bridges. */
685 * @param start_tile start tile of tunnel
686 * @param flags type of operation
687 * @param p1 bit 0-3 railtype or roadtypes
688 * bit 8-9 transport type
691 * @return the cost of this operation or an error
693 CommandCost
CmdBuildTunnel(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
695 CompanyID company
= _current_company
;
697 TransportType transport_type
= Extract
<TransportType
, 8, 2>(p1
);
699 RailType railtype
= INVALID_RAILTYPE
;
700 RoadTypes rts
= ROADTYPES_NONE
;
701 _build_tunnel_endtile
= 0;
702 switch (transport_type
) {
704 railtype
= Extract
<RailType
, 0, 4>(p1
);
705 if (!ValParamRailtype(railtype
)) return CMD_ERROR
;
709 rts
= Extract
<RoadTypes
, 0, 2>(p1
);
710 if (!HasExactlyOneBit(rts
) || !HasRoadTypesAvail(company
, rts
)) return CMD_ERROR
;
713 default: return CMD_ERROR
;
716 if (company
== OWNER_DEITY
) {
717 if (transport_type
!= TRANSPORT_ROAD
) return CMD_ERROR
;
718 const Town
*town
= CalcClosestTownFromTile(start_tile
);
720 company
= OWNER_TOWN
;
722 /* If we are not within a town, we are not owned by the town */
723 if (town
== NULL
|| DistanceSquare(start_tile
, town
->xy
) > town
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
724 company
= OWNER_NONE
;
730 Slope start_tileh
= GetTileSlope(start_tile
, &start_z
);
731 DiagDirection direction
= GetInclinedSlopeDirection(start_tileh
);
732 if (direction
== INVALID_DIAGDIR
) return_cmd_error(STR_ERROR_SITE_UNSUITABLE_FOR_TUNNEL
);
734 if (HasTileWaterGround(start_tile
)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER
);
736 CommandCost ret
= DoCommand(start_tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
737 if (ret
.Failed()) return ret
;
739 /* XXX - do NOT change 'ret' in the loop, as it is used as the price
740 * for the clearing of the entrance of the tunnel. Assigning it to
741 * cost before the loop will yield different costs depending on start-
742 * position, because of increased-cost-by-length: 'cost += cost >> 3' */
744 TileIndexDiff delta
= TileOffsByDiagDir(direction
);
745 DiagDirection tunnel_in_way_dir
;
746 if (DiagDirToAxis(direction
) == AXIS_Y
) {
747 tunnel_in_way_dir
= (TileX(start_tile
) < (MapMaxX() / 2)) ? DIAGDIR_SW
: DIAGDIR_NE
;
749 tunnel_in_way_dir
= (TileY(start_tile
) < (MapMaxX() / 2)) ? DIAGDIR_SE
: DIAGDIR_NW
;
752 TileIndex end_tile
= start_tile
;
754 /* Tile shift coefficient. Will decrease for very long tunnels to avoid exponential growth of price*/
756 /* Number of tiles from start of tunnel */
758 /* Number of tiles at which the cost increase coefficient per tile is halved */
761 CommandCost
cost(EXPENSES_CONSTRUCTION
);
765 if (!IsValidTile(end_tile
)) return_cmd_error(STR_ERROR_TUNNEL_THROUGH_MAP_BORDER
);
766 end_tileh
= GetTileSlope(end_tile
, &end_z
);
768 if (start_z
== end_z
) break;
770 if (!_cheats
.crossing_tunnels
.value
&& IsTunnelInWayDir(end_tile
, start_z
, tunnel_in_way_dir
)) {
771 return_cmd_error(STR_ERROR_ANOTHER_TUNNEL_IN_THE_WAY
);
775 if (tiles
== tiles_bump
) {
780 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
781 cost
.AddCost(cost
.GetCost() >> tiles_coef
); // add a multiplier for longer tunnels
784 /* Add the cost of the entrance */
785 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
788 /* if the command fails from here on we want the end tile to be highlighted */
789 _build_tunnel_endtile
= end_tile
;
791 if (tiles
> _settings_game
.construction
.max_tunnel_length
) return_cmd_error(STR_ERROR_TUNNEL_TOO_LONG
);
793 if (HasTileWaterGround(end_tile
)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER
);
795 /* Clear the tile in any case */
796 ret
= DoCommand(end_tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
797 if (ret
.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND
);
800 /* slope of end tile must be complementary to the slope of the start tile */
801 if (end_tileh
!= ComplementSlope(start_tileh
)) {
802 /* Mark the tile as already cleared for the terraform command.
803 * Do this for all tiles (like trees), not only objects. */
804 ClearedObjectArea
*coa
= FindClearedObject(end_tile
);
806 coa
= _cleared_object_areas
.Append();
807 coa
->first_tile
= end_tile
;
808 coa
->area
= TileArea(end_tile
, 1, 1);
811 /* Hide the tile from the terraforming command */
812 TileIndex old_first_tile
= coa
->first_tile
;
813 coa
->first_tile
= INVALID_TILE
;
814 ret
= DoCommand(end_tile
, end_tileh
& start_tileh
, 0, flags
, CMD_TERRAFORM_LAND
);
815 coa
->first_tile
= old_first_tile
;
816 if (ret
.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND
);
819 cost
.AddCost(_price
[PR_BUILD_TUNNEL
]);
821 /* Pay for the rail/road in the tunnel including entrances */
822 switch (transport_type
) {
823 case TRANSPORT_ROAD
: cost
.AddCost((tiles
+ 2) * _price
[PR_BUILD_ROAD
] * 2); break;
824 case TRANSPORT_RAIL
: cost
.AddCost((tiles
+ 2) * RailBuildCost(railtype
)); break;
825 default: NOT_REACHED();
828 if (flags
& DC_EXEC
) {
829 Company
*c
= Company::GetIfValid(company
);
830 uint num_pieces
= (tiles
+ 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
831 if (transport_type
== TRANSPORT_RAIL
) {
832 if (!IsTunnelTile(start_tile
) && c
!= NULL
) c
->infrastructure
.rail
[railtype
] += num_pieces
;
833 MakeRailTunnel(start_tile
, company
, direction
, railtype
);
834 MakeRailTunnel(end_tile
, company
, ReverseDiagDir(direction
), railtype
);
835 AddTunnelToSignalBuffer(start_tile
, company
);
836 YapfNotifyTrackLayoutChange();
840 FOR_EACH_SET_ROADTYPE(rt
, rts
^ (IsTunnelTile(start_tile
) ? GetRoadTypes(start_tile
) : ROADTYPES_NONE
)) {
841 c
->infrastructure
.road
[rt
] += num_pieces
* 2; // A full diagonal road has two road bits.
844 MakeRoadTunnel(start_tile
, company
, direction
, rts
);
845 MakeRoadTunnel(end_tile
, company
, ReverseDiagDir(direction
), rts
);
847 DirtyCompanyInfrastructureWindows(company
);