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/>.
10 /** @file road_cmd.cpp Commands related to road tiles. */
13 #include "cmd_helper.h"
14 #include "road_internal.h"
15 #include "viewport_func.h"
16 #include "command_func.h"
17 #include "pathfinder/yapf/yapf.h"
18 #include "depot_base.h"
20 #include "autoslope.h"
21 #include "map/zoneheight.h"
23 #include "map/bridge.h"
24 #include "map/tunnelbridge.h"
26 #include "strings_func.h"
27 #include "vehicle_func.h"
28 #include "sound_func.h"
29 #include "tunnelbridge.h"
30 #include "cheat_type.h"
31 #include "effectvehicle_func.h"
32 #include "effectvehicle_base.h"
33 #include "elrail_func.h"
36 #include "company_base.h"
37 #include "core/random_func.hpp"
38 #include "newgrf_railtype.h"
39 #include "date_func.h"
41 #include "company_gui.h"
43 #include "table/strings.h"
44 #include "table/road_land.h"
48 * Verify whether a road vehicle is available.
49 * @return \c true if at least one road vehicle is available, \c false if not
51 bool RoadVehiclesAreBuilt()
53 const RoadVehicle
*rv
;
54 FOR_ALL_ROADVEHICLES(rv
) return true;
59 /** Invalid RoadBits on a leveled slope. */
60 static const RoadBits _invalid_leveled_roadbits
[15] = {
61 ROAD_NONE
, // SLOPE_FLAT
62 ROAD_NE
| ROAD_SE
, // SLOPE_W
63 ROAD_NE
| ROAD_NW
, // SLOPE_S
65 ROAD_NW
| ROAD_SW
, // SLOPE_E
66 ROAD_NONE
, // SLOPE_EW
68 ROAD_NONE
, // SLOPE_WSE
69 ROAD_SE
| ROAD_SW
, // SLOPE_N
71 ROAD_NONE
, // SLOPE_NS
72 ROAD_NONE
, // SLOPE_ENW
74 ROAD_NONE
, // SLOPE_SEN
75 ROAD_NONE
, // SLOPE_NWS
78 /** Invalid straight RoadBits on a slope (with and without foundation). */
79 static const RoadBits _invalid_straight_roadbits
[15] = {
80 ROAD_NONE
, // SLOPE_FLAT
81 ROAD_NONE
, // SLOPE_W Foundation
82 ROAD_NONE
, // SLOPE_S Foundation
84 ROAD_NONE
, // SLOPE_E Foundation
87 ROAD_ALL
, // SLOPE_WSE
88 ROAD_NONE
, // SLOPE_N Foundation
91 ROAD_ALL
, // SLOPE_ENW
93 ROAD_ALL
, // SLOPE_SEN
94 ROAD_ALL
, // SLOPE_NWS
97 static Foundation
GetRoadFoundation(Slope tileh
, RoadBits bits
);
100 * Is it allowed to remove the given road bits from the given tile?
101 * @param tile the tile to remove the road from
102 * @param remove the roadbits that are going to be removed
103 * @param owner the actual owner of the roadbits of the tile
104 * @param rt the road type to remove the bits from
105 * @param flags command flags
106 * @param town_check Shall the town rating checked/affected
107 * @return A succeeded command when it is allowed to remove the road bits, a failed command otherwise.
109 CommandCost
CheckAllowRemoveRoad(TileIndex tile
, RoadBits remove
, Owner owner
, RoadType rt
, DoCommandFlag flags
, bool town_check
)
111 if (_game_mode
== GM_EDITOR
|| remove
== ROAD_NONE
) return CommandCost();
113 /* Water can always flood and towns can always remove "normal" road pieces.
114 * Towns are not be allowed to remove non "normal" road pieces, like tram
115 * tracks as that would result in trams that cannot turn. */
116 if (_current_company
== OWNER_WATER
||
117 (rt
== ROADTYPE_ROAD
&& !Company::IsValidID(_current_company
))) return CommandCost();
119 /* Only do the special processing if the road is owned
121 if (owner
!= OWNER_TOWN
) {
122 if (owner
== OWNER_NONE
) return CommandCost();
123 CommandCost ret
= CheckOwnership(owner
);
127 if (!town_check
) return CommandCost();
129 if (_cheats
.magic_bulldozer
.value
) return CommandCost();
131 Town
*t
= ClosestTownFromTile(tile
);
132 if (t
== NULL
) return CommandCost();
134 /* check if you're allowed to remove the street owned by a town
135 * removal allowance depends on difficulty setting */
136 CommandCost ret
= CheckforTownRating(flags
, t
, ROAD_REMOVE
);
137 if (ret
.Failed()) return ret
;
139 /* Get a bitmask of which neighbouring roads has a tile */
140 RoadBits n
= ROAD_NONE
;
141 RoadBits present
= GetAnyRoadBits(tile
, rt
);
142 if ((present
& ROAD_NE
) && (GetAnyRoadBits(TILE_ADDXY(tile
, -1, 0), rt
) & ROAD_SW
)) n
|= ROAD_NE
;
143 if ((present
& ROAD_SE
) && (GetAnyRoadBits(TILE_ADDXY(tile
, 0, 1), rt
) & ROAD_NW
)) n
|= ROAD_SE
;
144 if ((present
& ROAD_SW
) && (GetAnyRoadBits(TILE_ADDXY(tile
, 1, 0), rt
) & ROAD_NE
)) n
|= ROAD_SW
;
145 if ((present
& ROAD_NW
) && (GetAnyRoadBits(TILE_ADDXY(tile
, 0, -1), rt
) & ROAD_SE
)) n
|= ROAD_NW
;
147 int rating_decrease
= RATING_ROAD_DOWN_STEP_EDGE
;
148 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove,
150 if (KillFirstBit(n
) != ROAD_NONE
&& (n
& remove
) != ROAD_NONE
) {
151 /* you can remove all kind of roads with extra dynamite */
152 if (!_settings_game
.construction
.extra_dynamite
) {
153 SetDParam(0, t
->index
);
154 return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS
);
156 rating_decrease
= RATING_ROAD_DOWN_STEP_INNER
;
158 ChangeTownRating(t
, rating_decrease
, RATING_ROAD_MINIMUM
, flags
);
160 return CommandCost();
165 * Clear road bits and type and make necessary adjustments in a road tile
166 * @param tile tile to clear road type from
167 * @param rt road type to clear
168 * @pre IsRoadTile(tile)
170 static void ClearRoadType(TileIndex tile
, RoadType rt
)
172 assert(IsRoadTile(tile
));
174 RoadTypes rts
= GetRoadTypes(tile
) & ~RoadTypeToRoadTypes(rt
);
175 if (rts
== ROADTYPES_NONE
) {
180 if (rt
== ROADTYPE_ROAD
&& IsRoadOwner(tile
, ROADTYPE_ROAD
, OWNER_TOWN
)) {
181 /* Update nearest-town index */
182 SetTownIndex(tile
, CalcClosestTownIDFromTile(tile
));
185 SetRoadBits(tile
, ROAD_NONE
, rt
);
186 SetRoadTypes(tile
, rts
);
188 /* If the owner of a roadtype sells all their road, set the ownership
189 * of the tile to the owner of the other roadtype. */
190 RoadType other_rt
= (rt
== ROADTYPE_ROAD
) ? ROADTYPE_TRAM
: ROADTYPE_ROAD
;
191 Owner other_owner
= GetRoadOwner(tile
, other_rt
);
192 if (other_owner
!= GetTileOwner(tile
)) {
193 SetTileOwner(tile
, other_owner
);
199 * Delete a piece of road from a normal road tile
200 * @param tile tile where to remove road from
201 * @param flags operation to perform
202 * @param pieces roadbits to remove
203 * @param rt roadtype to remove
204 * @param town_check should we check if the town allows removal?
206 static CommandCost
RemoveRoad_Road(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
208 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
209 if (ret
.Failed()) return ret
;
211 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
212 if (ret
.Failed()) return ret
;
214 if (HasRoadWorks(tile
) && _current_company
!= OWNER_WATER
) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS
);
216 Slope tileh
= GetTileSlope(tile
);
218 /* Steep slopes behave the same as slopes with one corner raised. */
219 if (IsSteepSlope(tileh
)) {
220 tileh
= SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh
));
223 RoadBits present
= GetRoadBits(tile
, rt
);
224 const RoadBits other
= GetOtherRoadBits(tile
, rt
);
225 const Foundation f
= GetRoadFoundation(tileh
, present
);
227 /* Autocomplete to a straight road
228 * @li if the bits of the other roadtypes result in another foundation
229 * @li if build on slopes is disabled */
230 if ((IsStraightRoad(other
) && (other
& _invalid_leveled_roadbits
[tileh
& SLOPE_ELEVATED
]) != ROAD_NONE
) ||
231 (tileh
!= SLOPE_FLAT
&& !_settings_game
.construction
.build_on_slopes
)) {
232 pieces
|= MirrorRoadBits(pieces
);
235 /* limit the bits to delete to the existing bits. */
237 if (pieces
== ROAD_NONE
) return_cmd_error(rt
== ROADTYPE_TRAM
? STR_ERROR_THERE_IS_NO_TRAMWAY
: STR_ERROR_THERE_IS_NO_ROAD
);
239 /* Now set present what it will be after the remove */
242 /* Check for invalid RoadBit combinations on slopes */
243 if (tileh
!= SLOPE_FLAT
&& present
!= ROAD_NONE
&&
244 (present
& _invalid_leveled_roadbits
[tileh
& SLOPE_ELEVATED
]) == present
) {
248 if (flags
& DC_EXEC
) {
249 if (HasRoadWorks(tile
)) {
250 /* flooding tile with road works, don't forget to remove the effect vehicle too */
251 assert(_current_company
== OWNER_WATER
);
253 FOR_ALL_EFFECTVEHICLES(v
) {
254 if (TileVirtXY(v
->x_pos
, v
->y_pos
) == tile
) {
260 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
262 c
->infrastructure
.road
[rt
] -= CountBits(pieces
);
263 DirtyCompanyInfrastructureWindows(c
->index
);
266 if (present
== ROAD_NONE
) {
267 ClearRoadType(tile
, rt
);
269 /* When bits are removed, you *always* end up with something that
270 * is not a complete straight road tile. However, trams do not have
271 * onewayness, so they cannot remove it either. */
272 if (rt
!= ROADTYPE_TRAM
) SetDisallowedRoadDirections(tile
, DRD_NONE
);
273 SetRoadBits(tile
, present
, rt
);
274 MarkTileDirtyByTile(tile
);
278 CommandCost
cost(EXPENSES_CONSTRUCTION
, CountBits(pieces
) * _price
[PR_CLEAR_ROAD
]);
279 /* If we build a foundation we have to pay for it. */
280 if (f
== FOUNDATION_NONE
&& GetRoadFoundation(tileh
, present
) != FOUNDATION_NONE
) cost
.AddCost(_price
[PR_BUILD_FOUNDATION
]);
285 * Delete a piece of road from a bridge
286 * @param tile tile where to remove road from
287 * @param flags operation to perform
288 * @param pieces roadbits to remove
289 * @param rt roadtype to remove
290 * @param town_check should we check if the town allows removal?
292 static CommandCost
RemoveRoad_Bridge(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
294 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
296 CommandCost ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
297 if (ret
.Failed()) return ret
;
299 RoadBits bits
= GetRoadBits(tile
, rt
);
301 /* limit the bits to delete to the existing bits. */
303 if (pieces
== ROAD_NONE
) return_cmd_error(rt
== ROADTYPE_TRAM
? STR_ERROR_THERE_IS_NO_TRAMWAY
: STR_ERROR_THERE_IS_NO_ROAD
);
305 if (HasBridgeFlatRamp(GetTileSlope(tile
), DiagDirToAxis(dir
))) {
308 assert((pieces
& ~AxisToRoadBits(DiagDirToAxis(dir
))) == ROAD_NONE
);
309 pieces
= AxisToRoadBits(DiagDirToAxis(dir
));
313 CommandCost
cost(EXPENSES_CONSTRUCTION
);
315 /* Other end and length of the bridge, if we are removing the bridge piece */
319 /* Roadbits left at the other side */
320 RoadBits other_end_bits
= ROAD_NONE
;
322 /* Whether to remove the bridge itself */
323 bool remove_bridge
= false;
325 if ((pieces
& DiagDirToRoadBits(dir
)) == 0) {
326 /* Not removing the bridge piece */
327 other_end
= INVALID_TILE
;
329 ret
= EnsureNoVehicleOnGround(tile
);
330 if (ret
.Failed()) return ret
;
332 cost
.AddCost(CountBits(pieces
) * _price
[PR_CLEAR_ROAD
]);
334 /* Removing the bridge piece */
335 other_end
= GetOtherBridgeEnd(tile
);
336 len
= GetTunnelBridgeLength(tile
, other_end
);
338 ret
= TunnelBridgeIsFree(tile
, other_end
);
339 if (ret
.Failed()) return ret
;
341 if ((GetOtherRoadBits(tile
, rt
) & DiagDirToRoadBits(dir
)) != 0) {
342 /* The other road type has the bridge piece, so the bridge stays */
343 uint num
= CountBits(pieces
) + 2 * len
;
345 if (!IsExtendedRoadBridge(other_end
)) {
346 assert(GetRoadBits(other_end
, rt
) == AxisToRoadBits(DiagDirToAxis(dir
)));
347 assert(GetOtherRoadBits(other_end
, rt
) == AxisToRoadBits(DiagDirToAxis(dir
)));
350 other_end_bits
= GetRoadBits(other_end
, rt
) & ~DiagDirToRoadBits(ReverseDiagDir(dir
));
354 cost
.AddCost(num
* _price
[PR_CLEAR_ROAD
]);
356 /* Removing the last bridge piece and therefore the bridge itself */
357 remove_bridge
= true;
358 cost
.AddCost((len
+ 2) * _price
[PR_CLEAR_BRIDGE
]);
360 if (IsExtendedRoadBridge(other_end
)) {
361 other_end_bits
= GetRoadBits(other_end
, rt
) & ~DiagDirToRoadBits(ReverseDiagDir(dir
));
366 if (flags
& DC_EXEC
) {
367 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
369 if (other_end
!= INVALID_TILE
) {
370 c
->infrastructure
.road
[rt
] -= (CountBits(bits
| pieces
) + 2 * len
+ CountBits(GetRoadBits(other_end
, rt
))) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
371 c
->infrastructure
.road
[rt
] += CountBits(bits
) + CountBits(other_end_bits
);
372 } else if ((bits
& DiagDirToRoadBits(dir
)) != 0) {
373 c
->infrastructure
.road
[rt
] -= CountBits(pieces
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
375 c
->infrastructure
.road
[rt
] -= CountBits(pieces
);
377 DirtyCompanyInfrastructureWindows(c
->index
);
380 if (remove_bridge
) RemoveBridgeMiddleTiles(tile
, other_end
);
382 if (bits
!= ROAD_NONE
) {
383 SetRoadBits(tile
, bits
, rt
);
384 if (remove_bridge
) MakeNormalRoadFromBridge(tile
);
386 assert((GetRoadTypes(tile
) != RoadTypeToRoadTypes(rt
)) || remove_bridge
);
387 if (remove_bridge
) MakeNormalRoadFromBridge(tile
);
388 ClearRoadType(tile
, rt
);
391 MarkTileDirtyByTile(tile
);
393 if (other_end
!= INVALID_TILE
) {
394 if (other_end_bits
!= ROAD_NONE
) {
395 SetRoadBits(other_end
, other_end_bits
, rt
);
396 if (remove_bridge
) MakeNormalRoadFromBridge(other_end
);
398 assert((GetRoadTypes(other_end
) != RoadTypeToRoadTypes(rt
)) || remove_bridge
);
399 if (remove_bridge
) MakeNormalRoadFromBridge(other_end
);
400 ClearRoadType(other_end
, rt
);
403 if (!remove_bridge
) MarkBridgeTilesDirty (tile
, other_end
, dir
, false);
411 * Delete a piece of road from a crossing
412 * @param tile tile where to remove road from
413 * @param flags operation to perform
414 * @param pieces roadbits to remove
415 * @param rt roadtype to remove
416 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
417 * @param town_check should we check if the town allows removal?
419 static CommandCost
RemoveRoad_Crossing(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool crossing_check
, bool town_check
)
421 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
422 if (ret
.Failed()) return ret
;
424 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
425 if (ret
.Failed()) return ret
;
427 if (pieces
& ComplementRoadBits(GetCrossingRoadBits(tile
))) {
431 /* Don't allow road to be removed from the crossing when there is tram;
432 * we can't draw the crossing without roadbits ;) */
433 if (rt
== ROADTYPE_ROAD
&& HasTileRoadType(tile
, ROADTYPE_TRAM
) && (flags
& DC_EXEC
|| crossing_check
)) return CMD_ERROR
;
435 if (flags
& DC_EXEC
) {
436 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
438 /* A full diagonal road tile has two road bits. */
439 c
->infrastructure
.road
[rt
] -= 2;
440 DirtyCompanyInfrastructureWindows(c
->index
);
443 RoadTypes rts
= GetRoadTypes(tile
) & ComplementRoadTypes(RoadTypeToRoadTypes(rt
));
444 if (rts
== ROADTYPES_NONE
) {
445 TrackBits tracks
= GetCrossingRailBits(tile
);
446 bool reserved
= HasCrossingReservation(tile
);
447 MakeRailNormal(tile
, GetTileOwner(tile
), tracks
, GetRailType(tile
));
448 if (reserved
) SetTrackReservation(tile
, tracks
);
450 /* Update rail count for level crossings. The plain track should still be accounted
451 * for, so only subtract the difference to the level crossing cost. */
452 c
= Company::GetIfValid(GetTileOwner(tile
));
454 c
->infrastructure
.rail
[GetRailType(tile
)] -= LEVELCROSSING_TRACKBIT_FACTOR
- 1;
455 DirtyCompanyInfrastructureWindows(c
->index
);
458 SetRoadTypes(tile
, rts
);
460 MarkTileDirtyByTile(tile
);
461 YapfNotifyTrackLayoutChange();
464 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_ROAD
] * 2);
468 * Delete a piece of road from a tunnel
469 * @param tile tile where to remove road from
470 * @param flags operation to perform
471 * @param pieces roadbits to remove
472 * @param rt roadtype to remove
473 * @param town_check should we check if the town allows removal?
475 static CommandCost
RemoveRoad_Tunnel(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
477 assert(GetTunnelTransportType(tile
) == TRANSPORT_ROAD
);
479 TileIndex other_end
= GetOtherTunnelEnd(tile
);
480 CommandCost ret
= TunnelBridgeIsFree(tile
, other_end
);
481 if (ret
.Failed()) return ret
;
483 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
484 if (ret
.Failed()) return ret
;
486 /* If it's the last roadtype, just clear the whole tile */
487 if (GetRoadTypes(tile
) == RoadTypeToRoadTypes(rt
)) return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
489 /* Removing any roadbit in the tunnel axis removes the roadtype (that's the behaviour remove-long-roads needs) */
490 if ((AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile
))) & pieces
) == ROAD_NONE
) return_cmd_error(rt
== ROADTYPE_TRAM
? STR_ERROR_THERE_IS_NO_TRAMWAY
: STR_ERROR_THERE_IS_NO_ROAD
);
492 CommandCost
cost(EXPENSES_CONSTRUCTION
);
493 /* Pay for *every* tile of the tunnel */
494 uint len
= GetTunnelBridgeLength(other_end
, tile
) + 2;
495 cost
.AddCost(len
* 2 * _price
[PR_CLEAR_ROAD
]);
497 if (flags
& DC_EXEC
) {
498 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
500 /* A full diagonal road tile has two road bits. */
501 c
->infrastructure
.road
[rt
] -= len
* 2 * TUNNELBRIDGE_TRACKBIT_FACTOR
;
502 DirtyCompanyInfrastructureWindows(c
->index
);
505 SetRoadTypes(other_end
, GetRoadTypes(other_end
) & ~RoadTypeToRoadTypes(rt
));
506 SetRoadTypes(tile
, GetRoadTypes(tile
) & ~RoadTypeToRoadTypes(rt
));
508 /* If the owner of the bridge sells all its road, also move the ownership
509 * to the owner of the other roadtype, unless the bridge owner is a town. */
510 RoadType other_rt
= (rt
== ROADTYPE_ROAD
) ? ROADTYPE_TRAM
: ROADTYPE_ROAD
;
511 Owner other_owner
= GetRoadOwner(tile
, other_rt
);
512 if (!IsTileOwner(tile
, other_owner
) && !IsTileOwner(tile
, OWNER_TOWN
)) {
513 SetTileOwner(tile
, other_owner
);
514 SetTileOwner(other_end
, other_owner
);
517 /* Mark tiles dirty that have been repaved */
518 MarkTileDirtyByTile(tile
);
519 MarkTileDirtyByTile(other_end
);
526 * Delete a piece of road from a station
527 * @param tile tile where to remove road from
528 * @param flags operation to perform
529 * @param pieces roadbits to remove
530 * @param rt roadtype to remove
531 * @param town_check should we check if the town allows removal?
533 static CommandCost
RemoveRoad_Station(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
535 if (!IsDriveThroughStopTile(tile
)) return CMD_ERROR
;
537 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
538 if (ret
.Failed()) return ret
;
540 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
541 if (ret
.Failed()) return ret
;
543 /* If it's the last roadtype, just clear the whole tile */
544 if (GetRoadTypes(tile
) == RoadTypeToRoadTypes(rt
)) return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
546 if (flags
& DC_EXEC
) {
547 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
549 /* A full diagonal road tile has two road bits. */
550 c
->infrastructure
.road
[rt
] -= 2;
551 DirtyCompanyInfrastructureWindows(c
->index
);
553 SetRoadTypes(tile
, GetRoadTypes(tile
) & ~RoadTypeToRoadTypes(rt
));
554 MarkTileDirtyByTile(tile
);
557 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_ROAD
] * 2);
561 * Delete a piece of road.
562 * @param tile tile where to remove road from
563 * @param flags operation to perform
564 * @param pieces roadbits to remove
565 * @param rt roadtype to remove
566 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
567 * @param town_check should we check if the town allows removal?
569 CommandCost
RemoveRoad(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool crossing_check
, bool town_check
= true)
571 switch (GetTileType(tile
)) {
573 if (!HasTileRoadType(tile
, rt
)) break;
575 if (IsTileSubtype(tile
, TT_TRACK
)) {
576 return RemoveRoad_Road(tile
, flags
, pieces
, rt
, town_check
);
578 return RemoveRoad_Bridge(tile
, flags
, pieces
, rt
, town_check
);
583 switch (GetTileSubtype(tile
)) {
584 case TT_MISC_CROSSING
:
585 if (!HasTileRoadType(tile
, rt
)) break;
586 return RemoveRoad_Crossing(tile
, flags
, pieces
, rt
, crossing_check
, town_check
);
589 if (GetTunnelTransportType(tile
) != TRANSPORT_ROAD
) break;
590 if (!HasTileRoadType(tile
, rt
)) break;
591 if (GetTunnelTransportType(tile
) != TRANSPORT_ROAD
) break;
592 return RemoveRoad_Tunnel(tile
, flags
, pieces
, rt
, town_check
);
601 if (!HasTileRoadType(tile
, rt
)) break;
603 return RemoveRoad_Station(tile
, flags
, pieces
, rt
, town_check
);
609 /* The tile doesn't have the given road type */
610 return_cmd_error(rt
== ROADTYPE_TRAM
? STR_ERROR_THERE_IS_NO_TRAMWAY
: STR_ERROR_THERE_IS_NO_ROAD
);
615 * Calculate the costs for roads on slopes
616 * Also compute the road bits that have to be built to fit the slope
618 * @param tileh The current slope
619 * @param pieces The RoadBits we want to add
620 * @param existing The existent RoadBits of the current type
621 * @param other The existent RoadBits for the other type
622 * @param build The actual RoadBits to build
623 * @return The costs for these RoadBits on this slope
625 static CommandCost
CheckRoadSlope(Slope tileh
, RoadBits pieces
, RoadBits existing
, RoadBits other
, RoadBits
*build
)
627 /* Remove already build pieces */
628 CLRBITS(pieces
, existing
);
630 /* If we can't build anything stop here */
631 if (pieces
== ROAD_NONE
) return CMD_ERROR
;
633 /* All RoadBit combos are valid on flat land */
634 if (tileh
== SLOPE_FLAT
) {
635 if (build
!= NULL
) *build
= pieces
;
636 return CommandCost();
639 /* Steep slopes behave the same as slopes with one corner raised. */
640 if (IsSteepSlope(tileh
)) {
641 tileh
= SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh
));
644 /* Roads on slopes */
645 if (_settings_game
.construction
.build_on_slopes
&& (_invalid_leveled_roadbits
[tileh
] & (other
| existing
| pieces
)) == ROAD_NONE
) {
646 if (build
!= NULL
) *build
= pieces
;
648 /* If we add leveling we've got to pay for it */
649 if ((other
| existing
) == ROAD_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
651 return CommandCost();
654 /* Autocomplete uphill roads */
655 pieces
|= MirrorRoadBits(pieces
);
656 RoadBits type_bits
= existing
| pieces
;
659 if (IsStraightRoad(type_bits
) && (other
== type_bits
|| other
== ROAD_NONE
) &&
660 (_invalid_straight_roadbits
[tileh
] & type_bits
) == ROAD_NONE
) {
661 /* Slopes without foundation */
662 if (!IsSlopeWithOneCornerRaised(tileh
)) {
663 if (build
!= NULL
) *build
= pieces
;
664 if (HasExactlyOneBit(existing
) && GetRoadFoundation(tileh
, existing
) == FOUNDATION_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
665 return CommandCost();
668 /* Prevent build on slopes if it isn't allowed */
669 if (_settings_game
.construction
.build_on_slopes
) {
670 if (build
!= NULL
) *build
= pieces
;
672 /* If we add foundation we've got to pay for it */
673 if ((other
| existing
) == ROAD_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
675 return CommandCost();
682 * Check if a given roadbits set is valid for a road bridge head
683 * @param tileh The slope
684 * @param dir The bridge direction
685 * @param bits The roadbits
686 * @return Whether the given combination is valid
688 bool IsValidRoadBridgeBits(Slope tileh
, DiagDirection dir
, RoadBits bits
)
690 DiagDirDiff diff
= CheckExtendedBridgeHead(tileh
, dir
);
693 case DIAGDIRDIFF_SAME
: return true;
694 case DIAGDIRDIFF_REVERSE
: return false;
695 default: return (bits
& DiagDirToRoadBits(ChangeDiagDir(dir
, diff
))) == 0;
700 * Build a piece of road, clearing the land if necessary
701 * @param tile tile where to build road
702 * @param flags operation to perform
703 * @param rt roadtype to build
704 * @param pieces roadbits to build
705 * @param company company building the road
706 * @param town owner/closest town
707 * @param drd directions to disallow
708 * @return the cost of this operation or an error
710 static CommandCost
BuildRoad_Clear(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
712 CommandCost
cost(EXPENSES_CONSTRUCTION
);
714 CommandCost ret
= DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
715 if (ret
.Failed()) return ret
;
718 Slope tileh
= GetTileSlope(tile
);
720 /* Check the foundation/slopes when adding road/tram bits */
721 ret
= CheckRoadSlope(tileh
, pieces
, ROAD_NONE
, ROAD_NONE
, &pieces
);
722 /* Return an error if we need to build a foundation (ret != 0) but the
723 * current setting is turned off */
724 if (ret
.Failed() || (ret
.GetCost() != 0 && !_settings_game
.construction
.build_on_slopes
)) {
725 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
729 uint num_pieces
= CountBits(pieces
);
730 cost
.AddCost(num_pieces
* _price
[PR_BUILD_ROAD
]);
732 if (flags
& DC_EXEC
) {
733 MakeRoadNormal(tile
, pieces
, RoadTypeToRoadTypes(rt
), town
, company
, company
);
735 /* Update company infrastructure count. */
736 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
738 c
->infrastructure
.road
[rt
] += num_pieces
;
739 DirtyCompanyInfrastructureWindows(c
->index
);
742 if (rt
!= ROADTYPE_TRAM
&& IsStraightRoad(pieces
)) {
743 SetDisallowedRoadDirections(tile
, drd
);
746 MarkTileDirtyByTile(tile
);
753 * Build a piece of road on a road tile
754 * @param tile tile where to build road
755 * @param flags operation to perform
756 * @param rt roadtype to build
757 * @param pieces roadbits to build
758 * @param company company building the road
759 * @param town owner/closest town
760 * @param toggle_drd directions to toggle disallow
761 * @return the cost of this operation or an error
763 static CommandCost
BuildRoad_Road(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections toggle_drd
)
765 if (HasRoadWorks(tile
)) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS
);
767 RoadBits existing
= ROAD_NONE
;
769 if (HasTileRoadType(tile
, rt
)) {
770 existing
= GetRoadBits(tile
, rt
);
771 bool crossing
= !IsStraightRoad(existing
| pieces
);
773 if (rt
!= ROADTYPE_TRAM
&& (GetDisallowedRoadDirections(tile
) != DRD_NONE
|| toggle_drd
!= DRD_NONE
) && crossing
) {
774 /* Junctions cannot be one-way */
775 return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION
);
778 if ((existing
& pieces
) == pieces
) {
779 /* We only want to set the (dis)allowed road directions */
780 if (toggle_drd
== DRD_NONE
|| rt
== ROADTYPE_TRAM
) {
781 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
784 if (crossing
) return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION
);
786 Owner owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
787 if (owner
!= OWNER_NONE
) {
788 CommandCost ret
= CheckOwnership(owner
, tile
);
789 if (ret
.Failed()) return ret
;
792 DisallowedRoadDirections dis_existing
= GetDisallowedRoadDirections(tile
);
793 DisallowedRoadDirections dis_new
= dis_existing
^ toggle_drd
;
795 /* We allow removing disallowed directions to break up
796 * deadlocks, but adding them can break articulated
797 * vehicles. As such, only when less is disallowed,
798 * i.e. bits are removed, we skip the vehicle check. */
799 if (CountBits(dis_existing
) <= CountBits(dis_new
)) {
800 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
801 if (ret
.Failed()) return ret
;
804 /* Ignore half built tiles */
805 if ((flags
& DC_EXEC
) && rt
!= ROADTYPE_TRAM
&& IsStraightRoad(existing
)) {
806 SetDisallowedRoadDirections(tile
, dis_new
);
807 MarkTileDirtyByTile(tile
);
810 return CommandCost();
813 /* Disallow breaking end-of-line of someone else
814 * so trams can still reverse on this tile. */
815 if (rt
== ROADTYPE_TRAM
&& HasExactlyOneBit (existing
)) {
816 Owner owner
= GetRoadOwner (tile
, ROADTYPE_TRAM
);
817 if (owner
!= OWNER_NONE
) {
818 CommandCost ret
= CheckOwnership (owner
);
819 if (ret
.Failed()) return ret
;
824 CommandCost
cost(EXPENSES_CONSTRUCTION
);
826 RoadBits other_bits
= GetOtherRoadBits(tile
, rt
);
828 Slope tileh
= GetTileSlope(tile
);
830 if (other_bits
!= pieces
) {
831 /* Check the foundation/slopes when adding road/tram bits */
832 CommandCost ret
= CheckRoadSlope(tileh
, pieces
, existing
, other_bits
, &pieces
);
833 /* Return an error if we need to build a foundation (ret != 0) but the
834 * current setting is turned off */
835 if (ret
.Failed() || (ret
.GetCost() != 0 && !_settings_game
.construction
.build_on_slopes
)) {
836 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
841 /* Don't put the pieces that already exist */
842 pieces
&= ComplementRoadBits(existing
);
844 /* Check if new road bits will have the same foundation as other existing road types */
845 Foundation found_new
= GetRoadFoundation(tileh
, pieces
| existing
);
847 /* Test if all other roadtypes can be built at that foundation */
848 for (RoadType rtest
= ROADTYPE_ROAD
; rtest
< ROADTYPE_END
; rtest
++) {
849 if (rtest
!= rt
) { // check only other road types
850 RoadBits bits
= GetRoadBits(tile
, rtest
);
851 /* do not check if there are not road bits of given type */
852 if (bits
!= ROAD_NONE
&& GetRoadFoundation(tileh
, bits
) != found_new
) {
853 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
858 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
859 if (ret
.Failed()) return ret
;
861 uint num_pieces
= CountBits(pieces
);
862 cost
.AddCost(num_pieces
* _price
[PR_BUILD_ROAD
]);
864 if (flags
& DC_EXEC
) {
865 if (existing
== ROAD_NONE
) {
866 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
867 SetRoadOwner(tile
, rt
, company
);
868 if (rt
== ROADTYPE_ROAD
) SetTownIndex(tile
, town
);
871 SetRoadBits(tile
, existing
| pieces
, rt
);
873 /* Update company infrastructure count. */
874 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
876 c
->infrastructure
.road
[rt
] += num_pieces
;
877 DirtyCompanyInfrastructureWindows(c
->index
);
880 if (rt
!= ROADTYPE_TRAM
) {
881 SetDisallowedRoadDirections(tile
, IsStraightRoad(existing
| pieces
) ?
882 GetDisallowedRoadDirections(tile
) ^ toggle_drd
: DRD_NONE
);
885 MarkTileDirtyByTile(tile
);
892 * Build a piece of road on a bridge tile
893 * @param tile tile where to build road
894 * @param flags operation to perform
895 * @param rt roadtype to build
896 * @param pieces roadbits to build
897 * @param company company building the road
898 * @param town owner/closest town
899 * @param drd directions to disallow
900 * @return the cost of this operation or an error
902 static CommandCost
BuildRoad_Bridge(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
904 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
905 Slope tileh
= GetTileSlope(tile
);
909 if (HasBridgeFlatRamp(tileh
, DiagDirToAxis(dir
))) {
910 RoadBits existing
= GetRoadBits(tile
, rt
);
912 if (pieces
== ROAD_NONE
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
914 if (!IsValidRoadBridgeBits(tileh
, dir
, existing
| pieces
)) {
915 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
918 /* Disallow breaking end-of-line of someone else
919 * so trams can still reverse on this tile. */
920 if (rt
== ROADTYPE_TRAM
&& HasExactlyOneBit (existing
)) {
921 Owner owner
= GetRoadOwner (tile
, ROADTYPE_TRAM
);
922 if (owner
!= OWNER_NONE
) {
923 CommandCost ret
= CheckOwnership (owner
);
924 if (ret
.Failed()) return ret
;
928 num
= CountBits(pieces
);
929 other_end
= (pieces
& DiagDirToRoadBits(dir
)) != 0;
932 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
933 if (pieces
!= DiagDirToRoadBits(ReverseDiagDir(dir
))) {
934 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
937 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
939 pieces
= AxisToRoadBits(DiagDirToAxis(dir
));
944 TileIndex other_tile
;
945 RoadBits other_pieces
;
948 other_tile
= GetOtherBridgeEnd(tile
);
950 /* Don't allow adding roadtype to the bridge when vehicles are already driving on it */
951 CommandCost ret
= TunnelBridgeIsFree(tile
, other_tile
);
952 if (ret
.Failed()) return ret
;
954 /* Don't allow to mix owners */
955 CompanyID new_owner
= HasTileRoadType(tile
, rt
) ? GetRoadOwner(tile
, rt
) : company
;
956 CompanyID other_owner
= HasTileRoadType(other_tile
, rt
) ? GetRoadOwner(other_tile
, rt
) : company
;
957 if (new_owner
!= other_owner
) return CMD_ERROR
;
959 num
+= 2 * GetTunnelBridgeLength(tile
, other_tile
);
961 if (IsExtendedRoadBridge(other_tile
)) {
962 other_pieces
= GetRoadBits(other_tile
, rt
) | DiagDirToRoadBits(ReverseDiagDir(dir
));
965 assert(GetRoadBits(other_tile
, rt
) == ROAD_NONE
);
966 other_pieces
= AxisToRoadBits(DiagDirToAxis(dir
));
970 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
971 if (ret
.Failed()) return ret
;
974 if (flags
& DC_EXEC
) {
976 /* Update company infrastructure count. */
977 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
979 uint existing
= CountBits(GetRoadBits(tile
, rt
)) + CountBits(GetRoadBits(other_tile
, rt
));
980 c
->infrastructure
.road
[rt
] -= existing
;
981 c
->infrastructure
.road
[rt
] += (existing
+ num
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
982 DirtyCompanyInfrastructureWindows(c
->index
);
985 if (!HasTileRoadType(other_tile
, rt
)) {
986 SetRoadTypes(other_tile
, GetRoadTypes(other_tile
) | RoadTypeToRoadTypes(rt
));
987 SetRoadOwner(other_tile
, rt
, company
);
989 SetRoadBits(other_tile
, other_pieces
, rt
);
991 MarkBridgeTilesDirty(tile
, other_tile
, dir
, false);
993 /* Update company infrastructure count. */
994 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
996 c
->infrastructure
.road
[rt
] += (pieces
& DiagDirToRoadBits(dir
)) != 0 ? num
* TUNNELBRIDGE_TRACKBIT_FACTOR
: num
;
997 DirtyCompanyInfrastructureWindows(c
->index
);
1001 if (!HasTileRoadType(tile
, rt
)) {
1002 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1003 SetRoadOwner(tile
, rt
, company
);
1005 SetRoadBits(tile
, pieces
, rt
);
1006 MarkTileDirtyByTile(tile
);
1009 return CommandCost(EXPENSES_CONSTRUCTION
, num
* _price
[PR_BUILD_ROAD
]);
1013 * Build a piece of road on a crossing tile
1014 * @param tile tile where to build road
1015 * @param flags operation to perform
1016 * @param rt roadtype to build
1017 * @param pieces roadbits to build
1018 * @param company company building the road
1019 * @param town owner/closest town
1020 * @param drd directions to disallow
1021 * @return the cost of this operation or an error
1023 static CommandCost
BuildRoad_Crossing(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1025 if (pieces
& ComplementRoadBits(GetCrossingRoadBits(tile
))) {
1026 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1029 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1031 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1032 if (ret
.Failed()) return ret
;
1034 if (flags
& DC_EXEC
) {
1035 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1036 SetRoadOwner(tile
, rt
, company
);
1037 if (rt
== ROADTYPE_ROAD
) SetTownIndex(tile
, town
);
1039 /* Update company infrastructure count. */
1040 Company
*c
= Company::GetIfValid(company
);
1042 c
->infrastructure
.road
[rt
] += 2;
1043 DirtyCompanyInfrastructureWindows(c
->index
);
1046 MarkTileDirtyByTile(tile
);
1049 return CommandCost(EXPENSES_CONSTRUCTION
, 2 * _price
[PR_BUILD_ROAD
]);
1053 * Build a piece of road on a railway tile
1054 * @param tile tile where to build road
1055 * @param flags operation to perform
1056 * @param rt roadtype to build
1057 * @param pieces roadbits to build
1058 * @param company company building the road
1059 * @param town owner/closest town
1060 * @param drd directions to disallow
1061 * @return the cost of this operation or an error
1063 static CommandCost
BuildRoad_Railway(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1065 Slope tileh
= GetTileSlope(tile
);
1067 if (!IsTileSubtype(tile
, TT_TRACK
)) goto do_clear
;
1069 /* Level crossings may only be built on these slopes */
1070 if (IsSteepSlope(tileh
) || !HasBit(VALID_LEVEL_CROSSING_SLOPES
, tileh
)) {
1071 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
1074 if (RailNoLevelCrossings(GetRailType(tile
))) {
1075 return_cmd_error(STR_ERROR_CROSSING_DISALLOWED
);
1078 if (HasSignalOnTrack(tile
, TRACK_UPPER
)) goto do_clear
;
1081 switch (GetTrackBits(tile
)) {
1083 if (pieces
& ROAD_X
) goto do_clear
;
1088 if (pieces
& ROAD_Y
) goto do_clear
;
1094 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1097 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1098 if (ret
.Failed()) return ret
;
1100 if (flags
& DC_EXEC
) {
1101 YapfNotifyTrackLayoutChange();
1102 /* Update company infrastructure counts. A level crossing has two road bits. */
1103 Company
*c
= Company::GetIfValid(company
);
1105 c
->infrastructure
.road
[rt
] += 2;
1106 if (rt
!= ROADTYPE_ROAD
) c
->infrastructure
.road
[ROADTYPE_ROAD
] += 2;
1107 DirtyCompanyInfrastructureWindows(company
);
1109 /* Update rail count for level crossings. The plain track is already
1110 * counted, so only add the difference to the level crossing cost. */
1111 c
= Company::GetIfValid(GetTileOwner(tile
));
1113 c
->infrastructure
.rail
[GetRailType(tile
)] += LEVELCROSSING_TRACKBIT_FACTOR
- 1;
1114 DirtyCompanyInfrastructureWindows(c
->index
);
1117 /* Always add road to the roadtypes (can't draw without it) */
1118 bool reserved
= GetRailReservationTrackBits (tile
) != TRACK_BIT_NONE
;
1119 MakeRoadCrossing(tile
, company
, company
, GetTileOwner(tile
), roaddir
, GetRailType(tile
), RoadTypeToRoadTypes(rt
) | ROADTYPES_ROAD
, town
);
1120 SetCrossingReservation(tile
, reserved
);
1121 UpdateLevelCrossing(tile
, false);
1122 MarkTileDirtyByTile(tile
);
1125 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_ROAD
] * (rt
== ROADTYPE_ROAD
? 2 : 4));
1129 * Build a piece of road on a tunnel tile
1130 * @param tile tile where to build road
1131 * @param flags operation to perform
1132 * @param rt roadtype to build
1133 * @param pieces roadbits to build
1134 * @param company company building the road
1135 * @param town owner/closest town
1136 * @param drd directions to disallow
1137 * @return the cost of this operation or an error
1139 static CommandCost
BuildRoad_Tunnel(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1141 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
1142 if (GetTunnelTransportType(tile
) != TRANSPORT_ROAD
|| pieces
!= DiagDirToRoadBits(ReverseDiagDir(GetTunnelBridgeDirection(tile
)))) {
1143 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1146 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1148 TileIndex other_end
= GetOtherTunnelEnd(tile
);
1150 /* Don't allow adding roadtype to the tunnel when vehicles are already driving on it */
1151 CommandCost ret
= TunnelBridgeIsFree(tile
, other_end
);
1152 if (ret
.Failed()) return ret
;
1154 /* There are 2 pieces on *every* tile of the tunnel */
1155 uint num_pieces
= 2 * (GetTunnelBridgeLength(tile
, other_end
) + 2);
1157 if (flags
& DC_EXEC
) {
1158 SetRoadTypes(other_end
, GetRoadTypes(other_end
) | RoadTypeToRoadTypes(rt
));
1159 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1160 SetRoadOwner(other_end
, rt
, company
);
1161 SetRoadOwner(tile
, rt
, company
);
1163 /* Mark tiles dirty that have been repaved */
1164 MarkTileDirtyByTile(other_end
);
1165 MarkTileDirtyByTile(tile
);
1167 /* Update company infrastructure count. */
1168 Company
*c
= Company::GetIfValid(company
);
1170 c
->infrastructure
.road
[rt
] += num_pieces
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
1171 DirtyCompanyInfrastructureWindows(c
->index
);
1175 return CommandCost(EXPENSES_CONSTRUCTION
, num_pieces
* _price
[PR_BUILD_ROAD
]);
1179 * Build a piece of road on a station tile
1180 * @param tile tile where to build road
1181 * @param flags operation to perform
1182 * @param rt roadtype to build
1183 * @param pieces roadbits to build
1184 * @param company company building the road
1185 * @param town owner/closest town
1186 * @param drd directions to disallow
1187 * @return the cost of this operation or an error
1189 static CommandCost
BuildRoad_Station(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1191 if ((GetAnyRoadBits(tile
, rt
) & pieces
) == pieces
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1193 if (!IsDriveThroughStopTile(tile
) || (pieces
& ~AxisToRoadBits(GetRoadStopAxis(tile
)))) {
1194 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1197 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1199 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1200 if (ret
.Failed()) return ret
;
1202 if (flags
& DC_EXEC
) {
1203 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1204 SetRoadOwner(tile
, rt
, company
);
1206 /* Update company infrastructure count. */
1207 Company
*c
= Company::GetIfValid(company
);
1209 c
->infrastructure
.road
[rt
] += 2;
1210 DirtyCompanyInfrastructureWindows(c
->index
);
1213 MarkTileDirtyByTile(tile
);
1216 return CommandCost(EXPENSES_CONSTRUCTION
, 2 * _price
[PR_BUILD_ROAD
]);
1220 * Build a piece of road.
1221 * @param tile tile where to build road
1222 * @param flags operation to perform
1223 * @param p1 bit 0..3 road pieces to build (RoadBits)
1224 * bit 4..5 road type
1225 * bit 6..7 disallowed directions to toggle
1226 * @param p2 the town that is building the road (0 if not applicable)
1227 * @param text unused
1228 * @return the cost of this operation or an error
1230 CommandCost
CmdBuildRoad(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1232 CompanyID company
= _current_company
;
1234 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
1235 * if a non-company is building the road */
1236 if (company
== OWNER_TOWN
) {
1237 if (!Town::IsValidID(p2
)) return CMD_ERROR
;
1239 if (p2
!= 0) return CMD_ERROR
;
1241 const Town
*town
= CalcClosestTownFromTile(tile
);
1242 p2
= (town
!= NULL
) ? town
->index
: (TownID
)INVALID_TOWN
;
1244 if (company
== OWNER_DEITY
) {
1245 company
= OWNER_TOWN
;
1247 /* If we are not within a town, we are not owned by the town */
1248 if (town
== NULL
|| DistanceSquare(tile
, town
->xy
) > town
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
1249 company
= OWNER_NONE
;
1254 RoadBits pieces
= Extract
<RoadBits
, 0, 4>(p1
);
1256 /* do not allow building 'zero' road bits, code wouldn't handle it */
1257 if (pieces
== ROAD_NONE
) return CMD_ERROR
;
1259 RoadType rt
= Extract
<RoadType
, 4, 2>(p1
);
1260 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1262 DisallowedRoadDirections toggle_drd
= Extract
<DisallowedRoadDirections
, 6, 2>(p1
);
1264 switch (GetTileType(tile
)) {
1266 if (IsTileSubtype(tile
, TT_BRIDGE
)) {
1267 return BuildRoad_Bridge(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1269 return BuildRoad_Road(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1273 return BuildRoad_Railway(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1276 return BuildRoad_Station(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1279 switch (GetTileSubtype(tile
)) {
1280 case TT_MISC_CROSSING
:
1281 return BuildRoad_Crossing(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1283 case TT_MISC_TUNNEL
:
1284 return BuildRoad_Tunnel(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1287 if (IsRoadDepot(tile
) && (GetAnyRoadBits(tile
, rt
) & pieces
) == pieces
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1294 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1299 * Checks whether a road or tram connection can be found when building a new road or tram.
1300 * @param tile Tile at which the road being built will end.
1301 * @param rt Roadtype of the road being built.
1302 * @param dir Direction that the road is following.
1303 * @return True if the next tile at dir direction is suitable for being connected directly by a second roadbit at the end of the road being built.
1305 static bool CanConnectToRoad(TileIndex tile
, RoadType rt
, DiagDirection dir
)
1307 RoadBits bits
= GetAnyRoadBits(tile
+ TileOffsByDiagDir(dir
), rt
, false);
1308 return (bits
& DiagDirToRoadBits(ReverseDiagDir(dir
))) != 0;
1312 * Build a long piece of road.
1313 * @param start_tile start tile of drag (the building cost will appear over this tile)
1314 * @param flags operation to perform
1315 * @param p1 end tile of drag
1316 * @param p2 various bitstuffed elements
1317 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1). Only used if bit 6 is set or if we are building a single tile
1318 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2). Only used if bit 6 is set or if we are building a single tile
1319 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1320 * - p2 = (bit 3 + 4) - road type
1321 * - p2 = (bit 5) - set road direction
1322 * - p2 = (bit 6) - defines two different behaviors for this command:
1323 * - 0 = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile
1324 * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
1325 * @param text unused
1326 * @return the cost of this operation or an error
1328 CommandCost
CmdBuildLongRoad(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1330 DisallowedRoadDirections drd
= DRD_NORTHBOUND
;
1332 if (p1
>= MapSize()) return CMD_ERROR
;
1334 TileIndex end_tile
= p1
;
1335 RoadType rt
= Extract
<RoadType
, 3, 2>(p2
);
1336 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1338 Axis axis
= Extract
<Axis
, 2, 1>(p2
);
1339 /* Only drag in X or Y direction dictated by the direction variable */
1340 if (axis
== AXIS_X
&& TileY(start_tile
) != TileY(end_tile
)) return CMD_ERROR
; // x-axis
1341 if (axis
== AXIS_Y
&& TileX(start_tile
) != TileX(end_tile
)) return CMD_ERROR
; // y-axis
1343 DiagDirection dir
= AxisToDiagDir(axis
);
1345 /* Swap direction, also the half-tile drag var (bit 0 and 1) */
1346 if (start_tile
> end_tile
|| (start_tile
== end_tile
&& HasBit(p2
, 0))) {
1347 dir
= ReverseDiagDir(dir
);
1349 drd
= DRD_SOUTHBOUND
;
1352 /* On the X-axis, we have to swap the initial bits, so they
1353 * will be interpreted correctly in the GTTS. Furthermore
1354 * when you just 'click' on one tile to build them. */
1355 if ((axis
== AXIS_Y
) == (start_tile
== end_tile
&& HasBit(p2
, 0) == HasBit(p2
, 1))) drd
^= DRD_BOTH
;
1356 /* No disallowed direction bits have to be toggled */
1357 if (!HasBit(p2
, 5)) drd
= DRD_NONE
;
1359 CommandCost
cost(EXPENSES_CONSTRUCTION
);
1360 CommandCost last_error
= CMD_ERROR
;
1361 TileIndex tile
= start_tile
;
1362 bool had_bridge
= false;
1363 bool had_tunnel
= false;
1364 bool had_success
= false;
1365 bool is_ai
= HasBit(p2
, 6);
1367 /* Start tile is the first tile clicked by the user. */
1369 RoadBits bits
= AxisToRoadBits(axis
);
1371 /* Determine which road parts should be built. */
1372 if (!is_ai
&& start_tile
!= end_tile
) {
1373 /* Only build the first and last roadbit if they can connect to something. */
1374 if (tile
== end_tile
&& !CanConnectToRoad(tile
, rt
, dir
)) {
1375 bits
= DiagDirToRoadBits(ReverseDiagDir(dir
));
1376 } else if (tile
== start_tile
&& !CanConnectToRoad(tile
, rt
, ReverseDiagDir(dir
))) {
1377 bits
= DiagDirToRoadBits(dir
);
1380 /* Road parts only have to be built at the start tile or at the end tile. */
1381 if (tile
== end_tile
&& !HasBit(p2
, 1)) bits
&= DiagDirToRoadBits(ReverseDiagDir(dir
));
1382 if (tile
== start_tile
&& HasBit(p2
, 0)) bits
&= DiagDirToRoadBits(dir
);
1385 CommandCost ret
= DoCommand(tile
, drd
<< 6 | rt
<< 4 | bits
, 0, flags
, CMD_BUILD_ROAD
);
1388 if (last_error
.GetErrorMessage() != STR_ERROR_ALREADY_BUILT
) {
1389 if (is_ai
) return last_error
;
1394 /* Only pay for the upgrade on one side of the bridges and tunnels */
1395 if (IsTunnelTile(tile
)) {
1396 if (!had_tunnel
|| GetTunnelBridgeDirection(tile
) == dir
) {
1400 } else if (IsRoadBridgeTile(tile
)) {
1401 if (!had_bridge
|| GetTunnelBridgeDirection(tile
) == dir
) {
1410 if (tile
== end_tile
) break;
1412 tile
+= TileOffsByDiagDir(dir
);
1415 return had_success
? cost
: last_error
;
1419 * Remove a long piece of road.
1420 * @param start_tile start tile of drag
1421 * @param flags operation to perform
1422 * @param p1 end tile of drag
1423 * @param p2 various bitstuffed elements
1424 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
1425 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
1426 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1427 * - p2 = (bit 3 + 4) - road type
1428 * @param text unused
1429 * @return the cost of this operation or an error
1431 CommandCost
CmdRemoveLongRoad(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1433 CommandCost
cost(EXPENSES_CONSTRUCTION
);
1435 if (p1
>= MapSize()) return CMD_ERROR
;
1437 TileIndex end_tile
= p1
;
1438 RoadType rt
= Extract
<RoadType
, 3, 2>(p2
);
1439 if (!IsValidRoadType(rt
)) return CMD_ERROR
;
1441 Axis axis
= Extract
<Axis
, 2, 1>(p2
);
1442 /* Only drag in X or Y direction dictated by the direction variable */
1443 if (axis
== AXIS_X
&& TileY(start_tile
) != TileY(end_tile
)) return CMD_ERROR
; // x-axis
1444 if (axis
== AXIS_Y
&& TileX(start_tile
) != TileX(end_tile
)) return CMD_ERROR
; // y-axis
1446 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
1447 if (start_tile
> end_tile
|| (start_tile
== end_tile
&& HasBit(p2
, 0))) {
1448 TileIndex t
= start_tile
;
1449 start_tile
= end_tile
;
1451 p2
^= IsInsideMM(p2
& 3, 1, 3) ? 3 : 0;
1454 Money money
= GetAvailableMoneyForCommand();
1455 TileIndex tile
= start_tile
;
1456 CommandCost last_error
= CMD_ERROR
;
1457 bool had_success
= false;
1458 /* Start tile is the small number. */
1460 RoadBits bits
= AxisToRoadBits(axis
);
1462 if (tile
== end_tile
&& !HasBit(p2
, 1)) bits
&= ROAD_NW
| ROAD_NE
;
1463 if (tile
== start_tile
&& HasBit(p2
, 0)) bits
&= ROAD_SE
| ROAD_SW
;
1465 /* try to remove the halves. */
1467 CommandCost ret
= RemoveRoad(tile
, flags
& ~DC_EXEC
, bits
, rt
, true);
1468 if (ret
.Succeeded()) {
1469 if (flags
& DC_EXEC
) {
1470 money
-= ret
.GetCost();
1472 _additional_cash_required
= DoCommand(start_tile
, end_tile
, p2
, flags
& ~DC_EXEC
, CMD_REMOVE_LONG_ROAD
).GetCost();
1475 RemoveRoad(tile
, flags
, bits
, rt
, true, false);
1480 /* Ownership errors are more important. */
1481 if (last_error
.GetErrorMessage() != STR_ERROR_OWNED_BY
) last_error
= ret
;
1485 if (tile
== end_tile
) break;
1487 tile
+= (axis
== AXIS_Y
) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
1490 return had_success
? cost
: last_error
;
1494 * Build a road depot.
1495 * @param tile tile where to build the depot
1496 * @param flags operation to perform
1497 * @param p1 bit 0..1 entrance direction (DiagDirection)
1498 * bit 2..3 road type
1500 * @param text unused
1501 * @return the cost of this operation or an error
1503 * @todo When checking for the tile slope,
1504 * distinguish between "Flat land required" and "land sloped in wrong direction"
1506 CommandCost
CmdBuildRoadDepot(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1508 DiagDirection dir
= Extract
<DiagDirection
, 0, 2>(p1
);
1509 RoadType rt
= Extract
<RoadType
, 2, 2>(p1
);
1511 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1513 Slope tileh
= GetTileSlope(tile
);
1514 if (tileh
!= SLOPE_FLAT
&& (
1515 !_settings_game
.construction
.build_on_slopes
||
1516 !CanBuildDepotByTileh(dir
, tileh
)
1518 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED
);
1521 CommandCost cost
= DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
1522 if (cost
.Failed()) return cost
;
1524 if (HasBridgeAbove(tile
)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
1526 if (!Depot::CanAllocateItem()) return CMD_ERROR
;
1528 if (flags
& DC_EXEC
) {
1529 Depot
*dep
= new Depot(tile
);
1530 dep
->build_date
= _date
;
1532 /* A road depot has two road bits. */
1533 Company::Get(_current_company
)->infrastructure
.road
[rt
] += 2;
1534 DirtyCompanyInfrastructureWindows(_current_company
);
1536 MakeRoadDepot(tile
, _current_company
, dep
->index
, dir
, rt
);
1537 MarkTileDirtyByTile(tile
);
1538 MakeDefaultName(dep
);
1540 cost
.AddCost(_price
[PR_BUILD_DEPOT_ROAD
]);
1544 static CommandCost
ClearTile_Road(TileIndex tile
, DoCommandFlag flags
)
1546 if (IsTileSubtype(tile
, TT_TRACK
)) {
1547 RoadBits b
= GetAllRoadBits(tile
);
1549 /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
1550 if ((HasExactlyOneBit(b
) && GetRoadBits(tile
, ROADTYPE_TRAM
) == ROAD_NONE
) || !(flags
& DC_AUTO
)) {
1551 CommandCost
ret(EXPENSES_CONSTRUCTION
);
1553 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
1554 CommandCost tmp_ret
= RemoveRoad(tile
, flags
, GetRoadBits(tile
, rt
), rt
, true);
1555 if (tmp_ret
.Failed()) return tmp_ret
;
1556 ret
.AddCost(tmp_ret
);
1561 return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST
);
1563 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
1565 /* Floods can remove anything as well as the scenario editor */
1567 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
1568 RoadTypes rts
= GetRoadTypes(tile
);
1569 Owner road_owner
= _current_company
;
1570 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
1572 /* We can remove unowned road and if the town allows it */
1573 if (road_owner
== OWNER_TOWN
&& _current_company
!= OWNER_TOWN
&& !(_settings_game
.construction
.extra_dynamite
|| _cheats
.magic_bulldozer
.value
)) {
1574 /* Town does not allow */
1575 CommandCost ret
= CheckTileOwnership(tile
);
1576 if (ret
.Failed()) return ret
;
1578 if (road_owner
!= OWNER_NONE
&& road_owner
!= OWNER_TOWN
) {
1579 CommandCost ret
= CheckOwnership(road_owner
, tile
);
1580 if (ret
.Failed()) return ret
;
1583 if (HasBit(rts
, ROADTYPE_TRAM
)) {
1584 Owner tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
1585 if (tram_owner
!= OWNER_NONE
) {
1586 CommandCost ret
= CheckOwnership(tram_owner
, tile
);
1587 if (ret
.Failed()) return ret
;
1593 TileIndex endtile
= GetOtherBridgeEnd(tile
);
1595 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
1596 if (ret
.Failed()) return ret
;
1598 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
1599 Town
*t
= ClosestTownFromTile(tile
); // town penalty rating
1601 /* Check if you are allowed to remove the bridge owned by a town
1602 * Removal depends on difficulty settings */
1603 CommandCost ret
= CheckforTownRating(flags
, t
, TUNNELBRIDGE_REMOVE
);
1604 if (ret
.Failed()) return ret
;
1606 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
1607 * you have a "Poor" (0) town rating */
1608 ChangeTownRating(t
, RATING_TUNNEL_BRIDGE_DOWN_STEP
, RATING_TUNNEL_BRIDGE_MINIMUM
, flags
);
1611 uint len
= GetTunnelBridgeLength(tile
, endtile
);
1613 if (flags
& DC_EXEC
) {
1614 RemoveBridgeMiddleTiles(tile
, endtile
);
1616 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
1617 RoadBits bridge_piece
= DiagDirToRoadBits(dir
);
1618 RoadBits other_nonbridge_pieces
= ComplementRoadBits(DiagDirToRoadBits(ReverseDiagDir(dir
)));
1619 bool other_extended
= IsExtendedRoadBridge(endtile
);
1621 MakeNormalRoadFromBridge(endtile
);
1624 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
1625 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
1626 RoadBits pieces
= GetRoadBits(tile
, rt
);
1628 if ((pieces
& bridge_piece
) == 0) {
1629 /* This roadtype does not connect to the bridge */
1631 c
->infrastructure
.road
[rt
] -= CountBits(pieces
);
1632 DirtyCompanyInfrastructureWindows(c
->index
);
1635 /* This roadtype connects to the bridge */
1636 RoadBits other_pieces
= GetRoadBits(endtile
, rt
);
1639 /* A full diagonal road tile has two road bits. */
1640 c
->infrastructure
.road
[rt
] -= (CountBits(pieces
) + 2 * len
+ CountBits(other_pieces
)) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
1641 DirtyCompanyInfrastructureWindows(c
->index
);
1644 if (other_extended
&& ((other_pieces
&= other_nonbridge_pieces
) != 0)) {
1645 SetRoadBits(endtile
, other_pieces
, rt
);
1646 if (c
!= NULL
) c
->infrastructure
.road
[rt
] += CountBits(other_pieces
);
1648 ClearRoadType(endtile
, rt
);
1654 DoClearSquare(tile
);
1655 MarkTileDirtyByTile(endtile
);
1658 return CommandCost(EXPENSES_CONSTRUCTION
, (len
+ 2) * _price
[PR_CLEAR_BRIDGE
]);
1664 * Get the foundationtype of a RoadBits Slope combination
1666 * @param tileh The Slope part
1667 * @param bits The RoadBits part
1668 * @return The resulting Foundation
1670 static Foundation
GetRoadFoundation(Slope tileh
, RoadBits bits
)
1672 /* Flat land and land without a road doesn't require a foundation */
1673 if (tileh
== SLOPE_FLAT
|| bits
== ROAD_NONE
) return FOUNDATION_NONE
;
1675 /* Steep slopes behave the same as slopes with one corner raised. */
1676 if (IsSteepSlope(tileh
)) {
1677 tileh
= SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh
));
1680 /* Leveled RoadBits on a slope */
1681 if ((_invalid_leveled_roadbits
[tileh
] & bits
) == ROAD_NONE
) return FOUNDATION_LEVELED
;
1683 /* Straight roads without foundation on a slope */
1684 if (!IsSlopeWithOneCornerRaised(tileh
) &&
1685 (_invalid_straight_roadbits
[tileh
] & bits
) == ROAD_NONE
)
1686 return FOUNDATION_NONE
;
1688 /* Roads on steep Slopes or on Slopes with one corner raised */
1689 return (bits
== ROAD_X
? FOUNDATION_INCLINED_X
: FOUNDATION_INCLINED_Y
);
1692 const byte _road_sloped_sprites
[14] = {
1700 * Draw the ground sprite for a road tile
1701 * @param ti TileInfo of the tile to draw
1702 * @param roadside The roadside of the tile
1703 * @param image The sprite to draw
1704 * @param paved_offset The offset to add to the sprite if the road is paved
1705 * @param unpaved_offset The offset to add to the sprite if the tile is on snow or in the desert
1706 * @return The palette to use for further drawing
1708 static PaletteID
DrawRoadGroundSprite (const TileInfo
*ti
, Roadside roadside
, SpriteID image
, int paved_offset
, int unpaved_offset
)
1710 TileIndex tile
= ti
->tile
;
1711 PaletteID pal
= PAL_NONE
;
1714 case ROADSIDE_BARREN
:
1715 if (IsOnSnow(tile
)) {
1716 image
+= unpaved_offset
;
1718 pal
= PALETTE_TO_BARE_LAND
;
1722 case ROADSIDE_GRASS
:
1723 if (IsOnSnow(tile
)) image
+= unpaved_offset
;
1727 if (IsOnSnow(tile
) && !(_settings_game
.game_creation
.landscape
== LT_TROPIC
&& HasGrfMiscBit(GMB_DESERT_PAVED_ROADS
))) {
1728 image
+= unpaved_offset
;
1730 image
+= paved_offset
;
1735 DrawGroundSprite (ti
, image
, pal
);
1741 * Draws the catenary for the given tile
1742 * @param ti information about the tile (slopes, height etc)
1743 * @param tram the roadbits for the tram
1745 void DrawRoadCatenary(const TileInfo
*ti
, RoadBits tram
)
1747 /* Do not draw catenary if it is invisible */
1748 if (IsInvisibilitySet(TO_CATENARY
)) return;
1750 /* Don't draw the catenary under a low bridge */
1751 if (HasBridgeAbove(ti
->tile
) && !IsTransparencySet(TO_CATENARY
)) {
1752 int height
= GetBridgeHeight(GetNorthernBridgeEnd(ti
->tile
));
1754 if (height
<= GetTileMaxZ(ti
->tile
) + 1) return;
1760 if (ti
->tileh
!= SLOPE_FLAT
) {
1761 back
= SPR_TRAMWAY_BACK_WIRES_SLOPED
+ _road_sloped_sprites
[ti
->tileh
- 1];
1762 front
= SPR_TRAMWAY_FRONT_WIRES_SLOPED
+ _road_sloped_sprites
[ti
->tileh
- 1];
1764 back
= SPR_TRAMWAY_BASE
+ _road_backpole_sprites_1
[tram
];
1765 front
= SPR_TRAMWAY_BASE
+ _road_frontwire_sprites_1
[tram
];
1768 AddSortableSpriteToDraw (ti
->vd
, back
, PAL_NONE
, ti
->x
, ti
->y
, 16, 16, TILE_HEIGHT
+ BB_HEIGHT_UNDER_BRIDGE
, ti
->z
, IsTransparencySet(TO_CATENARY
));
1769 AddSortableSpriteToDraw (ti
->vd
, front
, PAL_NONE
, ti
->x
, ti
->y
, 16, 16, TILE_HEIGHT
+ BB_HEIGHT_UNDER_BRIDGE
, ti
->z
, IsTransparencySet(TO_CATENARY
));
1773 * Draws details on/around the road
1774 * @param img the sprite to draw
1775 * @param ti the tile to draw on
1776 * @param dx the offset from the top of the BB of the tile
1777 * @param dy the offset from the top of the BB of the tile
1778 * @param h the height of the sprite to draw
1780 static void DrawRoadDetail(SpriteID img
, const TileInfo
*ti
, int dx
, int dy
, int h
)
1785 if (ti
->tileh
!= SLOPE_FLAT
) z
= GetSlopePixelZ(x
, y
);
1786 AddSortableSpriteToDraw (ti
->vd
, img
, PAL_NONE
, x
, y
, 2, 2, h
, z
);
1790 * Draw ground sprite and road pieces
1791 * @param ti TileInfo
1793 static void DrawRoadBits(TileInfo
*ti
)
1795 RoadBits road
= GetRoadBits(ti
->tile
, ROADTYPE_ROAD
);
1796 RoadBits tram
= GetRoadBits(ti
->tile
, ROADTYPE_TRAM
);
1800 if (IsTileSubtype(ti
->tile
, TT_BRIDGE
)) {
1801 assert(ti
->tileh
!= SLOPE_FLAT
);
1802 DrawFoundation(ti
, FOUNDATION_LEVELED
, GetTunnelBridgeDirection(ti
->tile
));
1803 } else if (ti
->tileh
!= SLOPE_FLAT
) {
1804 Foundation f
= GetRoadFoundation(ti
->tileh
, road
| tram
);
1806 DrawFoundation(ti
, f
);
1808 /* DrawFoundation() modifies ti.
1809 * Default sloped sprites.. */
1810 if (ti
->tileh
!= SLOPE_FLAT
) image
= _road_sloped_sprites
[ti
->tileh
- 1] + SPR_ROAD_SLOPE_START
;
1813 if (image
== 0) image
= _road_tile_sprites_1
[road
!= ROAD_NONE
? road
: tram
];
1815 Roadside roadside
= IsTileSubtype(ti
->tile
, TT_TRACK
) ? GetRoadside(ti
->tile
) : ROADSIDE_GRASS
;
1817 PaletteID pal
= DrawRoadGroundSprite (ti
, roadside
, image
, -19, 19);
1819 /* For tram we overlay the road graphics with either tram tracks only
1820 * (when there is actual road beneath the trams) or with tram tracks
1821 * and some dirts which hides the road graphics */
1822 if (tram
!= ROAD_NONE
) {
1823 if (ti
->tileh
!= SLOPE_FLAT
) {
1824 image
= _road_sloped_sprites
[ti
->tileh
- 1] + SPR_TRAMWAY_SLOPED_OFFSET
;
1826 image
= _road_tile_sprites_1
[tram
] - SPR_ROAD_Y
;
1828 image
+= (road
== ROAD_NONE
) ? SPR_TRAMWAY_TRAM
: SPR_TRAMWAY_OVERLAY
;
1829 DrawGroundSprite (ti
, image
, pal
);
1832 if (IsTileSubtype(ti
->tile
, TT_TRACK
) && road
!= ROAD_NONE
) {
1833 DisallowedRoadDirections drd
= GetDisallowedRoadDirections(ti
->tile
);
1834 if (drd
!= DRD_NONE
) {
1835 DrawGroundSpriteAt (ti
, SPR_ONEWAY_BASE
+ drd
- 1 + ((road
== ROAD_X
) ? 0 : 3), PAL_NONE
, 8, 8, GetPartialPixelZ(8, 8, ti
->tileh
));
1839 if (IsTileSubtype(ti
->tile
, TT_TRACK
) && HasRoadWorks(ti
->tile
)) {
1841 DrawGroundSprite (ti
, (road
| tram
) & ROAD_X
? SPR_EXCAVATION_X
: SPR_EXCAVATION_Y
, PAL_NONE
);
1845 if (tram
!= ROAD_NONE
) DrawRoadCatenary(ti
, tram
);
1847 if (!IsTileSubtype(ti
->tile
, TT_TRACK
)) return;
1849 /* Return if full detail is disabled, or we are zoomed fully out. */
1850 if (!HasBit(_display_opt
, DO_FULL_DETAIL
)) return;
1851 if (!IsViewportDrawerDetailed (ti
->vd
)) return;
1853 /* Do not draw details (street lights, trees) under low bridge */
1854 if (HasBridgeAbove(ti
->tile
) && (roadside
== ROADSIDE_TREES
|| roadside
== ROADSIDE_STREET_LIGHTS
)) {
1855 int height
= GetBridgeHeight(GetNorthernBridgeEnd(ti
->tile
));
1856 int minz
= GetTileMaxZ(ti
->tile
) + 2;
1858 if (roadside
== ROADSIDE_TREES
) minz
++;
1860 if (height
< minz
) return;
1863 /* If there are no road bits, return, as there is nothing left to do */
1864 if (HasAtMostOneBit(road
)) return;
1866 /* Draw extra details. */
1867 for (const DrawRoadTileStruct
*drts
= _road_display_table
[roadside
][road
| tram
]; drts
->image
!= 0; drts
++) {
1868 DrawRoadDetail(drts
->image
, ti
, drts
->subcoord_x
, drts
->subcoord_y
, 0x10);
1872 /** Tile callback function for rendering a road tile to the screen */
1873 static void DrawTile_Road(TileInfo
*ti
)
1875 if (IsTileSubtype(ti
->tile
, TT_TRACK
) || IsExtendedRoadBridge(ti
->tile
)) {
1878 DrawBridgeGround(ti
);
1882 DiagDirection dir
= GetTunnelBridgeDirection(ti
->tile
);
1884 const PalSpriteID
*psid
= GetBridgeRampSprite(GetRoadBridgeType(ti
->tile
), 8, ti
->tileh
, dir
);
1886 /* Draw Trambits as SpriteCombine */
1887 StartSpriteCombine (ti
->vd
);
1889 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1890 * it doesn't disappear behind it
1892 /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1893 AddSortableSpriteToDraw (ti
->vd
, psid
->sprite
, psid
->pal
, ti
->x
, ti
->y
, 16, 16, ti
->tileh
== SLOPE_FLAT
? 0 : 8, ti
->z
);
1895 RoadTypes rts
= GetRoadTypes(ti
->tile
);
1897 if (HasBit(rts
, ROADTYPE_TRAM
)) {
1900 if (ti
->tileh
!= SLOPE_FLAT
) {
1901 offset
= (offset
+ 1) & 1;
1906 /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1907 DrawBridgeTramBits (ti
->vd
, ti
->x
, ti
->y
, z
, offset
, HasBit(rts
, ROADTYPE_ROAD
), true);
1910 EndSpriteCombine (ti
->vd
);
1913 DrawBridgeMiddle(ti
);
1916 #define TILE_SEQ_LINE(img, pal, dx, dy, sx, sy) { dx, dy, 0, sx, sy, 20, {img, pal} }
1917 #define TILE_SEQ_END() { (int8)0x80, 0, 0, 0, 0, 0, {0, 0} }
1919 /* Sprite layout for level crossings. The SpriteIDs are actually offsets
1920 * from the base SpriteID returned from the NewGRF sprite resolver. */
1921 static const DrawTileSeqStruct _crossing_layout
[] = {
1922 TILE_SEQ_LINE(2, PAL_NONE
, 0, 0, 3, 3),
1923 TILE_SEQ_LINE(4, PAL_NONE
, 0, 13, 3, 3),
1924 TILE_SEQ_LINE(6, PAL_NONE
, 13, 0, 3, 3),
1925 TILE_SEQ_LINE(8, PAL_NONE
, 13, 13, 3, 3),
1929 #undef TILE_SEQ_LINE
1932 void DrawLevelCrossing(TileInfo
*ti
)
1934 if (ti
->tileh
!= SLOPE_FLAT
) DrawFoundation(ti
, FOUNDATION_LEVELED
);
1936 PaletteID pal
= PAL_NONE
;
1937 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
1939 if (rti
->UsesOverlay()) {
1940 Axis axis
= GetCrossingRailAxis(ti
->tile
);
1942 DrawRoadGroundSprite (ti
, GetRoadside(ti
->tile
), SPR_ROAD_Y
+ axis
, -19, 19);
1944 SpriteID rail
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_CROSSING
) + axis
;
1945 /* Draw tracks, but draw PBS reserved tracks darker. */
1946 pal
= (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& HasCrossingReservation(ti
->tile
)) ? PALETTE_CRASH
: PAL_NONE
;
1947 DrawGroundSprite (ti
, rail
, pal
);
1949 DrawRailTileSeq (ti
, _crossing_layout
, TO_CATENARY
, rail
, 0, PAL_NONE
);
1951 SpriteID image
= rti
->base_sprites
.crossing
;
1953 if (GetCrossingRoadAxis(ti
->tile
) == AXIS_X
) image
++;
1954 if (IsCrossingBarred(ti
->tile
)) image
+= 2;
1956 pal
= DrawRoadGroundSprite (ti
, GetRoadside(ti
->tile
), image
, 4, 8);
1958 /* PBS debugging, draw reserved tracks darker */
1959 if (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& HasCrossingReservation(ti
->tile
)) {
1960 DrawGroundSprite (ti
, GetRailTypeInfo(GetRailType(ti
->tile
))->base_sprites
.single
[GetCrossingRailTrack(ti
->tile
)], PALETTE_CRASH
);
1964 if (HasTileRoadType(ti
->tile
, ROADTYPE_TRAM
)) {
1965 DrawGroundSprite (ti
, SPR_TRAMWAY_OVERLAY
+ (GetCrossingRoadAxis(ti
->tile
) ^ 1), pal
);
1966 DrawRoadCatenary(ti
, GetCrossingRoadBits(ti
->tile
));
1969 if (HasRailCatenaryDrawn (rti
)) {
1970 DrawRailAxisCatenary (ti
, rti
, GetCrossingRailAxis (ti
->tile
));
1973 DrawBridgeMiddle(ti
);
1977 * Updates cached nearest town for all road tiles
1978 * @param invalidate are we just invalidating cached data?
1979 * @pre invalidate == true implies _generating_world == true
1981 void UpdateNearestTownForRoadTiles(bool invalidate
)
1983 assert(!invalidate
|| _generating_world
);
1985 for (TileIndex t
= 0; t
< MapSize(); t
++) {
1986 if ((IsRoadTile(t
) || IsLevelCrossingTile(t
)) && !HasTownOwnedRoad(t
)) {
1987 TownID tid
= (TownID
)INVALID_TOWN
;
1989 const Town
*town
= CalcClosestTownFromTile(t
);
1990 if (town
!= NULL
) tid
= town
->index
;
1992 SetTownIndex(t
, tid
);
1997 static int GetSlopePixelZ_Road(TileIndex tile
, uint x
, uint y
)
2000 Slope tileh
= GetTilePixelSlope(tile
, &z
);
2002 if (IsTileSubtype(tile
, TT_TRACK
)) {
2003 if (tileh
== SLOPE_FLAT
) return z
;
2004 z
+= ApplyPixelFoundationToSlope(GetRoadFoundation(tileh
, GetAllRoadBits(tile
)), &tileh
);
2005 return z
+ GetPartialPixelZ(x
& 0xF, y
& 0xF, tileh
);
2006 } else if (IsExtendedRoadBridge(tile
)) {
2007 return z
+ (IsSteepSlope(tileh
) ? 2 * TILE_HEIGHT
: TILE_HEIGHT
);
2012 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
2014 z
+= ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh
, DiagDirToAxis(dir
)), &tileh
);
2016 /* On the bridge ramp? */
2017 uint pos
= (DiagDirToAxis(dir
) == AXIS_X
? y
: x
);
2018 if (5 <= pos
&& pos
<= 10) {
2019 return z
+ ((tileh
== SLOPE_FLAT
) ? GetBridgePartialPixelZ(dir
, x
, y
) : TILE_HEIGHT
);
2022 return z
+ GetPartialPixelZ(x
, y
, tileh
);
2026 static Foundation
GetFoundation_Road(TileIndex tile
, Slope tileh
)
2028 return IsTileSubtype(tile
, TT_TRACK
) ? GetRoadFoundation(tileh
, GetAllRoadBits(tile
)) :
2029 IsExtendedRoadBridge(tile
) ? FOUNDATION_LEVELED
:
2030 GetBridgeFoundation(tileh
, DiagDirToAxis(GetTunnelBridgeDirection(tile
)));
2033 static const Roadside _town_road_types
[][2] = {
2034 { ROADSIDE_GRASS
, ROADSIDE_GRASS
},
2035 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
2036 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
2037 { ROADSIDE_TREES
, ROADSIDE_TREES
},
2038 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
}
2041 static const Roadside _town_road_types_2
[][2] = {
2042 { ROADSIDE_GRASS
, ROADSIDE_GRASS
},
2043 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
2044 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
},
2045 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
},
2046 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
}
2049 void UpdateRoadSide(TileIndex tile
, HouseZonesBits grp
)
2051 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2052 const Roadside
*new_rs
= (_settings_game
.game_creation
.landscape
== LT_TOYLAND
) ? _town_road_types_2
[grp
] : _town_road_types
[grp
];
2053 Roadside cur_rs
= GetRoadside(tile
);
2055 /* We have our desired type, do nothing */
2056 if (cur_rs
== new_rs
[0]) return;
2058 /* We have the pre-type of the desired type, switch to the desired type */
2059 if (cur_rs
== new_rs
[1]) {
2061 /* We have barren land, install the pre-type */
2062 } else if (cur_rs
== ROADSIDE_BARREN
) {
2064 /* We're totally off limits, remove any installation and make barren land */
2066 cur_rs
= ROADSIDE_BARREN
;
2069 SetRoadside(tile
, cur_rs
);
2070 MarkTileDirtyByTile(tile
);
2073 static void TileLoop_Road(TileIndex tile
)
2075 switch (_settings_game
.game_creation
.landscape
) {
2077 int z
= IsTileSubtype(tile
, TT_TRACK
) ? GetTileZ(tile
) : GetTileMaxZ(tile
);
2078 if (IsOnSnow(tile
) != (z
> GetSnowLine())) {
2080 MarkTileDirtyByTile(tile
);
2086 if (GetTropicZone(tile
) == TROPICZONE_DESERT
&& !IsOnDesert(tile
)) {
2088 MarkTileDirtyByTile(tile
);
2093 if (!IsTileSubtype(tile
, TT_TRACK
)) return;
2095 const Town
*t
= ClosestTownFromTile(tile
);
2096 if (!HasRoadWorks(tile
)) {
2097 HouseZonesBits grp
= HZB_TOWN_EDGE
;
2100 grp
= GetTownRadiusGroup(t
, tile
);
2102 /* Show an animation to indicate road work */
2103 if (t
->road_build_months
!= 0 &&
2104 (DistanceManhattan(t
->xy
, tile
) < 8 || grp
!= HZB_TOWN_EDGE
) &&
2105 !HasAtMostOneBit(GetAllRoadBits(tile
)) &&
2106 GetFoundationSlope(tile
) == SLOPE_FLAT
&&
2107 EnsureNoVehicleOnGround(tile
).Succeeded() &&
2109 StartRoadWorks(tile
);
2110 /* Remove any trees or lamps in case or roadwork */
2111 switch (GetRoadside(tile
)) {
2112 case ROADSIDE_BARREN
:
2113 case ROADSIDE_GRASS
: SetRoadside(tile
, ROADSIDE_GRASS
); break;
2114 default: SetRoadside(tile
, ROADSIDE_PAVED
); break;
2117 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_21_JACKHAMMER
, tile
);
2118 CreateEffectVehicleAbove(
2119 TileX(tile
) * TILE_SIZE
+ 7,
2120 TileY(tile
) * TILE_SIZE
+ 7,
2123 MarkTileDirtyByTile(tile
);
2128 UpdateRoadSide(tile
, grp
);
2129 } else if (DecreaseRoadWorksCounter(tile
)) {
2130 if (_settings_game
.economy
.mod_road_rebuild
) {
2131 /* Generate a nicer town surface */
2132 const RoadBits old_rb
= GetAnyRoadBits(tile
, ROADTYPE_ROAD
);
2133 const RoadBits new_rb
= CleanUpRoadBits(tile
, old_rb
);
2135 if (old_rb
!= new_rb
) {
2136 RemoveRoad(tile
, DC_EXEC
| DC_AUTO
| DC_NO_WATER
, (old_rb
^ new_rb
), ROADTYPE_ROAD
, true);
2140 MarkTileDirtyByTile(tile
);
2144 static bool ClickTile_Road(TileIndex tile
)
2149 static TrackStatus
GetTileRoadStatus_Road(TileIndex tile
, uint sub_mode
, DiagDirection side
)
2151 /* Converts RoadBits to TrackdirBits */
2152 static const TrackdirBits road_trackdirbits
[16] = {
2153 TRACKDIR_BIT_NONE
, // ROAD_NONE
2154 TRACKDIR_BIT_NONE
, // ROAD_NW
2155 TRACKDIR_BIT_NONE
, // ROAD_SW
2156 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_LEFT_N
, // ROAD_W
2157 TRACKDIR_BIT_NONE
, // ROAD_SE
2158 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_Y_NW
, // ROAD_Y
2159 TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_LOWER_W
, // ROAD_S
2160 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_Y_SE
2161 | TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_Y_NW
, // ROAD_Y | ROAD_SW
2162 TRACKDIR_BIT_NONE
, // ROAD_NE
2163 TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_UPPER_W
, // ROAD_N
2164 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_X_SW
, // ROAD_X
2165 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_X_NE
2166 | TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_X_SW
, // ROAD_X | ROAD_NW
2167 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_RIGHT_N
, // ROAD_E
2168 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_Y_SE
2169 | TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_Y_NW
, // ROAD_Y | ROAD_NE
2170 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_X_NE
2171 | TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_X_SW
, // ROAD_X | ROAD_SE
2172 TRACKDIR_BIT_MASK
, // ROAD_ALL
2175 static const uint drd_mask
[DRD_END
] = { 0xFFFF, 0xFF00, 0xFF, 0x0 };
2177 if ((GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
2179 if (IsTileSubtype(tile
, TT_TRACK
)) {
2180 if (HasRoadWorks(tile
)) return 0;
2182 if (side
== GetTunnelBridgeDirection(tile
)) return 0;
2185 RoadType rt
= (RoadType
)FindFirstBit(sub_mode
);
2186 RoadBits bits
= GetRoadBits(tile
, rt
);
2188 /* no roadbit at this side of tile, return 0 */
2189 if (side
!= INVALID_DIAGDIR
&& (DiagDirToRoadBits(side
) & bits
) == 0) return 0;
2191 TrackdirBits trackdirbits
= road_trackdirbits
[bits
];
2192 if (IsTileSubtype(tile
, TT_TRACK
) && rt
== ROADTYPE_ROAD
) trackdirbits
&= (TrackdirBits
)drd_mask
[GetDisallowedRoadDirections(tile
)];
2194 return CombineTrackStatus(trackdirbits
, TRACKDIR_BIT_NONE
);
2197 static const StringID _road_tile_strings
[] = {
2198 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2199 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2200 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2201 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS
,
2202 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2203 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD
,
2204 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2205 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2208 static void GetTileDesc_Road(TileIndex tile
, TileDesc
*td
)
2210 RoadTypes rts
= GetRoadTypes(tile
);
2212 Owner tram_owner
= INVALID_OWNER
;
2213 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
2215 if (IsTileSubtype(tile
, TT_TRACK
)) {
2216 if (!HasBit(rts
, ROADTYPE_ROAD
)) {
2217 td
->str
= STR_LAI_ROAD_DESCRIPTION_TRAMWAY
;
2218 td
->owner
[0] = tram_owner
;
2221 td
->str
= _road_tile_strings
[GetRoadside(tile
)];
2223 const BridgeSpec
*spec
= GetBridgeSpec(GetRoadBridgeType(tile
));
2224 td
->str
= spec
->transport_name
[TRANSPORT_ROAD
];
2225 td
->road_speed
= spec
->speed
;
2226 if (!HasBit(rts
, ROADTYPE_ROAD
)) {
2227 td
->owner
[0] = tram_owner
;
2232 /* So the tile at least has a road; check if it has both road and tram */
2233 Owner road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
2235 if (HasBit(rts
, ROADTYPE_TRAM
)) {
2236 td
->owner_type
[0] = STR_LAND_AREA_INFORMATION_ROAD_OWNER
;
2237 td
->owner
[0] = road_owner
;
2238 td
->owner_type
[1] = STR_LAND_AREA_INFORMATION_TRAM_OWNER
;
2239 td
->owner
[1] = tram_owner
;
2241 /* One to rule them all */
2242 td
->owner
[0] = road_owner
;
2247 static void ChangeTileOwner_Road(TileIndex tile
, Owner old_owner
, Owner new_owner
)
2249 Company
*oldc
= Company::Get(old_owner
);
2252 if (new_owner
!= INVALID_OWNER
) {
2253 newc
= Company::Get(new_owner
);
2255 new_owner
= OWNER_NONE
;
2259 if (IsTileSubtype(tile
, TT_TRACK
)) {
2260 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
2261 /* Update all roadtypes, no matter if they are present */
2262 if (GetRoadOwner(tile
, rt
) == old_owner
) {
2263 if (HasTileRoadType(tile
, rt
)) {
2264 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
2265 uint num_bits
= CountBits(GetRoadBits(tile
, rt
));
2266 oldc
->infrastructure
.road
[rt
] -= num_bits
;
2267 if (newc
!= NULL
) newc
->infrastructure
.road
[rt
] += num_bits
;
2270 SetRoadOwner(tile
, rt
, new_owner
);
2274 TileIndex other_end
= GetOtherBridgeEnd(tile
);
2275 /* Set number of pieces to zero if it's the southern tile as we
2276 * don't want to update the infrastructure counts twice. */
2277 uint len
= tile
< other_end
? GetTunnelBridgeLength(tile
, other_end
) * 2 : 0;
2278 RoadBits bridge_piece
= DiagDirToRoadBits(GetTunnelBridgeDirection(tile
));
2280 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
2281 /* Update all roadtypes, no matter if they are present */
2282 if (GetRoadOwner(tile
, rt
) == old_owner
) {
2283 if (HasBit(GetRoadTypes(tile
), rt
)) {
2284 /* Update company infrastructure counts.
2285 * No need to dirty windows here, we'll redraw the whole screen anyway. */
2286 RoadBits pieces
= GetRoadBits(tile
, rt
);
2287 uint num_pieces
= CountBits(pieces
);
2288 if ((pieces
& bridge_piece
) != 0) {
2289 num_pieces
= (num_pieces
+ len
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
2291 oldc
->infrastructure
.road
[rt
] -= num_pieces
;
2292 if (newc
!= NULL
) newc
->infrastructure
.road
[rt
] += num_pieces
;
2295 SetRoadOwner(tile
, rt
, new_owner
);
2299 if (IsTileOwner(tile
, old_owner
)) SetTileOwner(tile
, new_owner
);
2303 static CommandCost
TerraformTile_Road(TileIndex tile
, DoCommandFlag flags
, int z_new
, Slope tileh_new
)
2305 if (_settings_game
.construction
.build_on_slopes
&& AutoslopeEnabled()) {
2306 if (IsTileSubtype(tile
, TT_TRACK
)) {
2307 RoadBits bits
= GetAllRoadBits(tile
);
2309 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2310 if (CheckRoadSlope(tileh_new
, bits
, ROAD_NONE
, ROAD_NONE
, &bits_new
).Succeeded()) {
2311 if (bits
== bits_new
) {
2313 Slope tileh_old
= GetTileSlope(tile
, &z_old
);
2315 /* Get the slope on top of the foundation */
2316 z_old
+= ApplyFoundationToSlope(GetRoadFoundation(tileh_old
, bits
), &tileh_old
);
2317 z_new
+= ApplyFoundationToSlope(GetRoadFoundation(tileh_new
, bits
), &tileh_new
);
2319 /* The surface slope must not be changed */
2320 if ((z_old
== z_new
) && (tileh_old
== tileh_new
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2323 } else if (IsExtendedRoadBridge(tile
)) {
2324 if (IsValidRoadBridgeBits(tileh_new
, GetTunnelBridgeDirection(tile
), GetAllRoadBits(tile
))) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2327 Slope tileh_old
= GetTileSlope(tile
, &z_old
);
2329 DiagDirection direction
= GetTunnelBridgeDirection(tile
);
2331 /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2332 CheckBridgeSlope(direction
, &tileh_old
, &z_old
);
2333 CommandCost res
= CheckBridgeSlope(direction
, &tileh_new
, &z_new
);
2335 /* Surface slope is valid and remains unchanged? */
2336 if (res
.Succeeded() && (z_old
== z_new
) && (tileh_old
== tileh_new
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2340 return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
2343 /** Tile callback functions for road tiles */
2344 extern const TileTypeProcs _tile_type_road_procs
= {
2345 DrawTile_Road
, // draw_tile_proc
2346 GetSlopePixelZ_Road
, // get_slope_z_proc
2347 ClearTile_Road
, // clear_tile_proc
2348 NULL
, // add_accepted_cargo_proc
2349 GetTileDesc_Road
, // get_tile_desc_proc
2350 NULL
, // get_tile_railway_status_proc
2351 GetTileRoadStatus_Road
, // get_tile_road_status_proc
2352 NULL
, // get_tile_waterway_status_proc
2353 ClickTile_Road
, // click_tile_proc
2354 NULL
, // animate_tile_proc
2355 TileLoop_Road
, // tile_loop_proc
2356 ChangeTileOwner_Road
, // change_tile_owner_proc
2357 NULL
, // add_produced_cargo_proc
2358 GetFoundation_Road
, // get_foundation_proc
2359 TerraformTile_Road
, // terraform_tile_proc