Remove SIGTYPE_LAST_NOPBS
[openttd/fttd.git] / src / road_cmd.cpp
blobe0e2116062e90c277372c5854d6a2e989bb3a2ac
1 /* $Id$ */
3 /*
4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8 */
10 /** @file road_cmd.cpp Commands related to road tiles. */
12 #include "stdafx.h"
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"
19 #include "newgrf.h"
20 #include "autoslope.h"
21 #include "map/zoneheight.h"
22 #include "map/road.h"
23 #include "map/bridge.h"
24 #include "map/tunnelbridge.h"
25 #include "bridge.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"
34 #include "roadveh.h"
35 #include "town.h"
36 #include "company_base.h"
37 #include "core/random_func.hpp"
38 #include "newgrf_railtype.h"
39 #include "date_func.h"
40 #include "genworld.h"
41 #include "company_gui.h"
43 #include "table/strings.h"
44 #include "table/road_land.h"
47 /**
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;
56 return false;
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
64 ROAD_NE, // SLOPE_SW
65 ROAD_NW | ROAD_SW, // SLOPE_E
66 ROAD_NONE, // SLOPE_EW
67 ROAD_NW, // SLOPE_SE
68 ROAD_NONE, // SLOPE_WSE
69 ROAD_SE | ROAD_SW, // SLOPE_N
70 ROAD_SE, // SLOPE_NW
71 ROAD_NONE, // SLOPE_NS
72 ROAD_NONE, // SLOPE_ENW
73 ROAD_SW, // SLOPE_NE
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
83 ROAD_Y, // SLOPE_SW
84 ROAD_NONE, // SLOPE_E Foundation
85 ROAD_ALL, // SLOPE_EW
86 ROAD_X, // SLOPE_SE
87 ROAD_ALL, // SLOPE_WSE
88 ROAD_NONE, // SLOPE_N Foundation
89 ROAD_X, // SLOPE_NW
90 ROAD_ALL, // SLOPE_NS
91 ROAD_ALL, // SLOPE_ENW
92 ROAD_Y, // SLOPE_NE
93 ROAD_ALL, // SLOPE_SEN
94 ROAD_ALL, // SLOPE_NWS
97 static Foundation GetRoadFoundation(Slope tileh, RoadBits bits);
99 /**
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
120 * by a town */
121 if (owner != OWNER_TOWN) {
122 if (owner == OWNER_NONE) return CommandCost();
123 CommandCost ret = CheckOwnership(owner);
124 return ret;
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,
149 * then allow it */
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) {
176 DoClearSquare(tile);
177 return;
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. */
236 pieces &= present;
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 */
240 present ^= pieces;
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) {
245 return CMD_ERROR;
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);
252 EffectVehicle *v;
253 FOR_ALL_EFFECTVEHICLES(v) {
254 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
255 delete v;
260 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
261 if (c != NULL) {
262 c->infrastructure.road[rt] -= CountBits(pieces);
263 DirtyCompanyInfrastructureWindows(c->index);
266 if (present == ROAD_NONE) {
267 ClearRoadType(tile, rt);
268 } else {
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]);
281 return cost;
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. */
302 pieces &= 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))) {
306 bits &= ~pieces;
307 } else {
308 assert((pieces & ~AxisToRoadBits(DiagDirToAxis(dir))) == ROAD_NONE);
309 pieces = AxisToRoadBits(DiagDirToAxis(dir));
310 bits = ROAD_NONE;
313 CommandCost cost(EXPENSES_CONSTRUCTION);
315 /* Other end and length of the bridge, if we are removing the bridge piece */
316 TileIndex other_end;
317 uint len;
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]);
333 } else {
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)));
348 num += 2;
349 } else {
350 other_end_bits = GetRoadBits(other_end, rt) & ~DiagDirToRoadBits(ReverseDiagDir(dir));
351 num++;
354 cost.AddCost(num * _price[PR_CLEAR_ROAD]);
355 } else {
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));
368 if (c != NULL) {
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;
374 } else {
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);
385 } else {
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);
397 } else {
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);
407 return cost;
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))) {
428 return CMD_ERROR;
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));
437 if (c != NULL) {
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;
455 } else {
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));
497 if (c != NULL) {
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);
520 return cost;
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));
546 if (c != NULL) {
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)) {
570 case TT_ROAD: {
571 if (!HasTileRoadType(tile, rt)) break;
573 if (IsTileSubtype(tile, TT_TRACK)) {
574 return RemoveRoad_Road(tile, flags, pieces, rt, town_check);
575 } else {
576 return RemoveRoad_Bridge(tile, flags, pieces, rt, town_check);
580 case TT_MISC:
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);
586 case TT_MISC_TUNNEL:
587 if (!HasTileRoadType(tile, rt)) break;
588 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) break;
589 return RemoveRoad_Tunnel(tile, flags, pieces, rt, town_check);
591 default:
592 break;
595 break;
597 case TT_STATION:
598 if (!HasTileRoadType(tile, rt)) break;
600 return RemoveRoad_Station(tile, flags, pieces, rt, town_check);
602 default:
603 break;
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;
655 /* Uphill roads */
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();
675 return CMD_ERROR;
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);
689 switch (diff) {
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;
713 cost.AddCost(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);
724 cost.AddCost(ret);
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));
734 if (c != NULL) {
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);
746 return cost;
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);
825 cost.AddCost(ret);
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));
862 if (c != NULL) {
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);
875 return cost;
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);
893 uint num;
894 bool other_end;
896 if (HasBridgeFlatRamp(tileh, DiagDirToAxis(dir))) {
897 RoadBits existing = GetRoadBits(tile, rt);
898 pieces &= ~existing;
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;
907 pieces |= existing;
908 } else {
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));
917 num = 2;
918 other_end = true;
921 TileIndex other_tile;
922 RoadBits other_pieces;
924 if (other_end) {
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));
940 num++;
941 } else {
942 assert(GetRoadBits(other_tile, rt) == ROAD_NONE);
943 other_pieces = AxisToRoadBits(DiagDirToAxis(dir));
944 num += 2;
946 } else {
947 CommandCost ret = EnsureNoVehicleOnGround(tile);
948 if (ret.Failed()) return ret;
951 if (flags & DC_EXEC) {
952 if (other_end) {
953 /* Update company infrastructure count. */
954 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
955 if (c != NULL) {
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);
969 } else {
970 /* Update company infrastructure count. */
971 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
972 if (c != NULL) {
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);
1018 if (c != NULL) {
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;
1057 Axis roaddir;
1058 switch (GetTrackBits(tile)) {
1059 case TRACK_BIT_X:
1060 if (pieces & ROAD_X) goto do_clear;
1061 roaddir = AXIS_Y;
1062 break;
1064 case TRACK_BIT_Y:
1065 if (pieces & ROAD_Y) goto do_clear;
1066 roaddir = AXIS_X;
1067 break;
1069 default:
1070 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);
1082 if (c != NULL) {
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);
1144 if (c != NULL) {
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);
1183 if (c != NULL) {
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;
1213 } else {
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)) {
1240 case TT_ROAD:
1241 if (IsTileSubtype(tile, TT_BRIDGE)) {
1242 return BuildRoad_Bridge(tile, flags, rt, pieces, company, p2, toggle_drd);
1243 } else {
1244 return BuildRoad_Road(tile, flags, rt, pieces, company, p2, toggle_drd);
1247 case TT_RAILWAY:
1248 return BuildRoad_Railway(tile, flags, rt, pieces, company, p2, toggle_drd);
1250 case TT_STATION:
1251 return BuildRoad_Station(tile, flags, rt, pieces, company, p2, toggle_drd);
1253 case TT_MISC:
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);
1261 case TT_MISC_DEPOT:
1262 if (IsRoadDepot(tile) && (GetAnyRoadBits(tile, rt) & pieces) == pieces) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1263 /* fall through */
1264 default:
1265 break;
1267 /* fall through */
1268 default:
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);
1323 p2 ^= 3;
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. */
1343 for (;;) {
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);
1354 } else {
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);
1361 if (ret.Failed()) {
1362 last_error = ret;
1363 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1364 if (is_ai) return last_error;
1365 break;
1367 } else {
1368 had_success = true;
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) {
1372 cost.AddCost(ret);
1374 had_tunnel = true;
1375 } else if (IsRoadBridgeTile(tile)) {
1376 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1377 cost.AddCost(ret);
1379 had_bridge = true;
1380 } else {
1381 cost.AddCost(ret);
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;
1425 end_tile = t;
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. */
1434 for (;;) {
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. */
1441 if (bits != 0) {
1442 CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
1443 if (ret.Succeeded()) {
1444 if (flags & DC_EXEC) {
1445 money -= ret.GetCost();
1446 if (money < 0) {
1447 _additional_cash_required = DoCommand(start_tile, end_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
1448 return cost;
1450 RemoveRoad(tile, flags, bits, rt, true, false);
1452 cost.AddCost(ret);
1453 had_success = true;
1454 } else {
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
1474 * @param p2 unused
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)
1492 )) {
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]);
1516 return cost;
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);
1527 RoadType rt;
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);
1533 return ret;
1536 return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1537 } else {
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;
1552 } else {
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); // 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);
1598 RoadType rt;
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 */
1605 if (c != NULL) {
1606 c->infrastructure.road[rt] -= CountBits(pieces);
1607 DirtyCompanyInfrastructureWindows(c->index);
1609 } else {
1610 /* This roadtype connects to the bridge */
1611 RoadBits other_pieces = GetRoadBits(endtile, rt);
1613 if (c != NULL) {
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);
1622 } else {
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] = {
1668 0, 0, 2, 0,
1669 0, 1, 0, 0,
1670 3, 0, 0, 0,
1671 0, 0
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;
1687 switch (roadside) {
1688 case ROADSIDE_BARREN:
1689 if (IsOnSnow(tile)) {
1690 image += unpaved_offset;
1691 } else {
1692 pal = PALETTE_TO_BARE_LAND;
1694 break;
1696 case ROADSIDE_GRASS:
1697 if (IsOnSnow(tile)) image += unpaved_offset;
1698 break;
1700 default:
1701 if (IsOnSnow(tile) && !(_settings_game.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS))) {
1702 image += unpaved_offset;
1703 } else {
1704 image += paved_offset;
1706 break;
1709 DrawGroundSprite(image, pal);
1711 return 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;
1731 SpriteID front;
1732 SpriteID back;
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];
1737 } else {
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)
1756 int x = ti->x | dx;
1757 int y = ti->y | dy;
1758 int z = ti->z;
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);
1772 SpriteID image = 0;
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;
1799 } else {
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)) {
1814 /* Road works */
1815 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1816 return;
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)) {
1849 DrawRoadBits(ti);
1850 } else {
1851 DrawBridgeGround(ti);
1853 /* draw ramp */
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)) {
1871 uint offset = dir;
1872 int z = ti->z;
1873 if (ti->tileh != SLOPE_FLAT) {
1874 offset = (offset + 1) & 1;
1875 z += TILE_HEIGHT;
1876 } else {
1877 offset += 2;
1879 /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1880 DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
1883 EndSpriteCombine();
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);
1907 } else {
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;
1943 if (!invalidate) {
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)
1954 int z;
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;
1963 } else {
1964 x &= 0xF;
1965 y &= 0xF;
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]) {
2015 cur_rs = new_rs[0];
2016 /* We have barren land, install the pre-type */
2017 } else if (cur_rs == ROADSIDE_BARREN) {
2018 cur_rs = new_rs[1];
2019 /* We're totally off limits, remove any installation and make barren land */
2020 } else {
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) {
2031 case LT_ARCTIC: {
2032 int z = IsTileSubtype(tile, TT_TRACK) ? GetTileZ(tile) : GetTileMaxZ(tile);
2033 if (IsOnSnow(tile) != (z > GetSnowLine())) {
2034 ToggleSnow(tile);
2035 MarkTileDirtyByTile(tile);
2037 break;
2040 case LT_TROPIC:
2041 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
2042 ToggleDesert(tile);
2043 MarkTileDirtyByTile(tile);
2045 break;
2048 if (!IsTileSubtype(tile, TT_TRACK)) return;
2050 const Town *t = ClosestTownFromTile(tile);
2051 if (!HasRoadWorks(tile)) {
2052 HouseZonesBits grp = HZB_TOWN_EDGE;
2054 if (t != NULL) {
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() &&
2063 Chance16(1, 40)) {
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,
2077 EV_BULLDOZER);
2078 MarkTileDirtyByTile(tile);
2079 return;
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)
2101 return false;
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;
2136 } else {
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;
2174 return;
2176 td->str = _road_tile_strings[GetRoadside(tile)];
2177 } else {
2178 const BridgeSpec *spec = GetBridgeSpec(GetRoadBridgeType(tile));
2179 td->str = spec->transport_name[TRANSPORT_ROAD];
2180 td->road_speed = spec->speed;
2181 if (!HasBit(rts, ROADTYPE_ROAD)) {
2182 td->owner[0] = tram_owner;
2183 return;
2187 /* So the tile at least has a road; check if it has both road and tram */
2188 Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
2190 if (HasBit(rts, ROADTYPE_TRAM)) {
2191 td->owner_type[0] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2192 td->owner[0] = road_owner;
2193 td->owner_type[1] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
2194 td->owner[1] = tram_owner;
2195 } else {
2196 /* One to rule them all */
2197 td->owner[0] = road_owner;
2202 static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2204 Company *oldc = Company::Get(old_owner);
2206 Company *newc;
2207 if (new_owner != INVALID_OWNER) {
2208 newc = Company::Get(new_owner);
2209 } else {
2210 new_owner = OWNER_NONE;
2211 newc = NULL;
2214 if (IsTileSubtype(tile, TT_TRACK)) {
2215 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2216 /* Update all roadtypes, no matter if they are present */
2217 if (GetRoadOwner(tile, rt) == old_owner) {
2218 if (HasTileRoadType(tile, rt)) {
2219 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
2220 uint num_bits = CountBits(GetRoadBits(tile, rt));
2221 oldc->infrastructure.road[rt] -= num_bits;
2222 if (newc != NULL) newc->infrastructure.road[rt] += num_bits;
2225 SetRoadOwner(tile, rt, new_owner);
2228 } else {
2229 TileIndex other_end = GetOtherBridgeEnd(tile);
2230 /* Set number of pieces to zero if it's the southern tile as we
2231 * don't want to update the infrastructure counts twice. */
2232 uint len = tile < other_end ? GetTunnelBridgeLength(tile, other_end) * 2 : 0;
2233 RoadBits bridge_piece = DiagDirToRoadBits(GetTunnelBridgeDirection(tile));
2235 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2236 /* Update all roadtypes, no matter if they are present */
2237 if (GetRoadOwner(tile, rt) == old_owner) {
2238 if (HasBit(GetRoadTypes(tile), rt)) {
2239 /* Update company infrastructure counts.
2240 * No need to dirty windows here, we'll redraw the whole screen anyway. */
2241 RoadBits pieces = GetRoadBits(tile, rt);
2242 uint num_pieces = CountBits(pieces);
2243 if ((pieces & bridge_piece) != 0) {
2244 num_pieces = (num_pieces + len) * TUNNELBRIDGE_TRACKBIT_FACTOR;
2246 oldc->infrastructure.road[rt] -= num_pieces;
2247 if (newc != NULL) newc->infrastructure.road[rt] += num_pieces;
2250 SetRoadOwner(tile, rt, new_owner);
2254 if (IsTileOwner(tile, old_owner)) SetTileOwner(tile, new_owner);
2258 static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2260 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
2261 if (IsTileSubtype(tile, TT_TRACK)) {
2262 RoadBits bits = GetAllRoadBits(tile);
2263 RoadBits bits_new;
2264 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2265 if (CheckRoadSlope(tileh_new, bits, ROAD_NONE, ROAD_NONE, &bits_new).Succeeded()) {
2266 if (bits == bits_new) {
2267 int z_old;
2268 Slope tileh_old = GetTileSlope(tile, &z_old);
2270 /* Get the slope on top of the foundation */
2271 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
2272 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
2274 /* The surface slope must not be changed */
2275 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2278 } else if (IsExtendedRoadBridge(tile)) {
2279 if (IsValidRoadBridgeBits(tileh_new, GetTunnelBridgeDirection(tile), GetAllRoadBits(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2280 } else {
2281 int z_old;
2282 Slope tileh_old = GetTileSlope(tile, &z_old);
2284 DiagDirection direction = GetTunnelBridgeDirection(tile);
2286 /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2287 CheckBridgeSlope(direction, &tileh_old, &z_old);
2288 CommandCost res = CheckBridgeSlope(direction, &tileh_new, &z_new);
2290 /* Surface slope is valid and remains unchanged? */
2291 if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2295 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2298 /** Tile callback functions for road tiles */
2299 extern const TileTypeProcs _tile_type_road_procs = {
2300 DrawTile_Road, // draw_tile_proc
2301 GetSlopePixelZ_Road, // get_slope_z_proc
2302 ClearTile_Road, // clear_tile_proc
2303 NULL, // add_accepted_cargo_proc
2304 GetTileDesc_Road, // get_tile_desc_proc
2305 NULL, // get_tile_railway_status_proc
2306 GetTileRoadStatus_Road, // get_tile_road_status_proc
2307 NULL, // get_tile_waterway_status_proc
2308 ClickTile_Road, // click_tile_proc
2309 NULL, // animate_tile_proc
2310 TileLoop_Road, // tile_loop_proc
2311 ChangeTileOwner_Road, // change_tile_owner_proc
2312 NULL, // add_produced_cargo_proc
2313 GetFoundation_Road, // get_foundation_proc
2314 TerraformTile_Road, // terraform_tile_proc