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
, UINT_MAX
);
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 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 Track railtrack
= GetCrossingRailTrack(tile
);
444 RoadTypes rts
= GetRoadTypes(tile
) & ComplementRoadTypes(RoadTypeToRoadTypes(rt
));
445 if (rts
== ROADTYPES_NONE
) {
446 TrackBits tracks
= GetCrossingRailBits(tile
);
447 bool reserved
= HasCrossingReservation(tile
);
448 MakeRailNormal(tile
, GetTileOwner(tile
), tracks
, GetRailType(tile
));
449 if (reserved
) SetTrackReservation(tile
, tracks
);
451 /* Update rail count for level crossings. The plain track should still be accounted
452 * for, so only subtract the difference to the level crossing cost. */
453 c
= Company::GetIfValid(GetTileOwner(tile
));
454 if (c
!= NULL
) c
->infrastructure
.rail
[GetRailType(tile
)] -= LEVELCROSSING_TRACKBIT_FACTOR
- 1;
456 SetRoadTypes(tile
, rts
);
458 MarkTileDirtyByTile(tile
);
459 YapfNotifyTrackLayoutChange(tile
, railtrack
);
462 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_ROAD
] * 2);
466 * Delete a piece of road from a tunnel
467 * @param tile tile where to remove road from
468 * @param flags operation to perform
469 * @param pieces roadbits to remove
470 * @param rt roadtype to remove
471 * @param town_check should we check if the town allows removal?
473 static CommandCost
RemoveRoad_Tunnel(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
475 assert(GetTunnelTransportType(tile
) == TRANSPORT_ROAD
);
477 TileIndex other_end
= GetOtherTunnelEnd(tile
);
478 CommandCost ret
= TunnelBridgeIsFree(tile
, other_end
);
479 if (ret
.Failed()) return ret
;
481 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
482 if (ret
.Failed()) return ret
;
484 /* If it's the last roadtype, just clear the whole tile */
485 if (GetRoadTypes(tile
) == RoadTypeToRoadTypes(rt
)) return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
487 /* Removing any roadbit in the tunnel axis removes the roadtype (that's the behaviour remove-long-roads needs) */
488 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
);
490 CommandCost
cost(EXPENSES_CONSTRUCTION
);
491 /* Pay for *every* tile of the tunnel */
492 uint len
= GetTunnelBridgeLength(other_end
, tile
) + 2;
493 cost
.AddCost(len
* _price
[PR_CLEAR_ROAD
]);
495 if (flags
& DC_EXEC
) {
496 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
498 /* A full diagonal road tile has two road bits. */
499 c
->infrastructure
.road
[rt
] -= len
* 2 * TUNNELBRIDGE_TRACKBIT_FACTOR
;
500 DirtyCompanyInfrastructureWindows(c
->index
);
503 SetRoadTypes(other_end
, GetRoadTypes(other_end
) & ~RoadTypeToRoadTypes(rt
));
504 SetRoadTypes(tile
, GetRoadTypes(tile
) & ~RoadTypeToRoadTypes(rt
));
506 /* If the owner of the bridge sells all its road, also move the ownership
507 * to the owner of the other roadtype. */
508 RoadType other_rt
= (rt
== ROADTYPE_ROAD
) ? ROADTYPE_TRAM
: ROADTYPE_ROAD
;
509 Owner other_owner
= GetRoadOwner(tile
, other_rt
);
510 if (other_owner
!= GetTileOwner(tile
)) {
511 SetTileOwner(tile
, other_owner
);
512 SetTileOwner(other_end
, other_owner
);
515 /* Mark tiles dirty that have been repaved */
516 MarkTileDirtyByTile(tile
);
517 MarkTileDirtyByTile(other_end
);
524 * Delete a piece of road from a station
525 * @param tile tile where to remove road from
526 * @param flags operation to perform
527 * @param pieces roadbits to remove
528 * @param rt roadtype to remove
529 * @param town_check should we check if the town allows removal?
531 static CommandCost
RemoveRoad_Station(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool town_check
)
533 if (!IsDriveThroughStopTile(tile
)) return CMD_ERROR
;
535 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
536 if (ret
.Failed()) return ret
;
538 ret
= CheckAllowRemoveRoad(tile
, pieces
, GetRoadOwner(tile
, rt
), rt
, flags
, town_check
);
539 if (ret
.Failed()) return ret
;
541 /* If it's the last roadtype, just clear the whole tile */
542 if (GetRoadTypes(tile
) == RoadTypeToRoadTypes(rt
)) return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
544 if (flags
& DC_EXEC
) {
545 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
547 /* A full diagonal road tile has two road bits. */
548 c
->infrastructure
.road
[rt
] -= 2;
549 DirtyCompanyInfrastructureWindows(c
->index
);
551 SetRoadTypes(tile
, GetRoadTypes(tile
) & ~RoadTypeToRoadTypes(rt
));
552 MarkTileDirtyByTile(tile
);
555 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_ROAD
] * 2);
559 * Delete a piece of road.
560 * @param tile tile where to remove road from
561 * @param flags operation to perform
562 * @param pieces roadbits to remove
563 * @param rt roadtype to remove
564 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
565 * @param town_check should we check if the town allows removal?
567 CommandCost
RemoveRoad(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool crossing_check
, bool town_check
= true)
569 switch (GetTileType(tile
)) {
571 if (!HasTileRoadType(tile
, rt
)) break;
573 if (IsTileSubtype(tile
, TT_TRACK
)) {
574 return RemoveRoad_Road(tile
, flags
, pieces
, rt
, town_check
);
576 return RemoveRoad_Bridge(tile
, flags
, pieces
, rt
, town_check
);
581 switch (GetTileSubtype(tile
)) {
582 case TT_MISC_CROSSING
:
583 if (!HasTileRoadType(tile
, rt
)) break;
584 return RemoveRoad_Crossing(tile
, flags
, pieces
, rt
, crossing_check
, town_check
);
587 if (!HasTileRoadType(tile
, rt
)) break;
588 if (GetTunnelTransportType(tile
) != TRANSPORT_ROAD
) break;
589 return RemoveRoad_Tunnel(tile
, flags
, pieces
, rt
, town_check
);
598 if (!HasTileRoadType(tile
, rt
)) break;
600 return RemoveRoad_Station(tile
, flags
, pieces
, rt
, town_check
);
606 /* The tile doesn't have the given road type */
607 return_cmd_error(rt
== ROADTYPE_TRAM
? STR_ERROR_THERE_IS_NO_TRAMWAY
: STR_ERROR_THERE_IS_NO_ROAD
);
612 * Calculate the costs for roads on slopes
613 * Also compute the road bits that have to be built to fit the slope
615 * @param tileh The current slope
616 * @param pieces The RoadBits we want to add
617 * @param existing The existent RoadBits of the current type
618 * @param other The existent RoadBits for the other type
619 * @param build The actual RoadBits to build
620 * @return The costs for these RoadBits on this slope
622 static CommandCost
CheckRoadSlope(Slope tileh
, RoadBits pieces
, RoadBits existing
, RoadBits other
, RoadBits
*build
)
624 /* Remove already build pieces */
625 CLRBITS(pieces
, existing
);
627 /* If we can't build anything stop here */
628 if (pieces
== ROAD_NONE
) return CMD_ERROR
;
630 /* All RoadBit combos are valid on flat land */
631 if (tileh
== SLOPE_FLAT
) {
632 if (build
!= NULL
) *build
= pieces
;
633 return CommandCost();
636 /* Steep slopes behave the same as slopes with one corner raised. */
637 if (IsSteepSlope(tileh
)) {
638 tileh
= SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh
));
641 /* Roads on slopes */
642 if (_settings_game
.construction
.build_on_slopes
&& (_invalid_leveled_roadbits
[tileh
] & (other
| existing
| pieces
)) == ROAD_NONE
) {
643 if (build
!= NULL
) *build
= pieces
;
645 /* If we add leveling we've got to pay for it */
646 if ((other
| existing
) == ROAD_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
648 return CommandCost();
651 /* Autocomplete uphill roads */
652 pieces
|= MirrorRoadBits(pieces
);
653 RoadBits type_bits
= existing
| pieces
;
656 if (IsStraightRoad(type_bits
) && (other
== type_bits
|| other
== ROAD_NONE
) &&
657 (_invalid_straight_roadbits
[tileh
] & type_bits
) == ROAD_NONE
) {
658 /* Slopes without foundation */
659 if (!IsSlopeWithOneCornerRaised(tileh
)) {
660 if (build
!= NULL
) *build
= pieces
;
661 if (HasExactlyOneBit(existing
) && GetRoadFoundation(tileh
, existing
) == FOUNDATION_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
662 return CommandCost();
665 /* Prevent build on slopes if it isn't allowed */
666 if (_settings_game
.construction
.build_on_slopes
) {
667 if (build
!= NULL
) *build
= pieces
;
669 /* If we add foundation we've got to pay for it */
670 if ((other
| existing
) == ROAD_NONE
) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
672 return CommandCost();
679 * Check if a given roadbits set is valid for a road bridge head
680 * @param tileh The slope
681 * @param dir The bridge direction
682 * @param bits The roadbits
683 * @return Whether the given combination is valid
685 bool IsValidRoadBridgeBits(Slope tileh
, DiagDirection dir
, RoadBits bits
)
687 DiagDirDiff diff
= CheckExtendedBridgeHead(tileh
, dir
);
690 case DIAGDIRDIFF_SAME
: return true;
691 case DIAGDIRDIFF_REVERSE
: return false;
692 default: return (bits
& DiagDirToRoadBits(ChangeDiagDir(dir
, diff
))) == 0;
697 * Build a piece of road, clearing the land if necessary
698 * @param tile tile where to build road
699 * @param flags operation to perform
700 * @param rt roadtype to build
701 * @param pieces roadbits to build
702 * @param company company building the road
703 * @param town owner/closest town
704 * @param drd directions to disallow
705 * @return the cost of this operation or an error
707 static CommandCost
BuildRoad_Clear(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
709 CommandCost
cost(EXPENSES_CONSTRUCTION
);
711 CommandCost ret
= DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
712 if (ret
.Failed()) return ret
;
715 Slope tileh
= GetTileSlope(tile
);
717 /* Check the foundation/slopes when adding road/tram bits */
718 ret
= CheckRoadSlope(tileh
, pieces
, ROAD_NONE
, ROAD_NONE
, &pieces
);
719 /* Return an error if we need to build a foundation (ret != 0) but the
720 * current setting is turned off */
721 if (ret
.Failed() || (ret
.GetCost() != 0 && !_settings_game
.construction
.build_on_slopes
)) {
722 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
726 uint num_pieces
= CountBits(pieces
);
727 cost
.AddCost(num_pieces
* _price
[PR_BUILD_ROAD
]);
729 if (flags
& DC_EXEC
) {
730 MakeRoadNormal(tile
, pieces
, RoadTypeToRoadTypes(rt
), town
, company
, company
);
732 /* Update company infrastructure count. */
733 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
735 c
->infrastructure
.road
[rt
] += num_pieces
;
736 DirtyCompanyInfrastructureWindows(c
->index
);
739 if (rt
!= ROADTYPE_TRAM
&& IsStraightRoad(pieces
)) {
740 SetDisallowedRoadDirections(tile
, drd
);
743 MarkTileDirtyByTile(tile
);
750 * Build a piece of road on a road tile
751 * @param tile tile where to build road
752 * @param flags operation to perform
753 * @param rt roadtype to build
754 * @param pieces roadbits to build
755 * @param company company building the road
756 * @param town owner/closest town
757 * @param toggle_drd directions to toggle disallow
758 * @return the cost of this operation or an error
760 static CommandCost
BuildRoad_Road(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections toggle_drd
)
762 if (HasRoadWorks(tile
)) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS
);
764 RoadBits existing
= ROAD_NONE
;
766 if (HasTileRoadType(tile
, rt
)) {
767 existing
= GetRoadBits(tile
, rt
);
768 bool crossing
= !IsStraightRoad(existing
| pieces
);
770 if (rt
!= ROADTYPE_TRAM
&& (GetDisallowedRoadDirections(tile
) != DRD_NONE
|| toggle_drd
!= DRD_NONE
) && crossing
) {
771 /* Junctions cannot be one-way */
772 return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION
);
775 if ((existing
& pieces
) == pieces
) {
776 /* We only want to set the (dis)allowed road directions */
777 if (toggle_drd
== DRD_NONE
|| rt
== ROADTYPE_TRAM
) {
778 return_cmd_error(STR_ERROR_ALREADY_BUILT
);
781 if (crossing
) return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION
);
783 Owner owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
784 if (owner
!= OWNER_NONE
) {
785 CommandCost ret
= CheckOwnership(owner
, tile
);
786 if (ret
.Failed()) return ret
;
789 DisallowedRoadDirections dis_existing
= GetDisallowedRoadDirections(tile
);
790 DisallowedRoadDirections dis_new
= dis_existing
^ toggle_drd
;
792 /* We allow removing disallowed directions to break up
793 * deadlocks, but adding them can break articulated
794 * vehicles. As such, only when less is disallowed,
795 * i.e. bits are removed, we skip the vehicle check. */
796 if (CountBits(dis_existing
) <= CountBits(dis_new
)) {
797 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
798 if (ret
.Failed()) return ret
;
801 /* Ignore half built tiles */
802 if ((flags
& DC_EXEC
) && rt
!= ROADTYPE_TRAM
&& IsStraightRoad(existing
)) {
803 SetDisallowedRoadDirections(tile
, dis_new
);
804 MarkTileDirtyByTile(tile
);
807 return CommandCost();
811 CommandCost
cost(EXPENSES_CONSTRUCTION
);
813 RoadBits other_bits
= GetOtherRoadBits(tile
, rt
);
815 Slope tileh
= GetTileSlope(tile
);
817 if (other_bits
!= pieces
) {
818 /* Check the foundation/slopes when adding road/tram bits */
819 CommandCost ret
= CheckRoadSlope(tileh
, pieces
, existing
, other_bits
, &pieces
);
820 /* Return an error if we need to build a foundation (ret != 0) but the
821 * current setting is turned off */
822 if (ret
.Failed() || (ret
.GetCost() != 0 && !_settings_game
.construction
.build_on_slopes
)) {
823 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
828 /* Don't put the pieces that already exist */
829 pieces
&= ComplementRoadBits(existing
);
831 /* Check if new road bits will have the same foundation as other existing road types */
832 Foundation found_new
= GetRoadFoundation(tileh
, pieces
| existing
);
834 /* Test if all other roadtypes can be built at that foundation */
835 for (RoadType rtest
= ROADTYPE_ROAD
; rtest
< ROADTYPE_END
; rtest
++) {
836 if (rtest
!= rt
) { // check only other road types
837 RoadBits bits
= GetRoadBits(tile
, rtest
);
838 /* do not check if there are not road bits of given type */
839 if (bits
!= ROAD_NONE
&& GetRoadFoundation(tileh
, bits
) != found_new
) {
840 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
845 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
846 if (ret
.Failed()) return ret
;
848 uint num_pieces
= CountBits(pieces
);
849 cost
.AddCost(num_pieces
* _price
[PR_BUILD_ROAD
]);
851 if (flags
& DC_EXEC
) {
852 if (existing
== ROAD_NONE
) {
853 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
854 SetRoadOwner(tile
, rt
, company
);
855 if (rt
== ROADTYPE_ROAD
) SetTownIndex(tile
, town
);
858 SetRoadBits(tile
, existing
| pieces
, rt
);
860 /* Update company infrastructure count. */
861 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
863 c
->infrastructure
.road
[rt
] += num_pieces
;
864 DirtyCompanyInfrastructureWindows(c
->index
);
867 if (rt
!= ROADTYPE_TRAM
) {
868 SetDisallowedRoadDirections(tile
, IsStraightRoad(existing
| pieces
) ?
869 GetDisallowedRoadDirections(tile
) ^ toggle_drd
: DRD_NONE
);
872 MarkTileDirtyByTile(tile
);
879 * Build a piece of road on a bridge tile
880 * @param tile tile where to build road
881 * @param flags operation to perform
882 * @param rt roadtype to build
883 * @param pieces roadbits to build
884 * @param company company building the road
885 * @param town owner/closest town
886 * @param drd directions to disallow
887 * @return the cost of this operation or an error
889 static CommandCost
BuildRoad_Bridge(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
891 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
892 Slope tileh
= GetTileSlope(tile
);
896 if (HasBridgeFlatRamp(tileh
, DiagDirToAxis(dir
))) {
897 RoadBits existing
= GetRoadBits(tile
, rt
);
899 if (pieces
== ROAD_NONE
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
901 if (!IsValidRoadBridgeBits(tileh
, dir
, existing
| pieces
)) {
902 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
905 num
= CountBits(pieces
);
906 other_end
= (pieces
& DiagDirToRoadBits(dir
)) != 0;
909 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
910 if (pieces
!= DiagDirToRoadBits(ReverseDiagDir(dir
))) {
911 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
914 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
916 pieces
= AxisToRoadBits(DiagDirToAxis(dir
));
921 TileIndex other_tile
;
922 RoadBits other_pieces
;
925 other_tile
= GetOtherBridgeEnd(tile
);
927 /* Don't allow adding roadtype to the bridge when vehicles are already driving on it */
928 CommandCost ret
= TunnelBridgeIsFree(tile
, other_tile
);
929 if (ret
.Failed()) return ret
;
931 /* Don't allow to mix owners */
932 CompanyID new_owner
= HasTileRoadType(tile
, rt
) ? GetRoadOwner(tile
, rt
) : company
;
933 CompanyID other_owner
= HasTileRoadType(other_tile
, rt
) ? GetRoadOwner(other_tile
, rt
) : company
;
934 if (new_owner
!= other_owner
) return CMD_ERROR
;
936 num
+= 2 * GetTunnelBridgeLength(tile
, other_tile
);
938 if (IsExtendedRoadBridge(other_tile
)) {
939 other_pieces
= GetRoadBits(other_tile
, rt
) | DiagDirToRoadBits(ReverseDiagDir(dir
));
942 assert(GetRoadBits(other_tile
, rt
) == ROAD_NONE
);
943 other_pieces
= AxisToRoadBits(DiagDirToAxis(dir
));
947 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
948 if (ret
.Failed()) return ret
;
951 if (flags
& DC_EXEC
) {
953 /* Update company infrastructure count. */
954 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
956 uint existing
= CountBits(GetRoadBits(tile
, rt
)) + CountBits(GetRoadBits(other_tile
, rt
));
957 c
->infrastructure
.road
[rt
] -= existing
;
958 c
->infrastructure
.road
[rt
] += (existing
+ num
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
959 DirtyCompanyInfrastructureWindows(c
->index
);
962 if (!HasTileRoadType(other_tile
, rt
)) {
963 SetRoadTypes(other_tile
, GetRoadTypes(other_tile
) | RoadTypeToRoadTypes(rt
));
964 SetRoadOwner(other_tile
, rt
, company
);
966 SetRoadBits(other_tile
, other_pieces
, rt
);
968 MarkBridgeTilesDirty(tile
, other_tile
, dir
, false);
970 /* Update company infrastructure count. */
971 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
973 c
->infrastructure
.road
[rt
] += (pieces
& DiagDirToRoadBits(dir
)) != 0 ? num
* TUNNELBRIDGE_TRACKBIT_FACTOR
: num
;
974 DirtyCompanyInfrastructureWindows(c
->index
);
978 if (!HasTileRoadType(tile
, rt
)) {
979 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
980 SetRoadOwner(tile
, rt
, company
);
982 SetRoadBits(tile
, pieces
, rt
);
983 MarkTileDirtyByTile(tile
);
986 return CommandCost(EXPENSES_CONSTRUCTION
, num
* _price
[PR_BUILD_ROAD
]);
990 * Build a piece of road on a crossing tile
991 * @param tile tile where to build road
992 * @param flags operation to perform
993 * @param rt roadtype to build
994 * @param pieces roadbits to build
995 * @param company company building the road
996 * @param town owner/closest town
997 * @param drd directions to disallow
998 * @return the cost of this operation or an error
1000 static CommandCost
BuildRoad_Crossing(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1002 if (pieces
& ComplementRoadBits(GetCrossingRoadBits(tile
))) {
1003 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1006 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1008 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1009 if (ret
.Failed()) return ret
;
1011 if (flags
& DC_EXEC
) {
1012 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1013 SetRoadOwner(tile
, rt
, company
);
1014 if (rt
== ROADTYPE_ROAD
) SetTownIndex(tile
, town
);
1016 /* Update company infrastructure count. */
1017 Company
*c
= Company::GetIfValid(company
);
1019 c
->infrastructure
.road
[rt
] += 2;
1020 DirtyCompanyInfrastructureWindows(c
->index
);
1023 MarkTileDirtyByTile(tile
);
1026 return CommandCost(EXPENSES_CONSTRUCTION
, 2 * _price
[PR_BUILD_ROAD
]);
1030 * Build a piece of road on a railway tile
1031 * @param tile tile where to build road
1032 * @param flags operation to perform
1033 * @param rt roadtype to build
1034 * @param pieces roadbits to build
1035 * @param company company building the road
1036 * @param town owner/closest town
1037 * @param drd directions to disallow
1038 * @return the cost of this operation or an error
1040 static CommandCost
BuildRoad_Railway(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1042 Slope tileh
= GetTileSlope(tile
);
1044 if (!IsTileSubtype(tile
, TT_TRACK
)) goto do_clear
;
1046 /* Level crossings may only be built on these slopes */
1047 if (IsSteepSlope(tileh
) || !HasBit(VALID_LEVEL_CROSSING_SLOPES
, tileh
)) {
1048 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION
);
1051 if (RailNoLevelCrossings(GetRailType(tile
))) {
1052 return_cmd_error(STR_ERROR_CROSSING_DISALLOWED
);
1055 if (HasSignalOnTrack(tile
, TRACK_UPPER
)) goto do_clear
;
1058 switch (GetTrackBits(tile
)) {
1060 if (pieces
& ROAD_X
) goto do_clear
;
1065 if (pieces
& ROAD_Y
) goto do_clear
;
1071 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1074 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1075 if (ret
.Failed()) return ret
;
1077 if (flags
& DC_EXEC
) {
1078 Track railtrack
= AxisToTrack(OtherAxis(roaddir
));
1079 YapfNotifyTrackLayoutChange(tile
, railtrack
);
1080 /* Update company infrastructure counts. A level crossing has two road bits. */
1081 Company
*c
= Company::GetIfValid(company
);
1083 c
->infrastructure
.road
[rt
] += 2;
1084 if (rt
!= ROADTYPE_ROAD
) c
->infrastructure
.road
[ROADTYPE_ROAD
] += 2;
1085 DirtyCompanyInfrastructureWindows(company
);
1087 /* Update rail count for level crossings. The plain track is already
1088 * counted, so only add the difference to the level crossing cost. */
1089 c
= Company::GetIfValid(GetTileOwner(tile
));
1090 if (c
!= NULL
) c
->infrastructure
.rail
[GetRailType(tile
)] += LEVELCROSSING_TRACKBIT_FACTOR
- 1;
1092 /* Always add road to the roadtypes (can't draw without it) */
1093 bool reserved
= HasBit(GetRailReservationTrackBits(tile
), railtrack
);
1094 MakeRoadCrossing(tile
, company
, company
, GetTileOwner(tile
), roaddir
, GetRailType(tile
), RoadTypeToRoadTypes(rt
) | ROADTYPES_ROAD
, town
);
1095 SetCrossingReservation(tile
, reserved
);
1096 UpdateLevelCrossing(tile
, false);
1097 MarkTileDirtyByTile(tile
);
1100 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_ROAD
] * (rt
== ROADTYPE_ROAD
? 2 : 4));
1104 * Build a piece of road on a tunnel tile
1105 * @param tile tile where to build road
1106 * @param flags operation to perform
1107 * @param rt roadtype to build
1108 * @param pieces roadbits to build
1109 * @param company company building the road
1110 * @param town owner/closest town
1111 * @param drd directions to disallow
1112 * @return the cost of this operation or an error
1114 static CommandCost
BuildRoad_Tunnel(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1116 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
1117 if (GetTunnelTransportType(tile
) != TRANSPORT_ROAD
|| pieces
!= DiagDirToRoadBits(ReverseDiagDir(GetTunnelBridgeDirection(tile
)))) {
1118 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1121 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1123 TileIndex other_end
= GetOtherTunnelEnd(tile
);
1125 /* Don't allow adding roadtype to the tunnel when vehicles are already driving on it */
1126 CommandCost ret
= TunnelBridgeIsFree(tile
, other_end
);
1127 if (ret
.Failed()) return ret
;
1129 /* There are 2 pieces on *every* tile of the tunnel */
1130 uint num_pieces
= 2 * (GetTunnelBridgeLength(tile
, other_end
) + 2);
1132 if (flags
& DC_EXEC
) {
1133 SetRoadTypes(other_end
, GetRoadTypes(other_end
) | RoadTypeToRoadTypes(rt
));
1134 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1135 SetRoadOwner(other_end
, rt
, company
);
1136 SetRoadOwner(tile
, rt
, company
);
1138 /* Mark tiles dirty that have been repaved */
1139 MarkTileDirtyByTile(other_end
);
1140 MarkTileDirtyByTile(tile
);
1142 /* Update company infrastructure count. */
1143 Company
*c
= Company::GetIfValid(company
);
1145 c
->infrastructure
.road
[rt
] += num_pieces
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
1146 DirtyCompanyInfrastructureWindows(c
->index
);
1150 return CommandCost(EXPENSES_CONSTRUCTION
, num_pieces
* _price
[PR_BUILD_ROAD
]);
1154 * Build a piece of road on a station tile
1155 * @param tile tile where to build road
1156 * @param flags operation to perform
1157 * @param rt roadtype to build
1158 * @param pieces roadbits to build
1159 * @param company company building the road
1160 * @param town owner/closest town
1161 * @param drd directions to disallow
1162 * @return the cost of this operation or an error
1164 static CommandCost
BuildRoad_Station(TileIndex tile
, DoCommandFlag flags
, RoadType rt
, RoadBits pieces
, CompanyID company
, TownID town
, DisallowedRoadDirections drd
)
1166 if ((GetAnyRoadBits(tile
, rt
) & pieces
) == pieces
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1168 if (!IsDriveThroughStopTile(tile
) || (pieces
& ~AxisToRoadBits(GetRoadStopAxis(tile
)))) {
1169 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, town
, drd
);
1172 if (HasTileRoadType(tile
, rt
)) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1174 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
1175 if (ret
.Failed()) return ret
;
1177 if (flags
& DC_EXEC
) {
1178 SetRoadTypes(tile
, GetRoadTypes(tile
) | RoadTypeToRoadTypes(rt
));
1179 SetRoadOwner(tile
, rt
, company
);
1181 /* Update company infrastructure count. */
1182 Company
*c
= Company::GetIfValid(company
);
1184 c
->infrastructure
.road
[rt
] += 2;
1185 DirtyCompanyInfrastructureWindows(c
->index
);
1188 MarkTileDirtyByTile(tile
);
1191 return CommandCost(EXPENSES_CONSTRUCTION
, 2 * _price
[PR_BUILD_ROAD
]);
1195 * Build a piece of road.
1196 * @param tile tile where to build road
1197 * @param flags operation to perform
1198 * @param p1 bit 0..3 road pieces to build (RoadBits)
1199 * bit 4..5 road type
1200 * bit 6..7 disallowed directions to toggle
1201 * @param p2 the town that is building the road (0 if not applicable)
1202 * @param text unused
1203 * @return the cost of this operation or an error
1205 CommandCost
CmdBuildRoad(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1207 CompanyID company
= _current_company
;
1209 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
1210 * if a non-company is building the road */
1211 if (company
== OWNER_TOWN
) {
1212 if (!Town::IsValidID(p2
)) return CMD_ERROR
;
1214 if (p2
!= 0) return CMD_ERROR
;
1216 const Town
*town
= CalcClosestTownFromTile(tile
);
1217 p2
= (town
!= NULL
) ? town
->index
: (TownID
)INVALID_TOWN
;
1219 if (company
== OWNER_DEITY
) {
1220 company
= OWNER_TOWN
;
1222 /* If we are not within a town, we are not owned by the town */
1223 if (town
== NULL
|| DistanceSquare(tile
, town
->xy
) > town
->cache
.squared_town_zone_radius
[HZB_TOWN_EDGE
]) {
1224 company
= OWNER_NONE
;
1229 RoadBits pieces
= Extract
<RoadBits
, 0, 4>(p1
);
1231 /* do not allow building 'zero' road bits, code wouldn't handle it */
1232 if (pieces
== ROAD_NONE
) return CMD_ERROR
;
1234 RoadType rt
= Extract
<RoadType
, 4, 2>(p1
);
1235 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1237 DisallowedRoadDirections toggle_drd
= Extract
<DisallowedRoadDirections
, 6, 2>(p1
);
1239 switch (GetTileType(tile
)) {
1241 if (IsTileSubtype(tile
, TT_BRIDGE
)) {
1242 return BuildRoad_Bridge(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1244 return BuildRoad_Road(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1248 return BuildRoad_Railway(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1251 return BuildRoad_Station(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1254 switch (GetTileSubtype(tile
)) {
1255 case TT_MISC_CROSSING
:
1256 return BuildRoad_Crossing(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1258 case TT_MISC_TUNNEL
:
1259 return BuildRoad_Tunnel(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1262 if (IsRoadDepot(tile
) && (GetAnyRoadBits(tile
, rt
) & pieces
) == pieces
) return_cmd_error(STR_ERROR_ALREADY_BUILT
);
1269 return BuildRoad_Clear(tile
, flags
, rt
, pieces
, company
, p2
, toggle_drd
);
1274 * Checks whether a road or tram connection can be found when building a new road or tram.
1275 * @param tile Tile at which the road being built will end.
1276 * @param rt Roadtype of the road being built.
1277 * @param dir Direction that the road is following.
1278 * @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.
1280 static bool CanConnectToRoad(TileIndex tile
, RoadType rt
, DiagDirection dir
)
1282 RoadBits bits
= GetAnyRoadBits(tile
+ TileOffsByDiagDir(dir
), rt
, false);
1283 return (bits
& DiagDirToRoadBits(ReverseDiagDir(dir
))) != 0;
1287 * Build a long piece of road.
1288 * @param start_tile start tile of drag (the building cost will appear over this tile)
1289 * @param flags operation to perform
1290 * @param p1 end tile of drag
1291 * @param p2 various bitstuffed elements
1292 * - 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
1293 * - 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
1294 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1295 * - p2 = (bit 3 + 4) - road type
1296 * - p2 = (bit 5) - set road direction
1297 * - p2 = (bit 6) - defines two different behaviors for this command:
1298 * - 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
1299 * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
1300 * @param text unused
1301 * @return the cost of this operation or an error
1303 CommandCost
CmdBuildLongRoad(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1305 DisallowedRoadDirections drd
= DRD_NORTHBOUND
;
1307 if (p1
>= MapSize()) return CMD_ERROR
;
1309 TileIndex end_tile
= p1
;
1310 RoadType rt
= Extract
<RoadType
, 3, 2>(p2
);
1311 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1313 Axis axis
= Extract
<Axis
, 2, 1>(p2
);
1314 /* Only drag in X or Y direction dictated by the direction variable */
1315 if (axis
== AXIS_X
&& TileY(start_tile
) != TileY(end_tile
)) return CMD_ERROR
; // x-axis
1316 if (axis
== AXIS_Y
&& TileX(start_tile
) != TileX(end_tile
)) return CMD_ERROR
; // y-axis
1318 DiagDirection dir
= AxisToDiagDir(axis
);
1320 /* Swap direction, also the half-tile drag var (bit 0 and 1) */
1321 if (start_tile
> end_tile
|| (start_tile
== end_tile
&& HasBit(p2
, 0))) {
1322 dir
= ReverseDiagDir(dir
);
1324 drd
= DRD_SOUTHBOUND
;
1327 /* On the X-axis, we have to swap the initial bits, so they
1328 * will be interpreted correctly in the GTTS. Furthermore
1329 * when you just 'click' on one tile to build them. */
1330 if ((axis
== AXIS_Y
) == (start_tile
== end_tile
&& HasBit(p2
, 0) == HasBit(p2
, 1))) drd
^= DRD_BOTH
;
1331 /* No disallowed direction bits have to be toggled */
1332 if (!HasBit(p2
, 5)) drd
= DRD_NONE
;
1334 CommandCost
cost(EXPENSES_CONSTRUCTION
);
1335 CommandCost last_error
= CMD_ERROR
;
1336 TileIndex tile
= start_tile
;
1337 bool had_bridge
= false;
1338 bool had_tunnel
= false;
1339 bool had_success
= false;
1340 bool is_ai
= HasBit(p2
, 6);
1342 /* Start tile is the first tile clicked by the user. */
1344 RoadBits bits
= AxisToRoadBits(axis
);
1346 /* Determine which road parts should be built. */
1347 if (!is_ai
&& start_tile
!= end_tile
) {
1348 /* Only build the first and last roadbit if they can connect to something. */
1349 if (tile
== end_tile
&& !CanConnectToRoad(tile
, rt
, dir
)) {
1350 bits
= DiagDirToRoadBits(ReverseDiagDir(dir
));
1351 } else if (tile
== start_tile
&& !CanConnectToRoad(tile
, rt
, ReverseDiagDir(dir
))) {
1352 bits
= DiagDirToRoadBits(dir
);
1355 /* Road parts only have to be built at the start tile or at the end tile. */
1356 if (tile
== end_tile
&& !HasBit(p2
, 1)) bits
&= DiagDirToRoadBits(ReverseDiagDir(dir
));
1357 if (tile
== start_tile
&& HasBit(p2
, 0)) bits
&= DiagDirToRoadBits(dir
);
1360 CommandCost ret
= DoCommand(tile
, drd
<< 6 | rt
<< 4 | bits
, 0, flags
, CMD_BUILD_ROAD
);
1363 if (last_error
.GetErrorMessage() != STR_ERROR_ALREADY_BUILT
) {
1364 if (is_ai
) return last_error
;
1369 /* Only pay for the upgrade on one side of the bridges and tunnels */
1370 if (IsTunnelTile(tile
)) {
1371 if (!had_tunnel
|| GetTunnelBridgeDirection(tile
) == dir
) {
1375 } else if (IsRoadBridgeTile(tile
)) {
1376 if (!had_bridge
|| GetTunnelBridgeDirection(tile
) == dir
) {
1385 if (tile
== end_tile
) break;
1387 tile
+= TileOffsByDiagDir(dir
);
1390 return had_success
? cost
: last_error
;
1394 * Remove a long piece of road.
1395 * @param start_tile start tile of drag
1396 * @param flags operation to perform
1397 * @param p1 end tile of drag
1398 * @param p2 various bitstuffed elements
1399 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
1400 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
1401 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1402 * - p2 = (bit 3 + 4) - road type
1403 * @param text unused
1404 * @return the cost of this operation or an error
1406 CommandCost
CmdRemoveLongRoad(TileIndex start_tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1408 CommandCost
cost(EXPENSES_CONSTRUCTION
);
1410 if (p1
>= MapSize()) return CMD_ERROR
;
1412 TileIndex end_tile
= p1
;
1413 RoadType rt
= Extract
<RoadType
, 3, 2>(p2
);
1414 if (!IsValidRoadType(rt
)) return CMD_ERROR
;
1416 Axis axis
= Extract
<Axis
, 2, 1>(p2
);
1417 /* Only drag in X or Y direction dictated by the direction variable */
1418 if (axis
== AXIS_X
&& TileY(start_tile
) != TileY(end_tile
)) return CMD_ERROR
; // x-axis
1419 if (axis
== AXIS_Y
&& TileX(start_tile
) != TileX(end_tile
)) return CMD_ERROR
; // y-axis
1421 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
1422 if (start_tile
> end_tile
|| (start_tile
== end_tile
&& HasBit(p2
, 0))) {
1423 TileIndex t
= start_tile
;
1424 start_tile
= end_tile
;
1426 p2
^= IsInsideMM(p2
& 3, 1, 3) ? 3 : 0;
1429 Money money
= GetAvailableMoneyForCommand();
1430 TileIndex tile
= start_tile
;
1431 CommandCost last_error
= CMD_ERROR
;
1432 bool had_success
= false;
1433 /* Start tile is the small number. */
1435 RoadBits bits
= AxisToRoadBits(axis
);
1437 if (tile
== end_tile
&& !HasBit(p2
, 1)) bits
&= ROAD_NW
| ROAD_NE
;
1438 if (tile
== start_tile
&& HasBit(p2
, 0)) bits
&= ROAD_SE
| ROAD_SW
;
1440 /* try to remove the halves. */
1442 CommandCost ret
= RemoveRoad(tile
, flags
& ~DC_EXEC
, bits
, rt
, true);
1443 if (ret
.Succeeded()) {
1444 if (flags
& DC_EXEC
) {
1445 money
-= ret
.GetCost();
1447 _additional_cash_required
= DoCommand(start_tile
, end_tile
, p2
, flags
& ~DC_EXEC
, CMD_REMOVE_LONG_ROAD
).GetCost();
1450 RemoveRoad(tile
, flags
, bits
, rt
, true, false);
1455 /* Ownership errors are more important. */
1456 if (last_error
.GetErrorMessage() != STR_ERROR_OWNED_BY
) last_error
= ret
;
1460 if (tile
== end_tile
) break;
1462 tile
+= (axis
== AXIS_Y
) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
1465 return had_success
? cost
: last_error
;
1469 * Build a road depot.
1470 * @param tile tile where to build the depot
1471 * @param flags operation to perform
1472 * @param p1 bit 0..1 entrance direction (DiagDirection)
1473 * bit 2..3 road type
1475 * @param text unused
1476 * @return the cost of this operation or an error
1478 * @todo When checking for the tile slope,
1479 * distinguish between "Flat land required" and "land sloped in wrong direction"
1481 CommandCost
CmdBuildRoadDepot(TileIndex tile
, DoCommandFlag flags
, uint32 p1
, uint32 p2
, const char *text
)
1483 DiagDirection dir
= Extract
<DiagDirection
, 0, 2>(p1
);
1484 RoadType rt
= Extract
<RoadType
, 2, 2>(p1
);
1486 if (!IsValidRoadType(rt
) || !ValParamRoadType(rt
)) return CMD_ERROR
;
1488 Slope tileh
= GetTileSlope(tile
);
1489 if (tileh
!= SLOPE_FLAT
&& (
1490 !_settings_game
.construction
.build_on_slopes
||
1491 !CanBuildDepotByTileh(dir
, tileh
)
1493 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED
);
1496 CommandCost cost
= DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
1497 if (cost
.Failed()) return cost
;
1499 if (HasBridgeAbove(tile
)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
1501 if (!Depot::CanAllocateItem()) return CMD_ERROR
;
1503 if (flags
& DC_EXEC
) {
1504 Depot
*dep
= new Depot(tile
);
1505 dep
->build_date
= _date
;
1507 /* A road depot has two road bits. */
1508 Company::Get(_current_company
)->infrastructure
.road
[rt
] += 2;
1509 DirtyCompanyInfrastructureWindows(_current_company
);
1511 MakeRoadDepot(tile
, _current_company
, dep
->index
, dir
, rt
);
1512 MarkTileDirtyByTile(tile
);
1513 MakeDefaultName(dep
);
1515 cost
.AddCost(_price
[PR_BUILD_DEPOT_ROAD
]);
1519 static CommandCost
ClearTile_Road(TileIndex tile
, DoCommandFlag flags
)
1521 if (IsTileSubtype(tile
, TT_TRACK
)) {
1522 RoadBits b
= GetAllRoadBits(tile
);
1524 /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
1525 if ((HasExactlyOneBit(b
) && GetRoadBits(tile
, ROADTYPE_TRAM
) == ROAD_NONE
) || !(flags
& DC_AUTO
)) {
1526 CommandCost
ret(EXPENSES_CONSTRUCTION
);
1528 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
1529 CommandCost tmp_ret
= RemoveRoad(tile
, flags
, GetRoadBits(tile
, rt
), rt
, true);
1530 if (tmp_ret
.Failed()) return tmp_ret
;
1531 ret
.AddCost(tmp_ret
);
1536 return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST
);
1538 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
1540 /* Floods can remove anything as well as the scenario editor */
1542 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
1543 RoadTypes rts
= GetRoadTypes(tile
);
1544 Owner road_owner
= _current_company
;
1545 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
1547 /* We can remove unowned road and if the town allows it */
1548 if (road_owner
== OWNER_TOWN
&& _current_company
!= OWNER_TOWN
&& !(_settings_game
.construction
.extra_dynamite
|| _cheats
.magic_bulldozer
.value
)) {
1549 /* Town does not allow */
1550 CommandCost ret
= CheckTileOwnership(tile
);
1551 if (ret
.Failed()) return ret
;
1553 if (road_owner
!= OWNER_NONE
&& road_owner
!= OWNER_TOWN
) {
1554 CommandCost ret
= CheckOwnership(road_owner
, tile
);
1555 if (ret
.Failed()) return ret
;
1558 if (HasBit(rts
, ROADTYPE_TRAM
)) {
1559 Owner tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
1560 if (tram_owner
!= OWNER_NONE
) {
1561 CommandCost ret
= CheckOwnership(tram_owner
, tile
);
1562 if (ret
.Failed()) return ret
;
1568 TileIndex endtile
= GetOtherBridgeEnd(tile
);
1570 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
1571 if (ret
.Failed()) return ret
;
1573 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
1574 Town
*t
= ClosestTownFromTile(tile
, UINT_MAX
); // town penalty rating
1576 /* Check if you are allowed to remove the bridge owned by a town
1577 * Removal depends on difficulty settings */
1578 CommandCost ret
= CheckforTownRating(flags
, t
, TUNNELBRIDGE_REMOVE
);
1579 if (ret
.Failed()) return ret
;
1581 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
1582 * you have a "Poor" (0) town rating */
1583 ChangeTownRating(t
, RATING_TUNNEL_BRIDGE_DOWN_STEP
, RATING_TUNNEL_BRIDGE_MINIMUM
, flags
);
1586 uint len
= GetTunnelBridgeLength(tile
, endtile
);
1588 if (flags
& DC_EXEC
) {
1589 RemoveBridgeMiddleTiles(tile
, endtile
);
1591 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
1592 RoadBits bridge_piece
= DiagDirToRoadBits(dir
);
1593 RoadBits other_nonbridge_pieces
= ComplementRoadBits(DiagDirToRoadBits(ReverseDiagDir(dir
)));
1594 bool other_extended
= IsExtendedRoadBridge(endtile
);
1596 MakeNormalRoadFromBridge(endtile
);
1599 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
1600 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
1601 RoadBits pieces
= GetRoadBits(tile
, rt
);
1603 if ((pieces
& bridge_piece
) == 0) {
1604 /* This roadtype does not connect to the bridge */
1606 c
->infrastructure
.road
[rt
] -= CountBits(pieces
);
1607 DirtyCompanyInfrastructureWindows(c
->index
);
1610 /* This roadtype connects to the bridge */
1611 RoadBits other_pieces
= GetRoadBits(endtile
, rt
);
1614 /* A full diagonal road tile has two road bits. */
1615 c
->infrastructure
.road
[rt
] -= (CountBits(pieces
) + 2 * len
+ CountBits(other_pieces
)) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
1616 DirtyCompanyInfrastructureWindows(c
->index
);
1619 if (other_extended
&& ((other_pieces
&= other_nonbridge_pieces
) != 0)) {
1620 SetRoadBits(endtile
, other_pieces
, rt
);
1621 if (c
!= NULL
) c
->infrastructure
.road
[rt
] += CountBits(other_pieces
);
1623 ClearRoadType(endtile
, rt
);
1629 DoClearSquare(tile
);
1630 MarkTileDirtyByTile(endtile
);
1633 return CommandCost(EXPENSES_CONSTRUCTION
, (len
+ 2) * _price
[PR_CLEAR_BRIDGE
]);
1639 * Get the foundationtype of a RoadBits Slope combination
1641 * @param tileh The Slope part
1642 * @param bits The RoadBits part
1643 * @return The resulting Foundation
1645 static Foundation
GetRoadFoundation(Slope tileh
, RoadBits bits
)
1647 /* Flat land and land without a road doesn't require a foundation */
1648 if (tileh
== SLOPE_FLAT
|| bits
== ROAD_NONE
) return FOUNDATION_NONE
;
1650 /* Steep slopes behave the same as slopes with one corner raised. */
1651 if (IsSteepSlope(tileh
)) {
1652 tileh
= SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh
));
1655 /* Leveled RoadBits on a slope */
1656 if ((_invalid_leveled_roadbits
[tileh
] & bits
) == ROAD_NONE
) return FOUNDATION_LEVELED
;
1658 /* Straight roads without foundation on a slope */
1659 if (!IsSlopeWithOneCornerRaised(tileh
) &&
1660 (_invalid_straight_roadbits
[tileh
] & bits
) == ROAD_NONE
)
1661 return FOUNDATION_NONE
;
1663 /* Roads on steep Slopes or on Slopes with one corner raised */
1664 return (bits
== ROAD_X
? FOUNDATION_INCLINED_X
: FOUNDATION_INCLINED_Y
);
1667 const byte _road_sloped_sprites
[14] = {
1675 * Draw the ground sprite for a road tile
1676 * @param tile The tile to draw
1677 * @param roadside The roadside of the tile
1678 * @param image The sprite to draw
1679 * @param paved_offset The offset to add to the sprite if the road is paved
1680 * @param unpaved_offset The offset to add to the sprite if the tile is on snow or in the desert
1681 * @return The palette to use for further drawing
1683 static PaletteID
DrawRoadGroundSprite(TileIndex tile
, Roadside roadside
, SpriteID image
, int paved_offset
, int unpaved_offset
)
1685 PaletteID pal
= PAL_NONE
;
1688 case ROADSIDE_BARREN
:
1689 if (IsOnSnow(tile
)) {
1690 image
+= unpaved_offset
;
1692 pal
= PALETTE_TO_BARE_LAND
;
1696 case ROADSIDE_GRASS
:
1697 if (IsOnSnow(tile
)) image
+= unpaved_offset
;
1701 if (IsOnSnow(tile
) && !(_settings_game
.game_creation
.landscape
== LT_TROPIC
&& HasGrfMiscBit(GMB_DESERT_PAVED_ROADS
))) {
1702 image
+= unpaved_offset
;
1704 image
+= paved_offset
;
1709 DrawGroundSprite(image
, pal
);
1715 * Draws the catenary for the given tile
1716 * @param ti information about the tile (slopes, height etc)
1717 * @param tram the roadbits for the tram
1719 void DrawTramCatenary(const TileInfo
*ti
, RoadBits tram
)
1721 /* Do not draw catenary if it is invisible */
1722 if (IsInvisibilitySet(TO_CATENARY
)) return;
1724 /* Don't draw the catenary under a low bridge */
1725 if (HasBridgeAbove(ti
->tile
) && !IsTransparencySet(TO_CATENARY
)) {
1726 int height
= GetBridgeHeight(GetNorthernBridgeEnd(ti
->tile
));
1728 if (height
<= GetTileMaxZ(ti
->tile
) + 1) return;
1734 if (ti
->tileh
!= SLOPE_FLAT
) {
1735 back
= SPR_TRAMWAY_BACK_WIRES_SLOPED
+ _road_sloped_sprites
[ti
->tileh
- 1];
1736 front
= SPR_TRAMWAY_FRONT_WIRES_SLOPED
+ _road_sloped_sprites
[ti
->tileh
- 1];
1738 back
= SPR_TRAMWAY_BASE
+ _road_backpole_sprites_1
[tram
];
1739 front
= SPR_TRAMWAY_BASE
+ _road_frontwire_sprites_1
[tram
];
1742 AddSortableSpriteToDraw(back
, PAL_NONE
, ti
->x
, ti
->y
, 16, 16, TILE_HEIGHT
+ BB_HEIGHT_UNDER_BRIDGE
, ti
->z
, IsTransparencySet(TO_CATENARY
));
1743 AddSortableSpriteToDraw(front
, PAL_NONE
, ti
->x
, ti
->y
, 16, 16, TILE_HEIGHT
+ BB_HEIGHT_UNDER_BRIDGE
, ti
->z
, IsTransparencySet(TO_CATENARY
));
1747 * Draws details on/around the road
1748 * @param img the sprite to draw
1749 * @param ti the tile to draw on
1750 * @param dx the offset from the top of the BB of the tile
1751 * @param dy the offset from the top of the BB of the tile
1752 * @param h the height of the sprite to draw
1754 static void DrawRoadDetail(SpriteID img
, const TileInfo
*ti
, int dx
, int dy
, int h
)
1759 if (ti
->tileh
!= SLOPE_FLAT
) z
= GetSlopePixelZ(x
, y
);
1760 AddSortableSpriteToDraw(img
, PAL_NONE
, x
, y
, 2, 2, h
, z
);
1764 * Draw ground sprite and road pieces
1765 * @param ti TileInfo
1767 static void DrawRoadBits(TileInfo
*ti
)
1769 RoadBits road
= GetRoadBits(ti
->tile
, ROADTYPE_ROAD
);
1770 RoadBits tram
= GetRoadBits(ti
->tile
, ROADTYPE_TRAM
);
1774 if (IsTileSubtype(ti
->tile
, TT_BRIDGE
)) {
1775 assert(ti
->tileh
!= SLOPE_FLAT
);
1776 DrawFoundation(ti
, FOUNDATION_LEVELED
, GetTunnelBridgeDirection(ti
->tile
));
1777 } else if (ti
->tileh
!= SLOPE_FLAT
) {
1778 Foundation f
= GetRoadFoundation(ti
->tileh
, road
| tram
);
1780 DrawFoundation(ti
, f
);
1782 /* DrawFoundation() modifies ti.
1783 * Default sloped sprites.. */
1784 if (ti
->tileh
!= SLOPE_FLAT
) image
= _road_sloped_sprites
[ti
->tileh
- 1] + SPR_ROAD_SLOPE_START
;
1787 if (image
== 0) image
= _road_tile_sprites_1
[road
!= ROAD_NONE
? road
: tram
];
1789 Roadside roadside
= IsTileSubtype(ti
->tile
, TT_TRACK
) ? GetRoadside(ti
->tile
) : ROADSIDE_GRASS
;
1791 PaletteID pal
= DrawRoadGroundSprite(ti
->tile
, roadside
, image
, -19, 19);
1793 /* For tram we overlay the road graphics with either tram tracks only
1794 * (when there is actual road beneath the trams) or with tram tracks
1795 * and some dirts which hides the road graphics */
1796 if (tram
!= ROAD_NONE
) {
1797 if (ti
->tileh
!= SLOPE_FLAT
) {
1798 image
= _road_sloped_sprites
[ti
->tileh
- 1] + SPR_TRAMWAY_SLOPED_OFFSET
;
1800 image
= _road_tile_sprites_1
[tram
] - SPR_ROAD_Y
;
1802 image
+= (road
== ROAD_NONE
) ? SPR_TRAMWAY_TRAM
: SPR_TRAMWAY_OVERLAY
;
1803 DrawGroundSprite(image
, pal
);
1806 if (IsTileSubtype(ti
->tile
, TT_TRACK
) && road
!= ROAD_NONE
) {
1807 DisallowedRoadDirections drd
= GetDisallowedRoadDirections(ti
->tile
);
1808 if (drd
!= DRD_NONE
) {
1809 DrawGroundSpriteAt(SPR_ONEWAY_BASE
+ drd
- 1 + ((road
== ROAD_X
) ? 0 : 3), PAL_NONE
, 8, 8, GetPartialPixelZ(8, 8, ti
->tileh
));
1813 if (IsTileSubtype(ti
->tile
, TT_TRACK
) && HasRoadWorks(ti
->tile
)) {
1815 DrawGroundSprite((road
| tram
) & ROAD_X
? SPR_EXCAVATION_X
: SPR_EXCAVATION_Y
, PAL_NONE
);
1819 if (tram
!= ROAD_NONE
) DrawTramCatenary(ti
, tram
);
1821 if (!IsTileSubtype(ti
->tile
, TT_TRACK
)) return;
1823 /* Return if full detail is disabled, or we are zoomed fully out. */
1824 if (!HasBit(_display_opt
, DO_FULL_DETAIL
) || _cur_dpi
->zoom
> ZOOM_LVL_DETAIL
) return;
1826 /* Do not draw details (street lights, trees) under low bridge */
1827 if (HasBridgeAbove(ti
->tile
) && (roadside
== ROADSIDE_TREES
|| roadside
== ROADSIDE_STREET_LIGHTS
)) {
1828 int height
= GetBridgeHeight(GetNorthernBridgeEnd(ti
->tile
));
1829 int minz
= GetTileMaxZ(ti
->tile
) + 2;
1831 if (roadside
== ROADSIDE_TREES
) minz
++;
1833 if (height
< minz
) return;
1836 /* If there are no road bits, return, as there is nothing left to do */
1837 if (HasAtMostOneBit(road
)) return;
1839 /* Draw extra details. */
1840 for (const DrawRoadTileStruct
*drts
= _road_display_table
[roadside
][road
| tram
]; drts
->image
!= 0; drts
++) {
1841 DrawRoadDetail(drts
->image
, ti
, drts
->subcoord_x
, drts
->subcoord_y
, 0x10);
1845 /** Tile callback function for rendering a road tile to the screen */
1846 static void DrawTile_Road(TileInfo
*ti
)
1848 if (IsTileSubtype(ti
->tile
, TT_TRACK
) || IsExtendedRoadBridge(ti
->tile
)) {
1851 DrawBridgeGround(ti
);
1855 DiagDirection dir
= GetTunnelBridgeDirection(ti
->tile
);
1857 const PalSpriteID
*psid
= GetBridgeRampSprite(GetRoadBridgeType(ti
->tile
), 8, ti
->tileh
, dir
);
1859 /* Draw Trambits as SpriteCombine */
1860 StartSpriteCombine();
1862 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1863 * it doesn't disappear behind it
1865 /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1866 AddSortableSpriteToDraw(psid
->sprite
, psid
->pal
, ti
->x
, ti
->y
, 16, 16, ti
->tileh
== SLOPE_FLAT
? 0 : 8, ti
->z
);
1868 RoadTypes rts
= GetRoadTypes(ti
->tile
);
1870 if (HasBit(rts
, ROADTYPE_TRAM
)) {
1873 if (ti
->tileh
!= SLOPE_FLAT
) {
1874 offset
= (offset
+ 1) & 1;
1879 /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1880 DrawBridgeTramBits(ti
->x
, ti
->y
, z
, offset
, HasBit(rts
, ROADTYPE_ROAD
), true);
1886 DrawBridgeMiddle(ti
);
1889 void DrawLevelCrossing(TileInfo
*ti
)
1891 if (ti
->tileh
!= SLOPE_FLAT
) DrawFoundation(ti
, FOUNDATION_LEVELED
);
1893 PaletteID pal
= PAL_NONE
;
1894 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
1896 if (rti
->UsesOverlay()) {
1897 Axis axis
= GetCrossingRailAxis(ti
->tile
);
1899 DrawRoadGroundSprite(ti
->tile
, GetRoadside(ti
->tile
), SPR_ROAD_Y
+ axis
, -19, 19);
1901 SpriteID rail
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_CROSSING
) + axis
;
1902 /* Draw tracks, but draw PBS reserved tracks darker. */
1903 pal
= (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& HasCrossingReservation(ti
->tile
)) ? PALETTE_CRASH
: PAL_NONE
;
1904 DrawGroundSprite(rail
, pal
);
1906 DrawRailTileSeq(ti
, &_crossing_layout
, TO_CATENARY
, rail
, 0, PAL_NONE
);
1908 SpriteID image
= rti
->base_sprites
.crossing
;
1910 if (GetCrossingRoadAxis(ti
->tile
) == AXIS_X
) image
++;
1911 if (IsCrossingBarred(ti
->tile
)) image
+= 2;
1913 pal
= DrawRoadGroundSprite(ti
->tile
, GetRoadside(ti
->tile
), image
, 4, 8);
1915 /* PBS debugging, draw reserved tracks darker */
1916 if (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& HasCrossingReservation(ti
->tile
)) {
1917 DrawGroundSprite(GetCrossingRoadAxis(ti
->tile
) == AXIS_Y
? GetRailTypeInfo(GetRailType(ti
->tile
))->base_sprites
.single_x
: GetRailTypeInfo(GetRailType(ti
->tile
))->base_sprites
.single_y
, PALETTE_CRASH
);
1921 if (HasTileRoadType(ti
->tile
, ROADTYPE_TRAM
)) {
1922 DrawGroundSprite(SPR_TRAMWAY_OVERLAY
+ (GetCrossingRoadAxis(ti
->tile
) ^ 1), pal
);
1923 DrawTramCatenary(ti
, GetCrossingRoadBits(ti
->tile
));
1926 if (HasCatenaryDrawn(GetRailType(ti
->tile
))) DrawCatenary(ti
);
1928 DrawBridgeMiddle(ti
);
1932 * Updates cached nearest town for all road tiles
1933 * @param invalidate are we just invalidating cached data?
1934 * @pre invalidate == true implies _generating_world == true
1936 void UpdateNearestTownForRoadTiles(bool invalidate
)
1938 assert(!invalidate
|| _generating_world
);
1940 for (TileIndex t
= 0; t
< MapSize(); t
++) {
1941 if ((IsRoadTile(t
) || IsLevelCrossingTile(t
)) && !HasTownOwnedRoad(t
)) {
1942 TownID tid
= (TownID
)INVALID_TOWN
;
1944 const Town
*town
= CalcClosestTownFromTile(t
);
1945 if (town
!= NULL
) tid
= town
->index
;
1947 SetTownIndex(t
, tid
);
1952 static int GetSlopePixelZ_Road(TileIndex tile
, uint x
, uint y
)
1955 Slope tileh
= GetTilePixelSlope(tile
, &z
);
1957 if (IsTileSubtype(tile
, TT_TRACK
)) {
1958 if (tileh
== SLOPE_FLAT
) return z
;
1959 z
+= ApplyPixelFoundationToSlope(GetRoadFoundation(tileh
, GetAllRoadBits(tile
)), &tileh
);
1960 return z
+ GetPartialPixelZ(x
& 0xF, y
& 0xF, tileh
);
1961 } else if (IsExtendedRoadBridge(tile
)) {
1962 return z
+ TILE_HEIGHT
;
1967 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
1969 z
+= ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh
, DiagDirToAxis(dir
)), &tileh
);
1971 /* On the bridge ramp? */
1972 uint pos
= (DiagDirToAxis(dir
) == AXIS_X
? y
: x
);
1973 if (5 <= pos
&& pos
<= 10) {
1974 return z
+ ((tileh
== SLOPE_FLAT
) ? GetBridgePartialPixelZ(dir
, x
, y
) : TILE_HEIGHT
);
1977 return z
+ GetPartialPixelZ(x
, y
, tileh
);
1981 static Foundation
GetFoundation_Road(TileIndex tile
, Slope tileh
)
1983 return IsTileSubtype(tile
, TT_TRACK
) ? GetRoadFoundation(tileh
, GetAllRoadBits(tile
)) :
1984 IsExtendedRoadBridge(tile
) ? FOUNDATION_LEVELED
:
1985 GetBridgeFoundation(tileh
, DiagDirToAxis(GetTunnelBridgeDirection(tile
)));
1988 static const Roadside _town_road_types
[][2] = {
1989 { ROADSIDE_GRASS
, ROADSIDE_GRASS
},
1990 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
1991 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
1992 { ROADSIDE_TREES
, ROADSIDE_TREES
},
1993 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
}
1996 static const Roadside _town_road_types_2
[][2] = {
1997 { ROADSIDE_GRASS
, ROADSIDE_GRASS
},
1998 { ROADSIDE_PAVED
, ROADSIDE_PAVED
},
1999 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
},
2000 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
},
2001 { ROADSIDE_STREET_LIGHTS
, ROADSIDE_PAVED
}
2004 void UpdateRoadSide(TileIndex tile
, HouseZonesBits grp
)
2006 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2007 const Roadside
*new_rs
= (_settings_game
.game_creation
.landscape
== LT_TOYLAND
) ? _town_road_types_2
[grp
] : _town_road_types
[grp
];
2008 Roadside cur_rs
= GetRoadside(tile
);
2010 /* We have our desired type, do nothing */
2011 if (cur_rs
== new_rs
[0]) return;
2013 /* We have the pre-type of the desired type, switch to the desired type */
2014 if (cur_rs
== new_rs
[1]) {
2016 /* We have barren land, install the pre-type */
2017 } else if (cur_rs
== ROADSIDE_BARREN
) {
2019 /* We're totally off limits, remove any installation and make barren land */
2021 cur_rs
= ROADSIDE_BARREN
;
2024 SetRoadside(tile
, cur_rs
);
2025 MarkTileDirtyByTile(tile
);
2028 static void TileLoop_Road(TileIndex tile
)
2030 switch (_settings_game
.game_creation
.landscape
) {
2032 int z
= IsTileSubtype(tile
, TT_TRACK
) ? GetTileZ(tile
) : GetTileMaxZ(tile
);
2033 if (IsOnSnow(tile
) != (z
> GetSnowLine())) {
2035 MarkTileDirtyByTile(tile
);
2041 if (GetTropicZone(tile
) == TROPICZONE_DESERT
&& !IsOnDesert(tile
)) {
2043 MarkTileDirtyByTile(tile
);
2048 if (!IsTileSubtype(tile
, TT_TRACK
)) return;
2050 const Town
*t
= ClosestTownFromTile(tile
, UINT_MAX
);
2051 if (!HasRoadWorks(tile
)) {
2052 HouseZonesBits grp
= HZB_TOWN_EDGE
;
2055 grp
= GetTownRadiusGroup(t
, tile
);
2057 /* Show an animation to indicate road work */
2058 if (t
->road_build_months
!= 0 &&
2059 (DistanceManhattan(t
->xy
, tile
) < 8 || grp
!= HZB_TOWN_EDGE
) &&
2060 !HasAtMostOneBit(GetAllRoadBits(tile
)) &&
2061 GetFoundationSlope(tile
) == SLOPE_FLAT
&&
2062 EnsureNoVehicleOnGround(tile
).Succeeded() &&
2064 StartRoadWorks(tile
);
2065 /* Remove any trees or lamps in case or roadwork */
2066 switch (GetRoadside(tile
)) {
2067 case ROADSIDE_BARREN
:
2068 case ROADSIDE_GRASS
: SetRoadside(tile
, ROADSIDE_GRASS
); break;
2069 default: SetRoadside(tile
, ROADSIDE_PAVED
); break;
2072 if (_settings_client
.sound
.ambient
) SndPlayTileFx(SND_21_JACKHAMMER
, tile
);
2073 CreateEffectVehicleAbove(
2074 TileX(tile
) * TILE_SIZE
+ 7,
2075 TileY(tile
) * TILE_SIZE
+ 7,
2078 MarkTileDirtyByTile(tile
);
2083 UpdateRoadSide(tile
, grp
);
2084 } else if (DecreaseRoadWorksCounter(tile
)) {
2085 if (_settings_game
.economy
.mod_road_rebuild
) {
2086 /* Generate a nicer town surface */
2087 const RoadBits old_rb
= GetAnyRoadBits(tile
, ROADTYPE_ROAD
);
2088 const RoadBits new_rb
= CleanUpRoadBits(tile
, old_rb
);
2090 if (old_rb
!= new_rb
) {
2091 RemoveRoad(tile
, DC_EXEC
| DC_AUTO
| DC_NO_WATER
, (old_rb
^ new_rb
), ROADTYPE_ROAD
, true);
2095 MarkTileDirtyByTile(tile
);
2099 static bool ClickTile_Road(TileIndex tile
)
2104 static TrackStatus
GetTileRoadStatus_Road(TileIndex tile
, uint sub_mode
, DiagDirection side
)
2106 /* Converts RoadBits to TrackdirBits */
2107 static const TrackdirBits road_trackdirbits
[16] = {
2108 TRACKDIR_BIT_NONE
, // ROAD_NONE
2109 TRACKDIR_BIT_NONE
, // ROAD_NW
2110 TRACKDIR_BIT_NONE
, // ROAD_SW
2111 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_LEFT_N
, // ROAD_W
2112 TRACKDIR_BIT_NONE
, // ROAD_SE
2113 TRACKDIR_BIT_Y_SE
| TRACKDIR_BIT_Y_NW
, // ROAD_Y
2114 TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_LOWER_W
, // ROAD_S
2115 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_Y_SE
2116 | TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_Y_NW
, // ROAD_Y | ROAD_SW
2117 TRACKDIR_BIT_NONE
, // ROAD_NE
2118 TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_UPPER_W
, // ROAD_N
2119 TRACKDIR_BIT_X_NE
| TRACKDIR_BIT_X_SW
, // ROAD_X
2120 TRACKDIR_BIT_LEFT_S
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_X_NE
2121 | TRACKDIR_BIT_LEFT_N
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_X_SW
, // ROAD_X | ROAD_NW
2122 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_RIGHT_N
, // ROAD_E
2123 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_UPPER_E
| TRACKDIR_BIT_Y_SE
2124 | TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_UPPER_W
| TRACKDIR_BIT_Y_NW
, // ROAD_Y | ROAD_NE
2125 TRACKDIR_BIT_RIGHT_S
| TRACKDIR_BIT_LOWER_E
| TRACKDIR_BIT_X_NE
2126 | TRACKDIR_BIT_RIGHT_N
| TRACKDIR_BIT_LOWER_W
| TRACKDIR_BIT_X_SW
, // ROAD_X | ROAD_SE
2127 TRACKDIR_BIT_MASK
, // ROAD_ALL
2130 static const uint drd_mask
[DRD_END
] = { 0xFFFF, 0xFF00, 0xFF, 0x0 };
2132 if ((GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
2134 if (IsTileSubtype(tile
, TT_TRACK
)) {
2135 if (HasRoadWorks(tile
)) return 0;
2137 if (side
== GetTunnelBridgeDirection(tile
)) return 0;
2140 RoadType rt
= (RoadType
)FindFirstBit(sub_mode
);
2141 RoadBits bits
= GetRoadBits(tile
, rt
);
2143 /* no roadbit at this side of tile, return 0 */
2144 if (side
!= INVALID_DIAGDIR
&& (DiagDirToRoadBits(side
) & bits
) == 0) return 0;
2146 TrackdirBits trackdirbits
= road_trackdirbits
[bits
];
2147 if (IsTileSubtype(tile
, TT_TRACK
) && rt
== ROADTYPE_ROAD
) trackdirbits
&= (TrackdirBits
)drd_mask
[GetDisallowedRoadDirections(tile
)];
2149 return CombineTrackStatus(trackdirbits
, TRACKDIR_BIT_NONE
);
2152 static const StringID _road_tile_strings
[] = {
2153 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2154 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2155 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2156 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS
,
2157 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2158 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD
,
2159 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2160 STR_LAI_ROAD_DESCRIPTION_ROAD
,
2163 static void GetTileDesc_Road(TileIndex tile
, TileDesc
*td
)
2165 RoadTypes rts
= GetRoadTypes(tile
);
2167 Owner tram_owner
= INVALID_OWNER
;
2168 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
2170 if (IsTileSubtype(tile
, TT_TRACK
)) {
2171 if (!HasBit(rts
, ROADTYPE_ROAD
)) {
2172 td
->str
= STR_LAI_ROAD_DESCRIPTION_TRAMWAY
;
2173 td
->owner
[0] = tram_owner
;
2176 td
->str
= _road_tile_strings
[GetRoadside(tile
)];
2178 td
->str
= GetBridgeSpec(GetRoadBridgeType(tile
))->transport_name
[TRANSPORT_ROAD
];
2179 if (!HasBit(rts
, ROADTYPE_ROAD
)) {
2180 td
->owner
[0] = tram_owner
;
2185 /* So the tile at least has a road; check if it has both road and tram */
2186 Owner road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
2188 if (HasBit(rts
, ROADTYPE_TRAM
)) {
2189 td
->owner_type
[0] = STR_LAND_AREA_INFORMATION_ROAD_OWNER
;
2190 td
->owner
[0] = road_owner
;
2191 td
->owner_type
[1] = STR_LAND_AREA_INFORMATION_TRAM_OWNER
;
2192 td
->owner
[1] = tram_owner
;
2194 /* One to rule them all */
2195 td
->owner
[0] = road_owner
;
2200 static void ChangeTileOwner_Road(TileIndex tile
, Owner old_owner
, Owner new_owner
)
2202 Company
*oldc
= Company::Get(old_owner
);
2205 if (new_owner
!= INVALID_OWNER
) {
2206 newc
= Company::Get(new_owner
);
2208 new_owner
= OWNER_NONE
;
2212 if (IsTileSubtype(tile
, TT_TRACK
)) {
2213 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
2214 /* Update all roadtypes, no matter if they are present */
2215 if (GetRoadOwner(tile
, rt
) == old_owner
) {
2216 if (HasTileRoadType(tile
, rt
)) {
2217 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
2218 uint num_bits
= CountBits(GetRoadBits(tile
, rt
));
2219 oldc
->infrastructure
.road
[rt
] -= num_bits
;
2220 if (newc
!= NULL
) newc
->infrastructure
.road
[rt
] += num_bits
;
2223 SetRoadOwner(tile
, rt
, new_owner
);
2227 TileIndex other_end
= GetOtherBridgeEnd(tile
);
2228 /* Set number of pieces to zero if it's the southern tile as we
2229 * don't want to update the infrastructure counts twice. */
2230 uint len
= tile
< other_end
? GetTunnelBridgeLength(tile
, other_end
) * 2 : 0;
2231 RoadBits bridge_piece
= DiagDirToRoadBits(GetTunnelBridgeDirection(tile
));
2233 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
2234 /* Update all roadtypes, no matter if they are present */
2235 if (GetRoadOwner(tile
, rt
) == old_owner
) {
2236 if (HasBit(GetRoadTypes(tile
), rt
)) {
2237 /* Update company infrastructure counts.
2238 * No need to dirty windows here, we'll redraw the whole screen anyway. */
2239 RoadBits pieces
= GetRoadBits(tile
, rt
);
2240 uint num_pieces
= CountBits(pieces
);
2241 if ((pieces
& bridge_piece
) != 0) {
2242 num_pieces
= (num_pieces
+ len
) * TUNNELBRIDGE_TRACKBIT_FACTOR
;
2244 oldc
->infrastructure
.road
[rt
] -= num_pieces
;
2245 if (newc
!= NULL
) newc
->infrastructure
.road
[rt
] += num_pieces
;
2248 SetRoadOwner(tile
, rt
, new_owner
);
2252 if (IsTileOwner(tile
, old_owner
)) SetTileOwner(tile
, new_owner
);
2256 static CommandCost
TerraformTile_Road(TileIndex tile
, DoCommandFlag flags
, int z_new
, Slope tileh_new
)
2258 if (_settings_game
.construction
.build_on_slopes
&& AutoslopeEnabled()) {
2259 if (IsTileSubtype(tile
, TT_TRACK
)) {
2260 RoadBits bits
= GetAllRoadBits(tile
);
2262 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2263 if (CheckRoadSlope(tileh_new
, bits
, ROAD_NONE
, ROAD_NONE
, &bits_new
).Succeeded()) {
2264 if (bits
== bits_new
) {
2266 Slope tileh_old
= GetTileSlope(tile
, &z_old
);
2268 /* Get the slope on top of the foundation */
2269 z_old
+= ApplyFoundationToSlope(GetRoadFoundation(tileh_old
, bits
), &tileh_old
);
2270 z_new
+= ApplyFoundationToSlope(GetRoadFoundation(tileh_new
, bits
), &tileh_new
);
2272 /* The surface slope must not be changed */
2273 if ((z_old
== z_new
) && (tileh_old
== tileh_new
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2276 } else if (IsExtendedRoadBridge(tile
)) {
2277 if (IsValidRoadBridgeBits(tileh_new
, GetTunnelBridgeDirection(tile
), GetAllRoadBits(tile
))) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2280 Slope tileh_old
= GetTileSlope(tile
, &z_old
);
2282 DiagDirection direction
= GetTunnelBridgeDirection(tile
);
2284 /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2285 CheckBridgeSlope(direction
, &tileh_old
, &z_old
);
2286 CommandCost res
= CheckBridgeSlope(direction
, &tileh_new
, &z_new
);
2288 /* Surface slope is valid and remains unchanged? */
2289 if (res
.Succeeded() && (z_old
== z_new
) && (tileh_old
== tileh_new
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
2293 return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
2296 /** Tile callback functions for road tiles */
2297 extern const TileTypeProcs _tile_type_road_procs
= {
2298 DrawTile_Road
, // draw_tile_proc
2299 GetSlopePixelZ_Road
, // get_slope_z_proc
2300 ClearTile_Road
, // clear_tile_proc
2301 NULL
, // add_accepted_cargo_proc
2302 GetTileDesc_Road
, // get_tile_desc_proc
2303 NULL
, // get_tile_railway_status_proc
2304 GetTileRoadStatus_Road
, // get_tile_road_status_proc
2305 NULL
, // get_tile_waterway_status_proc
2306 ClickTile_Road
, // click_tile_proc
2307 NULL
, // animate_tile_proc
2308 TileLoop_Road
, // tile_loop_proc
2309 ChangeTileOwner_Road
, // change_tile_owner_proc
2310 NULL
, // add_produced_cargo_proc
2311 GetFoundation_Road
, // get_foundation_proc
2312 TerraformTile_Road
, // terraform_tile_proc