Let HandleWindowDragging return a boolean status
[openttd/fttd.git] / src / road_cmd.cpp
blobdece397ba980b0459ba7d81364569e0ed35b9c4b
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 StringID str = CheckVehicleOnGround (tile);
209 if (str != STR_NULL) return_cmd_error(str);
211 CommandCost ret = CheckAllowRemoveRoad (tile, pieces,
212 GetRoadOwner (tile, rt), rt, flags, town_check);
213 if (ret.Failed()) return ret;
215 if (HasRoadWorks(tile) && _current_company != OWNER_WATER) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
217 Slope tileh = GetTileSlope(tile);
219 /* Steep slopes behave the same as slopes with one corner raised. */
220 if (IsSteepSlope(tileh)) {
221 tileh = SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh));
224 RoadBits present = GetRoadBits(tile, rt);
225 const RoadBits other = GetOtherRoadBits(tile, rt);
226 const Foundation f = GetRoadFoundation(tileh, present);
228 /* Autocomplete to a straight road
229 * @li if the bits of the other roadtypes result in another foundation
230 * @li if build on slopes is disabled */
231 if ((IsStraightRoad(other) && (other & _invalid_leveled_roadbits[tileh & SLOPE_ELEVATED]) != ROAD_NONE) ||
232 (tileh != SLOPE_FLAT && !_settings_game.construction.build_on_slopes)) {
233 pieces |= MirrorRoadBits(pieces);
236 /* limit the bits to delete to the existing bits. */
237 pieces &= present;
238 if (pieces == ROAD_NONE) return_cmd_error(rt == ROADTYPE_TRAM ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
240 /* Now set present what it will be after the remove */
241 present ^= pieces;
243 /* Check for invalid RoadBit combinations on slopes */
244 if (tileh != SLOPE_FLAT && present != ROAD_NONE &&
245 (present & _invalid_leveled_roadbits[tileh & SLOPE_ELEVATED]) == present) {
246 return CMD_ERROR;
249 if (flags & DC_EXEC) {
250 if (HasRoadWorks(tile)) {
251 /* flooding tile with road works, don't forget to remove the effect vehicle too */
252 assert(_current_company == OWNER_WATER);
253 EffectVehicle *v;
254 FOR_ALL_EFFECTVEHICLES(v) {
255 if (TileVirtXY(v->x_pos, v->y_pos) == tile) {
256 delete v;
261 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
262 if (c != NULL) {
263 c->infrastructure.road[rt] -= CountBits(pieces);
264 DirtyCompanyInfrastructureWindows(c->index);
267 if (present == ROAD_NONE) {
268 ClearRoadType(tile, rt);
269 } else {
270 /* When bits are removed, you *always* end up with something that
271 * is not a complete straight road tile. However, trams do not have
272 * onewayness, so they cannot remove it either. */
273 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE);
274 SetRoadBits(tile, present, rt);
275 MarkTileDirtyByTile(tile);
279 CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * _price[PR_CLEAR_ROAD]);
280 /* If we build a foundation we have to pay for it. */
281 if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[PR_BUILD_FOUNDATION]);
282 return cost;
286 * Delete a piece of road from a bridge
287 * @param tile tile where to remove road from
288 * @param flags operation to perform
289 * @param pieces roadbits to remove
290 * @param rt roadtype to remove
291 * @param town_check should we check if the town allows removal?
293 static CommandCost RemoveRoad_Bridge(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool town_check)
295 DiagDirection dir = GetTunnelBridgeDirection(tile);
297 CommandCost ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), rt, flags, town_check);
298 if (ret.Failed()) return ret;
300 RoadBits bits = GetRoadBits(tile, rt);
302 /* limit the bits to delete to the existing bits. */
303 pieces &= bits;
304 if (pieces == ROAD_NONE) return_cmd_error(rt == ROADTYPE_TRAM ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
306 if (HasBridgeFlatRamp(GetTileSlope(tile), DiagDirToAxis(dir))) {
307 bits &= ~pieces;
308 } else {
309 assert((pieces & ~AxisToRoadBits(DiagDirToAxis(dir))) == ROAD_NONE);
310 pieces = AxisToRoadBits(DiagDirToAxis(dir));
311 bits = ROAD_NONE;
314 CommandCost cost(EXPENSES_CONSTRUCTION);
316 /* Other end and length of the bridge, if we are removing the bridge piece */
317 TileIndex other_end;
318 uint len;
320 /* Roadbits left at the other side */
321 RoadBits other_end_bits = ROAD_NONE;
323 /* Whether to remove the bridge itself */
324 bool remove_bridge = false;
326 if ((pieces & DiagDirToRoadBits(dir)) == 0) {
327 /* Not removing the bridge piece */
328 other_end = INVALID_TILE;
330 StringID str = CheckVehicleOnGround (tile);
331 if (str != STR_NULL) return_cmd_error(str);
333 cost.AddCost(CountBits(pieces) * _price[PR_CLEAR_ROAD]);
334 } else {
335 /* Removing the bridge piece */
336 other_end = GetOtherBridgeEnd(tile);
337 len = GetTunnelBridgeLength(tile, other_end);
339 ret = TunnelBridgeIsFree(tile, other_end);
340 if (ret.Failed()) return ret;
342 if ((GetOtherRoadBits(tile, rt) & DiagDirToRoadBits(dir)) != 0) {
343 /* The other road type has the bridge piece, so the bridge stays */
344 uint num = CountBits(pieces) + 2 * len;
346 if (!IsExtendedRoadBridge(other_end)) {
347 assert(GetRoadBits(other_end, rt) == AxisToRoadBits(DiagDirToAxis(dir)));
348 assert(GetOtherRoadBits(other_end, rt) == AxisToRoadBits(DiagDirToAxis(dir)));
349 num += 2;
350 } else {
351 other_end_bits = GetRoadBits(other_end, rt) & ~DiagDirToRoadBits(ReverseDiagDir(dir));
352 num++;
355 cost.AddCost(num * _price[PR_CLEAR_ROAD]);
356 } else {
357 /* Removing the last bridge piece and therefore the bridge itself */
358 remove_bridge = true;
359 cost.AddCost((len + 2) * _price[PR_CLEAR_BRIDGE]);
361 if (IsExtendedRoadBridge(other_end)) {
362 other_end_bits = GetRoadBits(other_end, rt) & ~DiagDirToRoadBits(ReverseDiagDir(dir));
367 if (flags & DC_EXEC) {
368 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
369 if (c != NULL) {
370 if (other_end != INVALID_TILE) {
371 c->infrastructure.road[rt] -= (CountBits(bits | pieces) + 2 * len + CountBits(GetRoadBits(other_end, rt))) * TUNNELBRIDGE_TRACKBIT_FACTOR;
372 c->infrastructure.road[rt] += CountBits(bits) + CountBits(other_end_bits);
373 } else if ((bits & DiagDirToRoadBits(dir)) != 0) {
374 c->infrastructure.road[rt] -= CountBits(pieces) * TUNNELBRIDGE_TRACKBIT_FACTOR;
375 } else {
376 c->infrastructure.road[rt] -= CountBits(pieces);
378 DirtyCompanyInfrastructureWindows(c->index);
381 if (remove_bridge) RemoveBridgeMiddleTiles(tile, other_end);
383 if (bits != ROAD_NONE) {
384 SetRoadBits(tile, bits, rt);
385 if (remove_bridge) MakeNormalRoadFromBridge(tile);
386 } else {
387 assert((GetRoadTypes(tile) != RoadTypeToRoadTypes(rt)) || remove_bridge);
388 if (remove_bridge) MakeNormalRoadFromBridge(tile);
389 ClearRoadType(tile, rt);
392 MarkTileDirtyByTile(tile);
394 if (other_end != INVALID_TILE) {
395 if (other_end_bits != ROAD_NONE) {
396 SetRoadBits(other_end, other_end_bits, rt);
397 if (remove_bridge) MakeNormalRoadFromBridge(other_end);
398 } else {
399 assert((GetRoadTypes(other_end) != RoadTypeToRoadTypes(rt)) || remove_bridge);
400 if (remove_bridge) MakeNormalRoadFromBridge(other_end);
401 ClearRoadType(other_end, rt);
404 if (!remove_bridge) MarkBridgeTilesDirty (tile, other_end, dir, false);
408 return cost;
412 * Delete a piece of road from a crossing
413 * @param tile tile where to remove road from
414 * @param flags operation to perform
415 * @param pieces roadbits to remove
416 * @param rt roadtype to remove
417 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
418 * @param town_check should we check if the town allows removal?
420 static CommandCost RemoveRoad_Crossing(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check)
422 StringID str = CheckVehicleOnGround (tile);
423 if (str != STR_NULL) return_cmd_error(str);
425 CommandCost ret = CheckAllowRemoveRoad (tile, pieces,
426 GetRoadOwner (tile, rt), rt, flags, town_check);
427 if (ret.Failed()) return ret;
429 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
430 return CMD_ERROR;
433 /* Don't allow road to be removed from the crossing when there is tram;
434 * we can't draw the crossing without roadbits ;) */
435 if (rt == ROADTYPE_ROAD && HasTileRoadType(tile, ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR;
437 if (flags & DC_EXEC) {
438 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
439 if (c != NULL) {
440 /* A full diagonal road tile has two road bits. */
441 c->infrastructure.road[rt] -= 2;
442 DirtyCompanyInfrastructureWindows(c->index);
445 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
446 if (rts == ROADTYPES_NONE) {
447 TrackBits tracks = GetCrossingRailBits(tile);
448 bool reserved = HasCrossingReservation(tile);
449 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
450 if (reserved) SetTrackReservation(tile, tracks);
452 /* Update rail count for level crossings. The plain track should still be accounted
453 * for, so only subtract the difference to the level crossing cost. */
454 c = Company::GetIfValid(GetTileOwner(tile));
455 if (c != NULL) {
456 c->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR - 1;
457 DirtyCompanyInfrastructureWindows(c->index);
459 } else {
460 SetRoadTypes(tile, rts);
462 MarkTileDirtyByTile(tile);
463 YapfNotifyTrackLayoutChange();
466 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROAD] * 2);
470 * Delete a piece of road from a tunnel
471 * @param tile tile where to remove road from
472 * @param flags operation to perform
473 * @param pieces roadbits to remove
474 * @param rt roadtype to remove
475 * @param town_check should we check if the town allows removal?
477 static CommandCost RemoveRoad_Tunnel(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool town_check)
479 assert(GetTunnelTransportType(tile) == TRANSPORT_ROAD);
481 TileIndex other_end = GetOtherTunnelEnd(tile);
482 CommandCost ret = TunnelBridgeIsFree(tile, other_end);
483 if (ret.Failed()) return ret;
485 ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), rt, flags, town_check);
486 if (ret.Failed()) return ret;
488 /* If it's the last roadtype, just clear the whole tile */
489 if (GetRoadTypes(tile) == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
491 /* Removing any roadbit in the tunnel axis removes the roadtype (that's the behaviour remove-long-roads needs) */
492 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);
494 CommandCost cost(EXPENSES_CONSTRUCTION);
495 /* Pay for *every* tile of the tunnel */
496 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
497 cost.AddCost(len * 2 * _price[PR_CLEAR_ROAD]);
499 if (flags & DC_EXEC) {
500 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
501 if (c != NULL) {
502 /* A full diagonal road tile has two road bits. */
503 c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
504 DirtyCompanyInfrastructureWindows(c->index);
507 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
508 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
510 /* If the owner of the bridge sells all its road, also move the ownership
511 * to the owner of the other roadtype, unless the bridge owner is a town. */
512 RoadType other_rt = (rt == ROADTYPE_ROAD) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
513 Owner other_owner = GetRoadOwner(tile, other_rt);
514 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
515 SetTileOwner(tile, other_owner);
516 SetTileOwner(other_end, other_owner);
519 /* Mark tiles dirty that have been repaved */
520 MarkTileDirtyByTile(tile);
521 MarkTileDirtyByTile(other_end);
524 return cost;
528 * Delete a piece of road from a station
529 * @param tile tile where to remove road from
530 * @param flags operation to perform
531 * @param pieces roadbits to remove
532 * @param rt roadtype to remove
533 * @param town_check should we check if the town allows removal?
535 static CommandCost RemoveRoad_Station(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool town_check)
537 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
539 StringID str = CheckVehicleOnGround (tile);
540 if (str != STR_NULL) return_cmd_error(str);
542 CommandCost ret = CheckAllowRemoveRoad (tile, pieces,
543 GetRoadOwner (tile, rt), rt, flags, town_check);
544 if (ret.Failed()) return ret;
546 /* If it's the last roadtype, just clear the whole tile */
547 if (GetRoadTypes(tile) == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
549 if (flags & DC_EXEC) {
550 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
551 if (c != NULL) {
552 /* A full diagonal road tile has two road bits. */
553 c->infrastructure.road[rt] -= 2;
554 DirtyCompanyInfrastructureWindows(c->index);
556 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
557 MarkTileDirtyByTile(tile);
560 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROAD] * 2);
564 * Delete a piece of road.
565 * @param tile tile where to remove road from
566 * @param flags operation to perform
567 * @param pieces roadbits to remove
568 * @param rt roadtype to remove
569 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
570 * @param town_check should we check if the town allows removal?
572 CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
574 switch (GetTileType(tile)) {
575 case TT_ROAD: {
576 if (!HasTileRoadType(tile, rt)) break;
578 if (IsTileSubtype(tile, TT_TRACK)) {
579 return RemoveRoad_Road(tile, flags, pieces, rt, town_check);
580 } else {
581 return RemoveRoad_Bridge(tile, flags, pieces, rt, town_check);
585 case TT_MISC:
586 switch (GetTileSubtype(tile)) {
587 case TT_MISC_CROSSING:
588 if (!HasTileRoadType(tile, rt)) break;
589 return RemoveRoad_Crossing(tile, flags, pieces, rt, crossing_check, town_check);
591 case TT_MISC_TUNNEL:
592 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) break;
593 if (!HasTileRoadType(tile, rt)) break;
594 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) break;
595 return RemoveRoad_Tunnel(tile, flags, pieces, rt, town_check);
597 default:
598 break;
601 break;
603 case TT_STATION:
604 if (!HasTileRoadType(tile, rt)) break;
606 return RemoveRoad_Station(tile, flags, pieces, rt, town_check);
608 default:
609 break;
612 /* The tile doesn't have the given road type */
613 return_cmd_error(rt == ROADTYPE_TRAM ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
618 * Calculate the costs for roads on slopes
619 * Also compute the road bits that have to be built to fit the slope
621 * @param tileh The current slope
622 * @param pieces The RoadBits we want to add
623 * @param existing The existent RoadBits of the current type
624 * @param other The existent RoadBits for the other type
625 * @param build The actual RoadBits to build
626 * @return The costs for these RoadBits on this slope
628 static CommandCost CheckRoadSlope(Slope tileh, RoadBits pieces, RoadBits existing, RoadBits other, RoadBits *build)
630 /* Remove already build pieces */
631 CLRBITS(pieces, existing);
633 /* If we can't build anything stop here */
634 if (pieces == ROAD_NONE) return CMD_ERROR;
636 /* All RoadBit combos are valid on flat land */
637 if (tileh == SLOPE_FLAT) {
638 if (build != NULL) *build = pieces;
639 return CommandCost();
642 /* Steep slopes behave the same as slopes with one corner raised. */
643 if (IsSteepSlope(tileh)) {
644 tileh = SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh));
647 /* Roads on slopes */
648 if (_settings_game.construction.build_on_slopes && (_invalid_leveled_roadbits[tileh] & (other | existing | pieces)) == ROAD_NONE) {
649 if (build != NULL) *build = pieces;
651 /* If we add leveling we've got to pay for it */
652 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
654 return CommandCost();
657 /* Autocomplete uphill roads */
658 pieces |= MirrorRoadBits(pieces);
659 RoadBits type_bits = existing | pieces;
661 /* Uphill roads */
662 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
663 (_invalid_straight_roadbits[tileh] & type_bits) == ROAD_NONE) {
664 /* Slopes without foundation */
665 if (!IsSlopeWithOneCornerRaised(tileh)) {
666 if (build != NULL) *build = pieces;
667 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
668 return CommandCost();
671 /* Prevent build on slopes if it isn't allowed */
672 if (_settings_game.construction.build_on_slopes) {
673 if (build != NULL) *build = pieces;
675 /* If we add foundation we've got to pay for it */
676 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
678 return CommandCost();
681 return CMD_ERROR;
685 * Check if a given roadbits set is valid for a road bridge head
686 * @param tileh The slope
687 * @param dir The bridge direction
688 * @param bits The roadbits
689 * @return Whether the given combination is valid
691 bool IsValidRoadBridgeBits(Slope tileh, DiagDirection dir, RoadBits bits)
693 DiagDirDiff diff = CheckExtendedBridgeHead(tileh, dir);
695 switch (diff) {
696 case DIAGDIRDIFF_SAME: return true;
697 case DIAGDIRDIFF_REVERSE: return false;
698 default: return (bits & DiagDirToRoadBits(ChangeDiagDir(dir, diff))) == 0;
703 * Build a piece of road, clearing the land if necessary
704 * @param tile tile where to build road
705 * @param flags operation to perform
706 * @param rt roadtype to build
707 * @param pieces roadbits to build
708 * @param company company building the road
709 * @param town owner/closest town
710 * @param drd directions to disallow
711 * @return the cost of this operation or an error
713 static CommandCost BuildRoad_Clear(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
715 CommandCost cost(EXPENSES_CONSTRUCTION);
717 CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
718 if (ret.Failed()) return ret;
719 cost.AddCost(ret);
721 Slope tileh = GetTileSlope(tile);
723 /* Check the foundation/slopes when adding road/tram bits */
724 ret = CheckRoadSlope(tileh, pieces, ROAD_NONE, ROAD_NONE, &pieces);
725 /* Return an error if we need to build a foundation (ret != 0) but the
726 * current setting is turned off */
727 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
728 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
730 cost.AddCost(ret);
732 uint num_pieces = CountBits(pieces);
733 cost.AddCost(num_pieces * _price[PR_BUILD_ROAD]);
735 if (flags & DC_EXEC) {
736 MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), town, company, company);
738 /* Update company infrastructure count. */
739 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
740 if (c != NULL) {
741 c->infrastructure.road[rt] += num_pieces;
742 DirtyCompanyInfrastructureWindows(c->index);
745 if (rt != ROADTYPE_TRAM && IsStraightRoad(pieces)) {
746 SetDisallowedRoadDirections(tile, drd);
749 MarkTileDirtyByTile(tile);
752 return cost;
756 * Build a piece of road on a road tile
757 * @param tile tile where to build road
758 * @param flags operation to perform
759 * @param rt roadtype to build
760 * @param pieces roadbits to build
761 * @param company company building the road
762 * @param town owner/closest town
763 * @param toggle_drd directions to toggle disallow
764 * @return the cost of this operation or an error
766 static CommandCost BuildRoad_Road(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections toggle_drd)
768 if (HasRoadWorks(tile)) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
770 RoadBits existing = ROAD_NONE;
772 if (HasTileRoadType(tile, rt)) {
773 existing = GetRoadBits(tile, rt);
774 bool crossing = !IsStraightRoad(existing | pieces);
776 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
777 /* Junctions cannot be one-way */
778 return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
781 if ((existing & pieces) == pieces) {
782 /* We only want to set the (dis)allowed road directions */
783 if (toggle_drd == DRD_NONE || rt == ROADTYPE_TRAM) {
784 return_cmd_error(STR_ERROR_ALREADY_BUILT);
787 if (crossing) return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
789 Owner owner = GetRoadOwner(tile, ROADTYPE_ROAD);
790 if (owner != OWNER_NONE) {
791 CommandCost ret = CheckOwnership(owner, tile);
792 if (ret.Failed()) return ret;
795 DisallowedRoadDirections dis_existing = GetDisallowedRoadDirections(tile);
796 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
798 /* We allow removing disallowed directions to break up
799 * deadlocks, but adding them can break articulated
800 * vehicles. As such, only when less is disallowed,
801 * i.e. bits are removed, we skip the vehicle check. */
802 if (CountBits(dis_existing) <= CountBits(dis_new)) {
803 StringID str = CheckVehicleOnGround (tile);
804 if (str != STR_NULL) return_cmd_error(str);
807 /* Ignore half built tiles */
808 if ((flags & DC_EXEC) && rt != ROADTYPE_TRAM && IsStraightRoad(existing)) {
809 SetDisallowedRoadDirections(tile, dis_new);
810 MarkTileDirtyByTile(tile);
813 return CommandCost();
816 /* Disallow breaking end-of-line of someone else
817 * so trams can still reverse on this tile. */
818 if (rt == ROADTYPE_TRAM && HasExactlyOneBit (existing)) {
819 Owner owner = GetRoadOwner (tile, ROADTYPE_TRAM);
820 if (owner != OWNER_NONE) {
821 CommandCost ret = CheckOwnership (owner);
822 if (ret.Failed()) return ret;
827 CommandCost cost(EXPENSES_CONSTRUCTION);
829 RoadBits other_bits = GetOtherRoadBits(tile, rt);
831 Slope tileh = GetTileSlope(tile);
833 if (other_bits != pieces) {
834 /* Check the foundation/slopes when adding road/tram bits */
835 CommandCost ret = CheckRoadSlope(tileh, pieces, existing, other_bits, &pieces);
836 /* Return an error if we need to build a foundation (ret != 0) but the
837 * current setting is turned off */
838 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
839 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
841 cost.AddCost(ret);
844 /* Don't put the pieces that already exist */
845 pieces &= ComplementRoadBits(existing);
847 /* Check if new road bits will have the same foundation as other existing road types */
848 Foundation found_new = GetRoadFoundation(tileh, pieces | existing);
850 /* Test if all other roadtypes can be built at that foundation */
851 for (RoadType rtest = ROADTYPE_ROAD; rtest < ROADTYPE_END; rtest++) {
852 if (rtest != rt) { // check only other road types
853 RoadBits bits = GetRoadBits(tile, rtest);
854 /* do not check if there are not road bits of given type */
855 if (bits != ROAD_NONE && GetRoadFoundation(tileh, bits) != found_new) {
856 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
861 StringID str = CheckVehicleOnGround (tile);
862 if (str != STR_NULL) return_cmd_error(str);
864 uint num_pieces = CountBits(pieces);
865 cost.AddCost(num_pieces * _price[PR_BUILD_ROAD]);
867 if (flags & DC_EXEC) {
868 if (existing == ROAD_NONE) {
869 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
870 SetRoadOwner(tile, rt, company);
871 if (rt == ROADTYPE_ROAD) SetTownIndex(tile, town);
874 SetRoadBits(tile, existing | pieces, rt);
876 /* Update company infrastructure count. */
877 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
878 if (c != NULL) {
879 c->infrastructure.road[rt] += num_pieces;
880 DirtyCompanyInfrastructureWindows(c->index);
883 if (rt != ROADTYPE_TRAM) {
884 SetDisallowedRoadDirections(tile, IsStraightRoad(existing | pieces) ?
885 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
888 MarkTileDirtyByTile(tile);
891 return cost;
895 * Build a piece of road on a bridge tile
896 * @param tile tile where to build road
897 * @param flags operation to perform
898 * @param rt roadtype to build
899 * @param pieces roadbits to build
900 * @param company company building the road
901 * @param town owner/closest town
902 * @param drd directions to disallow
903 * @return the cost of this operation or an error
905 static CommandCost BuildRoad_Bridge(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
907 DiagDirection dir = GetTunnelBridgeDirection(tile);
908 Slope tileh = GetTileSlope(tile);
909 uint num;
910 bool other_end;
912 if (HasBridgeFlatRamp(tileh, DiagDirToAxis(dir))) {
913 RoadBits existing = GetRoadBits(tile, rt);
914 pieces &= ~existing;
915 if (pieces == ROAD_NONE) return_cmd_error(STR_ERROR_ALREADY_BUILT);
917 if (!IsValidRoadBridgeBits(tileh, dir, existing | pieces)) {
918 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
921 /* Disallow breaking end-of-line of someone else
922 * so trams can still reverse on this tile. */
923 if (rt == ROADTYPE_TRAM && HasExactlyOneBit (existing)) {
924 Owner owner = GetRoadOwner (tile, ROADTYPE_TRAM);
925 if (owner != OWNER_NONE) {
926 CommandCost ret = CheckOwnership (owner);
927 if (ret.Failed()) return ret;
931 num = CountBits(pieces);
932 other_end = (pieces & DiagDirToRoadBits(dir)) != 0;
933 pieces |= existing;
934 } else {
935 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
936 if (pieces != DiagDirToRoadBits(ReverseDiagDir(dir))) {
937 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
940 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
942 pieces = AxisToRoadBits(DiagDirToAxis(dir));
943 num = 2;
944 other_end = true;
947 TileIndex other_tile;
948 RoadBits other_pieces;
950 if (other_end) {
951 other_tile = GetOtherBridgeEnd(tile);
953 /* Don't allow adding roadtype to the bridge when vehicles are already driving on it */
954 CommandCost ret = TunnelBridgeIsFree(tile, other_tile);
955 if (ret.Failed()) return ret;
957 /* Don't allow to mix owners */
958 CompanyID new_owner = HasTileRoadType(tile, rt) ? GetRoadOwner(tile, rt) : company;
959 CompanyID other_owner = HasTileRoadType(other_tile, rt) ? GetRoadOwner(other_tile, rt) : company;
960 if (new_owner != other_owner) return CMD_ERROR;
962 num += 2 * GetTunnelBridgeLength(tile, other_tile);
964 if (IsExtendedRoadBridge(other_tile)) {
965 other_pieces = GetRoadBits(other_tile, rt) | DiagDirToRoadBits(ReverseDiagDir(dir));
966 num++;
967 } else {
968 assert(GetRoadBits(other_tile, rt) == ROAD_NONE);
969 other_pieces = AxisToRoadBits(DiagDirToAxis(dir));
970 num += 2;
972 } else {
973 StringID str = CheckVehicleOnGround (tile);
974 if (str != STR_NULL) return_cmd_error(str);
977 if (flags & DC_EXEC) {
978 if (other_end) {
979 /* Update company infrastructure count. */
980 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
981 if (c != NULL) {
982 uint existing = CountBits(GetRoadBits(tile, rt)) + CountBits(GetRoadBits(other_tile, rt));
983 c->infrastructure.road[rt] -= existing;
984 c->infrastructure.road[rt] += (existing + num) * TUNNELBRIDGE_TRACKBIT_FACTOR;
985 DirtyCompanyInfrastructureWindows(c->index);
988 if (!HasTileRoadType(other_tile, rt)) {
989 SetRoadTypes(other_tile, GetRoadTypes(other_tile) | RoadTypeToRoadTypes(rt));
990 SetRoadOwner(other_tile, rt, company);
992 SetRoadBits(other_tile, other_pieces, rt);
994 MarkBridgeTilesDirty(tile, other_tile, dir, false);
995 } else {
996 /* Update company infrastructure count. */
997 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
998 if (c != NULL) {
999 c->infrastructure.road[rt] += (pieces & DiagDirToRoadBits(dir)) != 0 ? num * TUNNELBRIDGE_TRACKBIT_FACTOR : num;
1000 DirtyCompanyInfrastructureWindows(c->index);
1004 if (!HasTileRoadType(tile, rt)) {
1005 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1006 SetRoadOwner(tile, rt, company);
1008 SetRoadBits(tile, pieces, rt);
1009 MarkTileDirtyByTile(tile);
1012 return CommandCost(EXPENSES_CONSTRUCTION, num * _price[PR_BUILD_ROAD]);
1016 * Build a piece of road on a crossing tile
1017 * @param tile tile where to build road
1018 * @param flags operation to perform
1019 * @param rt roadtype to build
1020 * @param pieces roadbits to build
1021 * @param company company building the road
1022 * @param town owner/closest town
1023 * @param drd directions to disallow
1024 * @return the cost of this operation or an error
1026 static CommandCost BuildRoad_Crossing(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1028 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
1029 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1032 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1034 StringID str = CheckVehicleOnGround (tile);
1035 if (str != STR_NULL) return_cmd_error(str);
1037 if (flags & DC_EXEC) {
1038 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1039 SetRoadOwner(tile, rt, company);
1040 if (rt == ROADTYPE_ROAD) SetTownIndex(tile, town);
1042 /* Update company infrastructure count. */
1043 Company *c = Company::GetIfValid(company);
1044 if (c != NULL) {
1045 c->infrastructure.road[rt] += 2;
1046 DirtyCompanyInfrastructureWindows(c->index);
1049 MarkTileDirtyByTile(tile);
1052 return CommandCost(EXPENSES_CONSTRUCTION, 2 * _price[PR_BUILD_ROAD]);
1056 * Build a piece of road on a railway tile
1057 * @param tile tile where to build road
1058 * @param flags operation to perform
1059 * @param rt roadtype to build
1060 * @param pieces roadbits to build
1061 * @param company company building the road
1062 * @param town owner/closest town
1063 * @param drd directions to disallow
1064 * @return the cost of this operation or an error
1066 static CommandCost BuildRoad_Railway(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1068 Slope tileh = GetTileSlope(tile);
1070 if (!IsTileSubtype(tile, TT_TRACK)) goto do_clear;
1072 /* Level crossings may only be built on these slopes */
1073 if (IsSteepSlope(tileh) || !HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
1074 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
1077 if (RailNoLevelCrossings(GetRailType(tile))) {
1078 return_cmd_error(STR_ERROR_CROSSING_DISALLOWED);
1081 if (HasSignalOnTrack(tile, TRACK_UPPER)) goto do_clear;
1083 Axis roaddir;
1084 switch (GetTrackBits(tile)) {
1085 case TRACK_BIT_X:
1086 if (pieces & ROAD_X) goto do_clear;
1087 roaddir = AXIS_Y;
1088 break;
1090 case TRACK_BIT_Y:
1091 if (pieces & ROAD_Y) goto do_clear;
1092 roaddir = AXIS_X;
1093 break;
1095 default:
1096 do_clear:
1097 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1100 StringID str = CheckVehicleOnGround (tile);
1101 if (str != STR_NULL) return_cmd_error(str);
1103 if (flags & DC_EXEC) {
1104 YapfNotifyTrackLayoutChange();
1105 /* Update company infrastructure counts. A level crossing has two road bits. */
1106 Company *c = Company::GetIfValid(company);
1107 if (c != NULL) {
1108 c->infrastructure.road[rt] += 2;
1109 if (rt != ROADTYPE_ROAD) c->infrastructure.road[ROADTYPE_ROAD] += 2;
1110 DirtyCompanyInfrastructureWindows(company);
1112 /* Update rail count for level crossings. The plain track is already
1113 * counted, so only add the difference to the level crossing cost. */
1114 c = Company::GetIfValid(GetTileOwner(tile));
1115 if (c != NULL) {
1116 c->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR - 1;
1117 DirtyCompanyInfrastructureWindows(c->index);
1120 /* Always add road to the roadtypes (can't draw without it) */
1121 bool reserved = GetRailReservationTrackBits (tile) != TRACK_BIT_NONE;
1122 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, town);
1123 SetCrossingReservation(tile, reserved);
1124 UpdateLevelCrossing(tile, false);
1125 MarkTileDirtyByTile(tile);
1128 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_ROAD] * (rt == ROADTYPE_ROAD ? 2 : 4));
1132 * Build a piece of road on a tunnel tile
1133 * @param tile tile where to build road
1134 * @param flags operation to perform
1135 * @param rt roadtype to build
1136 * @param pieces roadbits to build
1137 * @param company company building the road
1138 * @param town owner/closest town
1139 * @param drd directions to disallow
1140 * @return the cost of this operation or an error
1142 static CommandCost BuildRoad_Tunnel(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1144 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
1145 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD || pieces != DiagDirToRoadBits(ReverseDiagDir(GetTunnelBridgeDirection(tile)))) {
1146 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1149 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1151 TileIndex other_end = GetOtherTunnelEnd(tile);
1153 /* Don't allow adding roadtype to the tunnel when vehicles are already driving on it */
1154 CommandCost ret = TunnelBridgeIsFree(tile, other_end);
1155 if (ret.Failed()) return ret;
1157 /* There are 2 pieces on *every* tile of the tunnel */
1158 uint num_pieces = 2 * (GetTunnelBridgeLength(tile, other_end) + 2);
1160 if (flags & DC_EXEC) {
1161 SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt));
1162 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1163 SetRoadOwner(other_end, rt, company);
1164 SetRoadOwner(tile, rt, company);
1166 /* Mark tiles dirty that have been repaved */
1167 MarkTileDirtyByTile(other_end);
1168 MarkTileDirtyByTile(tile);
1170 /* Update company infrastructure count. */
1171 Company *c = Company::GetIfValid(company);
1172 if (c != NULL) {
1173 c->infrastructure.road[rt] += num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR;
1174 DirtyCompanyInfrastructureWindows(c->index);
1178 return CommandCost(EXPENSES_CONSTRUCTION, num_pieces * _price[PR_BUILD_ROAD]);
1182 * Build a piece of road on a station tile
1183 * @param tile tile where to build road
1184 * @param flags operation to perform
1185 * @param rt roadtype to build
1186 * @param pieces roadbits to build
1187 * @param company company building the road
1188 * @param town owner/closest town
1189 * @param drd directions to disallow
1190 * @return the cost of this operation or an error
1192 static CommandCost BuildRoad_Station(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1194 if ((GetAnyRoadBits(tile, rt) & pieces) == pieces) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1196 if (!IsDriveThroughStopTile(tile) || (pieces & ~AxisToRoadBits(GetRoadStopAxis(tile)))) {
1197 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1200 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1202 StringID str = CheckVehicleOnGround (tile);
1203 if (str != STR_NULL) return_cmd_error(str);
1205 if (flags & DC_EXEC) {
1206 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1207 SetRoadOwner(tile, rt, company);
1209 /* Update company infrastructure count. */
1210 Company *c = Company::GetIfValid(company);
1211 if (c != NULL) {
1212 c->infrastructure.road[rt] += 2;
1213 DirtyCompanyInfrastructureWindows(c->index);
1216 MarkTileDirtyByTile(tile);
1219 return CommandCost(EXPENSES_CONSTRUCTION, 2 * _price[PR_BUILD_ROAD]);
1223 * Build a piece of road.
1224 * @param tile tile where to build road
1225 * @param flags operation to perform
1226 * @param p1 bit 0..3 road pieces to build (RoadBits)
1227 * bit 4..5 road type
1228 * bit 6..7 disallowed directions to toggle
1229 * @param p2 the town that is building the road (0 if not applicable)
1230 * @param text unused
1231 * @return the cost of this operation or an error
1233 CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1235 CompanyID company = _current_company;
1237 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
1238 * if a non-company is building the road */
1239 if (company == OWNER_TOWN) {
1240 if (!Town::IsValidID(p2)) return CMD_ERROR;
1241 } else {
1242 if (p2 != 0) return CMD_ERROR;
1244 const Town *town = CalcClosestTownFromTile(tile);
1245 p2 = (town != NULL) ? town->index : (TownID)INVALID_TOWN;
1247 if (company == OWNER_DEITY) {
1248 company = OWNER_TOWN;
1250 /* If we are not within a town, we are not owned by the town */
1251 if (town == NULL || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
1252 company = OWNER_NONE;
1257 RoadBits pieces = Extract<RoadBits, 0, 4>(p1);
1259 /* do not allow building 'zero' road bits, code wouldn't handle it */
1260 if (pieces == ROAD_NONE) return CMD_ERROR;
1262 RoadType rt = Extract<RoadType, 4, 2>(p1);
1263 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1265 DisallowedRoadDirections toggle_drd = Extract<DisallowedRoadDirections, 6, 2>(p1);
1267 switch (GetTileType(tile)) {
1268 case TT_ROAD:
1269 if (IsTileSubtype(tile, TT_BRIDGE)) {
1270 return BuildRoad_Bridge(tile, flags, rt, pieces, company, p2, toggle_drd);
1271 } else {
1272 return BuildRoad_Road(tile, flags, rt, pieces, company, p2, toggle_drd);
1275 case TT_RAILWAY:
1276 return BuildRoad_Railway(tile, flags, rt, pieces, company, p2, toggle_drd);
1278 case TT_STATION:
1279 return BuildRoad_Station(tile, flags, rt, pieces, company, p2, toggle_drd);
1281 case TT_MISC:
1282 switch (GetTileSubtype(tile)) {
1283 case TT_MISC_CROSSING:
1284 return BuildRoad_Crossing(tile, flags, rt, pieces, company, p2, toggle_drd);
1286 case TT_MISC_TUNNEL:
1287 return BuildRoad_Tunnel(tile, flags, rt, pieces, company, p2, toggle_drd);
1289 case TT_MISC_DEPOT:
1290 if (IsRoadDepot(tile) && (GetAnyRoadBits(tile, rt) & pieces) == pieces) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1291 /* fall through */
1292 default:
1293 break;
1295 /* fall through */
1296 default:
1297 return BuildRoad_Clear(tile, flags, rt, pieces, company, p2, toggle_drd);
1302 * Checks whether a road or tram connection can be found when building a new road or tram.
1303 * @param tile Tile at which the road being built will end.
1304 * @param rt Roadtype of the road being built.
1305 * @param dir Direction that the road is following.
1306 * @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.
1308 static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
1310 RoadBits bits = GetAnyRoadBits(tile + TileOffsByDiagDir(dir), rt, false);
1311 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
1315 * Build a long piece of road.
1316 * @param start_tile start tile of drag (the building cost will appear over this tile)
1317 * @param flags operation to perform
1318 * @param p1 end tile of drag
1319 * @param p2 various bitstuffed elements
1320 * - 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
1321 * - 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
1322 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1323 * - p2 = (bit 3 + 4) - road type
1324 * - p2 = (bit 5) - set road direction
1325 * - p2 = (bit 6) - defines two different behaviors for this command:
1326 * - 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
1327 * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
1328 * @param text unused
1329 * @return the cost of this operation or an error
1331 CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1333 DisallowedRoadDirections drd = DRD_NORTHBOUND;
1335 if (p1 >= MapSize()) return CMD_ERROR;
1337 TileIndex end_tile = p1;
1338 RoadType rt = Extract<RoadType, 3, 2>(p2);
1339 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1341 Axis axis = Extract<Axis, 2, 1>(p2);
1342 /* Only drag in X or Y direction dictated by the direction variable */
1343 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
1344 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
1346 DiagDirection dir = AxisToDiagDir(axis);
1348 /* Swap direction, also the half-tile drag var (bit 0 and 1) */
1349 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
1350 dir = ReverseDiagDir(dir);
1351 p2 ^= 3;
1352 drd = DRD_SOUTHBOUND;
1355 /* On the X-axis, we have to swap the initial bits, so they
1356 * will be interpreted correctly in the GTTS. Furthermore
1357 * when you just 'click' on one tile to build them. */
1358 if ((axis == AXIS_Y) == (start_tile == end_tile && HasBit(p2, 0) == HasBit(p2, 1))) drd ^= DRD_BOTH;
1359 /* No disallowed direction bits have to be toggled */
1360 if (!HasBit(p2, 5)) drd = DRD_NONE;
1362 CommandCost cost(EXPENSES_CONSTRUCTION);
1363 CommandCost last_error = CMD_ERROR;
1364 TileIndex tile = start_tile;
1365 bool had_bridge = false;
1366 bool had_tunnel = false;
1367 bool had_success = false;
1368 bool is_ai = HasBit(p2, 6);
1370 /* Start tile is the first tile clicked by the user. */
1371 for (;;) {
1372 RoadBits bits = AxisToRoadBits(axis);
1374 /* Determine which road parts should be built. */
1375 if (!is_ai && start_tile != end_tile) {
1376 /* Only build the first and last roadbit if they can connect to something. */
1377 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1378 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1379 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1380 bits = DiagDirToRoadBits(dir);
1382 } else {
1383 /* Road parts only have to be built at the start tile or at the end tile. */
1384 if (tile == end_tile && !HasBit(p2, 1)) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1385 if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir);
1388 CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
1389 if (ret.Failed()) {
1390 last_error = ret;
1391 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1392 if (is_ai) return last_error;
1393 break;
1395 } else {
1396 had_success = true;
1397 /* Only pay for the upgrade on one side of the bridges and tunnels */
1398 if (IsTunnelTile(tile)) {
1399 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1400 cost.AddCost(ret);
1402 had_tunnel = true;
1403 } else if (IsRoadBridgeTile(tile)) {
1404 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1405 cost.AddCost(ret);
1407 had_bridge = true;
1408 } else {
1409 cost.AddCost(ret);
1413 if (tile == end_tile) break;
1415 tile += TileOffsByDiagDir(dir);
1418 return had_success ? cost : last_error;
1422 * Remove a long piece of road.
1423 * @param start_tile start tile of drag
1424 * @param flags operation to perform
1425 * @param p1 end tile of drag
1426 * @param p2 various bitstuffed elements
1427 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
1428 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
1429 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1430 * - p2 = (bit 3 + 4) - road type
1431 * @param text unused
1432 * @return the cost of this operation or an error
1434 CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1436 CommandCost cost(EXPENSES_CONSTRUCTION);
1438 if (p1 >= MapSize()) return CMD_ERROR;
1440 TileIndex end_tile = p1;
1441 RoadType rt = Extract<RoadType, 3, 2>(p2);
1442 if (!IsValidRoadType(rt)) return CMD_ERROR;
1444 Axis axis = Extract<Axis, 2, 1>(p2);
1445 /* Only drag in X or Y direction dictated by the direction variable */
1446 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
1447 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
1449 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
1450 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
1451 TileIndex t = start_tile;
1452 start_tile = end_tile;
1453 end_tile = t;
1454 p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0;
1457 Money money = GetAvailableMoneyForCommand();
1458 TileIndex tile = start_tile;
1459 CommandCost last_error = CMD_ERROR;
1460 bool had_success = false;
1461 /* Start tile is the small number. */
1462 for (;;) {
1463 RoadBits bits = AxisToRoadBits(axis);
1465 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
1466 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
1468 /* try to remove the halves. */
1469 if (bits != 0) {
1470 CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
1471 if (ret.Succeeded()) {
1472 if (flags & DC_EXEC) {
1473 money -= ret.GetCost();
1474 if (money < 0) {
1475 _additional_cash_required = DoCommand(start_tile, end_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
1476 return cost;
1478 RemoveRoad(tile, flags, bits, rt, true, false);
1480 cost.AddCost(ret);
1481 had_success = true;
1482 } else {
1483 /* Ownership errors are more important. */
1484 if (last_error.GetErrorMessage() != STR_ERROR_OWNED_BY) last_error = ret;
1488 if (tile == end_tile) break;
1490 tile += (axis == AXIS_Y) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
1493 return had_success ? cost : last_error;
1497 * Build a road depot.
1498 * @param tile tile where to build the depot
1499 * @param flags operation to perform
1500 * @param p1 bit 0..1 entrance direction (DiagDirection)
1501 * bit 2..3 road type
1502 * @param p2 unused
1503 * @param text unused
1504 * @return the cost of this operation or an error
1506 * @todo When checking for the tile slope,
1507 * distinguish between "Flat land required" and "land sloped in wrong direction"
1509 CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1511 DiagDirection dir = Extract<DiagDirection, 0, 2>(p1);
1512 RoadType rt = Extract<RoadType, 2, 2>(p1);
1514 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1516 Slope tileh = GetTileSlope(tile);
1517 if (tileh != SLOPE_FLAT && (
1518 !_settings_game.construction.build_on_slopes ||
1519 !CanBuildDepotByTileh(dir, tileh)
1520 )) {
1521 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
1524 CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1525 if (cost.Failed()) return cost;
1527 if (HasBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1529 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1531 if (flags & DC_EXEC) {
1532 Depot *dep = new Depot(tile);
1533 dep->build_date = _date;
1535 /* A road depot has two road bits. */
1536 Company::Get(_current_company)->infrastructure.road[rt] += 2;
1537 DirtyCompanyInfrastructureWindows(_current_company);
1539 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1540 MarkTileDirtyByTile(tile);
1541 MakeDefaultName(dep);
1543 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
1544 return cost;
1547 static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlag flags)
1549 if (IsTileSubtype(tile, TT_TRACK)) {
1550 RoadBits b = GetAllRoadBits(tile);
1552 /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
1553 if ((HasExactlyOneBit(b) && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || !(flags & DC_AUTO)) {
1554 CommandCost ret(EXPENSES_CONSTRUCTION);
1555 RoadType rt;
1556 FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1557 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
1558 if (tmp_ret.Failed()) return tmp_ret;
1559 ret.AddCost(tmp_ret);
1561 return ret;
1564 return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1565 } else {
1566 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1568 /* Floods can remove anything as well as the scenario editor */
1570 if (_current_company != OWNER_WATER && _game_mode != GM_EDITOR) {
1571 RoadTypes rts = GetRoadTypes(tile);
1572 Owner road_owner = _current_company;
1573 if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
1575 /* We can remove unowned road and if the town allows it */
1576 if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
1577 /* Town does not allow */
1578 CommandCost ret = CheckTileOwnership(tile);
1579 if (ret.Failed()) return ret;
1580 } else {
1581 if (road_owner != OWNER_NONE && road_owner != OWNER_TOWN) {
1582 CommandCost ret = CheckOwnership(road_owner, tile);
1583 if (ret.Failed()) return ret;
1586 if (HasBit(rts, ROADTYPE_TRAM)) {
1587 Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
1588 if (tram_owner != OWNER_NONE) {
1589 CommandCost ret = CheckOwnership(tram_owner, tile);
1590 if (ret.Failed()) return ret;
1596 TileIndex endtile = GetOtherBridgeEnd(tile);
1598 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
1599 if (ret.Failed()) return ret;
1601 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
1602 Town *t = ClosestTownFromTile(tile); // town penalty rating
1604 /* Check if you are allowed to remove the bridge owned by a town
1605 * Removal depends on difficulty settings */
1606 CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
1607 if (ret.Failed()) return ret;
1609 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
1610 * you have a "Poor" (0) town rating */
1611 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
1614 uint len = GetTunnelBridgeLength(tile, endtile);
1616 if (flags & DC_EXEC) {
1617 RemoveBridgeMiddleTiles(tile, endtile);
1619 DiagDirection dir = GetTunnelBridgeDirection(tile);
1620 RoadBits bridge_piece = DiagDirToRoadBits(dir);
1621 RoadBits other_nonbridge_pieces = ComplementRoadBits(DiagDirToRoadBits(ReverseDiagDir(dir)));
1622 bool other_extended = IsExtendedRoadBridge(endtile);
1624 MakeNormalRoadFromBridge(endtile);
1626 RoadType rt;
1627 FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1628 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
1629 RoadBits pieces = GetRoadBits(tile, rt);
1631 if ((pieces & bridge_piece) == 0) {
1632 /* This roadtype does not connect to the bridge */
1633 if (c != NULL) {
1634 c->infrastructure.road[rt] -= CountBits(pieces);
1635 DirtyCompanyInfrastructureWindows(c->index);
1637 } else {
1638 /* This roadtype connects to the bridge */
1639 RoadBits other_pieces = GetRoadBits(endtile, rt);
1641 if (c != NULL) {
1642 /* A full diagonal road tile has two road bits. */
1643 c->infrastructure.road[rt] -= (CountBits(pieces) + 2 * len + CountBits(other_pieces)) * TUNNELBRIDGE_TRACKBIT_FACTOR;
1644 DirtyCompanyInfrastructureWindows(c->index);
1647 if (other_extended && ((other_pieces &= other_nonbridge_pieces) != 0)) {
1648 SetRoadBits(endtile, other_pieces, rt);
1649 if (c != NULL) c->infrastructure.road[rt] += CountBits(other_pieces);
1650 } else {
1651 ClearRoadType(endtile, rt);
1657 DoClearSquare(tile);
1658 MarkTileDirtyByTile(endtile);
1661 return CommandCost(EXPENSES_CONSTRUCTION, (len + 2) * _price[PR_CLEAR_BRIDGE]);
1667 * Get the foundationtype of a RoadBits Slope combination
1669 * @param tileh The Slope part
1670 * @param bits The RoadBits part
1671 * @return The resulting Foundation
1673 static Foundation GetRoadFoundation(Slope tileh, RoadBits bits)
1675 /* Flat land and land without a road doesn't require a foundation */
1676 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1678 /* Steep slopes behave the same as slopes with one corner raised. */
1679 if (IsSteepSlope(tileh)) {
1680 tileh = SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh));
1683 /* Leveled RoadBits on a slope */
1684 if ((_invalid_leveled_roadbits[tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1686 /* Straight roads without foundation on a slope */
1687 if (!IsSlopeWithOneCornerRaised(tileh) &&
1688 (_invalid_straight_roadbits[tileh] & bits) == ROAD_NONE)
1689 return FOUNDATION_NONE;
1691 /* Roads on steep Slopes or on Slopes with one corner raised */
1692 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y);
1695 const byte _road_sloped_sprites[14] = {
1696 0, 0, 2, 0,
1697 0, 1, 0, 0,
1698 3, 0, 0, 0,
1699 0, 0
1703 * Draw the ground sprite for a road tile
1704 * @param ti TileInfo of the tile to draw
1705 * @param roadside The roadside of the tile
1706 * @param image The sprite to draw
1707 * @param paved_offset The offset to add to the sprite if the road is paved
1708 * @param unpaved_offset The offset to add to the sprite if the tile is on snow or in the desert
1709 * @return The palette to use for further drawing
1711 static PaletteID DrawRoadGroundSprite (const TileInfo *ti, Roadside roadside, SpriteID image, int paved_offset, int unpaved_offset)
1713 TileIndex tile = ti->tile;
1714 PaletteID pal = PAL_NONE;
1716 switch (roadside) {
1717 case ROADSIDE_BARREN:
1718 if (IsOnSnow(tile)) {
1719 image += unpaved_offset;
1720 } else {
1721 pal = PALETTE_TO_BARE_LAND;
1723 break;
1725 case ROADSIDE_GRASS:
1726 if (IsOnSnow(tile)) image += unpaved_offset;
1727 break;
1729 default:
1730 if (IsOnSnow(tile) && !(_settings_game.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS))) {
1731 image += unpaved_offset;
1732 } else {
1733 image += paved_offset;
1735 break;
1738 DrawGroundSprite (ti, image, pal);
1740 return pal;
1744 * Draws the catenary for the given tile
1745 * @param ti information about the tile (slopes, height etc)
1746 * @param tram the roadbits for the tram
1748 void DrawRoadCatenary(const TileInfo *ti, RoadBits tram)
1750 /* Do not draw catenary if it is invisible */
1751 if (IsInvisibilitySet(TO_CATENARY)) return;
1753 /* Don't draw the catenary under a low bridge */
1754 if (HasBridgeAbove(ti->tile) && !IsTransparencySet(TO_CATENARY)) {
1755 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1757 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1760 SpriteID front;
1761 SpriteID back;
1763 if (ti->tileh != SLOPE_FLAT) {
1764 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1765 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1766 } else {
1767 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[tram];
1768 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[tram];
1771 AddSortableSpriteToDraw (ti->vd, back, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_CATENARY));
1772 AddSortableSpriteToDraw (ti->vd, front, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_CATENARY));
1776 * Draws details on/around the road
1777 * @param img the sprite to draw
1778 * @param ti the tile to draw on
1779 * @param dx the offset from the top of the BB of the tile
1780 * @param dy the offset from the top of the BB of the tile
1781 * @param h the height of the sprite to draw
1783 static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h)
1785 int x = ti->x | dx;
1786 int y = ti->y | dy;
1787 int z = ti->z;
1788 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1789 AddSortableSpriteToDraw (ti->vd, img, PAL_NONE, x, y, 2, 2, h, z);
1793 * Draw ground sprite and road pieces
1794 * @param ti TileInfo
1796 static void DrawRoadBits(TileInfo *ti)
1798 RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
1799 RoadBits tram = GetRoadBits(ti->tile, ROADTYPE_TRAM);
1801 SpriteID image = 0;
1803 if (IsTileSubtype(ti->tile, TT_BRIDGE)) {
1804 assert(ti->tileh != SLOPE_FLAT);
1805 DrawFoundation(ti, FOUNDATION_LEVELED, GetTunnelBridgeDirection(ti->tile));
1806 } else if (ti->tileh != SLOPE_FLAT) {
1807 Foundation f = GetRoadFoundation(ti->tileh, road | tram);
1809 DrawFoundation(ti, f);
1811 /* DrawFoundation() modifies ti.
1812 * Default sloped sprites.. */
1813 if (ti->tileh != SLOPE_FLAT) image = _road_sloped_sprites[ti->tileh - 1] + SPR_ROAD_SLOPE_START;
1816 if (image == 0) image = _road_tile_sprites_1[road != ROAD_NONE ? road : tram];
1818 Roadside roadside = IsTileSubtype(ti->tile, TT_TRACK) ? GetRoadside(ti->tile) : ROADSIDE_GRASS;
1820 PaletteID pal = DrawRoadGroundSprite (ti, roadside, image, -19, 19);
1822 /* For tram we overlay the road graphics with either tram tracks only
1823 * (when there is actual road beneath the trams) or with tram tracks
1824 * and some dirts which hides the road graphics */
1825 if (tram != ROAD_NONE) {
1826 if (ti->tileh != SLOPE_FLAT) {
1827 image = _road_sloped_sprites[ti->tileh - 1] + SPR_TRAMWAY_SLOPED_OFFSET;
1828 } else {
1829 image = _road_tile_sprites_1[tram] - SPR_ROAD_Y;
1831 image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY;
1832 DrawGroundSprite (ti, image, pal);
1835 if (IsTileSubtype(ti->tile, TT_TRACK) && road != ROAD_NONE) {
1836 DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
1837 if (drd != DRD_NONE) {
1838 DrawGroundSpriteAt (ti, SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1842 if (IsTileSubtype(ti->tile, TT_TRACK) && HasRoadWorks(ti->tile)) {
1843 /* Road works */
1844 DrawGroundSprite (ti, (road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1845 return;
1848 if (tram != ROAD_NONE) DrawRoadCatenary(ti, tram);
1850 if (!IsTileSubtype(ti->tile, TT_TRACK)) return;
1852 /* Return if full detail is disabled, or we are zoomed fully out. */
1853 if (!HasBit(_display_opt, DO_FULL_DETAIL)) return;
1854 if (!IsViewportDrawerDetailed (ti->vd)) return;
1856 /* Do not draw details (street lights, trees) under low bridge */
1857 if (HasBridgeAbove(ti->tile) && (roadside == ROADSIDE_TREES || roadside == ROADSIDE_STREET_LIGHTS)) {
1858 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1859 int minz = GetTileMaxZ(ti->tile) + 2;
1861 if (roadside == ROADSIDE_TREES) minz++;
1863 if (height < minz) return;
1866 /* If there are no road bits, return, as there is nothing left to do */
1867 if (HasAtMostOneBit(road)) return;
1869 /* Draw extra details. */
1870 for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
1871 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10);
1875 /** Tile callback function for rendering a road tile to the screen */
1876 static void DrawTile_Road(TileInfo *ti)
1878 if (IsTileSubtype(ti->tile, TT_TRACK) || IsExtendedRoadBridge(ti->tile)) {
1879 DrawRoadBits(ti);
1880 } else {
1881 DrawBridgeGround(ti);
1883 /* draw ramp */
1885 DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
1887 const PalSpriteID *psid = GetBridgeRampSprite(GetRoadBridgeType(ti->tile), 8, ti->tileh, dir);
1889 /* Draw Trambits as SpriteCombine */
1890 StartSpriteCombine (ti->vd);
1892 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1893 * it doesn't disappear behind it
1895 /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1896 AddSortableSpriteToDraw (ti->vd, psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1898 RoadTypes rts = GetRoadTypes(ti->tile);
1900 if (HasBit(rts, ROADTYPE_TRAM)) {
1901 uint offset = dir;
1902 int z = ti->z;
1903 if (ti->tileh != SLOPE_FLAT) {
1904 offset = (offset + 1) & 1;
1905 z += TILE_HEIGHT;
1906 } else {
1907 offset += 2;
1909 /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1910 DrawBridgeTramBits (ti->vd, ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
1913 EndSpriteCombine (ti->vd);
1916 DrawBridgeMiddle(ti);
1919 #define TILE_SEQ_LINE(img, pal, dx, dy, sx, sy) { dx, dy, 0, sx, sy, 20, {img, pal} }
1920 #define TILE_SEQ_END() { (int8)0x80, 0, 0, 0, 0, 0, {0, 0} }
1922 /* Sprite layout for level crossings. The SpriteIDs are actually offsets
1923 * from the base SpriteID returned from the NewGRF sprite resolver. */
1924 static const DrawTileSeqStruct _crossing_layout[] = {
1925 TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3),
1926 TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3),
1927 TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3),
1928 TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3),
1929 TILE_SEQ_END()
1932 #undef TILE_SEQ_LINE
1933 #undef TILE_SEQ_END
1935 void DrawLevelCrossing(TileInfo *ti)
1937 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
1939 PaletteID pal = PAL_NONE;
1940 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1942 if (rti->UsesOverlay()) {
1943 Axis axis = GetCrossingRailAxis(ti->tile);
1945 DrawRoadGroundSprite (ti, GetRoadside(ti->tile), SPR_ROAD_Y + axis, -19, 19);
1947 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1948 /* Draw tracks, but draw PBS reserved tracks darker. */
1949 pal = (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile)) ? PALETTE_CRASH : PAL_NONE;
1950 DrawGroundSprite (ti, rail, pal);
1952 DrawRailTileSeq (ti, _crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1953 } else {
1954 SpriteID image = rti->base_sprites.crossing;
1956 if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++;
1957 if (IsCrossingBarred(ti->tile)) image += 2;
1959 pal = DrawRoadGroundSprite (ti, GetRoadside(ti->tile), image, 4, 8);
1961 /* PBS debugging, draw reserved tracks darker */
1962 if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile)) {
1963 DrawGroundSprite (ti, GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single[GetCrossingRailTrack(ti->tile)], PALETTE_CRASH);
1967 if (HasTileRoadType(ti->tile, ROADTYPE_TRAM)) {
1968 DrawGroundSprite (ti, SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal);
1969 DrawRoadCatenary(ti, GetCrossingRoadBits(ti->tile));
1972 if (HasRailCatenaryDrawn (rti)) {
1973 DrawRailAxisCatenary (ti, rti, GetCrossingRailAxis (ti->tile));
1976 DrawBridgeMiddle(ti);
1980 * Updates cached nearest town for all road tiles
1981 * @param invalidate are we just invalidating cached data?
1982 * @pre invalidate == true implies _generating_world == true
1984 void UpdateNearestTownForRoadTiles(bool invalidate)
1986 assert(!invalidate || _generating_world);
1988 for (TileIndex t = 0; t < MapSize(); t++) {
1989 if ((IsRoadTile(t) || IsLevelCrossingTile(t)) && !HasTownOwnedRoad(t)) {
1990 TownID tid = (TownID)INVALID_TOWN;
1991 if (!invalidate) {
1992 const Town *town = CalcClosestTownFromTile(t);
1993 if (town != NULL) tid = town->index;
1995 SetTownIndex(t, tid);
2000 static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y)
2002 int z;
2003 Slope tileh = GetTilePixelSlope(tile, &z);
2005 if (IsTileSubtype(tile, TT_TRACK)) {
2006 if (tileh == SLOPE_FLAT) return z;
2007 z += ApplyPixelFoundationToSlope(GetRoadFoundation(tileh, GetAllRoadBits(tile)), &tileh);
2008 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
2009 } else if (IsExtendedRoadBridge(tile)) {
2010 return z + (IsSteepSlope(tileh) ? 2 * TILE_HEIGHT : TILE_HEIGHT);
2011 } else {
2012 x &= 0xF;
2013 y &= 0xF;
2015 DiagDirection dir = GetTunnelBridgeDirection(tile);
2017 z += ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
2019 /* On the bridge ramp? */
2020 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
2021 if (5 <= pos && pos <= 10) {
2022 return z + ((tileh == SLOPE_FLAT) ? GetBridgePartialPixelZ(dir, x, y) : TILE_HEIGHT);
2025 return z + GetPartialPixelZ(x, y, tileh);
2029 static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
2031 return IsTileSubtype(tile, TT_TRACK) ? GetRoadFoundation(tileh, GetAllRoadBits(tile)) :
2032 IsExtendedRoadBridge(tile) ? FOUNDATION_LEVELED :
2033 GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
2036 static const Roadside _town_road_types[][2] = {
2037 { ROADSIDE_GRASS, ROADSIDE_GRASS },
2038 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2039 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2040 { ROADSIDE_TREES, ROADSIDE_TREES },
2041 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
2044 static const Roadside _town_road_types_2[][2] = {
2045 { ROADSIDE_GRASS, ROADSIDE_GRASS },
2046 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2047 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED },
2048 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED },
2049 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
2052 void UpdateRoadSide(TileIndex tile, HouseZonesBits grp)
2054 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2055 const Roadside *new_rs = (_settings_game.game_creation.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp];
2056 Roadside cur_rs = GetRoadside(tile);
2058 /* We have our desired type, do nothing */
2059 if (cur_rs == new_rs[0]) return;
2061 /* We have the pre-type of the desired type, switch to the desired type */
2062 if (cur_rs == new_rs[1]) {
2063 cur_rs = new_rs[0];
2064 /* We have barren land, install the pre-type */
2065 } else if (cur_rs == ROADSIDE_BARREN) {
2066 cur_rs = new_rs[1];
2067 /* We're totally off limits, remove any installation and make barren land */
2068 } else {
2069 cur_rs = ROADSIDE_BARREN;
2072 SetRoadside(tile, cur_rs);
2073 MarkTileDirtyByTile(tile);
2076 static void TileLoop_Road(TileIndex tile)
2078 switch (_settings_game.game_creation.landscape) {
2079 case LT_ARCTIC: {
2080 int z = IsTileSubtype(tile, TT_TRACK) ? GetTileZ(tile) : GetTileMaxZ(tile);
2081 if (IsOnSnow(tile) != (z > GetSnowLine())) {
2082 ToggleSnow(tile);
2083 MarkTileDirtyByTile(tile);
2085 break;
2088 case LT_TROPIC:
2089 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
2090 ToggleDesert(tile);
2091 MarkTileDirtyByTile(tile);
2093 break;
2096 if (!IsTileSubtype(tile, TT_TRACK)) return;
2098 const Town *t = ClosestTownFromTile(tile);
2099 if (!HasRoadWorks(tile)) {
2100 HouseZonesBits grp = HZB_TOWN_EDGE;
2102 if (t != NULL) {
2103 grp = GetTownRadiusGroup(t, tile);
2105 /* Show an animation to indicate road work */
2106 if (t->road_build_months != 0 &&
2107 (DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) &&
2108 !HasAtMostOneBit(GetAllRoadBits(tile)) &&
2109 GetFoundationSlope(tile) == SLOPE_FLAT &&
2110 CheckVehicleOnGround(tile) == STR_NULL &&
2111 Chance16(1, 40)) {
2112 StartRoadWorks(tile);
2113 /* Remove any trees or lamps in case or roadwork */
2114 switch (GetRoadside(tile)) {
2115 case ROADSIDE_BARREN:
2116 case ROADSIDE_GRASS: SetRoadside(tile, ROADSIDE_GRASS); break;
2117 default: SetRoadside(tile, ROADSIDE_PAVED); break;
2120 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_JACKHAMMER, tile);
2121 CreateEffectVehicleAbove(
2122 TileX(tile) * TILE_SIZE + 7,
2123 TileY(tile) * TILE_SIZE + 7,
2125 EV_BULLDOZER);
2126 MarkTileDirtyByTile(tile);
2127 return;
2131 UpdateRoadSide(tile, grp);
2132 } else if (DecreaseRoadWorksCounter(tile)) {
2133 if (_settings_game.economy.mod_road_rebuild) {
2134 /* Generate a nicer town surface */
2135 const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
2136 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2138 if (old_rb != new_rb) {
2139 RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true);
2143 MarkTileDirtyByTile(tile);
2147 static bool ClickTile_Road(TileIndex tile)
2149 return false;
2152 static TrackStatus GetTileRoadStatus_Road(TileIndex tile, uint sub_mode, DiagDirection side)
2154 /* Converts RoadBits to TrackdirBits */
2155 static const TrackdirBits road_trackdirbits[16] = {
2156 TRACKDIR_BIT_NONE, // ROAD_NONE
2157 TRACKDIR_BIT_NONE, // ROAD_NW
2158 TRACKDIR_BIT_NONE, // ROAD_SW
2159 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_LEFT_N, // ROAD_W
2160 TRACKDIR_BIT_NONE, // ROAD_SE
2161 TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_Y_NW, // ROAD_Y
2162 TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LOWER_W, // ROAD_S
2163 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE
2164 | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_Y_NW, // ROAD_Y | ROAD_SW
2165 TRACKDIR_BIT_NONE, // ROAD_NE
2166 TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_UPPER_W, // ROAD_N
2167 TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW, // ROAD_X
2168 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_X_NE
2169 | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_X_SW, // ROAD_X | ROAD_NW
2170 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_RIGHT_N, // ROAD_E
2171 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_Y_SE
2172 | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_Y_NW, // ROAD_Y | ROAD_NE
2173 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_X_NE
2174 | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_X_SW, // ROAD_X | ROAD_SE
2175 TRACKDIR_BIT_MASK, // ROAD_ALL
2178 static const uint drd_mask[DRD_END] = { 0xFFFF, 0xFF00, 0xFF, 0x0 };
2180 if ((GetRoadTypes(tile) & sub_mode) == 0) return 0;
2182 if (IsTileSubtype(tile, TT_TRACK)) {
2183 if (HasRoadWorks(tile)) return 0;
2184 } else {
2185 if (side == GetTunnelBridgeDirection(tile)) return 0;
2188 RoadType rt = (RoadType)FindFirstBit(sub_mode);
2189 RoadBits bits = GetRoadBits(tile, rt);
2191 /* no roadbit at this side of tile, return 0 */
2192 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) return 0;
2194 TrackdirBits trackdirbits = road_trackdirbits[bits];
2195 if (IsTileSubtype(tile, TT_TRACK) && rt == ROADTYPE_ROAD) trackdirbits &= (TrackdirBits)drd_mask[GetDisallowedRoadDirections(tile)];
2197 return CombineTrackStatus(trackdirbits, TRACKDIR_BIT_NONE);
2200 static const StringID _road_tile_strings[] = {
2201 STR_LAI_ROAD_DESCRIPTION_ROAD,
2202 STR_LAI_ROAD_DESCRIPTION_ROAD,
2203 STR_LAI_ROAD_DESCRIPTION_ROAD,
2204 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2205 STR_LAI_ROAD_DESCRIPTION_ROAD,
2206 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2207 STR_LAI_ROAD_DESCRIPTION_ROAD,
2208 STR_LAI_ROAD_DESCRIPTION_ROAD,
2211 static void GetTileDesc_Road(TileIndex tile, TileDesc *td)
2213 RoadTypes rts = GetRoadTypes(tile);
2215 Owner tram_owner = INVALID_OWNER;
2216 if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
2218 if (IsTileSubtype(tile, TT_TRACK)) {
2219 if (!HasBit(rts, ROADTYPE_ROAD)) {
2220 td->str = STR_LAI_ROAD_DESCRIPTION_TRAMWAY;
2221 td->owner[0] = tram_owner;
2222 return;
2224 td->str = _road_tile_strings[GetRoadside(tile)];
2225 } else {
2226 const BridgeSpec *spec = GetBridgeSpec(GetRoadBridgeType(tile));
2227 td->str = spec->transport_name[TRANSPORT_ROAD];
2228 td->road_speed = spec->speed;
2229 if (!HasBit(rts, ROADTYPE_ROAD)) {
2230 td->owner[0] = tram_owner;
2231 return;
2235 /* So the tile at least has a road; check if it has both road and tram */
2236 Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
2238 if (HasBit(rts, ROADTYPE_TRAM)) {
2239 td->owner_type[0] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2240 td->owner[0] = road_owner;
2241 td->owner_type[1] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
2242 td->owner[1] = tram_owner;
2243 } else {
2244 /* One to rule them all */
2245 td->owner[0] = road_owner;
2250 static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2252 Company *oldc = Company::Get(old_owner);
2254 Company *newc;
2255 if (new_owner != INVALID_OWNER) {
2256 newc = Company::Get(new_owner);
2257 } else {
2258 new_owner = OWNER_NONE;
2259 newc = NULL;
2262 if (IsTileSubtype(tile, TT_TRACK)) {
2263 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2264 /* Update all roadtypes, no matter if they are present */
2265 if (GetRoadOwner(tile, rt) == old_owner) {
2266 if (HasTileRoadType(tile, rt)) {
2267 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
2268 uint num_bits = CountBits(GetRoadBits(tile, rt));
2269 oldc->infrastructure.road[rt] -= num_bits;
2270 if (newc != NULL) newc->infrastructure.road[rt] += num_bits;
2273 SetRoadOwner(tile, rt, new_owner);
2276 } else {
2277 TileIndex other_end = GetOtherBridgeEnd(tile);
2278 /* Set number of pieces to zero if it's the southern tile as we
2279 * don't want to update the infrastructure counts twice. */
2280 uint len = tile < other_end ? GetTunnelBridgeLength(tile, other_end) * 2 : 0;
2281 RoadBits bridge_piece = DiagDirToRoadBits(GetTunnelBridgeDirection(tile));
2283 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2284 /* Update all roadtypes, no matter if they are present */
2285 if (GetRoadOwner(tile, rt) == old_owner) {
2286 if (HasBit(GetRoadTypes(tile), rt)) {
2287 /* Update company infrastructure counts.
2288 * No need to dirty windows here, we'll redraw the whole screen anyway. */
2289 RoadBits pieces = GetRoadBits(tile, rt);
2290 uint num_pieces = CountBits(pieces);
2291 if ((pieces & bridge_piece) != 0) {
2292 num_pieces = (num_pieces + len) * TUNNELBRIDGE_TRACKBIT_FACTOR;
2294 oldc->infrastructure.road[rt] -= num_pieces;
2295 if (newc != NULL) newc->infrastructure.road[rt] += num_pieces;
2298 SetRoadOwner(tile, rt, new_owner);
2302 if (IsTileOwner(tile, old_owner)) SetTileOwner(tile, new_owner);
2306 static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2308 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
2309 if (IsTileSubtype(tile, TT_TRACK)) {
2310 RoadBits bits = GetAllRoadBits(tile);
2311 RoadBits bits_new;
2312 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2313 if (CheckRoadSlope(tileh_new, bits, ROAD_NONE, ROAD_NONE, &bits_new).Succeeded()) {
2314 if (bits == bits_new) {
2315 int z_old;
2316 Slope tileh_old = GetTileSlope(tile, &z_old);
2318 /* Get the slope on top of the foundation */
2319 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
2320 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
2322 /* The surface slope must not be changed */
2323 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2326 } else if (IsExtendedRoadBridge(tile)) {
2327 if (IsValidRoadBridgeBits(tileh_new, GetTunnelBridgeDirection(tile), GetAllRoadBits(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2328 } else {
2329 int z_old;
2330 Slope tileh_old = GetTileSlope(tile, &z_old);
2332 DiagDirection direction = GetTunnelBridgeDirection(tile);
2334 /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2335 CheckBridgeSlope(direction, &tileh_old, &z_old);
2336 CommandCost res = CheckBridgeSlope(direction, &tileh_new, &z_new);
2338 /* Surface slope is valid and remains unchanged? */
2339 if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2343 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2346 /** Tile callback functions for road tiles */
2347 extern const TileTypeProcs _tile_type_road_procs = {
2348 DrawTile_Road, // draw_tile_proc
2349 GetSlopePixelZ_Road, // get_slope_z_proc
2350 ClearTile_Road, // clear_tile_proc
2351 NULL, // add_accepted_cargo_proc
2352 GetTileDesc_Road, // get_tile_desc_proc
2353 NULL, // get_tile_railway_status_proc
2354 GetTileRoadStatus_Road, // get_tile_road_status_proc
2355 NULL, // get_tile_waterway_status_proc
2356 ClickTile_Road, // click_tile_proc
2357 NULL, // animate_tile_proc
2358 TileLoop_Road, // tile_loop_proc
2359 ChangeTileOwner_Road, // change_tile_owner_proc
2360 NULL, // add_produced_cargo_proc
2361 GetFoundation_Road, // get_foundation_proc
2362 TerraformTile_Road, // terraform_tile_proc