Translations update
[openttd/fttd.git] / src / road_cmd.cpp
blob561299b57f5925d5008c234f103da0f607baef67
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 if (!remove_bridge) 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 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt));
444 if (rts == ROADTYPES_NONE) {
445 TrackBits tracks = GetCrossingRailBits(tile);
446 bool reserved = HasCrossingReservation(tile);
447 MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile));
448 if (reserved) SetTrackReservation(tile, tracks);
450 /* Update rail count for level crossings. The plain track should still be accounted
451 * for, so only subtract the difference to the level crossing cost. */
452 c = Company::GetIfValid(GetTileOwner(tile));
453 if (c != NULL) {
454 c->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR - 1;
455 DirtyCompanyInfrastructureWindows(c->index);
457 } else {
458 SetRoadTypes(tile, rts);
460 MarkTileDirtyByTile(tile);
461 YapfNotifyTrackLayoutChange();
464 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROAD] * 2);
468 * Delete a piece of road from a tunnel
469 * @param tile tile where to remove road from
470 * @param flags operation to perform
471 * @param pieces roadbits to remove
472 * @param rt roadtype to remove
473 * @param town_check should we check if the town allows removal?
475 static CommandCost RemoveRoad_Tunnel(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool town_check)
477 assert(GetTunnelTransportType(tile) == TRANSPORT_ROAD);
479 TileIndex other_end = GetOtherTunnelEnd(tile);
480 CommandCost ret = TunnelBridgeIsFree(tile, other_end);
481 if (ret.Failed()) return ret;
483 ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), rt, flags, town_check);
484 if (ret.Failed()) return ret;
486 /* If it's the last roadtype, just clear the whole tile */
487 if (GetRoadTypes(tile) == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
489 /* Removing any roadbit in the tunnel axis removes the roadtype (that's the behaviour remove-long-roads needs) */
490 if ((AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))) & pieces) == ROAD_NONE) return_cmd_error(rt == ROADTYPE_TRAM ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
492 CommandCost cost(EXPENSES_CONSTRUCTION);
493 /* Pay for *every* tile of the tunnel */
494 uint len = GetTunnelBridgeLength(other_end, tile) + 2;
495 cost.AddCost(len * 2 * _price[PR_CLEAR_ROAD]);
497 if (flags & DC_EXEC) {
498 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
499 if (c != NULL) {
500 /* A full diagonal road tile has two road bits. */
501 c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
502 DirtyCompanyInfrastructureWindows(c->index);
505 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt));
506 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
508 /* If the owner of the bridge sells all its road, also move the ownership
509 * to the owner of the other roadtype, unless the bridge owner is a town. */
510 RoadType other_rt = (rt == ROADTYPE_ROAD) ? ROADTYPE_TRAM : ROADTYPE_ROAD;
511 Owner other_owner = GetRoadOwner(tile, other_rt);
512 if (!IsTileOwner(tile, other_owner) && !IsTileOwner(tile, OWNER_TOWN)) {
513 SetTileOwner(tile, other_owner);
514 SetTileOwner(other_end, other_owner);
517 /* Mark tiles dirty that have been repaved */
518 MarkTileDirtyByTile(tile);
519 MarkTileDirtyByTile(other_end);
522 return cost;
526 * Delete a piece of road from a station
527 * @param tile tile where to remove road from
528 * @param flags operation to perform
529 * @param pieces roadbits to remove
530 * @param rt roadtype to remove
531 * @param town_check should we check if the town allows removal?
533 static CommandCost RemoveRoad_Station(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool town_check)
535 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR;
537 CommandCost ret = EnsureNoVehicleOnGround(tile);
538 if (ret.Failed()) return ret;
540 ret = CheckAllowRemoveRoad(tile, pieces, GetRoadOwner(tile, rt), rt, flags, town_check);
541 if (ret.Failed()) return ret;
543 /* If it's the last roadtype, just clear the whole tile */
544 if (GetRoadTypes(tile) == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
546 if (flags & DC_EXEC) {
547 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
548 if (c != NULL) {
549 /* A full diagonal road tile has two road bits. */
550 c->infrastructure.road[rt] -= 2;
551 DirtyCompanyInfrastructureWindows(c->index);
553 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt));
554 MarkTileDirtyByTile(tile);
557 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROAD] * 2);
561 * Delete a piece of road.
562 * @param tile tile where to remove road from
563 * @param flags operation to perform
564 * @param pieces roadbits to remove
565 * @param rt roadtype to remove
566 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
567 * @param town_check should we check if the town allows removal?
569 CommandCost RemoveRoad(TileIndex tile, DoCommandFlag flags, RoadBits pieces, RoadType rt, bool crossing_check, bool town_check = true)
571 switch (GetTileType(tile)) {
572 case TT_ROAD: {
573 if (!HasTileRoadType(tile, rt)) break;
575 if (IsTileSubtype(tile, TT_TRACK)) {
576 return RemoveRoad_Road(tile, flags, pieces, rt, town_check);
577 } else {
578 return RemoveRoad_Bridge(tile, flags, pieces, rt, town_check);
582 case TT_MISC:
583 switch (GetTileSubtype(tile)) {
584 case TT_MISC_CROSSING:
585 if (!HasTileRoadType(tile, rt)) break;
586 return RemoveRoad_Crossing(tile, flags, pieces, rt, crossing_check, town_check);
588 case TT_MISC_TUNNEL:
589 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) break;
590 if (!HasTileRoadType(tile, rt)) break;
591 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD) break;
592 return RemoveRoad_Tunnel(tile, flags, pieces, rt, town_check);
594 default:
595 break;
598 break;
600 case TT_STATION:
601 if (!HasTileRoadType(tile, rt)) break;
603 return RemoveRoad_Station(tile, flags, pieces, rt, town_check);
605 default:
606 break;
609 /* The tile doesn't have the given road type */
610 return_cmd_error(rt == ROADTYPE_TRAM ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD);
615 * Calculate the costs for roads on slopes
616 * Also compute the road bits that have to be built to fit the slope
618 * @param tileh The current slope
619 * @param pieces The RoadBits we want to add
620 * @param existing The existent RoadBits of the current type
621 * @param other The existent RoadBits for the other type
622 * @param build The actual RoadBits to build
623 * @return The costs for these RoadBits on this slope
625 static CommandCost CheckRoadSlope(Slope tileh, RoadBits pieces, RoadBits existing, RoadBits other, RoadBits *build)
627 /* Remove already build pieces */
628 CLRBITS(pieces, existing);
630 /* If we can't build anything stop here */
631 if (pieces == ROAD_NONE) return CMD_ERROR;
633 /* All RoadBit combos are valid on flat land */
634 if (tileh == SLOPE_FLAT) {
635 if (build != NULL) *build = pieces;
636 return CommandCost();
639 /* Steep slopes behave the same as slopes with one corner raised. */
640 if (IsSteepSlope(tileh)) {
641 tileh = SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh));
644 /* Roads on slopes */
645 if (_settings_game.construction.build_on_slopes && (_invalid_leveled_roadbits[tileh] & (other | existing | pieces)) == ROAD_NONE) {
646 if (build != NULL) *build = pieces;
648 /* If we add leveling we've got to pay for it */
649 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
651 return CommandCost();
654 /* Autocomplete uphill roads */
655 pieces |= MirrorRoadBits(pieces);
656 RoadBits type_bits = existing | pieces;
658 /* Uphill roads */
659 if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) &&
660 (_invalid_straight_roadbits[tileh] & type_bits) == ROAD_NONE) {
661 /* Slopes without foundation */
662 if (!IsSlopeWithOneCornerRaised(tileh)) {
663 if (build != NULL) *build = pieces;
664 if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
665 return CommandCost();
668 /* Prevent build on slopes if it isn't allowed */
669 if (_settings_game.construction.build_on_slopes) {
670 if (build != NULL) *build = pieces;
672 /* If we add foundation we've got to pay for it */
673 if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
675 return CommandCost();
678 return CMD_ERROR;
682 * Check if a given roadbits set is valid for a road bridge head
683 * @param tileh The slope
684 * @param dir The bridge direction
685 * @param bits The roadbits
686 * @return Whether the given combination is valid
688 bool IsValidRoadBridgeBits(Slope tileh, DiagDirection dir, RoadBits bits)
690 DiagDirDiff diff = CheckExtendedBridgeHead(tileh, dir);
692 switch (diff) {
693 case DIAGDIRDIFF_SAME: return true;
694 case DIAGDIRDIFF_REVERSE: return false;
695 default: return (bits & DiagDirToRoadBits(ChangeDiagDir(dir, diff))) == 0;
700 * Build a piece of road, clearing the land if necessary
701 * @param tile tile where to build road
702 * @param flags operation to perform
703 * @param rt roadtype to build
704 * @param pieces roadbits to build
705 * @param company company building the road
706 * @param town owner/closest town
707 * @param drd directions to disallow
708 * @return the cost of this operation or an error
710 static CommandCost BuildRoad_Clear(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
712 CommandCost cost(EXPENSES_CONSTRUCTION);
714 CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
715 if (ret.Failed()) return ret;
716 cost.AddCost(ret);
718 Slope tileh = GetTileSlope(tile);
720 /* Check the foundation/slopes when adding road/tram bits */
721 ret = CheckRoadSlope(tileh, pieces, ROAD_NONE, ROAD_NONE, &pieces);
722 /* Return an error if we need to build a foundation (ret != 0) but the
723 * current setting is turned off */
724 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
725 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
727 cost.AddCost(ret);
729 uint num_pieces = CountBits(pieces);
730 cost.AddCost(num_pieces * _price[PR_BUILD_ROAD]);
732 if (flags & DC_EXEC) {
733 MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), town, company, company);
735 /* Update company infrastructure count. */
736 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
737 if (c != NULL) {
738 c->infrastructure.road[rt] += num_pieces;
739 DirtyCompanyInfrastructureWindows(c->index);
742 if (rt != ROADTYPE_TRAM && IsStraightRoad(pieces)) {
743 SetDisallowedRoadDirections(tile, drd);
746 MarkTileDirtyByTile(tile);
749 return cost;
753 * Build a piece of road on a road tile
754 * @param tile tile where to build road
755 * @param flags operation to perform
756 * @param rt roadtype to build
757 * @param pieces roadbits to build
758 * @param company company building the road
759 * @param town owner/closest town
760 * @param toggle_drd directions to toggle disallow
761 * @return the cost of this operation or an error
763 static CommandCost BuildRoad_Road(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections toggle_drd)
765 if (HasRoadWorks(tile)) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
767 RoadBits existing = ROAD_NONE;
769 if (HasTileRoadType(tile, rt)) {
770 existing = GetRoadBits(tile, rt);
771 bool crossing = !IsStraightRoad(existing | pieces);
773 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) {
774 /* Junctions cannot be one-way */
775 return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
778 if ((existing & pieces) == pieces) {
779 /* We only want to set the (dis)allowed road directions */
780 if (toggle_drd == DRD_NONE || rt == ROADTYPE_TRAM) {
781 return_cmd_error(STR_ERROR_ALREADY_BUILT);
784 if (crossing) return_cmd_error(STR_ERROR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION);
786 Owner owner = GetRoadOwner(tile, ROADTYPE_ROAD);
787 if (owner != OWNER_NONE) {
788 CommandCost ret = CheckOwnership(owner, tile);
789 if (ret.Failed()) return ret;
792 DisallowedRoadDirections dis_existing = GetDisallowedRoadDirections(tile);
793 DisallowedRoadDirections dis_new = dis_existing ^ toggle_drd;
795 /* We allow removing disallowed directions to break up
796 * deadlocks, but adding them can break articulated
797 * vehicles. As such, only when less is disallowed,
798 * i.e. bits are removed, we skip the vehicle check. */
799 if (CountBits(dis_existing) <= CountBits(dis_new)) {
800 CommandCost ret = EnsureNoVehicleOnGround(tile);
801 if (ret.Failed()) return ret;
804 /* Ignore half built tiles */
805 if ((flags & DC_EXEC) && rt != ROADTYPE_TRAM && IsStraightRoad(existing)) {
806 SetDisallowedRoadDirections(tile, dis_new);
807 MarkTileDirtyByTile(tile);
810 return CommandCost();
813 /* Disallow breaking end-of-line of someone else
814 * so trams can still reverse on this tile. */
815 if (rt == ROADTYPE_TRAM && HasExactlyOneBit (existing)) {
816 Owner owner = GetRoadOwner (tile, ROADTYPE_TRAM);
817 if (owner != OWNER_NONE) {
818 CommandCost ret = CheckOwnership (owner);
819 if (ret.Failed()) return ret;
824 CommandCost cost(EXPENSES_CONSTRUCTION);
826 RoadBits other_bits = GetOtherRoadBits(tile, rt);
828 Slope tileh = GetTileSlope(tile);
830 if (other_bits != pieces) {
831 /* Check the foundation/slopes when adding road/tram bits */
832 CommandCost ret = CheckRoadSlope(tileh, pieces, existing, other_bits, &pieces);
833 /* Return an error if we need to build a foundation (ret != 0) but the
834 * current setting is turned off */
835 if (ret.Failed() || (ret.GetCost() != 0 && !_settings_game.construction.build_on_slopes)) {
836 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
838 cost.AddCost(ret);
841 /* Don't put the pieces that already exist */
842 pieces &= ComplementRoadBits(existing);
844 /* Check if new road bits will have the same foundation as other existing road types */
845 Foundation found_new = GetRoadFoundation(tileh, pieces | existing);
847 /* Test if all other roadtypes can be built at that foundation */
848 for (RoadType rtest = ROADTYPE_ROAD; rtest < ROADTYPE_END; rtest++) {
849 if (rtest != rt) { // check only other road types
850 RoadBits bits = GetRoadBits(tile, rtest);
851 /* do not check if there are not road bits of given type */
852 if (bits != ROAD_NONE && GetRoadFoundation(tileh, bits) != found_new) {
853 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
858 CommandCost ret = EnsureNoVehicleOnGround(tile);
859 if (ret.Failed()) return ret;
861 uint num_pieces = CountBits(pieces);
862 cost.AddCost(num_pieces * _price[PR_BUILD_ROAD]);
864 if (flags & DC_EXEC) {
865 if (existing == ROAD_NONE) {
866 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
867 SetRoadOwner(tile, rt, company);
868 if (rt == ROADTYPE_ROAD) SetTownIndex(tile, town);
871 SetRoadBits(tile, existing | pieces, rt);
873 /* Update company infrastructure count. */
874 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
875 if (c != NULL) {
876 c->infrastructure.road[rt] += num_pieces;
877 DirtyCompanyInfrastructureWindows(c->index);
880 if (rt != ROADTYPE_TRAM) {
881 SetDisallowedRoadDirections(tile, IsStraightRoad(existing | pieces) ?
882 GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
885 MarkTileDirtyByTile(tile);
888 return cost;
892 * Build a piece of road on a bridge tile
893 * @param tile tile where to build road
894 * @param flags operation to perform
895 * @param rt roadtype to build
896 * @param pieces roadbits to build
897 * @param company company building the road
898 * @param town owner/closest town
899 * @param drd directions to disallow
900 * @return the cost of this operation or an error
902 static CommandCost BuildRoad_Bridge(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
904 DiagDirection dir = GetTunnelBridgeDirection(tile);
905 Slope tileh = GetTileSlope(tile);
906 uint num;
907 bool other_end;
909 if (HasBridgeFlatRamp(tileh, DiagDirToAxis(dir))) {
910 RoadBits existing = GetRoadBits(tile, rt);
911 pieces &= ~existing;
912 if (pieces == ROAD_NONE) return_cmd_error(STR_ERROR_ALREADY_BUILT);
914 if (!IsValidRoadBridgeBits(tileh, dir, existing | pieces)) {
915 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
918 /* Disallow breaking end-of-line of someone else
919 * so trams can still reverse on this tile. */
920 if (rt == ROADTYPE_TRAM && HasExactlyOneBit (existing)) {
921 Owner owner = GetRoadOwner (tile, ROADTYPE_TRAM);
922 if (owner != OWNER_NONE) {
923 CommandCost ret = CheckOwnership (owner);
924 if (ret.Failed()) return ret;
928 num = CountBits(pieces);
929 other_end = (pieces & DiagDirToRoadBits(dir)) != 0;
930 pieces |= existing;
931 } else {
932 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
933 if (pieces != DiagDirToRoadBits(ReverseDiagDir(dir))) {
934 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
937 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
939 pieces = AxisToRoadBits(DiagDirToAxis(dir));
940 num = 2;
941 other_end = true;
944 TileIndex other_tile;
945 RoadBits other_pieces;
947 if (other_end) {
948 other_tile = GetOtherBridgeEnd(tile);
950 /* Don't allow adding roadtype to the bridge when vehicles are already driving on it */
951 CommandCost ret = TunnelBridgeIsFree(tile, other_tile);
952 if (ret.Failed()) return ret;
954 /* Don't allow to mix owners */
955 CompanyID new_owner = HasTileRoadType(tile, rt) ? GetRoadOwner(tile, rt) : company;
956 CompanyID other_owner = HasTileRoadType(other_tile, rt) ? GetRoadOwner(other_tile, rt) : company;
957 if (new_owner != other_owner) return CMD_ERROR;
959 num += 2 * GetTunnelBridgeLength(tile, other_tile);
961 if (IsExtendedRoadBridge(other_tile)) {
962 other_pieces = GetRoadBits(other_tile, rt) | DiagDirToRoadBits(ReverseDiagDir(dir));
963 num++;
964 } else {
965 assert(GetRoadBits(other_tile, rt) == ROAD_NONE);
966 other_pieces = AxisToRoadBits(DiagDirToAxis(dir));
967 num += 2;
969 } else {
970 CommandCost ret = EnsureNoVehicleOnGround(tile);
971 if (ret.Failed()) return ret;
974 if (flags & DC_EXEC) {
975 if (other_end) {
976 /* Update company infrastructure count. */
977 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
978 if (c != NULL) {
979 uint existing = CountBits(GetRoadBits(tile, rt)) + CountBits(GetRoadBits(other_tile, rt));
980 c->infrastructure.road[rt] -= existing;
981 c->infrastructure.road[rt] += (existing + num) * TUNNELBRIDGE_TRACKBIT_FACTOR;
982 DirtyCompanyInfrastructureWindows(c->index);
985 if (!HasTileRoadType(other_tile, rt)) {
986 SetRoadTypes(other_tile, GetRoadTypes(other_tile) | RoadTypeToRoadTypes(rt));
987 SetRoadOwner(other_tile, rt, company);
989 SetRoadBits(other_tile, other_pieces, rt);
991 MarkBridgeTilesDirty(tile, other_tile, dir, false);
992 } else {
993 /* Update company infrastructure count. */
994 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
995 if (c != NULL) {
996 c->infrastructure.road[rt] += (pieces & DiagDirToRoadBits(dir)) != 0 ? num * TUNNELBRIDGE_TRACKBIT_FACTOR : num;
997 DirtyCompanyInfrastructureWindows(c->index);
1001 if (!HasTileRoadType(tile, rt)) {
1002 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1003 SetRoadOwner(tile, rt, company);
1005 SetRoadBits(tile, pieces, rt);
1006 MarkTileDirtyByTile(tile);
1009 return CommandCost(EXPENSES_CONSTRUCTION, num * _price[PR_BUILD_ROAD]);
1013 * Build a piece of road on a crossing tile
1014 * @param tile tile where to build road
1015 * @param flags operation to perform
1016 * @param rt roadtype to build
1017 * @param pieces roadbits to build
1018 * @param company company building the road
1019 * @param town owner/closest town
1020 * @param drd directions to disallow
1021 * @return the cost of this operation or an error
1023 static CommandCost BuildRoad_Crossing(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1025 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
1026 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1029 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1031 CommandCost ret = EnsureNoVehicleOnGround(tile);
1032 if (ret.Failed()) return ret;
1034 if (flags & DC_EXEC) {
1035 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1036 SetRoadOwner(tile, rt, company);
1037 if (rt == ROADTYPE_ROAD) SetTownIndex(tile, town);
1039 /* Update company infrastructure count. */
1040 Company *c = Company::GetIfValid(company);
1041 if (c != NULL) {
1042 c->infrastructure.road[rt] += 2;
1043 DirtyCompanyInfrastructureWindows(c->index);
1046 MarkTileDirtyByTile(tile);
1049 return CommandCost(EXPENSES_CONSTRUCTION, 2 * _price[PR_BUILD_ROAD]);
1053 * Build a piece of road on a railway tile
1054 * @param tile tile where to build road
1055 * @param flags operation to perform
1056 * @param rt roadtype to build
1057 * @param pieces roadbits to build
1058 * @param company company building the road
1059 * @param town owner/closest town
1060 * @param drd directions to disallow
1061 * @return the cost of this operation or an error
1063 static CommandCost BuildRoad_Railway(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1065 Slope tileh = GetTileSlope(tile);
1067 if (!IsTileSubtype(tile, TT_TRACK)) goto do_clear;
1069 /* Level crossings may only be built on these slopes */
1070 if (IsSteepSlope(tileh) || !HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) {
1071 return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
1074 if (RailNoLevelCrossings(GetRailType(tile))) {
1075 return_cmd_error(STR_ERROR_CROSSING_DISALLOWED);
1078 if (HasSignalOnTrack(tile, TRACK_UPPER)) goto do_clear;
1080 Axis roaddir;
1081 switch (GetTrackBits(tile)) {
1082 case TRACK_BIT_X:
1083 if (pieces & ROAD_X) goto do_clear;
1084 roaddir = AXIS_Y;
1085 break;
1087 case TRACK_BIT_Y:
1088 if (pieces & ROAD_Y) goto do_clear;
1089 roaddir = AXIS_X;
1090 break;
1092 default:
1093 do_clear:
1094 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1097 CommandCost ret = EnsureNoVehicleOnGround(tile);
1098 if (ret.Failed()) return ret;
1100 if (flags & DC_EXEC) {
1101 YapfNotifyTrackLayoutChange();
1102 /* Update company infrastructure counts. A level crossing has two road bits. */
1103 Company *c = Company::GetIfValid(company);
1104 if (c != NULL) {
1105 c->infrastructure.road[rt] += 2;
1106 if (rt != ROADTYPE_ROAD) c->infrastructure.road[ROADTYPE_ROAD] += 2;
1107 DirtyCompanyInfrastructureWindows(company);
1109 /* Update rail count for level crossings. The plain track is already
1110 * counted, so only add the difference to the level crossing cost. */
1111 c = Company::GetIfValid(GetTileOwner(tile));
1112 if (c != NULL) {
1113 c->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR - 1;
1114 DirtyCompanyInfrastructureWindows(c->index);
1117 /* Always add road to the roadtypes (can't draw without it) */
1118 bool reserved = GetRailReservationTrackBits (tile) != TRACK_BIT_NONE;
1119 MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, town);
1120 SetCrossingReservation(tile, reserved);
1121 UpdateLevelCrossing(tile, false);
1122 MarkTileDirtyByTile(tile);
1125 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_ROAD] * (rt == ROADTYPE_ROAD ? 2 : 4));
1129 * Build a piece of road on a tunnel tile
1130 * @param tile tile where to build road
1131 * @param flags operation to perform
1132 * @param rt roadtype to build
1133 * @param pieces roadbits to build
1134 * @param company company building the road
1135 * @param town owner/closest town
1136 * @param drd directions to disallow
1137 * @return the cost of this operation or an error
1139 static CommandCost BuildRoad_Tunnel(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1141 /* Only allow building the outern roadbit, so building long roads stops at existing bridges */
1142 if (GetTunnelTransportType(tile) != TRANSPORT_ROAD || pieces != DiagDirToRoadBits(ReverseDiagDir(GetTunnelBridgeDirection(tile)))) {
1143 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1146 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1148 TileIndex other_end = GetOtherTunnelEnd(tile);
1150 /* Don't allow adding roadtype to the tunnel when vehicles are already driving on it */
1151 CommandCost ret = TunnelBridgeIsFree(tile, other_end);
1152 if (ret.Failed()) return ret;
1154 /* There are 2 pieces on *every* tile of the tunnel */
1155 uint num_pieces = 2 * (GetTunnelBridgeLength(tile, other_end) + 2);
1157 if (flags & DC_EXEC) {
1158 SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt));
1159 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1160 SetRoadOwner(other_end, rt, company);
1161 SetRoadOwner(tile, rt, company);
1163 /* Mark tiles dirty that have been repaved */
1164 MarkTileDirtyByTile(other_end);
1165 MarkTileDirtyByTile(tile);
1167 /* Update company infrastructure count. */
1168 Company *c = Company::GetIfValid(company);
1169 if (c != NULL) {
1170 c->infrastructure.road[rt] += num_pieces * TUNNELBRIDGE_TRACKBIT_FACTOR;
1171 DirtyCompanyInfrastructureWindows(c->index);
1175 return CommandCost(EXPENSES_CONSTRUCTION, num_pieces * _price[PR_BUILD_ROAD]);
1179 * Build a piece of road on a station tile
1180 * @param tile tile where to build road
1181 * @param flags operation to perform
1182 * @param rt roadtype to build
1183 * @param pieces roadbits to build
1184 * @param company company building the road
1185 * @param town owner/closest town
1186 * @param drd directions to disallow
1187 * @return the cost of this operation or an error
1189 static CommandCost BuildRoad_Station(TileIndex tile, DoCommandFlag flags, RoadType rt, RoadBits pieces, CompanyID company, TownID town, DisallowedRoadDirections drd)
1191 if ((GetAnyRoadBits(tile, rt) & pieces) == pieces) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1193 if (!IsDriveThroughStopTile(tile) || (pieces & ~AxisToRoadBits(GetRoadStopAxis(tile)))) {
1194 return BuildRoad_Clear(tile, flags, rt, pieces, company, town, drd);
1197 if (HasTileRoadType(tile, rt)) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1199 CommandCost ret = EnsureNoVehicleOnGround(tile);
1200 if (ret.Failed()) return ret;
1202 if (flags & DC_EXEC) {
1203 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt));
1204 SetRoadOwner(tile, rt, company);
1206 /* Update company infrastructure count. */
1207 Company *c = Company::GetIfValid(company);
1208 if (c != NULL) {
1209 c->infrastructure.road[rt] += 2;
1210 DirtyCompanyInfrastructureWindows(c->index);
1213 MarkTileDirtyByTile(tile);
1216 return CommandCost(EXPENSES_CONSTRUCTION, 2 * _price[PR_BUILD_ROAD]);
1220 * Build a piece of road.
1221 * @param tile tile where to build road
1222 * @param flags operation to perform
1223 * @param p1 bit 0..3 road pieces to build (RoadBits)
1224 * bit 4..5 road type
1225 * bit 6..7 disallowed directions to toggle
1226 * @param p2 the town that is building the road (0 if not applicable)
1227 * @param text unused
1228 * @return the cost of this operation or an error
1230 CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1232 CompanyID company = _current_company;
1234 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
1235 * if a non-company is building the road */
1236 if (company == OWNER_TOWN) {
1237 if (!Town::IsValidID(p2)) return CMD_ERROR;
1238 } else {
1239 if (p2 != 0) return CMD_ERROR;
1241 const Town *town = CalcClosestTownFromTile(tile);
1242 p2 = (town != NULL) ? town->index : (TownID)INVALID_TOWN;
1244 if (company == OWNER_DEITY) {
1245 company = OWNER_TOWN;
1247 /* If we are not within a town, we are not owned by the town */
1248 if (town == NULL || DistanceSquare(tile, town->xy) > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE]) {
1249 company = OWNER_NONE;
1254 RoadBits pieces = Extract<RoadBits, 0, 4>(p1);
1256 /* do not allow building 'zero' road bits, code wouldn't handle it */
1257 if (pieces == ROAD_NONE) return CMD_ERROR;
1259 RoadType rt = Extract<RoadType, 4, 2>(p1);
1260 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1262 DisallowedRoadDirections toggle_drd = Extract<DisallowedRoadDirections, 6, 2>(p1);
1264 switch (GetTileType(tile)) {
1265 case TT_ROAD:
1266 if (IsTileSubtype(tile, TT_BRIDGE)) {
1267 return BuildRoad_Bridge(tile, flags, rt, pieces, company, p2, toggle_drd);
1268 } else {
1269 return BuildRoad_Road(tile, flags, rt, pieces, company, p2, toggle_drd);
1272 case TT_RAILWAY:
1273 return BuildRoad_Railway(tile, flags, rt, pieces, company, p2, toggle_drd);
1275 case TT_STATION:
1276 return BuildRoad_Station(tile, flags, rt, pieces, company, p2, toggle_drd);
1278 case TT_MISC:
1279 switch (GetTileSubtype(tile)) {
1280 case TT_MISC_CROSSING:
1281 return BuildRoad_Crossing(tile, flags, rt, pieces, company, p2, toggle_drd);
1283 case TT_MISC_TUNNEL:
1284 return BuildRoad_Tunnel(tile, flags, rt, pieces, company, p2, toggle_drd);
1286 case TT_MISC_DEPOT:
1287 if (IsRoadDepot(tile) && (GetAnyRoadBits(tile, rt) & pieces) == pieces) return_cmd_error(STR_ERROR_ALREADY_BUILT);
1288 /* fall through */
1289 default:
1290 break;
1292 /* fall through */
1293 default:
1294 return BuildRoad_Clear(tile, flags, rt, pieces, company, p2, toggle_drd);
1299 * Checks whether a road or tram connection can be found when building a new road or tram.
1300 * @param tile Tile at which the road being built will end.
1301 * @param rt Roadtype of the road being built.
1302 * @param dir Direction that the road is following.
1303 * @return True if the next tile at dir direction is suitable for being connected directly by a second roadbit at the end of the road being built.
1305 static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
1307 RoadBits bits = GetAnyRoadBits(tile + TileOffsByDiagDir(dir), rt, false);
1308 return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0;
1312 * Build a long piece of road.
1313 * @param start_tile start tile of drag (the building cost will appear over this tile)
1314 * @param flags operation to perform
1315 * @param p1 end tile of drag
1316 * @param p2 various bitstuffed elements
1317 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1). Only used if bit 6 is set or if we are building a single tile
1318 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2). Only used if bit 6 is set or if we are building a single tile
1319 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1320 * - p2 = (bit 3 + 4) - road type
1321 * - p2 = (bit 5) - set road direction
1322 * - p2 = (bit 6) - defines two different behaviors for this command:
1323 * - 0 = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile
1324 * - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
1325 * @param text unused
1326 * @return the cost of this operation or an error
1328 CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1330 DisallowedRoadDirections drd = DRD_NORTHBOUND;
1332 if (p1 >= MapSize()) return CMD_ERROR;
1334 TileIndex end_tile = p1;
1335 RoadType rt = Extract<RoadType, 3, 2>(p2);
1336 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1338 Axis axis = Extract<Axis, 2, 1>(p2);
1339 /* Only drag in X or Y direction dictated by the direction variable */
1340 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
1341 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
1343 DiagDirection dir = AxisToDiagDir(axis);
1345 /* Swap direction, also the half-tile drag var (bit 0 and 1) */
1346 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
1347 dir = ReverseDiagDir(dir);
1348 p2 ^= 3;
1349 drd = DRD_SOUTHBOUND;
1352 /* On the X-axis, we have to swap the initial bits, so they
1353 * will be interpreted correctly in the GTTS. Furthermore
1354 * when you just 'click' on one tile to build them. */
1355 if ((axis == AXIS_Y) == (start_tile == end_tile && HasBit(p2, 0) == HasBit(p2, 1))) drd ^= DRD_BOTH;
1356 /* No disallowed direction bits have to be toggled */
1357 if (!HasBit(p2, 5)) drd = DRD_NONE;
1359 CommandCost cost(EXPENSES_CONSTRUCTION);
1360 CommandCost last_error = CMD_ERROR;
1361 TileIndex tile = start_tile;
1362 bool had_bridge = false;
1363 bool had_tunnel = false;
1364 bool had_success = false;
1365 bool is_ai = HasBit(p2, 6);
1367 /* Start tile is the first tile clicked by the user. */
1368 for (;;) {
1369 RoadBits bits = AxisToRoadBits(axis);
1371 /* Determine which road parts should be built. */
1372 if (!is_ai && start_tile != end_tile) {
1373 /* Only build the first and last roadbit if they can connect to something. */
1374 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1375 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1376 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1377 bits = DiagDirToRoadBits(dir);
1379 } else {
1380 /* Road parts only have to be built at the start tile or at the end tile. */
1381 if (tile == end_tile && !HasBit(p2, 1)) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1382 if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir);
1385 CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
1386 if (ret.Failed()) {
1387 last_error = ret;
1388 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1389 if (is_ai) return last_error;
1390 break;
1392 } else {
1393 had_success = true;
1394 /* Only pay for the upgrade on one side of the bridges and tunnels */
1395 if (IsTunnelTile(tile)) {
1396 if (!had_tunnel || GetTunnelBridgeDirection(tile) == dir) {
1397 cost.AddCost(ret);
1399 had_tunnel = true;
1400 } else if (IsRoadBridgeTile(tile)) {
1401 if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
1402 cost.AddCost(ret);
1404 had_bridge = true;
1405 } else {
1406 cost.AddCost(ret);
1410 if (tile == end_tile) break;
1412 tile += TileOffsByDiagDir(dir);
1415 return had_success ? cost : last_error;
1419 * Remove a long piece of road.
1420 * @param start_tile start tile of drag
1421 * @param flags operation to perform
1422 * @param p1 end tile of drag
1423 * @param p2 various bitstuffed elements
1424 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
1425 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
1426 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
1427 * - p2 = (bit 3 + 4) - road type
1428 * @param text unused
1429 * @return the cost of this operation or an error
1431 CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1433 CommandCost cost(EXPENSES_CONSTRUCTION);
1435 if (p1 >= MapSize()) return CMD_ERROR;
1437 TileIndex end_tile = p1;
1438 RoadType rt = Extract<RoadType, 3, 2>(p2);
1439 if (!IsValidRoadType(rt)) return CMD_ERROR;
1441 Axis axis = Extract<Axis, 2, 1>(p2);
1442 /* Only drag in X or Y direction dictated by the direction variable */
1443 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
1444 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
1446 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
1447 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
1448 TileIndex t = start_tile;
1449 start_tile = end_tile;
1450 end_tile = t;
1451 p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0;
1454 Money money = GetAvailableMoneyForCommand();
1455 TileIndex tile = start_tile;
1456 CommandCost last_error = CMD_ERROR;
1457 bool had_success = false;
1458 /* Start tile is the small number. */
1459 for (;;) {
1460 RoadBits bits = AxisToRoadBits(axis);
1462 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
1463 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
1465 /* try to remove the halves. */
1466 if (bits != 0) {
1467 CommandCost ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
1468 if (ret.Succeeded()) {
1469 if (flags & DC_EXEC) {
1470 money -= ret.GetCost();
1471 if (money < 0) {
1472 _additional_cash_required = DoCommand(start_tile, end_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
1473 return cost;
1475 RemoveRoad(tile, flags, bits, rt, true, false);
1477 cost.AddCost(ret);
1478 had_success = true;
1479 } else {
1480 /* Ownership errors are more important. */
1481 if (last_error.GetErrorMessage() != STR_ERROR_OWNED_BY) last_error = ret;
1485 if (tile == end_tile) break;
1487 tile += (axis == AXIS_Y) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
1490 return had_success ? cost : last_error;
1494 * Build a road depot.
1495 * @param tile tile where to build the depot
1496 * @param flags operation to perform
1497 * @param p1 bit 0..1 entrance direction (DiagDirection)
1498 * bit 2..3 road type
1499 * @param p2 unused
1500 * @param text unused
1501 * @return the cost of this operation or an error
1503 * @todo When checking for the tile slope,
1504 * distinguish between "Flat land required" and "land sloped in wrong direction"
1506 CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1508 DiagDirection dir = Extract<DiagDirection, 0, 2>(p1);
1509 RoadType rt = Extract<RoadType, 2, 2>(p1);
1511 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
1513 Slope tileh = GetTileSlope(tile);
1514 if (tileh != SLOPE_FLAT && (
1515 !_settings_game.construction.build_on_slopes ||
1516 !CanBuildDepotByTileh(dir, tileh)
1517 )) {
1518 return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
1521 CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
1522 if (cost.Failed()) return cost;
1524 if (HasBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1526 if (!Depot::CanAllocateItem()) return CMD_ERROR;
1528 if (flags & DC_EXEC) {
1529 Depot *dep = new Depot(tile);
1530 dep->build_date = _date;
1532 /* A road depot has two road bits. */
1533 Company::Get(_current_company)->infrastructure.road[rt] += 2;
1534 DirtyCompanyInfrastructureWindows(_current_company);
1536 MakeRoadDepot(tile, _current_company, dep->index, dir, rt);
1537 MarkTileDirtyByTile(tile);
1538 MakeDefaultName(dep);
1540 cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]);
1541 return cost;
1544 static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlag flags)
1546 if (IsTileSubtype(tile, TT_TRACK)) {
1547 RoadBits b = GetAllRoadBits(tile);
1549 /* Clear the road if only one piece is on the tile OR we are not using the DC_AUTO flag */
1550 if ((HasExactlyOneBit(b) && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || !(flags & DC_AUTO)) {
1551 CommandCost ret(EXPENSES_CONSTRUCTION);
1552 RoadType rt;
1553 FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1554 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
1555 if (tmp_ret.Failed()) return tmp_ret;
1556 ret.AddCost(tmp_ret);
1558 return ret;
1561 return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST);
1562 } else {
1563 if (flags & DC_AUTO) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
1565 /* Floods can remove anything as well as the scenario editor */
1567 if (_current_company != OWNER_WATER && _game_mode != GM_EDITOR) {
1568 RoadTypes rts = GetRoadTypes(tile);
1569 Owner road_owner = _current_company;
1570 if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
1572 /* We can remove unowned road and if the town allows it */
1573 if (road_owner == OWNER_TOWN && _current_company != OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) {
1574 /* Town does not allow */
1575 CommandCost ret = CheckTileOwnership(tile);
1576 if (ret.Failed()) return ret;
1577 } else {
1578 if (road_owner != OWNER_NONE && road_owner != OWNER_TOWN) {
1579 CommandCost ret = CheckOwnership(road_owner, tile);
1580 if (ret.Failed()) return ret;
1583 if (HasBit(rts, ROADTYPE_TRAM)) {
1584 Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
1585 if (tram_owner != OWNER_NONE) {
1586 CommandCost ret = CheckOwnership(tram_owner, tile);
1587 if (ret.Failed()) return ret;
1593 TileIndex endtile = GetOtherBridgeEnd(tile);
1595 CommandCost ret = TunnelBridgeIsFree(tile, endtile);
1596 if (ret.Failed()) return ret;
1598 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
1599 Town *t = ClosestTownFromTile(tile); // town penalty rating
1601 /* Check if you are allowed to remove the bridge owned by a town
1602 * Removal depends on difficulty settings */
1603 CommandCost ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE);
1604 if (ret.Failed()) return ret;
1606 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
1607 * you have a "Poor" (0) town rating */
1608 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
1611 uint len = GetTunnelBridgeLength(tile, endtile);
1613 if (flags & DC_EXEC) {
1614 RemoveBridgeMiddleTiles(tile, endtile);
1616 DiagDirection dir = GetTunnelBridgeDirection(tile);
1617 RoadBits bridge_piece = DiagDirToRoadBits(dir);
1618 RoadBits other_nonbridge_pieces = ComplementRoadBits(DiagDirToRoadBits(ReverseDiagDir(dir)));
1619 bool other_extended = IsExtendedRoadBridge(endtile);
1621 MakeNormalRoadFromBridge(endtile);
1623 RoadType rt;
1624 FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) {
1625 Company *c = Company::GetIfValid(GetRoadOwner(tile, rt));
1626 RoadBits pieces = GetRoadBits(tile, rt);
1628 if ((pieces & bridge_piece) == 0) {
1629 /* This roadtype does not connect to the bridge */
1630 if (c != NULL) {
1631 c->infrastructure.road[rt] -= CountBits(pieces);
1632 DirtyCompanyInfrastructureWindows(c->index);
1634 } else {
1635 /* This roadtype connects to the bridge */
1636 RoadBits other_pieces = GetRoadBits(endtile, rt);
1638 if (c != NULL) {
1639 /* A full diagonal road tile has two road bits. */
1640 c->infrastructure.road[rt] -= (CountBits(pieces) + 2 * len + CountBits(other_pieces)) * TUNNELBRIDGE_TRACKBIT_FACTOR;
1641 DirtyCompanyInfrastructureWindows(c->index);
1644 if (other_extended && ((other_pieces &= other_nonbridge_pieces) != 0)) {
1645 SetRoadBits(endtile, other_pieces, rt);
1646 if (c != NULL) c->infrastructure.road[rt] += CountBits(other_pieces);
1647 } else {
1648 ClearRoadType(endtile, rt);
1654 DoClearSquare(tile);
1655 MarkTileDirtyByTile(endtile);
1658 return CommandCost(EXPENSES_CONSTRUCTION, (len + 2) * _price[PR_CLEAR_BRIDGE]);
1664 * Get the foundationtype of a RoadBits Slope combination
1666 * @param tileh The Slope part
1667 * @param bits The RoadBits part
1668 * @return The resulting Foundation
1670 static Foundation GetRoadFoundation(Slope tileh, RoadBits bits)
1672 /* Flat land and land without a road doesn't require a foundation */
1673 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE;
1675 /* Steep slopes behave the same as slopes with one corner raised. */
1676 if (IsSteepSlope(tileh)) {
1677 tileh = SlopeWithOneCornerRaised(GetHighestSlopeCorner(tileh));
1680 /* Leveled RoadBits on a slope */
1681 if ((_invalid_leveled_roadbits[tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED;
1683 /* Straight roads without foundation on a slope */
1684 if (!IsSlopeWithOneCornerRaised(tileh) &&
1685 (_invalid_straight_roadbits[tileh] & bits) == ROAD_NONE)
1686 return FOUNDATION_NONE;
1688 /* Roads on steep Slopes or on Slopes with one corner raised */
1689 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y);
1692 const byte _road_sloped_sprites[14] = {
1693 0, 0, 2, 0,
1694 0, 1, 0, 0,
1695 3, 0, 0, 0,
1696 0, 0
1700 * Draw the ground sprite for a road tile
1701 * @param ti TileInfo of the tile to draw
1702 * @param roadside The roadside of the tile
1703 * @param image The sprite to draw
1704 * @param paved_offset The offset to add to the sprite if the road is paved
1705 * @param unpaved_offset The offset to add to the sprite if the tile is on snow or in the desert
1706 * @return The palette to use for further drawing
1708 static PaletteID DrawRoadGroundSprite (const TileInfo *ti, Roadside roadside, SpriteID image, int paved_offset, int unpaved_offset)
1710 TileIndex tile = ti->tile;
1711 PaletteID pal = PAL_NONE;
1713 switch (roadside) {
1714 case ROADSIDE_BARREN:
1715 if (IsOnSnow(tile)) {
1716 image += unpaved_offset;
1717 } else {
1718 pal = PALETTE_TO_BARE_LAND;
1720 break;
1722 case ROADSIDE_GRASS:
1723 if (IsOnSnow(tile)) image += unpaved_offset;
1724 break;
1726 default:
1727 if (IsOnSnow(tile) && !(_settings_game.game_creation.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS))) {
1728 image += unpaved_offset;
1729 } else {
1730 image += paved_offset;
1732 break;
1735 DrawGroundSprite (ti, image, pal);
1737 return pal;
1741 * Draws the catenary for the given tile
1742 * @param ti information about the tile (slopes, height etc)
1743 * @param tram the roadbits for the tram
1745 void DrawRoadCatenary(const TileInfo *ti, RoadBits tram)
1747 /* Do not draw catenary if it is invisible */
1748 if (IsInvisibilitySet(TO_CATENARY)) return;
1750 /* Don't draw the catenary under a low bridge */
1751 if (HasBridgeAbove(ti->tile) && !IsTransparencySet(TO_CATENARY)) {
1752 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1754 if (height <= GetTileMaxZ(ti->tile) + 1) return;
1757 SpriteID front;
1758 SpriteID back;
1760 if (ti->tileh != SLOPE_FLAT) {
1761 back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1762 front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1];
1763 } else {
1764 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[tram];
1765 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[tram];
1768 AddSortableSpriteToDraw (ti->vd, back, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_CATENARY));
1769 AddSortableSpriteToDraw (ti->vd, front, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_CATENARY));
1773 * Draws details on/around the road
1774 * @param img the sprite to draw
1775 * @param ti the tile to draw on
1776 * @param dx the offset from the top of the BB of the tile
1777 * @param dy the offset from the top of the BB of the tile
1778 * @param h the height of the sprite to draw
1780 static void DrawRoadDetail(SpriteID img, const TileInfo *ti, int dx, int dy, int h)
1782 int x = ti->x | dx;
1783 int y = ti->y | dy;
1784 int z = ti->z;
1785 if (ti->tileh != SLOPE_FLAT) z = GetSlopePixelZ(x, y);
1786 AddSortableSpriteToDraw (ti->vd, img, PAL_NONE, x, y, 2, 2, h, z);
1790 * Draw ground sprite and road pieces
1791 * @param ti TileInfo
1793 static void DrawRoadBits(TileInfo *ti)
1795 RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD);
1796 RoadBits tram = GetRoadBits(ti->tile, ROADTYPE_TRAM);
1798 SpriteID image = 0;
1800 if (IsTileSubtype(ti->tile, TT_BRIDGE)) {
1801 assert(ti->tileh != SLOPE_FLAT);
1802 DrawFoundation(ti, FOUNDATION_LEVELED, GetTunnelBridgeDirection(ti->tile));
1803 } else if (ti->tileh != SLOPE_FLAT) {
1804 Foundation f = GetRoadFoundation(ti->tileh, road | tram);
1806 DrawFoundation(ti, f);
1808 /* DrawFoundation() modifies ti.
1809 * Default sloped sprites.. */
1810 if (ti->tileh != SLOPE_FLAT) image = _road_sloped_sprites[ti->tileh - 1] + SPR_ROAD_SLOPE_START;
1813 if (image == 0) image = _road_tile_sprites_1[road != ROAD_NONE ? road : tram];
1815 Roadside roadside = IsTileSubtype(ti->tile, TT_TRACK) ? GetRoadside(ti->tile) : ROADSIDE_GRASS;
1817 PaletteID pal = DrawRoadGroundSprite (ti, roadside, image, -19, 19);
1819 /* For tram we overlay the road graphics with either tram tracks only
1820 * (when there is actual road beneath the trams) or with tram tracks
1821 * and some dirts which hides the road graphics */
1822 if (tram != ROAD_NONE) {
1823 if (ti->tileh != SLOPE_FLAT) {
1824 image = _road_sloped_sprites[ti->tileh - 1] + SPR_TRAMWAY_SLOPED_OFFSET;
1825 } else {
1826 image = _road_tile_sprites_1[tram] - SPR_ROAD_Y;
1828 image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY;
1829 DrawGroundSprite (ti, image, pal);
1832 if (IsTileSubtype(ti->tile, TT_TRACK) && road != ROAD_NONE) {
1833 DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile);
1834 if (drd != DRD_NONE) {
1835 DrawGroundSpriteAt (ti, SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh));
1839 if (IsTileSubtype(ti->tile, TT_TRACK) && HasRoadWorks(ti->tile)) {
1840 /* Road works */
1841 DrawGroundSprite (ti, (road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE);
1842 return;
1845 if (tram != ROAD_NONE) DrawRoadCatenary(ti, tram);
1847 if (!IsTileSubtype(ti->tile, TT_TRACK)) return;
1849 /* Return if full detail is disabled, or we are zoomed fully out. */
1850 if (!HasBit(_display_opt, DO_FULL_DETAIL)) return;
1851 if (!IsViewportDrawerDetailed (ti->vd)) return;
1853 /* Do not draw details (street lights, trees) under low bridge */
1854 if (HasBridgeAbove(ti->tile) && (roadside == ROADSIDE_TREES || roadside == ROADSIDE_STREET_LIGHTS)) {
1855 int height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
1856 int minz = GetTileMaxZ(ti->tile) + 2;
1858 if (roadside == ROADSIDE_TREES) minz++;
1860 if (height < minz) return;
1863 /* If there are no road bits, return, as there is nothing left to do */
1864 if (HasAtMostOneBit(road)) return;
1866 /* Draw extra details. */
1867 for (const DrawRoadTileStruct *drts = _road_display_table[roadside][road | tram]; drts->image != 0; drts++) {
1868 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10);
1872 /** Tile callback function for rendering a road tile to the screen */
1873 static void DrawTile_Road(TileInfo *ti)
1875 if (IsTileSubtype(ti->tile, TT_TRACK) || IsExtendedRoadBridge(ti->tile)) {
1876 DrawRoadBits(ti);
1877 } else {
1878 DrawBridgeGround(ti);
1880 /* draw ramp */
1882 DiagDirection dir = GetTunnelBridgeDirection(ti->tile);
1884 const PalSpriteID *psid = GetBridgeRampSprite(GetRoadBridgeType(ti->tile), 8, ti->tileh, dir);
1886 /* Draw Trambits as SpriteCombine */
1887 StartSpriteCombine (ti->vd);
1889 /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
1890 * it doesn't disappear behind it
1892 /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
1893 AddSortableSpriteToDraw (ti->vd, psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
1895 RoadTypes rts = GetRoadTypes(ti->tile);
1897 if (HasBit(rts, ROADTYPE_TRAM)) {
1898 uint offset = dir;
1899 int z = ti->z;
1900 if (ti->tileh != SLOPE_FLAT) {
1901 offset = (offset + 1) & 1;
1902 z += TILE_HEIGHT;
1903 } else {
1904 offset += 2;
1906 /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1907 DrawBridgeTramBits (ti->vd, ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
1910 EndSpriteCombine (ti->vd);
1913 DrawBridgeMiddle(ti);
1916 #define TILE_SEQ_LINE(img, pal, dx, dy, sx, sy) { dx, dy, 0, sx, sy, 20, {img, pal} }
1917 #define TILE_SEQ_END() { (int8)0x80, 0, 0, 0, 0, 0, {0, 0} }
1919 /* Sprite layout for level crossings. The SpriteIDs are actually offsets
1920 * from the base SpriteID returned from the NewGRF sprite resolver. */
1921 static const DrawTileSeqStruct _crossing_layout[] = {
1922 TILE_SEQ_LINE(2, PAL_NONE, 0, 0, 3, 3),
1923 TILE_SEQ_LINE(4, PAL_NONE, 0, 13, 3, 3),
1924 TILE_SEQ_LINE(6, PAL_NONE, 13, 0, 3, 3),
1925 TILE_SEQ_LINE(8, PAL_NONE, 13, 13, 3, 3),
1926 TILE_SEQ_END()
1929 #undef TILE_SEQ_LINE
1930 #undef TILE_SEQ_END
1932 void DrawLevelCrossing(TileInfo *ti)
1934 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
1936 PaletteID pal = PAL_NONE;
1937 const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
1939 if (rti->UsesOverlay()) {
1940 Axis axis = GetCrossingRailAxis(ti->tile);
1942 DrawRoadGroundSprite (ti, GetRoadside(ti->tile), SPR_ROAD_Y + axis, -19, 19);
1944 SpriteID rail = GetCustomRailSprite(rti, ti->tile, RTSG_CROSSING) + axis;
1945 /* Draw tracks, but draw PBS reserved tracks darker. */
1946 pal = (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile)) ? PALETTE_CRASH : PAL_NONE;
1947 DrawGroundSprite (ti, rail, pal);
1949 DrawRailTileSeq (ti, _crossing_layout, TO_CATENARY, rail, 0, PAL_NONE);
1950 } else {
1951 SpriteID image = rti->base_sprites.crossing;
1953 if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++;
1954 if (IsCrossingBarred(ti->tile)) image += 2;
1956 pal = DrawRoadGroundSprite (ti, GetRoadside(ti->tile), image, 4, 8);
1958 /* PBS debugging, draw reserved tracks darker */
1959 if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasCrossingReservation(ti->tile)) {
1960 DrawGroundSprite (ti, GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.single[GetCrossingRailTrack(ti->tile)], PALETTE_CRASH);
1964 if (HasTileRoadType(ti->tile, ROADTYPE_TRAM)) {
1965 DrawGroundSprite (ti, SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal);
1966 DrawRoadCatenary(ti, GetCrossingRoadBits(ti->tile));
1969 if (HasRailCatenaryDrawn (rti)) {
1970 DrawRailAxisCatenary (ti, rti, GetCrossingRailAxis (ti->tile));
1973 DrawBridgeMiddle(ti);
1977 * Updates cached nearest town for all road tiles
1978 * @param invalidate are we just invalidating cached data?
1979 * @pre invalidate == true implies _generating_world == true
1981 void UpdateNearestTownForRoadTiles(bool invalidate)
1983 assert(!invalidate || _generating_world);
1985 for (TileIndex t = 0; t < MapSize(); t++) {
1986 if ((IsRoadTile(t) || IsLevelCrossingTile(t)) && !HasTownOwnedRoad(t)) {
1987 TownID tid = (TownID)INVALID_TOWN;
1988 if (!invalidate) {
1989 const Town *town = CalcClosestTownFromTile(t);
1990 if (town != NULL) tid = town->index;
1992 SetTownIndex(t, tid);
1997 static int GetSlopePixelZ_Road(TileIndex tile, uint x, uint y)
1999 int z;
2000 Slope tileh = GetTilePixelSlope(tile, &z);
2002 if (IsTileSubtype(tile, TT_TRACK)) {
2003 if (tileh == SLOPE_FLAT) return z;
2004 z += ApplyPixelFoundationToSlope(GetRoadFoundation(tileh, GetAllRoadBits(tile)), &tileh);
2005 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
2006 } else if (IsExtendedRoadBridge(tile)) {
2007 return z + (IsSteepSlope(tileh) ? 2 * TILE_HEIGHT : TILE_HEIGHT);
2008 } else {
2009 x &= 0xF;
2010 y &= 0xF;
2012 DiagDirection dir = GetTunnelBridgeDirection(tile);
2014 z += ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh, DiagDirToAxis(dir)), &tileh);
2016 /* On the bridge ramp? */
2017 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x);
2018 if (5 <= pos && pos <= 10) {
2019 return z + ((tileh == SLOPE_FLAT) ? GetBridgePartialPixelZ(dir, x, y) : TILE_HEIGHT);
2022 return z + GetPartialPixelZ(x, y, tileh);
2026 static Foundation GetFoundation_Road(TileIndex tile, Slope tileh)
2028 return IsTileSubtype(tile, TT_TRACK) ? GetRoadFoundation(tileh, GetAllRoadBits(tile)) :
2029 IsExtendedRoadBridge(tile) ? FOUNDATION_LEVELED :
2030 GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(tile)));
2033 static const Roadside _town_road_types[][2] = {
2034 { ROADSIDE_GRASS, ROADSIDE_GRASS },
2035 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2036 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2037 { ROADSIDE_TREES, ROADSIDE_TREES },
2038 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
2041 static const Roadside _town_road_types_2[][2] = {
2042 { ROADSIDE_GRASS, ROADSIDE_GRASS },
2043 { ROADSIDE_PAVED, ROADSIDE_PAVED },
2044 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED },
2045 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED },
2046 { ROADSIDE_STREET_LIGHTS, ROADSIDE_PAVED }
2049 void UpdateRoadSide(TileIndex tile, HouseZonesBits grp)
2051 /* Adjust road ground type depending on 'grp' (grp is the distance to the center) */
2052 const Roadside *new_rs = (_settings_game.game_creation.landscape == LT_TOYLAND) ? _town_road_types_2[grp] : _town_road_types[grp];
2053 Roadside cur_rs = GetRoadside(tile);
2055 /* We have our desired type, do nothing */
2056 if (cur_rs == new_rs[0]) return;
2058 /* We have the pre-type of the desired type, switch to the desired type */
2059 if (cur_rs == new_rs[1]) {
2060 cur_rs = new_rs[0];
2061 /* We have barren land, install the pre-type */
2062 } else if (cur_rs == ROADSIDE_BARREN) {
2063 cur_rs = new_rs[1];
2064 /* We're totally off limits, remove any installation and make barren land */
2065 } else {
2066 cur_rs = ROADSIDE_BARREN;
2069 SetRoadside(tile, cur_rs);
2070 MarkTileDirtyByTile(tile);
2073 static void TileLoop_Road(TileIndex tile)
2075 switch (_settings_game.game_creation.landscape) {
2076 case LT_ARCTIC: {
2077 int z = IsTileSubtype(tile, TT_TRACK) ? GetTileZ(tile) : GetTileMaxZ(tile);
2078 if (IsOnSnow(tile) != (z > GetSnowLine())) {
2079 ToggleSnow(tile);
2080 MarkTileDirtyByTile(tile);
2082 break;
2085 case LT_TROPIC:
2086 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
2087 ToggleDesert(tile);
2088 MarkTileDirtyByTile(tile);
2090 break;
2093 if (!IsTileSubtype(tile, TT_TRACK)) return;
2095 const Town *t = ClosestTownFromTile(tile);
2096 if (!HasRoadWorks(tile)) {
2097 HouseZonesBits grp = HZB_TOWN_EDGE;
2099 if (t != NULL) {
2100 grp = GetTownRadiusGroup(t, tile);
2102 /* Show an animation to indicate road work */
2103 if (t->road_build_months != 0 &&
2104 (DistanceManhattan(t->xy, tile) < 8 || grp != HZB_TOWN_EDGE) &&
2105 !HasAtMostOneBit(GetAllRoadBits(tile)) &&
2106 GetFoundationSlope(tile) == SLOPE_FLAT &&
2107 EnsureNoVehicleOnGround(tile).Succeeded() &&
2108 Chance16(1, 40)) {
2109 StartRoadWorks(tile);
2110 /* Remove any trees or lamps in case or roadwork */
2111 switch (GetRoadside(tile)) {
2112 case ROADSIDE_BARREN:
2113 case ROADSIDE_GRASS: SetRoadside(tile, ROADSIDE_GRASS); break;
2114 default: SetRoadside(tile, ROADSIDE_PAVED); break;
2117 if (_settings_client.sound.ambient) SndPlayTileFx(SND_21_JACKHAMMER, tile);
2118 CreateEffectVehicleAbove(
2119 TileX(tile) * TILE_SIZE + 7,
2120 TileY(tile) * TILE_SIZE + 7,
2122 EV_BULLDOZER);
2123 MarkTileDirtyByTile(tile);
2124 return;
2128 UpdateRoadSide(tile, grp);
2129 } else if (DecreaseRoadWorksCounter(tile)) {
2130 if (_settings_game.economy.mod_road_rebuild) {
2131 /* Generate a nicer town surface */
2132 const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
2133 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
2135 if (old_rb != new_rb) {
2136 RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true);
2140 MarkTileDirtyByTile(tile);
2144 static bool ClickTile_Road(TileIndex tile)
2146 return false;
2149 static TrackStatus GetTileRoadStatus_Road(TileIndex tile, uint sub_mode, DiagDirection side)
2151 /* Converts RoadBits to TrackdirBits */
2152 static const TrackdirBits road_trackdirbits[16] = {
2153 TRACKDIR_BIT_NONE, // ROAD_NONE
2154 TRACKDIR_BIT_NONE, // ROAD_NW
2155 TRACKDIR_BIT_NONE, // ROAD_SW
2156 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_LEFT_N, // ROAD_W
2157 TRACKDIR_BIT_NONE, // ROAD_SE
2158 TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_Y_NW, // ROAD_Y
2159 TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LOWER_W, // ROAD_S
2160 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE
2161 | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_Y_NW, // ROAD_Y | ROAD_SW
2162 TRACKDIR_BIT_NONE, // ROAD_NE
2163 TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_UPPER_W, // ROAD_N
2164 TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW, // ROAD_X
2165 TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_X_NE
2166 | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_X_SW, // ROAD_X | ROAD_NW
2167 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_RIGHT_N, // ROAD_E
2168 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_Y_SE
2169 | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_Y_NW, // ROAD_Y | ROAD_NE
2170 TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_X_NE
2171 | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_X_SW, // ROAD_X | ROAD_SE
2172 TRACKDIR_BIT_MASK, // ROAD_ALL
2175 static const uint drd_mask[DRD_END] = { 0xFFFF, 0xFF00, 0xFF, 0x0 };
2177 if ((GetRoadTypes(tile) & sub_mode) == 0) return 0;
2179 if (IsTileSubtype(tile, TT_TRACK)) {
2180 if (HasRoadWorks(tile)) return 0;
2181 } else {
2182 if (side == GetTunnelBridgeDirection(tile)) return 0;
2185 RoadType rt = (RoadType)FindFirstBit(sub_mode);
2186 RoadBits bits = GetRoadBits(tile, rt);
2188 /* no roadbit at this side of tile, return 0 */
2189 if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) return 0;
2191 TrackdirBits trackdirbits = road_trackdirbits[bits];
2192 if (IsTileSubtype(tile, TT_TRACK) && rt == ROADTYPE_ROAD) trackdirbits &= (TrackdirBits)drd_mask[GetDisallowedRoadDirections(tile)];
2194 return CombineTrackStatus(trackdirbits, TRACKDIR_BIT_NONE);
2197 static const StringID _road_tile_strings[] = {
2198 STR_LAI_ROAD_DESCRIPTION_ROAD,
2199 STR_LAI_ROAD_DESCRIPTION_ROAD,
2200 STR_LAI_ROAD_DESCRIPTION_ROAD,
2201 STR_LAI_ROAD_DESCRIPTION_ROAD_WITH_STREETLIGHTS,
2202 STR_LAI_ROAD_DESCRIPTION_ROAD,
2203 STR_LAI_ROAD_DESCRIPTION_TREE_LINED_ROAD,
2204 STR_LAI_ROAD_DESCRIPTION_ROAD,
2205 STR_LAI_ROAD_DESCRIPTION_ROAD,
2208 static void GetTileDesc_Road(TileIndex tile, TileDesc *td)
2210 RoadTypes rts = GetRoadTypes(tile);
2212 Owner tram_owner = INVALID_OWNER;
2213 if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
2215 if (IsTileSubtype(tile, TT_TRACK)) {
2216 if (!HasBit(rts, ROADTYPE_ROAD)) {
2217 td->str = STR_LAI_ROAD_DESCRIPTION_TRAMWAY;
2218 td->owner[0] = tram_owner;
2219 return;
2221 td->str = _road_tile_strings[GetRoadside(tile)];
2222 } else {
2223 const BridgeSpec *spec = GetBridgeSpec(GetRoadBridgeType(tile));
2224 td->str = spec->transport_name[TRANSPORT_ROAD];
2225 td->road_speed = spec->speed;
2226 if (!HasBit(rts, ROADTYPE_ROAD)) {
2227 td->owner[0] = tram_owner;
2228 return;
2232 /* So the tile at least has a road; check if it has both road and tram */
2233 Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
2235 if (HasBit(rts, ROADTYPE_TRAM)) {
2236 td->owner_type[0] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
2237 td->owner[0] = road_owner;
2238 td->owner_type[1] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
2239 td->owner[1] = tram_owner;
2240 } else {
2241 /* One to rule them all */
2242 td->owner[0] = road_owner;
2247 static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owner)
2249 Company *oldc = Company::Get(old_owner);
2251 Company *newc;
2252 if (new_owner != INVALID_OWNER) {
2253 newc = Company::Get(new_owner);
2254 } else {
2255 new_owner = OWNER_NONE;
2256 newc = NULL;
2259 if (IsTileSubtype(tile, TT_TRACK)) {
2260 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2261 /* Update all roadtypes, no matter if they are present */
2262 if (GetRoadOwner(tile, rt) == old_owner) {
2263 if (HasTileRoadType(tile, rt)) {
2264 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
2265 uint num_bits = CountBits(GetRoadBits(tile, rt));
2266 oldc->infrastructure.road[rt] -= num_bits;
2267 if (newc != NULL) newc->infrastructure.road[rt] += num_bits;
2270 SetRoadOwner(tile, rt, new_owner);
2273 } else {
2274 TileIndex other_end = GetOtherBridgeEnd(tile);
2275 /* Set number of pieces to zero if it's the southern tile as we
2276 * don't want to update the infrastructure counts twice. */
2277 uint len = tile < other_end ? GetTunnelBridgeLength(tile, other_end) * 2 : 0;
2278 RoadBits bridge_piece = DiagDirToRoadBits(GetTunnelBridgeDirection(tile));
2280 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
2281 /* Update all roadtypes, no matter if they are present */
2282 if (GetRoadOwner(tile, rt) == old_owner) {
2283 if (HasBit(GetRoadTypes(tile), rt)) {
2284 /* Update company infrastructure counts.
2285 * No need to dirty windows here, we'll redraw the whole screen anyway. */
2286 RoadBits pieces = GetRoadBits(tile, rt);
2287 uint num_pieces = CountBits(pieces);
2288 if ((pieces & bridge_piece) != 0) {
2289 num_pieces = (num_pieces + len) * TUNNELBRIDGE_TRACKBIT_FACTOR;
2291 oldc->infrastructure.road[rt] -= num_pieces;
2292 if (newc != NULL) newc->infrastructure.road[rt] += num_pieces;
2295 SetRoadOwner(tile, rt, new_owner);
2299 if (IsTileOwner(tile, old_owner)) SetTileOwner(tile, new_owner);
2303 static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
2305 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
2306 if (IsTileSubtype(tile, TT_TRACK)) {
2307 RoadBits bits = GetAllRoadBits(tile);
2308 RoadBits bits_new;
2309 /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */
2310 if (CheckRoadSlope(tileh_new, bits, ROAD_NONE, ROAD_NONE, &bits_new).Succeeded()) {
2311 if (bits == bits_new) {
2312 int z_old;
2313 Slope tileh_old = GetTileSlope(tile, &z_old);
2315 /* Get the slope on top of the foundation */
2316 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old);
2317 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new);
2319 /* The surface slope must not be changed */
2320 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2323 } else if (IsExtendedRoadBridge(tile)) {
2324 if (IsValidRoadBridgeBits(tileh_new, GetTunnelBridgeDirection(tile), GetAllRoadBits(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2325 } else {
2326 int z_old;
2327 Slope tileh_old = GetTileSlope(tile, &z_old);
2329 DiagDirection direction = GetTunnelBridgeDirection(tile);
2331 /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
2332 CheckBridgeSlope(direction, &tileh_old, &z_old);
2333 CommandCost res = CheckBridgeSlope(direction, &tileh_new, &z_new);
2335 /* Surface slope is valid and remains unchanged? */
2336 if (res.Succeeded() && (z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
2340 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
2343 /** Tile callback functions for road tiles */
2344 extern const TileTypeProcs _tile_type_road_procs = {
2345 DrawTile_Road, // draw_tile_proc
2346 GetSlopePixelZ_Road, // get_slope_z_proc
2347 ClearTile_Road, // clear_tile_proc
2348 NULL, // add_accepted_cargo_proc
2349 GetTileDesc_Road, // get_tile_desc_proc
2350 NULL, // get_tile_railway_status_proc
2351 GetTileRoadStatus_Road, // get_tile_road_status_proc
2352 NULL, // get_tile_waterway_status_proc
2353 ClickTile_Road, // click_tile_proc
2354 NULL, // animate_tile_proc
2355 TileLoop_Road, // tile_loop_proc
2356 ChangeTileOwner_Road, // change_tile_owner_proc
2357 NULL, // add_produced_cargo_proc
2358 GetFoundation_Road, // get_foundation_proc
2359 TerraformTile_Road, // terraform_tile_proc