4 * This file is part of OpenTTD.
5 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
10 /** @file misctile_cmd.cpp Handling of misc tiles. */
13 #include "map/zoneheight.h"
17 #include "signal_func.h"
18 #include "command_func.h"
19 #include "company_func.h"
20 #include "vehicle_func.h"
24 #include "depot_base.h"
25 #include "viewport_func.h"
26 #include "newgrf_railtype.h"
27 #include "elrail_func.h"
28 #include "depot_func.h"
29 #include "autoslope.h"
32 #include "tunnelbridge.h"
34 #include "company_base.h"
35 #include "strings_func.h"
36 #include "company_gui.h"
37 #include "cheat_type.h"
38 #include "sound_func.h"
39 #include "newgrf_sound.h"
41 #include "pathfinder/yapf/yapf.h"
43 #include "table/strings.h"
44 #include "table/track_land.h"
45 #include "table/road_land.h"
49 * Draws a tunnel tile.
50 * @param ti TileInfo of the structure to draw
51 * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
53 static void DrawTunnel(TileInfo
*ti
)
55 TransportType transport_type
= GetTunnelTransportType(ti
->tile
);
56 DiagDirection tunnelbridge_direction
= GetTunnelBridgeDirection(ti
->tile
);
58 /* Front view of tunnel bounding boxes:
60 * 122223 <- BB_Z_SEPARATOR
62 * 1 3 1,3 = empty helper BB
63 * 1 3 2 = SpriteCombine of tunnel-roof and catenary (tram & elrail)
67 static const int _tunnel_BB
[4][12] = {
68 /* tunnnel-roof | Z-separator | tram-catenary
69 * w h bb_x bb_y| x y w h |bb_x bb_y w h */
70 { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // NE
71 { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // SE
72 { 1, 0, -15, -14, 0, 15, 16, 1, 0, 1, 16, 15 }, // SW
73 { 0, 1, -14, -15, 15, 0, 1, 16, 1, 0, 15, 16 }, // NW
75 const int *BB_data
= _tunnel_BB
[tunnelbridge_direction
];
77 bool catenary
= false;
80 SpriteID railtype_overlay
= 0;
81 if (transport_type
== TRANSPORT_RAIL
) {
82 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
83 image
= rti
->base_sprites
.tunnel
;
84 if (rti
->UsesOverlay()) {
85 /* Check if the railtype has custom tunnel portals. */
86 railtype_overlay
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_TUNNEL_PORTAL
);
87 if (railtype_overlay
!= 0) image
= SPR_RAILTYPE_TUNNEL_BASE
; // Draw blank grass tunnel base.
90 image
= SPR_TUNNEL_ENTRY_REAR_ROAD
;
93 if (IsOnSnow(ti
->tile
)) image
+= railtype_overlay
!= 0 ? 8 : 32;
95 image
+= tunnelbridge_direction
* 2;
96 DrawGroundSprite(image
, PAL_NONE
);
98 /* PBS debugging, draw reserved tracks darker */
99 if (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& (transport_type
== TRANSPORT_RAIL
&& HasTunnelHeadReservation(ti
->tile
))) {
100 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
101 DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction
) == AXIS_X
? rti
->base_sprites
.single_x
: rti
->base_sprites
.single_y
, PALETTE_CRASH
);
104 if (transport_type
== TRANSPORT_ROAD
) {
105 RoadTypes rts
= GetRoadTypes(ti
->tile
);
107 if (HasBit(rts
, ROADTYPE_TRAM
)) {
108 static const SpriteID tunnel_sprites
[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
110 DrawGroundSprite(SPR_TRAMWAY_BASE
+ tunnel_sprites
[rts
- ROADTYPES_TRAM
][tunnelbridge_direction
], PAL_NONE
);
112 /* Do not draw wires if they are invisible */
113 if (!IsInvisibilitySet(TO_CATENARY
)) {
115 StartSpriteCombine();
116 AddSortableSpriteToDraw(SPR_TRAMWAY_TUNNEL_WIRES
+ tunnelbridge_direction
, PAL_NONE
, ti
->x
, ti
->y
, BB_data
[10], BB_data
[11], TILE_HEIGHT
, ti
->z
, IsTransparencySet(TO_CATENARY
), BB_data
[8], BB_data
[9], BB_Z_SEPARATOR
);
120 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
121 if (rti
->UsesOverlay()) {
122 SpriteID surface
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_TUNNEL
);
123 if (surface
!= 0) DrawGroundSprite(surface
+ tunnelbridge_direction
, PAL_NONE
);
126 if (HasCatenaryDrawn(GetRailType(ti
->tile
))) {
127 /* Maybe draw pylons on the entry side */
131 StartSpriteCombine();
132 /* Draw wire above the ramp */
133 DrawCatenaryOnTunnel(ti
);
136 if (maptile_has_tunnel_signals(ti
->tile
)) {
137 static const struct {
138 Point pos
[2][2]; // signal position (outwards, inwards), (left side, right side)
139 uint image
; // offset from base signal sprite
140 } SignalData
[DIAGDIR_END
] = {
141 { { { { 0, 3}, { 0, 13} }, { {15, 3}, {15, 13} } }, 0 }, // DIAGDIR_NE
142 { { { { 3, 15}, {13, 15} }, { { 3, 0}, {13, 0} } }, 2 }, // DIAGDIR_SE
143 { { { {15, 13}, {15, 3} }, { { 0, 13}, { 0, 3} } }, 1 }, // DIAGDIR_SW
144 { { { {13, 0}, { 3, 0} }, { {13, 15}, { 3, 15} } }, 3 }, // DIAGDIR_NW
147 assert(maptile_has_tunnel_signal(ti
->tile
, true) != maptile_has_tunnel_signal(ti
->tile
, false));
149 DiagDirection dd
= tunnelbridge_direction
;
150 bool inwards
= maptile_has_tunnel_signal(ti
->tile
, true);
151 if (!inwards
) dd
= ReverseDiagDir(dd
);
153 SignalType type
= maptile_get_tunnel_signal_type(ti
->tile
);
154 SignalVariant variant
= maptile_get_tunnel_signal_variant(ti
->tile
);
155 SignalState condition
= maptile_get_tunnel_signal_state(ti
->tile
, inwards
);
157 assert(type
== SIGTYPE_NORMAL
|| (!inwards
&& type
== SIGTYPE_PBS_ONEWAY
));
159 SpriteID sprite
= GetCustomSignalSprite(GetRailTypeInfo(GetRailType(ti
->tile
)), ti
->tile
, type
, variant
, condition
);
160 uint image
= SignalData
[dd
].image
;
164 /* Normal electric signals are stored in a different sprite block than all other signals. */
165 sprite
= (type
== SIGTYPE_NORMAL
&& variant
== SIG_ELECTRIC
) ? SPR_ORIGINAL_SIGNALS_BASE
: SPR_SIGNALS_BASE
- 16;
166 sprite
+= (type
== SIGTYPE_NORMAL
? SIGTYPE_NORMAL
* 16 : SIGTYPE_PBS_ONEWAY
* 16 + 64) + variant
* 64 + image
* 2 + condition
;
170 switch (_settings_game
.construction
.train_signal_side
) {
171 case 0: side
= false; break; // left
172 case 2: side
= true; break; // right
173 default: side
= _settings_game
.vehicle
.road_side
!= 0; break; // driving side
175 uint x
= TileX(ti
->tile
) * TILE_SIZE
+ SignalData
[dd
].pos
[inwards
][side
].x
;
176 uint y
= TileY(ti
->tile
) * TILE_SIZE
+ SignalData
[dd
].pos
[inwards
][side
].y
;
178 AddSortableSpriteToDraw(sprite
, PAL_NONE
, x
, y
, 1, 1, BB_HEIGHT_UNDER_BRIDGE
, ti
->z
);
182 if (railtype_overlay
!= 0 && !catenary
) StartSpriteCombine();
184 AddSortableSpriteToDraw(image
+ 1, PAL_NONE
, ti
->x
+ TILE_SIZE
- 1, ti
->y
+ TILE_SIZE
- 1, BB_data
[0], BB_data
[1], TILE_HEIGHT
, ti
->z
, false, BB_data
[2], BB_data
[3], BB_Z_SEPARATOR
);
185 /* Draw railtype tunnel portal overlay if defined. */
186 if (railtype_overlay
!= 0) AddSortableSpriteToDraw(railtype_overlay
+ tunnelbridge_direction
, PAL_NONE
, ti
->x
+ TILE_SIZE
- 1, ti
->y
+ TILE_SIZE
- 1, BB_data
[0], BB_data
[1], TILE_HEIGHT
, ti
->z
, false, BB_data
[2], BB_data
[3], BB_Z_SEPARATOR
);
188 if (catenary
|| railtype_overlay
!= 0) EndSpriteCombine();
190 /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
191 AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX
, PAL_NONE
, ti
->x
, ti
->y
, BB_data
[6], BB_data
[7], TILE_HEIGHT
, ti
->z
);
192 AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX
, PAL_NONE
, ti
->x
+ BB_data
[4], ti
->y
+ BB_data
[5], BB_data
[6], BB_data
[7], TILE_HEIGHT
, ti
->z
);
194 DrawBridgeMiddle(ti
);
197 static void DrawTrainDepot(TileInfo
*ti
)
199 assert(IsRailDepotTile(ti
->tile
));
201 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
203 uint32 palette
= COMPANY_SPRITE_COLOUR(GetTileOwner(ti
->tile
));
206 const DrawTileSprites
*dts
;
207 PaletteID pal
= PAL_NONE
;
210 if (ti
->tileh
!= SLOPE_FLAT
) DrawFoundation(ti
, FOUNDATION_LEVELED
);
212 if (IsInvisibilitySet(TO_BUILDINGS
)) {
213 /* Draw rail instead of depot */
214 dts
= &_depot_invisible_gfx_table
[GetGroundDepotDirection(ti
->tile
)];
216 dts
= &_depot_gfx_table
[GetGroundDepotDirection(ti
->tile
)];
220 if (rti
->UsesOverlay()) {
221 image
= SPR_FLAT_GRASS_TILE
;
223 image
= dts
->ground
.sprite
;
224 if (image
!= SPR_FLAT_GRASS_TILE
) image
+= rti
->GetRailtypeSpriteOffset();
227 /* adjust ground tile for desert
228 * don't adjust for snow, because snow in depots looks weird */
229 if (IsOnSnow(ti
->tile
) && _settings_game
.game_creation
.landscape
== LT_TROPIC
) {
230 if (image
!= SPR_FLAT_GRASS_TILE
) {
231 image
+= rti
->snow_offset
; // tile with tracks
233 image
= SPR_FLAT_SNOW_DESERT_TILE
; // flat ground
237 DrawGroundSprite(image
, GroundSpritePaletteTransform(image
, pal
, palette
));
239 if (rti
->UsesOverlay()) {
240 SpriteID ground
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_GROUND
);
242 switch (GetGroundDepotDirection(ti
->tile
)) {
243 case DIAGDIR_NE
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
244 case DIAGDIR_SW
: DrawGroundSprite(ground
+ RTO_X
, PAL_NONE
); break;
245 case DIAGDIR_NW
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
246 case DIAGDIR_SE
: DrawGroundSprite(ground
+ RTO_Y
, PAL_NONE
); break;
250 if (_settings_client
.gui
.show_track_reservation
&& HasDepotReservation(ti
->tile
)) {
251 SpriteID overlay
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_OVERLAY
);
253 switch (GetGroundDepotDirection(ti
->tile
)) {
254 case DIAGDIR_NE
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
255 case DIAGDIR_SW
: DrawGroundSprite(overlay
+ RTO_X
, PALETTE_CRASH
); break;
256 case DIAGDIR_NW
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
257 case DIAGDIR_SE
: DrawGroundSprite(overlay
+ RTO_Y
, PALETTE_CRASH
); break;
262 /* PBS debugging, draw reserved tracks darker */
263 if (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
&& HasDepotReservation(ti
->tile
)) {
264 switch (GetGroundDepotDirection(ti
->tile
)) {
265 case DIAGDIR_NE
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
266 case DIAGDIR_SW
: DrawGroundSprite(rti
->base_sprites
.single_x
, PALETTE_CRASH
); break;
267 case DIAGDIR_NW
: if (!IsInvisibilitySet(TO_BUILDINGS
)) break; // else FALL THROUGH
268 case DIAGDIR_SE
: DrawGroundSprite(rti
->base_sprites
.single_y
, PALETTE_CRASH
); break;
274 int depot_sprite
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_DEPOT
);
275 relocation
= depot_sprite
!= 0 ? depot_sprite
- SPR_RAIL_DEPOT_SE_1
: rti
->GetRailtypeSpriteOffset();
277 if (HasCatenaryDrawn(GetRailType(ti
->tile
))) DrawCatenary(ti
);
279 DrawRailTileSeq(ti
, dts
, TO_BUILDINGS
, relocation
, 0, palette
);
282 void DrawTrainDepotSprite(int x
, int y
, int dir
, RailType railtype
)
284 const DrawTileSprites
*dts
= &_depot_gfx_table
[dir
];
285 const RailtypeInfo
*rti
= GetRailTypeInfo(railtype
);
286 SpriteID image
= rti
->UsesOverlay() ? SPR_FLAT_GRASS_TILE
: dts
->ground
.sprite
;
287 uint32 offset
= rti
->GetRailtypeSpriteOffset();
292 if (image
!= SPR_FLAT_GRASS_TILE
) image
+= offset
;
293 PaletteID palette
= COMPANY_SPRITE_COLOUR(_local_company
);
295 DrawSprite(image
, PAL_NONE
, x
, y
);
297 if (rti
->UsesOverlay()) {
298 SpriteID ground
= GetCustomRailSprite(rti
, INVALID_TILE
, RTSG_GROUND
);
301 case DIAGDIR_SW
: DrawSprite(ground
+ RTO_X
, PAL_NONE
, x
, y
); break;
302 case DIAGDIR_SE
: DrawSprite(ground
+ RTO_Y
, PAL_NONE
, x
, y
); break;
307 int depot_sprite
= GetCustomRailSprite(rti
, INVALID_TILE
, RTSG_DEPOT
);
308 if (depot_sprite
!= 0) offset
= depot_sprite
- SPR_RAIL_DEPOT_SE_1
;
310 DrawRailTileSeqInGUI(x
, y
, dts
, offset
, 0, palette
);
313 static void DrawRoadDepot(TileInfo
*ti
)
315 assert(IsRoadDepotTile(ti
->tile
));
317 if (ti
->tileh
!= SLOPE_FLAT
) DrawFoundation(ti
, FOUNDATION_LEVELED
);
319 PaletteID palette
= COMPANY_SPRITE_COLOUR(GetTileOwner(ti
->tile
));
321 const DrawTileSprites
*dts
;
322 if (HasTileRoadType(ti
->tile
, ROADTYPE_TRAM
)) {
323 dts
= &_tram_depot
[GetGroundDepotDirection(ti
->tile
)];
325 dts
= &_road_depot
[GetGroundDepotDirection(ti
->tile
)];
328 DrawGroundSprite(dts
->ground
.sprite
, PAL_NONE
);
329 DrawOrigTileSeq(ti
, dts
, TO_BUILDINGS
, palette
);
333 * Draw the road depot sprite.
334 * @param x The x offset to draw at.
335 * @param y The y offset to draw at.
336 * @param dir The direction the depot must be facing.
337 * @param rt The road type of the depot to draw.
339 void DrawRoadDepotSprite(int x
, int y
, DiagDirection dir
, RoadType rt
)
341 PaletteID palette
= COMPANY_SPRITE_COLOUR(_local_company
);
342 const DrawTileSprites
*dts
= (rt
== ROADTYPE_TRAM
) ? &_tram_depot
[dir
] : &_road_depot
[dir
];
347 DrawSprite(dts
->ground
.sprite
, PAL_NONE
, x
, y
);
348 DrawOrigTileSeqInGUI(x
, y
, dts
, palette
);
351 static void DrawTile_Misc(TileInfo
*ti
)
353 switch (GetTileSubtype(ti
->tile
)) {
354 default: NOT_REACHED();
356 case TT_MISC_CROSSING
:
357 DrawLevelCrossing(ti
);
360 case TT_MISC_AQUEDUCT
:
361 DrawAqueductRamp(ti
);
362 DrawBridgeMiddle(ti
);
370 if (IsRailDepot(ti
->tile
)) {
379 static int GetSlopePixelZ_Misc(TileIndex tile
, uint x
, uint y
)
381 switch (GetTileSubtype(tile
)) {
382 case TT_MISC_AQUEDUCT
: {
384 Slope tileh
= GetTilePixelSlope(tile
, &z
);
389 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
391 z
+= ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh
, DiagDirToAxis(dir
)), &tileh
);
393 /* On the bridge ramp? */
394 uint pos
= (DiagDirToAxis(dir
) == AXIS_X
? y
: x
);
395 if (5 <= pos
&& pos
<= 10) {
396 return z
+ ((tileh
== SLOPE_FLAT
) ? GetBridgePartialPixelZ(dir
, x
, y
) : TILE_HEIGHT
);
399 return z
+ GetPartialPixelZ(x
, y
, tileh
);
402 case TT_MISC_TUNNEL
: {
404 Slope tileh
= GetTilePixelSlope(tile
, &z
);
409 /* In the tunnel entrance? */
410 uint pos
= (DiagDirToAxis(GetTunnelBridgeDirection(tile
)) == AXIS_X
? y
: x
);
411 if (5 <= pos
&& pos
<= 10) return z
;
413 return z
+ GetPartialPixelZ(x
, y
, tileh
);
416 default: // TT_MISC_CROSSING, TT_MISC_DEPOT
417 return GetTileMaxPixelZ(tile
);
423 * Remove a tunnel from the game.
424 * @param tile Tile containing one of the endpoints.
425 * @param flags Command flags.
426 * @return Succeeded or failed command.
428 static CommandCost
RemoveTunnel(TileIndex tile
, DoCommandFlag flags
)
430 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST
);
432 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
433 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
434 CommandCost ret
= CheckOwnership(GetTileOwner(tile
));
435 if (ret
.Failed()) return ret
;
437 RoadTypes rts
= GetRoadTypes(tile
);
438 Owner road_owner
= _current_company
;
439 Owner tram_owner
= _current_company
;
441 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
442 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
444 /* We can remove unowned road and if the town allows it */
445 if (road_owner
== OWNER_TOWN
&& !(_settings_game
.construction
.extra_dynamite
|| _cheats
.magic_bulldozer
.value
)) {
446 CommandCost ret
= CheckTileOwnership(tile
);
447 if (ret
.Failed()) return ret
;
449 if (road_owner
== OWNER_NONE
|| road_owner
== OWNER_TOWN
) road_owner
= _current_company
;
450 if (tram_owner
== OWNER_NONE
) tram_owner
= _current_company
;
452 CommandCost ret
= CheckOwnership(road_owner
, tile
);
453 if (ret
.Failed()) return ret
;
454 ret
= CheckOwnership(tram_owner
, tile
);
455 if (ret
.Failed()) return ret
;
460 TileIndex endtile
= GetOtherTunnelEnd(tile
);
462 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
463 if (ret
.Failed()) return ret
;
465 _build_tunnel_endtile
= endtile
;
468 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
469 t
= ClosestTownFromTile(tile
); // town penalty rating
471 /* Check if you are allowed to remove the tunnel owned by a town
472 * Removal depends on difficulty settings */
473 CommandCost ret
= CheckforTownRating(flags
, t
, TUNNELBRIDGE_REMOVE
);
474 if (ret
.Failed()) return ret
;
477 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
478 * you have a "Poor" (0) town rating */
479 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
480 ChangeTownRating(t
, RATING_TUNNEL_BRIDGE_DOWN_STEP
, RATING_TUNNEL_BRIDGE_MINIMUM
, flags
);
483 uint len
= GetTunnelBridgeLength(tile
, endtile
) + 2; // Don't forget the end tiles.
484 uint nsignals
= GetTunnelTransportType(tile
) != TRANSPORT_RAIL
? 0 :
485 (maptile_has_tunnel_signals(tile
) ? 1 : 0) + (maptile_has_tunnel_signals(endtile
) ? 1 : 0);
487 if (flags
& DC_EXEC
) {
488 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
489 /* We first need to request values before calling DoClearSquare */
490 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
491 Track track
= DiagDirToDiagTrack(dir
);
492 Owner owner
= GetTileOwner(tile
);
497 if (HasTunnelHeadReservation(tile
)) {
498 v1
= GetTrainForReservation(tile
, track
);
499 if (v1
!= NULL
) FreeTrainTrackReservation(v1
);
502 if (HasTunnelHeadReservation(endtile
)) {
503 v2
= GetTrainForReservation(endtile
, track
);
504 if (v2
!= NULL
) FreeTrainTrackReservation(v2
);
507 if (Company::IsValidID(owner
)) {
508 Company::Get(owner
)->infrastructure
.rail
[GetRailType(tile
)] -= len
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
509 DirtyCompanyInfrastructureWindows(owner
);
513 DoClearSquare(endtile
);
515 /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
516 AddSideToSignalBuffer(tile
, ReverseDiagDir(dir
), owner
);
517 AddSideToSignalBuffer(endtile
, dir
, owner
);
519 YapfNotifyTrackLayoutChange(tile
, track
);
520 YapfNotifyTrackLayoutChange(endtile
, track
);
522 if (v1
!= NULL
) TryPathReserve(v1
);
523 if (v2
!= NULL
) TryPathReserve(v2
);
526 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
527 /* A full diagonal road tile has two road bits. */
528 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
530 c
->infrastructure
.road
[rt
] -= len
* 2 * TUNNELBRIDGE_TRACKBIT_FACTOR
;
531 DirtyCompanyInfrastructureWindows(c
->index
);
536 DoClearSquare(endtile
);
540 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_TUNNEL
] * len
+ _price
[PR_CLEAR_SIGNALS
] * nsignals
);
543 static CommandCost
RemoveTrainDepot(TileIndex tile
, DoCommandFlag flags
)
545 if (_current_company
!= OWNER_WATER
) {
546 CommandCost ret
= CheckTileOwnership(tile
);
547 if (ret
.Failed()) return ret
;
550 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
551 if (ret
.Failed()) return ret
;
553 if (flags
& DC_EXEC
) {
554 /* read variables before the depot is removed */
555 DiagDirection dir
= GetGroundDepotDirection(tile
);
556 Owner owner
= GetTileOwner(tile
);
559 if (HasDepotReservation(tile
)) {
560 v
= GetTrainForReservation(tile
, DiagDirToDiagTrack(dir
));
561 if (v
!= NULL
) FreeTrainTrackReservation(v
);
564 Company::Get(owner
)->infrastructure
.rail
[GetRailType(tile
)]--;
565 DirtyCompanyInfrastructureWindows(owner
);
567 delete Depot::GetByTile(tile
);
569 AddSideToSignalBuffer(tile
, dir
, owner
);
570 YapfNotifyTrackLayoutChange(tile
, DiagDirToDiagTrack(dir
));
571 if (v
!= NULL
) TryPathReserve(v
, true);
574 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_DEPOT_TRAIN
]);
577 static CommandCost
RemoveRoadDepot(TileIndex tile
, DoCommandFlag flags
)
579 if (_current_company
!= OWNER_WATER
) {
580 CommandCost ret
= CheckTileOwnership(tile
);
581 if (ret
.Failed()) return ret
;
584 CommandCost ret
= EnsureNoVehicleOnGround(tile
);
585 if (ret
.Failed()) return ret
;
587 if (flags
& DC_EXEC
) {
588 Company
*c
= Company::GetIfValid(GetTileOwner(tile
));
590 /* A road depot has two road bits. */
591 c
->infrastructure
.road
[FIND_FIRST_BIT(GetRoadTypes(tile
))] -= 2;
592 DirtyCompanyInfrastructureWindows(c
->index
);
595 delete Depot::GetByTile(tile
);
599 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_DEPOT_ROAD
]);
602 extern CommandCost
RemoveRoad(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool crossing_check
, bool town_check
= true);
604 static CommandCost
ClearTile_Misc(TileIndex tile
, DoCommandFlag flags
)
606 switch (GetTileSubtype(tile
)) {
607 default: NOT_REACHED();
609 case TT_MISC_CROSSING
: {
610 RoadTypes rts
= GetRoadTypes(tile
);
611 CommandCost
ret(EXPENSES_CONSTRUCTION
);
613 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST
);
615 /* Must iterate over the roadtypes in a reverse manner because
616 * tram tracks must be removed before the road bits. */
617 RoadType rt
= ROADTYPE_TRAM
;
619 if (HasBit(rts
, rt
)) {
620 CommandCost tmp_ret
= RemoveRoad(tile
, flags
, GetCrossingRoadBits(tile
), rt
, false);
621 if (tmp_ret
.Failed()) return tmp_ret
;
622 ret
.AddCost(tmp_ret
);
624 } while (rt
-- != ROADTYPE_ROAD
);
626 if (flags
& DC_EXEC
) {
627 DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
632 case TT_MISC_AQUEDUCT
: {
633 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
635 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
636 Owner owner
= GetTileOwner(tile
);
637 if (owner
!= OWNER_NONE
) {
638 CommandCost ret
= CheckOwnership(owner
);
639 if (ret
.Failed()) return ret
;
643 TileIndex endtile
= GetOtherBridgeEnd(tile
);
645 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
646 if (ret
.Failed()) return ret
;
648 uint len
= GetTunnelBridgeLength(tile
, endtile
) + 2; // Don't forget the end tiles.
650 if (flags
& DC_EXEC
) {
651 /* Update company infrastructure counts. */
652 Owner owner
= GetTileOwner(tile
);
653 if (Company::IsValidID(owner
)) Company::Get(owner
)->infrastructure
.water
-= len
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
654 DirtyCompanyInfrastructureWindows(owner
);
656 RemoveBridgeMiddleTiles(tile
, endtile
);
658 DoClearSquare(endtile
);
661 return CommandCost(EXPENSES_CONSTRUCTION
, len
* _price
[PR_CLEAR_AQUEDUCT
]);
665 return RemoveTunnel(tile
, flags
);
668 if (flags
& DC_AUTO
) {
669 if (!IsTileOwner(tile
, _current_company
)) {
670 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
672 return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED
);
674 return IsRailDepot(tile
) ? RemoveTrainDepot(tile
, flags
) : RemoveRoadDepot(tile
, flags
);
679 static void GetTileDesc_Misc(TileIndex tile
, TileDesc
*td
)
681 switch (GetTileSubtype(tile
)) {
682 default: NOT_REACHED();
684 case TT_MISC_CROSSING
: {
685 td
->str
= STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING
;
687 RoadTypes rts
= GetRoadTypes(tile
);
688 Owner road_owner
= HasBit(rts
, ROADTYPE_ROAD
) ? GetRoadOwner(tile
, ROADTYPE_ROAD
) : INVALID_OWNER
;
689 Owner tram_owner
= HasBit(rts
, ROADTYPE_TRAM
) ? GetRoadOwner(tile
, ROADTYPE_TRAM
) : INVALID_OWNER
;
690 Owner rail_owner
= GetTileOwner(tile
);
692 td
->rail_speed
= GetRailTypeInfo(GetRailType(tile
))->max_speed
;
694 Owner first_owner
= (road_owner
== INVALID_OWNER
? tram_owner
: road_owner
);
695 bool mixed_owners
= (tram_owner
!= INVALID_OWNER
&& tram_owner
!= first_owner
) || (rail_owner
!= INVALID_OWNER
&& rail_owner
!= first_owner
);
698 /* Multiple owners */
699 td
->owner_type
[0] = (rail_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_RAIL_OWNER
);
700 td
->owner
[0] = rail_owner
;
701 td
->owner_type
[1] = (road_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_ROAD_OWNER
);
702 td
->owner
[1] = road_owner
;
703 td
->owner_type
[2] = (tram_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_TRAM_OWNER
);
704 td
->owner
[2] = tram_owner
;
706 /* One to rule them all */
707 td
->owner
[0] = first_owner
;
713 case TT_MISC_AQUEDUCT
:
714 td
->str
= STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT
;
715 td
->owner
[0] = GetTileOwner(tile
);
719 td
->owner
[0] = GetTileOwner(tile
);
721 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
722 td
->str
= STR_LAI_TUNNEL_DESCRIPTION_RAILROAD
;
723 td
->rail_speed
= GetRailTypeInfo(GetRailType(tile
))->max_speed
;
725 td
->str
= STR_LAI_TUNNEL_DESCRIPTION_ROAD
;
727 Owner road_owner
= INVALID_OWNER
;
728 Owner tram_owner
= INVALID_OWNER
;
729 RoadTypes rts
= GetRoadTypes(tile
);
730 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
731 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
733 /* Is there a mix of owners? */
734 if ((tram_owner
!= INVALID_OWNER
&& tram_owner
!= td
->owner
[0]) ||
735 (road_owner
!= INVALID_OWNER
&& road_owner
!= td
->owner
[0])) {
737 if (road_owner
!= INVALID_OWNER
) {
738 td
->owner_type
[i
] = STR_LAND_AREA_INFORMATION_ROAD_OWNER
;
739 td
->owner
[i
] = road_owner
;
742 if (tram_owner
!= INVALID_OWNER
) {
743 td
->owner_type
[i
] = STR_LAND_AREA_INFORMATION_TRAM_OWNER
;
744 td
->owner
[i
] = tram_owner
;
752 td
->owner
[0] = GetTileOwner(tile
);
753 td
->build_date
= Depot::GetByTile(tile
)->build_date
;
755 if (IsRailDepot(tile
)) {
756 td
->str
= STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT
;
758 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(tile
));
759 SetDParamX(td
->dparam
, 0, rti
->strings
.name
);
760 td
->rail_speed
= rti
->max_speed
;
762 if (_settings_game
.vehicle
.train_acceleration_model
!= AM_ORIGINAL
) {
763 if (td
->rail_speed
> 0) {
764 td
->rail_speed
= min(td
->rail_speed
, 61);
770 td
->str
= STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT
;
778 static TrackStatus
GetTileRailwayStatus_Misc(TileIndex tile
, DiagDirection side
)
780 switch (GetTileSubtype(tile
)) {
781 default: NOT_REACHED();
783 case TT_MISC_CROSSING
:
784 return CombineTrackStatus(TrackBitsToTrackdirBits(GetCrossingRailBits(tile
)), TRACKDIR_BIT_NONE
);
786 case TT_MISC_AQUEDUCT
:
789 case TT_MISC_TUNNEL
: {
790 if (GetTunnelTransportType(tile
) != TRANSPORT_RAIL
) return 0;
792 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
793 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return 0;
795 TrackdirBits trackdirs
= TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
));
796 TrackdirBits red_signals
;
797 switch (maptile_get_tunnel_present_signals(tile
)) {
798 default: NOT_REACHED();
800 case 0: red_signals
= TRACKDIR_BIT_NONE
; break;
803 red_signals
= maptile_get_tunnel_signal_state(tile
, false) == SIGNAL_STATE_RED
? trackdirs
:
804 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(dir
));
808 red_signals
= maptile_get_tunnel_signal_state(tile
, true) == SIGNAL_STATE_RED
? trackdirs
:
809 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(ReverseDiagDir(dir
)));
813 return CombineTrackStatus(trackdirs
, red_signals
);
816 case TT_MISC_DEPOT
: {
817 if (!IsRailDepot(tile
)) return 0;
819 DiagDirection dir
= GetGroundDepotDirection(tile
);
820 if (side
!= INVALID_DIAGDIR
&& side
!= dir
) return 0;
821 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
826 static TrackStatus
GetTileRoadStatus_Misc(TileIndex tile
, uint sub_mode
, DiagDirection side
)
828 switch (GetTileSubtype(tile
)) {
829 default: NOT_REACHED();
831 case TT_MISC_CROSSING
: {
832 if ((GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
834 Axis axis
= GetCrossingRoadAxis(tile
);
835 if (side
!= INVALID_DIAGDIR
&& axis
!= DiagDirToAxis(side
)) return 0;
837 TrackdirBits trackdirbits
= TrackBitsToTrackdirBits(AxisToTrackBits(axis
));
838 return CombineTrackStatus(trackdirbits
, IsCrossingBarred(tile
) ? trackdirbits
: TRACKDIR_BIT_NONE
);
841 case TT_MISC_AQUEDUCT
:
844 case TT_MISC_TUNNEL
: {
845 TransportType transport_type
= GetTunnelTransportType(tile
);
846 if (transport_type
!= TRANSPORT_ROAD
|| (GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
848 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
849 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return 0;
850 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
853 case TT_MISC_DEPOT
: {
854 if (!IsRoadDepot(tile
) || (GetRoadTypes(tile
) & sub_mode
) == 0) {
858 DiagDirection dir
= GetGroundDepotDirection(tile
);
859 if (side
!= INVALID_DIAGDIR
&& side
!= dir
) return 0;
860 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
865 static TrackdirBits
GetTileWaterwayStatus_Misc(TileIndex tile
, DiagDirection side
)
867 if (!IsTileSubtype(tile
, TT_MISC_AQUEDUCT
)) return TRACKDIR_BIT_NONE
;
869 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
870 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return TRACKDIR_BIT_NONE
;
871 return TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
));
875 static bool ClickTile_Misc(TileIndex tile
)
877 if (!IsGroundDepotTile(tile
)) return false;
879 ShowDepotWindow(tile
, IsRailDepot(tile
) ? VEH_TRAIN
: VEH_ROAD
);
884 static void TileLoop_Misc(TileIndex tile
)
886 switch (_settings_game
.game_creation
.landscape
) {
888 int z
= IsTileSubtype(tile
, TT_MISC_AQUEDUCT
) ? GetTileMaxZ(tile
) : GetTileZ(tile
);
889 if (IsOnSnow(tile
) != (z
> GetSnowLine())) {
891 MarkTileDirtyByTile(tile
);
897 if (GetTropicZone(tile
) == TROPICZONE_DESERT
&& !IsOnDesert(tile
)) {
898 SetDesert(tile
, true);
899 MarkTileDirtyByTile(tile
);
904 if (IsTileSubtype(tile
, TT_MISC_CROSSING
)) {
905 const Town
*t
= ClosestTownFromTile(tile
);
906 UpdateRoadSide(tile
, t
!= NULL
? GetTownRadiusGroup(t
, tile
) : HZB_TOWN_EDGE
);
911 static void ChangeTileOwner_Misc(TileIndex tile
, Owner old_owner
, Owner new_owner
)
913 switch (GetTileSubtype(tile
)) {
914 default: NOT_REACHED();
916 case TT_MISC_CROSSING
:
917 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
918 /* Update all roadtypes, no matter if they are present */
919 if (GetRoadOwner(tile
, rt
) == old_owner
) {
920 if (HasTileRoadType(tile
, rt
)) {
921 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
922 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= 2;
923 if (new_owner
!= INVALID_OWNER
) Company::Get(new_owner
)->infrastructure
.road
[rt
] += 2;
926 SetRoadOwner(tile
, rt
, new_owner
== INVALID_OWNER
? OWNER_NONE
: new_owner
);
930 if (GetTileOwner(tile
) == old_owner
) {
931 if (new_owner
== INVALID_OWNER
) {
932 DoCommand(tile
, 0, GetCrossingRailTrack(tile
), DC_EXEC
| DC_BANKRUPT
, CMD_REMOVE_SINGLE_RAIL
);
934 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
935 RailType rt
= GetRailType(tile
);
936 Company::Get(old_owner
)->infrastructure
.rail
[rt
] -= LEVELCROSSING_TRACKBIT_FACTOR
;
937 Company::Get(new_owner
)->infrastructure
.rail
[rt
] += LEVELCROSSING_TRACKBIT_FACTOR
;
939 SetTileOwner(tile
, new_owner
);
945 case TT_MISC_AQUEDUCT
: {
946 if (!IsTileOwner(tile
, old_owner
)) return;
948 TileIndex other_end
= GetOtherTunnelBridgeEnd(tile
);
949 /* Set number of pieces to zero if it's the southern tile as we
950 * don't want to update the infrastructure counts twice. */
951 uint num_pieces
= tile
< other_end
? (GetTunnelBridgeLength(tile
, other_end
) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
: 0;
953 /* Update company infrastructure counts.
954 * No need to dirty windows here, we'll redraw the whole screen anyway. */
955 Company::Get(old_owner
)->infrastructure
.water
-= num_pieces
;
956 if (new_owner
!= INVALID_OWNER
) {
957 Company::Get(new_owner
)->infrastructure
.water
+= num_pieces
;
958 SetTileOwner(tile
, new_owner
);
960 SetTileOwner(tile
, OWNER_NONE
);
965 case TT_MISC_TUNNEL
: {
966 TileIndex other_end
= GetOtherTunnelEnd(tile
);
967 /* Set number of pieces to zero if it's the southern tile as we
968 * don't want to update the infrastructure counts twice. */
969 uint num_pieces
= tile
< other_end
? (GetTunnelBridgeLength(tile
, other_end
) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
: 0;
971 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
972 /* Update all roadtypes, no matter if they are present */
973 if (GetRoadOwner(tile
, rt
) == old_owner
) {
974 if (HasBit(GetRoadTypes(tile
), rt
)) {
975 /* Update company infrastructure counts. A full diagonal road tile has two road bits.
976 * No need to dirty windows here, we'll redraw the whole screen anyway. */
977 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= num_pieces
* 2;
978 if (new_owner
!= INVALID_OWNER
) Company::Get(new_owner
)->infrastructure
.road
[rt
] += num_pieces
* 2;
981 SetRoadOwner(tile
, rt
, new_owner
== INVALID_OWNER
? OWNER_NONE
: new_owner
);
985 if (!IsTileOwner(tile
, old_owner
)) return;
987 /* Update company infrastructure counts for rail and water as well.
988 * No need to dirty windows here, we'll redraw the whole screen anyway. */
989 TransportType tt
= GetTunnelTransportType(tile
);
990 Company
*old
= Company::Get(old_owner
);
991 if (tt
== TRANSPORT_RAIL
) {
992 old
->infrastructure
.rail
[GetRailType(tile
)] -= num_pieces
;
993 if (new_owner
!= INVALID_OWNER
) Company::Get(new_owner
)->infrastructure
.rail
[GetRailType(tile
)] += num_pieces
;
996 if (new_owner
!= INVALID_OWNER
) {
997 SetTileOwner(tile
, new_owner
);
998 } else if (tt
== TRANSPORT_RAIL
) {
999 /* Since all of our vehicles have been removed, it is safe to remove the rail
1001 CommandCost ret
= DoCommand(tile
, 0, 0, DC_EXEC
| DC_BANKRUPT
, CMD_LANDSCAPE_CLEAR
);
1002 assert(ret
.Succeeded());
1004 /* In any other case, we can safely reassign the ownership to OWNER_NONE. */
1005 SetTileOwner(tile
, OWNER_NONE
);
1012 if (!IsTileOwner(tile
, old_owner
)) return;
1014 if (new_owner
!= INVALID_OWNER
) {
1015 /* Update company infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
1016 if (IsRailDepot(tile
)) {
1017 RailType rt
= GetRailType(tile
);
1018 Company::Get(old_owner
)->infrastructure
.rail
[rt
]--;
1019 Company::Get(new_owner
)->infrastructure
.rail
[rt
]++;
1021 /* A road depot has two road bits. */
1022 RoadType rt
= (RoadType
)FIND_FIRST_BIT(GetRoadTypes(tile
));
1023 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= 2;
1024 Company::Get(new_owner
)->infrastructure
.road
[rt
] += 2;
1027 SetTileOwner(tile
, new_owner
);
1029 DoCommand(tile
, 0, 0, DC_EXEC
| DC_BANKRUPT
, CMD_LANDSCAPE_CLEAR
);
1037 * Frame when a vehicle should be hidden in a tunnel with a certain direction.
1038 * This differs per direction, because of visibility / bounding box issues.
1039 * Note that direction, in this case, is the direction leading into the tunnel.
1040 * When entering a tunnel, hide the vehicle when it reaches the given frame.
1041 * When leaving a tunnel, show the vehicle when it is one frame further
1042 * to the 'outside', i.e. at (TILE_SIZE-1) - (frame) + 1
1044 extern const byte _tunnel_visibility_frame
[DIAGDIR_END
] = {12, 8, 8, 12};
1047 static Foundation
GetFoundation_Misc(TileIndex tile
, Slope tileh
)
1049 switch (GetTileSubtype(tile
)) {
1050 case TT_MISC_AQUEDUCT
: return GetBridgeFoundation(tileh
, DiagDirToAxis(GetTunnelBridgeDirection(tile
)));
1051 case TT_MISC_TUNNEL
: return FOUNDATION_NONE
;
1052 default: return FlatteningFoundation(tileh
);
1057 static CommandCost
TerraformTile_Misc(TileIndex tile
, DoCommandFlag flags
, int z_new
, Slope tileh_new
)
1059 if (_settings_game
.construction
.build_on_slopes
&& AutoslopeEnabled()) {
1060 switch (GetTileSubtype(tile
)) {
1063 case TT_MISC_CROSSING
:
1064 if (!IsSteepSlope(tileh_new
) && (GetTileMaxZ(tile
) == z_new
+ GetSlopeMaxZ(tileh_new
)) && HasBit(VALID_LEVEL_CROSSING_SLOPES
, tileh_new
)) return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
1068 if (AutoslopeCheckForEntranceEdge(tile
, z_new
, tileh_new
, GetGroundDepotDirection(tile
))) {
1069 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
1075 return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
1079 extern const TileTypeProcs _tile_type_misc_procs
= {
1080 DrawTile_Misc
, // draw_tile_proc
1081 GetSlopePixelZ_Misc
, // get_slope_z_proc
1082 ClearTile_Misc
, // clear_tile_proc
1083 NULL
, // add_accepted_cargo_proc
1084 GetTileDesc_Misc
, // get_tile_desc_proc
1085 GetTileRailwayStatus_Misc
, // get_tile_railway_status_proc
1086 GetTileRoadStatus_Misc
, // get_tile_road_status_proc
1087 GetTileWaterwayStatus_Misc
, // get_tile_waterway_status_proc
1088 ClickTile_Misc
, // click_tile_proc
1089 NULL
, // animate_tile_proc
1090 TileLoop_Misc
, // tile_loop_proc
1091 ChangeTileOwner_Misc
, // change_tile_owner_proc
1092 NULL
, // add_produced_cargo_proc
1093 GetFoundation_Misc
, // get_foundation_proc
1094 TerraformTile_Misc
, // terraform_tile_proc