Let HandleWindowDragging return a boolean status
[openttd/fttd.git] / src / tunnelbridge_cmd.cpp
blobb7cdfc7e310b376e67e857d35c2dd3ab2eed9f19
1 /* $Id$ */
3 /*
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/>.
8 */
10 /**
11 * @file tunnelbridge_cmd.cpp
12 * This file deals with tunnels and bridges (non-gui stuff)
13 * @todo separate this file into two
16 #include "stdafx.h"
17 #include "newgrf_object.h"
18 #include "viewport_func.h"
19 #include "cmd_helper.h"
20 #include "command_func.h"
21 #include "town.h"
22 #include "train.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"
28 #include "map/road.h"
29 #include "strings_func.h"
30 #include "tunnelbridge.h"
31 #include "bridge.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);
45 /**
46 * Build a road bridge
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]) {
66 company = OWNER_NONE;
67 } else {
68 company = OWNER_TOWN;
69 town = t->index;
71 } else if (company == OWNER_TOWN) {
72 if (!Town::IsValidID(town)) return CMD_ERROR;
73 } else {
74 town = INVALID_TOWN;
77 Axis direction;
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);
109 owner[rt][1] = o;
110 if (o == company || o == OWNER_NONE || o == OWNER_TOWN) {
111 replace_allowed = true;
113 continue;
115 } else {
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);
122 } else {
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) {
170 return CMD_ERROR;
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.
180 /* do the drill? */
181 if (flags & DC_EXEC) {
182 Company *c = Company::GetIfValid(company);
184 /* Also give unowned present roadtypes to new owner */
185 RoadType rt;
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);
191 if (c != NULL) {
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);
205 uint count = 0;
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);
214 count += 2;
215 } else {
216 SetRoadBits (tile_start, bridge_bit, new_rt);
217 count++;
219 } else {
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);
227 } else {
228 count++;
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);
239 count += 2;
240 } else {
241 SetRoadBits (tile_end, reverse_bit, new_rt);
242 count++;
244 } else {
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);
252 } else {
253 count++;
257 if (c != NULL) {
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. */
272 rts |= bridge_rts;
273 } else {
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));
281 if (!clear_start) {
282 RoadType rt;
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));
293 if (!clear_end) {
294 RoadType rt;
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. */
301 int height;
302 CommandCost ret = CheckBridgeBuildable (tile_start, tile_end,
303 flags, clear_start, clear_end, &height);
304 if (ret.Failed()) return ret;
305 cost.AddCost(ret);
307 /* do the drill? */
308 if (flags & DC_EXEC) {
309 Company *c = Company::GetIfValid(company);
310 uint num_pieces = 2 * bridge_len;
312 if (clear_start) {
313 MakeRoadBridgeRamp(tile_start, company, company, bridge_type, dir, rts, town != INVALID_TOWN ? town : CalcClosestTownIDFromTile(tile_start));
314 num_pieces += 2;
315 } else {
316 MakeRoadBridgeFromRoad(tile_start, bridge_type, dir);
317 SetRoadTypes(tile_start, GetRoadTypes(tile_start) | rts);
319 RoadBits bits = DiagDirToRoadBits(dir);
320 RoadType new_rt;
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);
329 if (clear_end) {
330 MakeRoadBridgeRamp(tile_end, company, company, bridge_type, ReverseDiagDir(dir), rts, town != INVALID_TOWN ? town : CalcClosestTownIDFromTile(tile_end));
331 num_pieces += 2;
332 } else {
333 MakeRoadBridgeFromRoad(tile_end, bridge_type, ReverseDiagDir(dir));
334 SetRoadTypes(tile_end, GetRoadTypes(tile_end) | rts);
336 RoadBits bits = DiagDirToRoadBits(ReverseDiagDir(dir));
337 RoadType new_rt;
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;
347 if (c != NULL) {
348 /* Add all new road types to the company infrastructure counter. */
349 RoadType new_rt;
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);
376 return cost;
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);
395 switch (diff) {
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;
410 } else {
411 return bridgebits & TrackToTrackBits(TrackToOppositeTrack(track));
415 default: {
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;
446 Axis direction;
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.
480 /* do the drill? */
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));
487 } else {
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. */
494 int height;
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;
499 cost.AddCost(ret);
501 /* do the drill? */
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);
509 pieces++;
510 } else {
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)) {
517 pieces++;
518 } else {
519 uint n = CountBits(bits);
520 c->infrastructure.rail[railtype] -= n * n;
521 n = CountBits(bits | add_start);
522 pieces += n * n;
526 if (add_end == TRACK_BIT_NONE) {
527 MakeRailBridgeRamp(tile_end, _current_company, bridge_type, ReverseDiagDir(dir), railtype);
528 pieces++;
529 } else {
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)) {
536 pieces++;
537 } else {
538 uint n = CountBits(bits);
539 c->infrastructure.rail[railtype] -= n * n;
540 n = CountBits(bits | add_end);
541 pieces += n * n;
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);
573 return cost;
578 * Build an aqueduct
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;
588 Axis direction;
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. */
606 int height;
607 ret = CheckBridgeBuildable (tile_start, tile_end, flags, true, true,
608 &height, true);
609 if (ret.Failed()) return ret;
610 cost.AddCost(ret);
612 assert ((uint) height == TileHeight (tile_start));
614 /* do the drill? */
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]);
641 return cost;
646 * Build a Bridge
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)
655 * @param text unused
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);
665 /* type of bridge */
666 switch (Extract<TransportType, 12, 2>(p2)) {
667 case TRANSPORT_ROAD:
668 return BuildRoadBridge(p1, end_tile, bridge_type, Extract<RoadTypes, 8, 2>(p2), GB(p2, 16, 16), flags);
670 case TRANSPORT_RAIL:
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);
676 default:
677 /* Airports don't have bridges. */
678 return CMD_ERROR;
684 * Build Tunnel.
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
689 * @param p2 unused
690 * @param text unused
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) {
703 case TRANSPORT_RAIL:
704 railtype = Extract<RailType, 0, 4>(p1);
705 if (!ValParamRailtype(railtype)) return CMD_ERROR;
706 break;
708 case TRANSPORT_ROAD:
709 rts = Extract<RoadTypes, 0, 2>(p1);
710 if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(company, rts)) return CMD_ERROR;
711 break;
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;
728 int start_z;
729 int end_z;
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;
748 } else {
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*/
755 int tiles_coef = 3;
756 /* Number of tiles from start of tunnel */
757 int tiles = 0;
758 /* Number of tiles at which the cost increase coefficient per tile is halved */
759 int tiles_bump = 25;
761 CommandCost cost(EXPENSES_CONSTRUCTION);
762 Slope end_tileh;
763 for (;;) {
764 end_tile += delta;
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);
774 tiles++;
775 if (tiles == tiles_bump) {
776 tiles_coef++;
777 tiles_bump *= 2;
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]);
786 cost.AddCost(ret);
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);
798 cost.AddCost(ret);
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);
805 if (coa == NULL) {
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);
817 cost.AddCost(ret);
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();
837 } else {
838 if (c != NULL) {
839 RoadType rt;
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);
850 return cost;