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 "signalbuffer.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/road_land.h"
48 * Draws a tunnel tile.
49 * @param ti TileInfo of the structure to draw
50 * Please note that in this code, "roads" are treated as railtype 1, whilst the real railtypes are 0, 2 and 3
52 static void DrawTunnel(TileInfo
*ti
)
54 const RailtypeInfo
*rti
= (GetTunnelTransportType(ti
->tile
) == TRANSPORT_RAIL
) ?
55 GetRailTypeInfo (GetRailType (ti
->tile
)) : NULL
;
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;
82 image
= rti
->base_sprites
.tunnel
;
83 if (rti
->UsesOverlay()) {
84 /* Check if the railtype has custom tunnel portals. */
85 railtype_overlay
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_TUNNEL_PORTAL
);
86 if (railtype_overlay
!= 0) image
= SPR_RAILTYPE_TUNNEL_BASE
; // Draw blank grass tunnel base.
89 image
= SPR_TUNNEL_ENTRY_REAR_ROAD
;
92 if (IsOnSnow(ti
->tile
)) image
+= railtype_overlay
!= 0 ? 8 : 32;
94 image
+= tunnelbridge_direction
* 2;
95 DrawGroundSprite (ti
, image
, PAL_NONE
);
97 /* PBS debugging, draw reserved tracks darker */
98 if (_game_mode
!= GM_MENU
&& _settings_client
.gui
.show_track_reservation
99 && rti
!= NULL
&& HasTunnelHeadReservation (ti
->tile
)) {
100 Axis axis
= DiagDirToAxis (tunnelbridge_direction
);
101 SpriteID image
= rti
->UsesOverlay() ?
102 GetCustomRailSprite (rti
, ti
->tile
, RTSG_OVERLAY
) + RTO_X
+ axis
:
103 rti
->base_sprites
.single
[AxisToTrack(axis
)];
104 DrawGroundSprite (ti
, image
, PALETTE_CRASH
);
108 RoadTypes rts
= GetRoadTypes(ti
->tile
);
110 if (HasBit(rts
, ROADTYPE_TRAM
)) {
111 static const SpriteID tunnel_sprites
[2][4] = { { 28, 78, 79, 27 }, { 5, 76, 77, 4 } };
113 DrawGroundSprite (ti
, SPR_TRAMWAY_BASE
+ tunnel_sprites
[rts
- ROADTYPES_TRAM
][tunnelbridge_direction
], PAL_NONE
);
115 /* Do not draw wires if they are invisible */
116 if (!IsInvisibilitySet(TO_CATENARY
)) {
118 StartSpriteCombine (ti
->vd
);
119 AddSortableSpriteToDraw (ti
->vd
, 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
);
123 if (rti
->UsesOverlay()) {
124 SpriteID surface
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_TUNNEL
);
125 if (surface
!= 0) DrawGroundSprite (ti
, surface
+ tunnelbridge_direction
, PAL_NONE
);
128 if (HasRailCatenaryDrawn (rti
)) {
129 /* Draw pylon and wire on the entry side. Note that
130 * DrawRailTunnelCatenary calls StartSpriteCombine. */
131 DrawRailTunnelCatenary (ti
, tunnelbridge_direction
);
135 if (maptile_has_tunnel_signals(ti
->tile
)) {
136 static const struct {
137 Point pos
[2][2]; // signal position (outwards, inwards), (left side, right side)
138 uint image
; // offset from base signal sprite
139 } SignalData
[DIAGDIR_END
] = {
140 { { { { 0, 3}, { 0, 13} }, { {15, 3}, {15, 13} } }, 0 }, // DIAGDIR_NE
141 { { { { 3, 15}, {13, 15} }, { { 3, 0}, {13, 0} } }, 2 }, // DIAGDIR_SE
142 { { { {15, 13}, {15, 3} }, { { 0, 13}, { 0, 3} } }, 1 }, // DIAGDIR_SW
143 { { { {13, 0}, { 3, 0} }, { {13, 15}, { 3, 15} } }, 3 }, // DIAGDIR_NW
146 assert(maptile_has_tunnel_signal(ti
->tile
, true) != maptile_has_tunnel_signal(ti
->tile
, false));
148 DiagDirection dd
= tunnelbridge_direction
;
149 bool inwards
= maptile_has_tunnel_signal(ti
->tile
, true);
150 if (!inwards
) dd
= ReverseDiagDir(dd
);
152 SignalType type
= maptile_get_tunnel_signal_type(ti
->tile
);
153 SignalVariant variant
= maptile_get_tunnel_signal_variant(ti
->tile
);
154 SignalState condition
= maptile_get_tunnel_signal_state(ti
->tile
, inwards
);
156 assert(type
== SIGTYPE_NORMAL
|| (!inwards
&& type
== SIGTYPE_PBS_ONEWAY
));
158 SpriteID sprite
= GetCustomSignalSprite(GetRailTypeInfo(GetRailType(ti
->tile
)), ti
->tile
, type
, variant
, condition
);
159 uint image
= SignalData
[dd
].image
;
163 /* Normal electric signals are stored in a different sprite block than all other signals. */
164 sprite
= (type
== SIGTYPE_NORMAL
&& variant
== SIG_ELECTRIC
) ? SPR_ORIGINAL_SIGNALS_BASE
: SPR_SIGNALS_BASE
- 16;
165 sprite
+= (type
== SIGTYPE_NORMAL
? SIGTYPE_NORMAL
* 16 : SIGTYPE_PBS_ONEWAY
* 16 + 64) + variant
* 64 + image
* 2 + condition
;
168 bool side
= (_settings_game
.construction
.train_signal_side
+
169 (_settings_game
.vehicle
.road_side
!= 0)) > 1;
171 uint x
= TileX(ti
->tile
) * TILE_SIZE
+ SignalData
[dd
].pos
[inwards
][side
].x
;
172 uint y
= TileY(ti
->tile
) * TILE_SIZE
+ SignalData
[dd
].pos
[inwards
][side
].y
;
174 AddSortableSpriteToDraw (ti
->vd
, sprite
, PAL_NONE
, x
, y
, 1, 1, BB_HEIGHT_UNDER_BRIDGE
, ti
->z
);
178 if (railtype_overlay
!= 0 && !catenary
) StartSpriteCombine (ti
->vd
);
180 AddSortableSpriteToDraw (ti
->vd
, 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
);
181 /* Draw railtype tunnel portal overlay if defined. */
182 if (railtype_overlay
!= 0) AddSortableSpriteToDraw (ti
->vd
, 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
);
184 if (catenary
|| railtype_overlay
!= 0) EndSpriteCombine (ti
->vd
);
186 /* Add helper BB for sprite sorting that separates the tunnel from things beside of it. */
187 AddSortableSpriteToDraw (ti
->vd
, SPR_EMPTY_BOUNDING_BOX
, PAL_NONE
, ti
->x
, ti
->y
, BB_data
[6], BB_data
[7], TILE_HEIGHT
, ti
->z
);
188 AddSortableSpriteToDraw (ti
->vd
, 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
);
190 DrawBridgeMiddle(ti
);
194 #define TILE_SEQ_LINE(img, dx, dy, sx, sy) \
195 { dx, dy, 0, sx, sy, 23, {(img) | (1 << PALETTE_MODIFIER_COLOUR), PAL_NONE} }
196 #define TILE_SEQ_END() { (int8)0x80, 0, 0, 0, 0, 0, {0, 0} }
198 static const DrawTileSeqStruct _depot_gfx_NE
[] = {
199 TILE_SEQ_LINE(SPR_RAIL_DEPOT_NE
, 2, 13, 13, 1),
203 static const DrawTileSeqStruct _depot_gfx_SE
[] = {
204 TILE_SEQ_LINE(SPR_RAIL_DEPOT_SE_1
, 2, 2, 1, 13),
205 TILE_SEQ_LINE(SPR_RAIL_DEPOT_SE_2
, 13, 2, 1, 13),
209 static const DrawTileSeqStruct _depot_gfx_SW
[] = {
210 TILE_SEQ_LINE(SPR_RAIL_DEPOT_SW_1
, 2, 2, 13, 1),
211 TILE_SEQ_LINE(SPR_RAIL_DEPOT_SW_2
, 2, 13, 13, 1),
215 static const DrawTileSeqStruct _depot_gfx_NW
[] = {
216 TILE_SEQ_LINE(SPR_RAIL_DEPOT_NW
, 13, 2, 1, 13),
223 struct TrainDepotSprites
{
224 SpriteID ground
[2]; ///< Ground sprites, visible and invisible.
225 const DrawTileSeqStruct
*seq
; ///< Array of child sprites.
228 static const TrainDepotSprites _depot_gfx_table
[DIAGDIR_END
] = {
229 { {SPR_FLAT_GRASS_TILE
, SPR_RAIL_TRACK_X
}, _depot_gfx_NE
},
230 { {SPR_RAIL_TRACK_Y
, SPR_RAIL_TRACK_Y
}, _depot_gfx_SE
},
231 { {SPR_RAIL_TRACK_X
, SPR_RAIL_TRACK_X
}, _depot_gfx_SW
},
232 { {SPR_FLAT_GRASS_TILE
, SPR_RAIL_TRACK_Y
}, _depot_gfx_NW
},
235 static void DrawTrainDepot(TileInfo
*ti
)
237 assert(IsRailDepotTile(ti
->tile
));
239 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(ti
->tile
));
241 uint32 palette
= COMPANY_SPRITE_COLOUR(GetTileOwner(ti
->tile
));
245 DiagDirection dir
= GetGroundDepotDirection (ti
->tile
);
247 const TrainDepotSprites
*dts
= &_depot_gfx_table
[dir
];
250 if (rti
->UsesOverlay()) {
251 image
= SPR_FLAT_GRASS_TILE
;
253 /* Draw rail instead of depot if invisible. */
254 image
= dts
->ground
[IsInvisibilitySet(TO_BUILDINGS
)];
255 if (image
!= SPR_FLAT_GRASS_TILE
) image
+= rti
->GetRailtypeSpriteOffset();
258 /* adjust ground tile for desert
259 * don't adjust for snow, because snow in depots looks weird */
260 if (IsOnSnow(ti
->tile
) && _settings_game
.game_creation
.landscape
== LT_TROPIC
) {
261 if (image
!= SPR_FLAT_GRASS_TILE
) {
262 image
+= rti
->snow_offset
; // tile with tracks
264 image
= SPR_FLAT_SNOW_DESERT_TILE
; // flat ground
268 DrawGroundSprite (ti
, image
, GroundSpritePaletteTransform (image
, PAL_NONE
, palette
));
270 Axis axis
= DiagDirToAxis (dir
);
271 if ((dir
== AxisToDiagDir(axis
)) || IsInvisibilitySet(TO_BUILDINGS
)) {
272 /* The depot faces south or buildings are set to invisible. */
273 bool reserved
= false;
275 if (rti
->UsesOverlay()) {
276 assert_compile ((int)AXIS_X
== (int)RTO_X
);
277 assert_compile ((int)AXIS_Y
== (int)RTO_Y
);
279 SpriteID ground
= GetCustomRailSprite (rti
, ti
->tile
, RTSG_GROUND
);
280 DrawGroundSprite (ti
, ground
+ axis
, PAL_NONE
);
282 if (_settings_client
.gui
.show_track_reservation
283 && HasDepotReservation (ti
->tile
)) {
284 overlay
= GetCustomRailSprite (rti
, ti
->tile
,
285 RTSG_OVERLAY
) + axis
;
288 } else if (_game_mode
!= GM_MENU
289 && _settings_client
.gui
.show_track_reservation
290 && HasDepotReservation (ti
->tile
)) {
291 /* PBS debugging, draw reserved tracks darker */
292 overlay
= rti
->base_sprites
.single
[AxisToTrack(axis
)];
296 DrawGroundSprite (ti
, overlay
, PALETTE_CRASH
);
300 if (HasRailCatenaryDrawn (rti
)) DrawRailDepotCatenary (ti
, rti
, dir
);
302 int depot_sprite
= GetCustomRailSprite(rti
, ti
->tile
, RTSG_DEPOT
);
303 SpriteID relocation
= depot_sprite
!= 0 ? depot_sprite
- SPR_RAIL_DEPOT_SE_1
: rti
->GetRailtypeSpriteOffset();
304 DrawRailTileSeq (ti
, dts
->seq
, TO_BUILDINGS
, relocation
, 0, palette
);
307 void DrawTrainDepotSprite (BlitArea
*dpi
, int x
, int y
, int dir
, RailType railtype
)
309 const TrainDepotSprites
*dts
= &_depot_gfx_table
[dir
];
310 const RailtypeInfo
*rti
= GetRailTypeInfo(railtype
);
311 SpriteID image
= rti
->UsesOverlay() ? SPR_FLAT_GRASS_TILE
: dts
->ground
[0];
312 uint32 offset
= rti
->GetRailtypeSpriteOffset();
314 if (image
!= SPR_FLAT_GRASS_TILE
) image
+= offset
;
315 PaletteID palette
= COMPANY_SPRITE_COLOUR(_local_company
);
317 DrawSprite (dpi
, image
, PAL_NONE
, x
, y
);
319 Axis axis
= DiagDirToAxis ((DiagDirection
)dir
);
320 if ((dir
== AxisToDiagDir(axis
)) && rti
->UsesOverlay()) {
321 assert_compile ((int)AXIS_X
== (int)RTO_X
);
322 assert_compile ((int)AXIS_Y
== (int)RTO_Y
);
324 SpriteID ground
= GetCustomRailSprite(rti
, INVALID_TILE
, RTSG_GROUND
);
325 DrawSprite (dpi
, ground
+ axis
, PAL_NONE
, x
, y
);
328 int depot_sprite
= GetCustomRailSprite(rti
, INVALID_TILE
, RTSG_DEPOT
);
329 if (depot_sprite
!= 0) offset
= depot_sprite
- SPR_RAIL_DEPOT_SE_1
;
331 DrawRailTileSeqInGUI (dpi
, x
, y
, dts
->seq
, offset
, 0, palette
);
335 #define TILE_SEQ_LINE(img, pal, dx, dy, sx, sy) \
336 { dx, dy, 0, sx, sy, 20, {(img) | (1 << PALETTE_MODIFIER_COLOUR), pal} }
337 #define TILE_SEQ_END() { (int8)0x80, 0, 0, 0, 0, 0, {0, 0} }
339 static const DrawTileSeqStruct _road_depot_NE
[] = {
340 TILE_SEQ_LINE(0x584, PAL_NONE
, 0, 15, 16, 1),
344 static const DrawTileSeqStruct _road_depot_SE
[] = {
345 TILE_SEQ_LINE(0x580, PAL_NONE
, 0, 0, 1, 16),
346 TILE_SEQ_LINE(0x581, PAL_NONE
, 15, 0, 1, 16),
350 static const DrawTileSeqStruct _road_depot_SW
[] = {
351 TILE_SEQ_LINE(0x582, PAL_NONE
, 0, 0, 16, 1),
352 TILE_SEQ_LINE(0x583, PAL_NONE
, 0, 15, 16, 1),
356 static const DrawTileSeqStruct _road_depot_NW
[] = {
357 TILE_SEQ_LINE(0x585, PAL_NONE
, 15, 0, 1, 16),
361 static const DrawTileSeqStruct _tram_depot_NE
[] = {
362 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x35, PAL_NONE
, 0, 15, 16, 1),
366 static const DrawTileSeqStruct _tram_depot_SE
[] = {
367 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x31, PAL_NONE
, 0, 0, 1, 16),
368 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x32, PAL_NONE
, 15, 0, 1, 16),
372 static const DrawTileSeqStruct _tram_depot_SW
[] = {
373 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x33, PAL_NONE
, 0, 0, 16, 1),
374 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x34, PAL_NONE
, 0, 15, 16, 1),
378 static const DrawTileSeqStruct _tram_depot_NW
[] = {
379 TILE_SEQ_LINE(SPR_TRAMWAY_BASE
+ 0x36, PAL_NONE
, 15, 0, 1, 16),
383 static const DrawTileSeqStruct
*_road_depot
[2][DIAGDIR_END
] = {
384 { _road_depot_NE
, _road_depot_SE
, _road_depot_SW
, _road_depot_NW
},
385 { _tram_depot_NE
, _tram_depot_SE
, _tram_depot_SW
, _tram_depot_NW
},
391 static void DrawRoadDepot(TileInfo
*ti
)
393 assert(IsRoadDepotTile(ti
->tile
));
395 DrawGroundSprite (ti
, 0xA4A, PAL_NONE
);
397 PaletteID palette
= COMPANY_SPRITE_COLOUR(GetTileOwner(ti
->tile
));
398 bool tram
= HasTileRoadType (ti
->tile
, ROADTYPE_TRAM
);
399 DiagDirection dir
= GetGroundDepotDirection (ti
->tile
);
400 DrawOrigTileSeq (ti
, _road_depot
[tram
][dir
], TO_BUILDINGS
, palette
);
404 * Draw the road depot sprite.
405 * @param dpi The area to draw on.
406 * @param x The x offset to draw at.
407 * @param y The y offset to draw at.
408 * @param dir The direction the depot must be facing.
409 * @param rt The road type of the depot to draw.
411 void DrawRoadDepotSprite (BlitArea
*dpi
, int x
, int y
, DiagDirection dir
, RoadType rt
)
413 DrawSprite (dpi
, 0xA4A, PAL_NONE
, x
, y
);
415 PaletteID palette
= COMPANY_SPRITE_COLOUR(_local_company
);
416 DrawOrigTileSeqInGUI (dpi
, x
, y
, _road_depot
[rt
][dir
], palette
);
419 static void DrawTile_Misc(TileInfo
*ti
)
421 switch (GetTileSubtype(ti
->tile
)) {
422 default: NOT_REACHED();
424 case TT_MISC_CROSSING
:
425 DrawLevelCrossing(ti
);
428 case TT_MISC_AQUEDUCT
:
429 DrawAqueductRamp(ti
);
430 DrawBridgeMiddle(ti
);
438 if (ti
->tileh
!= SLOPE_FLAT
) {
439 DrawFoundation (ti
, FOUNDATION_LEVELED
);
442 if (IsRailDepot(ti
->tile
)) {
451 static int GetSlopePixelZ_Misc(TileIndex tile
, uint x
, uint y
)
453 switch (GetTileSubtype(tile
)) {
454 case TT_MISC_AQUEDUCT
: {
456 Slope tileh
= GetTilePixelSlope(tile
, &z
);
461 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
463 z
+= ApplyPixelFoundationToSlope(GetBridgeFoundation(tileh
, DiagDirToAxis(dir
)), &tileh
);
465 /* On the bridge ramp? */
466 uint pos
= (DiagDirToAxis(dir
) == AXIS_X
? y
: x
);
467 if (5 <= pos
&& pos
<= 10) {
468 return z
+ ((tileh
== SLOPE_FLAT
) ? GetBridgePartialPixelZ(dir
, x
, y
) : TILE_HEIGHT
);
471 return z
+ GetPartialPixelZ(x
, y
, tileh
);
474 case TT_MISC_TUNNEL
: {
476 Slope tileh
= GetTilePixelSlope(tile
, &z
);
481 /* In the tunnel entrance? */
482 uint pos
= (DiagDirToAxis(GetTunnelBridgeDirection(tile
)) == AXIS_X
? y
: x
);
483 if (5 <= pos
&& pos
<= 10) return z
;
485 return z
+ GetPartialPixelZ(x
, y
, tileh
);
488 default: // TT_MISC_CROSSING, TT_MISC_DEPOT
489 return GetTileMaxPixelZ(tile
);
495 * Remove a tunnel from the game.
496 * @param tile Tile containing one of the endpoints.
497 * @param flags Command flags.
498 * @return Succeeded or failed command.
500 static CommandCost
RemoveTunnel(TileIndex tile
, DoCommandFlag flags
)
502 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_TUNNEL_FIRST
);
504 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
505 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
506 CommandCost ret
= CheckOwnership(GetTileOwner(tile
));
507 if (ret
.Failed()) return ret
;
509 RoadTypes rts
= GetRoadTypes(tile
);
510 Owner road_owner
= _current_company
;
511 Owner tram_owner
= _current_company
;
513 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
514 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
516 /* We can remove unowned road and if the town allows it */
517 if (road_owner
== OWNER_TOWN
&& !(_settings_game
.construction
.extra_dynamite
|| _cheats
.magic_bulldozer
.value
)) {
518 CommandCost ret
= CheckTileOwnership(tile
);
519 if (ret
.Failed()) return ret
;
521 if (road_owner
== OWNER_NONE
|| road_owner
== OWNER_TOWN
) road_owner
= _current_company
;
522 if (tram_owner
== OWNER_NONE
) tram_owner
= _current_company
;
524 CommandCost ret
= CheckOwnership(road_owner
, tile
);
525 if (ret
.Failed()) return ret
;
526 ret
= CheckOwnership(tram_owner
, tile
);
527 if (ret
.Failed()) return ret
;
532 TileIndex endtile
= GetOtherTunnelEnd(tile
);
534 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
535 if (ret
.Failed()) return ret
;
537 _build_tunnel_endtile
= endtile
;
540 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
541 t
= ClosestTownFromTile(tile
); // town penalty rating
543 /* Check if you are allowed to remove the tunnel owned by a town
544 * Removal depends on difficulty settings */
545 CommandCost ret
= CheckforTownRating(flags
, t
, TUNNELBRIDGE_REMOVE
);
546 if (ret
.Failed()) return ret
;
549 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
550 * you have a "Poor" (0) town rating */
551 if (IsTileOwner(tile
, OWNER_TOWN
) && _game_mode
!= GM_EDITOR
) {
552 ChangeTownRating(t
, RATING_TUNNEL_BRIDGE_DOWN_STEP
, RATING_TUNNEL_BRIDGE_MINIMUM
, flags
);
555 uint len
= GetTunnelBridgeLength(tile
, endtile
) + 2; // Don't forget the end tiles.
556 uint nsignals
= GetTunnelTransportType(tile
) != TRANSPORT_RAIL
? 0 :
557 (maptile_has_tunnel_signals(tile
) ? 1 : 0) + (maptile_has_tunnel_signals(endtile
) ? 1 : 0);
559 if (flags
& DC_EXEC
) {
560 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
561 /* We first need to request values before calling DoClearSquare */
562 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
563 Track track
= DiagDirToDiagTrack(dir
);
564 Owner owner
= GetTileOwner(tile
);
569 if (HasTunnelHeadReservation(tile
)) {
570 v1
= GetTrainForReservation (tile
, track
, true);
573 if (HasTunnelHeadReservation(endtile
)) {
574 v2
= GetTrainForReservation (endtile
, track
, true);
577 if (Company::IsValidID(owner
)) {
578 Company::Get(owner
)->infrastructure
.rail
[GetRailType(tile
)] -= len
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
579 DirtyCompanyInfrastructureWindows(owner
);
583 DoClearSquare(endtile
);
585 /* cannot use INVALID_DIAGDIR for signal update because the tunnel doesn't exist anymore */
586 AddSideToSignalBuffer(tile
, ReverseDiagDir(dir
), owner
);
587 AddSideToSignalBuffer(endtile
, dir
, owner
);
589 YapfNotifyTrackLayoutChange();
591 if (v1
!= NULL
) TryPathReserve(v1
);
592 if (v2
!= NULL
) TryPathReserve(v2
);
595 FOR_EACH_SET_ROADTYPE(rt
, GetRoadTypes(tile
)) {
596 /* A full diagonal road tile has two road bits. */
597 Company
*c
= Company::GetIfValid(GetRoadOwner(tile
, rt
));
599 c
->infrastructure
.road
[rt
] -= len
* 2 * TUNNELBRIDGE_TRACKBIT_FACTOR
;
600 DirtyCompanyInfrastructureWindows(c
->index
);
605 DoClearSquare(endtile
);
609 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_TUNNEL
] * len
+ _price
[PR_CLEAR_SIGNALS
] * nsignals
);
612 static CommandCost
RemoveTrainDepot(TileIndex tile
, DoCommandFlag flags
)
614 if (flags
& DC_EXEC
) {
615 /* read variables before the depot is removed */
616 DiagDirection dir
= GetGroundDepotDirection(tile
);
617 Owner owner
= GetTileOwner(tile
);
620 if (HasDepotReservation(tile
)) {
621 v
= GetTrainForReservation (tile
, DiagDirToDiagTrack (dir
), true);
624 Company::Get(owner
)->infrastructure
.rail
[GetRailType(tile
)]--;
625 DirtyCompanyInfrastructureWindows(owner
);
627 delete Depot::GetByTile(tile
);
629 AddSideToSignalBuffer(tile
, dir
, owner
);
630 YapfNotifyTrackLayoutChange();
631 if (v
!= NULL
) TryPathReserve(v
, true);
634 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_DEPOT_TRAIN
]);
637 static CommandCost
RemoveRoadDepot(TileIndex tile
, DoCommandFlag flags
)
639 if (flags
& DC_EXEC
) {
640 Company
*c
= Company::GetIfValid(GetTileOwner(tile
));
642 /* A road depot has two road bits. */
643 c
->infrastructure
.road
[FIND_FIRST_BIT(GetRoadTypes(tile
))] -= 2;
644 DirtyCompanyInfrastructureWindows(c
->index
);
647 delete Depot::GetByTile(tile
);
651 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_CLEAR_DEPOT_ROAD
]);
654 extern CommandCost
RemoveRoad(TileIndex tile
, DoCommandFlag flags
, RoadBits pieces
, RoadType rt
, bool crossing_check
, bool town_check
= true);
656 static CommandCost
ClearTile_Misc(TileIndex tile
, DoCommandFlag flags
)
658 switch (GetTileSubtype(tile
)) {
659 default: NOT_REACHED();
661 case TT_MISC_CROSSING
: {
662 RoadTypes rts
= GetRoadTypes(tile
);
663 CommandCost
ret(EXPENSES_CONSTRUCTION
);
665 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_REMOVE_ROAD_FIRST
);
667 /* Must iterate over the roadtypes in a reverse manner because
668 * tram tracks must be removed before the road bits. */
669 RoadType rt
= ROADTYPE_TRAM
;
671 if (HasBit(rts
, rt
)) {
672 CommandCost tmp_ret
= RemoveRoad(tile
, flags
, GetCrossingRoadBits(tile
), rt
, false);
673 if (tmp_ret
.Failed()) return tmp_ret
;
674 ret
.AddCost(tmp_ret
);
676 } while (rt
-- != ROADTYPE_ROAD
);
678 if (flags
& DC_EXEC
) {
679 DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
684 case TT_MISC_AQUEDUCT
: {
685 if (flags
& DC_AUTO
) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST
);
687 if (_current_company
!= OWNER_WATER
&& _game_mode
!= GM_EDITOR
) {
688 Owner owner
= GetTileOwner(tile
);
689 if (owner
!= OWNER_NONE
) {
690 CommandCost ret
= CheckOwnership(owner
);
691 if (ret
.Failed()) return ret
;
695 TileIndex endtile
= GetOtherBridgeEnd(tile
);
697 CommandCost ret
= TunnelBridgeIsFree(tile
, endtile
);
698 if (ret
.Failed()) return ret
;
700 uint len
= GetTunnelBridgeLength(tile
, endtile
) + 2; // Don't forget the end tiles.
702 if (flags
& DC_EXEC
) {
703 /* Update company infrastructure counts. */
704 Owner owner
= GetTileOwner(tile
);
705 if (Company::IsValidID(owner
)) Company::Get(owner
)->infrastructure
.water
-= len
* TUNNELBRIDGE_TRACKBIT_FACTOR
;
706 DirtyCompanyInfrastructureWindows(owner
);
708 RemoveBridgeMiddleTiles(tile
, endtile
);
710 DoClearSquare(endtile
);
713 return CommandCost(EXPENSES_CONSTRUCTION
, len
* _price
[PR_CLEAR_AQUEDUCT
]);
717 return RemoveTunnel(tile
, flags
);
720 if (flags
& DC_AUTO
) {
721 if (!IsTileOwner(tile
, _current_company
)) {
722 return_cmd_error(STR_ERROR_AREA_IS_OWNED_BY_ANOTHER
);
724 return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED
);
727 if (_current_company
!= OWNER_WATER
) {
728 CommandCost ret
= CheckTileOwnership (tile
);
729 if (ret
.Failed()) return ret
;
732 StringID str
= CheckVehicleOnGround (tile
);
733 if (str
!= STR_NULL
) return_cmd_error(str
);
735 return IsRailDepot(tile
) ? RemoveTrainDepot(tile
, flags
) : RemoveRoadDepot(tile
, flags
);
740 static void GetTileDesc_Misc(TileIndex tile
, TileDesc
*td
)
742 switch (GetTileSubtype(tile
)) {
743 default: NOT_REACHED();
745 case TT_MISC_CROSSING
: {
746 td
->str
= STR_LAI_ROAD_DESCRIPTION_ROAD_RAIL_LEVEL_CROSSING
;
748 RoadTypes rts
= GetRoadTypes(tile
);
749 Owner road_owner
= HasBit(rts
, ROADTYPE_ROAD
) ? GetRoadOwner(tile
, ROADTYPE_ROAD
) : INVALID_OWNER
;
750 Owner tram_owner
= HasBit(rts
, ROADTYPE_TRAM
) ? GetRoadOwner(tile
, ROADTYPE_TRAM
) : INVALID_OWNER
;
751 Owner rail_owner
= GetTileOwner(tile
);
753 const RailtypeInfo
*rti
= GetRailTypeInfo (GetRailType (tile
));
754 td
->rail
[0].type
= rti
->strings
.name
;
755 td
->rail
[0].speed
= rti
->max_speed
;
757 Owner first_owner
= (road_owner
== INVALID_OWNER
? tram_owner
: road_owner
);
758 bool mixed_owners
= (tram_owner
!= INVALID_OWNER
&& tram_owner
!= first_owner
) || (rail_owner
!= INVALID_OWNER
&& rail_owner
!= first_owner
);
761 /* Multiple owners */
762 td
->owner_type
[0] = (rail_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_RAIL_OWNER
);
763 td
->owner
[0] = rail_owner
;
764 td
->owner_type
[1] = (road_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_ROAD_OWNER
);
765 td
->owner
[1] = road_owner
;
766 td
->owner_type
[2] = (tram_owner
== INVALID_OWNER
? STR_NULL
: STR_LAND_AREA_INFORMATION_TRAM_OWNER
);
767 td
->owner
[2] = tram_owner
;
769 /* One to rule them all */
770 td
->owner
[0] = first_owner
;
776 case TT_MISC_AQUEDUCT
:
777 td
->str
= STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT
;
778 td
->owner
[0] = GetTileOwner(tile
);
782 td
->owner
[0] = GetTileOwner(tile
);
784 if (GetTunnelTransportType(tile
) == TRANSPORT_RAIL
) {
785 td
->str
= STR_LAI_TUNNEL_DESCRIPTION_RAILROAD
;
786 const RailtypeInfo
*rti
= GetRailTypeInfo (GetRailType (tile
));
787 td
->rail
[0].type
= rti
->strings
.name
;
788 td
->rail
[0].speed
= rti
->max_speed
;
790 td
->str
= STR_LAI_TUNNEL_DESCRIPTION_ROAD
;
792 Owner road_owner
= INVALID_OWNER
;
793 Owner tram_owner
= INVALID_OWNER
;
794 RoadTypes rts
= GetRoadTypes(tile
);
795 if (HasBit(rts
, ROADTYPE_ROAD
)) road_owner
= GetRoadOwner(tile
, ROADTYPE_ROAD
);
796 if (HasBit(rts
, ROADTYPE_TRAM
)) tram_owner
= GetRoadOwner(tile
, ROADTYPE_TRAM
);
798 /* Is there a mix of owners? */
799 if ((tram_owner
!= INVALID_OWNER
&& tram_owner
!= td
->owner
[0]) ||
800 (road_owner
!= INVALID_OWNER
&& road_owner
!= td
->owner
[0])) {
802 if (road_owner
!= INVALID_OWNER
) {
803 td
->owner_type
[i
] = STR_LAND_AREA_INFORMATION_ROAD_OWNER
;
804 td
->owner
[i
] = road_owner
;
807 if (tram_owner
!= INVALID_OWNER
) {
808 td
->owner_type
[i
] = STR_LAND_AREA_INFORMATION_TRAM_OWNER
;
809 td
->owner
[i
] = tram_owner
;
817 td
->owner
[0] = GetTileOwner(tile
);
818 td
->build_date
= Depot::GetByTile(tile
)->build_date
;
820 if (IsRailDepot(tile
)) {
821 td
->str
= STR_LAI_RAIL_DESCRIPTION_TRAIN_DEPOT
;
823 const RailtypeInfo
*rti
= GetRailTypeInfo(GetRailType(tile
));
824 td
->rail
[0].type
= rti
->strings
.name
;
825 td
->rail
[0].speed
= rti
->max_speed
;
827 if (_settings_game
.vehicle
.train_acceleration_model
!= AM_ORIGINAL
) {
828 if (td
->rail
[0].speed
> 0) {
829 td
->rail
[0].speed
= min (td
->rail
[0].speed
, 61);
831 td
->rail
[0].speed
= 61;
835 td
->str
= STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT
;
843 static TrackStatus
GetTileRailwayStatus_Misc(TileIndex tile
, DiagDirection side
)
845 switch (GetTileSubtype(tile
)) {
846 default: NOT_REACHED();
848 case TT_MISC_CROSSING
:
849 return CombineTrackStatus(TrackBitsToTrackdirBits(GetCrossingRailBits(tile
)), TRACKDIR_BIT_NONE
);
851 case TT_MISC_AQUEDUCT
:
854 case TT_MISC_TUNNEL
: {
855 if (GetTunnelTransportType(tile
) != TRANSPORT_RAIL
) return 0;
857 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
858 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return 0;
860 TrackdirBits trackdirs
= TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
));
861 TrackdirBits red_signals
;
862 switch (maptile_get_tunnel_present_signals(tile
)) {
863 default: NOT_REACHED();
865 case 0: red_signals
= TRACKDIR_BIT_NONE
; break;
868 red_signals
= maptile_get_tunnel_signal_state(tile
, false) == SIGNAL_STATE_RED
? trackdirs
:
869 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(dir
));
873 red_signals
= maptile_get_tunnel_signal_state(tile
, true) == SIGNAL_STATE_RED
? trackdirs
:
874 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(ReverseDiagDir(dir
)));
878 return CombineTrackStatus(trackdirs
, red_signals
);
881 case TT_MISC_DEPOT
: {
882 if (!IsRailDepot(tile
)) return 0;
884 DiagDirection dir
= GetGroundDepotDirection(tile
);
885 if (side
!= INVALID_DIAGDIR
&& side
!= dir
) return 0;
886 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
891 static TrackStatus
GetTileRoadStatus_Misc(TileIndex tile
, uint sub_mode
, DiagDirection side
)
893 switch (GetTileSubtype(tile
)) {
894 default: NOT_REACHED();
896 case TT_MISC_CROSSING
: {
897 if ((GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
899 Axis axis
= GetCrossingRoadAxis(tile
);
900 if (side
!= INVALID_DIAGDIR
&& axis
!= DiagDirToAxis(side
)) return 0;
902 TrackdirBits trackdirbits
= TrackBitsToTrackdirBits(AxisToTrackBits(axis
));
903 return CombineTrackStatus(trackdirbits
, IsCrossingBarred(tile
) ? trackdirbits
: TRACKDIR_BIT_NONE
);
906 case TT_MISC_AQUEDUCT
:
909 case TT_MISC_TUNNEL
: {
910 TransportType transport_type
= GetTunnelTransportType(tile
);
911 if (transport_type
!= TRANSPORT_ROAD
|| (GetRoadTypes(tile
) & sub_mode
) == 0) return 0;
913 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
914 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return 0;
915 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
918 case TT_MISC_DEPOT
: {
919 if (!IsRoadDepot(tile
) || (GetRoadTypes(tile
) & sub_mode
) == 0) {
923 DiagDirection dir
= GetGroundDepotDirection(tile
);
924 if (side
!= INVALID_DIAGDIR
&& side
!= dir
) return 0;
925 return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
)), TRACKDIR_BIT_NONE
);
930 static TrackdirBits
GetTileWaterwayStatus_Misc(TileIndex tile
, DiagDirection side
)
932 if (!IsTileSubtype(tile
, TT_MISC_AQUEDUCT
)) return TRACKDIR_BIT_NONE
;
934 DiagDirection dir
= GetTunnelBridgeDirection(tile
);
935 if (side
!= INVALID_DIAGDIR
&& side
!= ReverseDiagDir(dir
)) return TRACKDIR_BIT_NONE
;
936 return TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir
));
940 static bool ClickTile_Misc(TileIndex tile
)
942 if (!IsGroundDepotTile(tile
)) return false;
944 ShowDepotWindow(tile
, IsRailDepot(tile
) ? VEH_TRAIN
: VEH_ROAD
);
949 static void TileLoop_Misc(TileIndex tile
)
951 switch (_settings_game
.game_creation
.landscape
) {
953 int z
= IsTileSubtype(tile
, TT_MISC_AQUEDUCT
) ? GetTileMaxZ(tile
) : GetTileZ(tile
);
954 if (IsOnSnow(tile
) != (z
> GetSnowLine())) {
956 MarkTileDirtyByTile(tile
);
962 if (GetTropicZone(tile
) == TROPICZONE_DESERT
&& !IsOnDesert(tile
)) {
963 SetDesert(tile
, true);
964 MarkTileDirtyByTile(tile
);
969 if (IsTileSubtype(tile
, TT_MISC_CROSSING
)) {
970 const Town
*t
= ClosestTownFromTile(tile
);
971 UpdateRoadSide(tile
, t
!= NULL
? GetTownRadiusGroup(t
, tile
) : HZB_TOWN_EDGE
);
976 static void ChangeTileOwner_Misc(TileIndex tile
, Owner old_owner
, Owner new_owner
)
978 switch (GetTileSubtype(tile
)) {
979 default: NOT_REACHED();
981 case TT_MISC_CROSSING
:
982 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
983 /* Update all roadtypes, no matter if they are present */
984 if (GetRoadOwner(tile
, rt
) == old_owner
) {
985 if (HasTileRoadType(tile
, rt
)) {
986 /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */
987 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= 2;
988 if (new_owner
!= INVALID_OWNER
) Company::Get(new_owner
)->infrastructure
.road
[rt
] += 2;
991 SetRoadOwner(tile
, rt
, new_owner
== INVALID_OWNER
? OWNER_NONE
: new_owner
);
995 if (GetTileOwner(tile
) == old_owner
) {
996 if (new_owner
== INVALID_OWNER
) {
997 DoCommand(tile
, 0, GetCrossingRailTrack(tile
), DC_EXEC
| DC_BANKRUPT
, CMD_REMOVE_SINGLE_RAIL
);
999 /* Update infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
1000 RailType rt
= GetRailType(tile
);
1001 Company::Get(old_owner
)->infrastructure
.rail
[rt
] -= LEVELCROSSING_TRACKBIT_FACTOR
;
1002 Company::Get(new_owner
)->infrastructure
.rail
[rt
] += LEVELCROSSING_TRACKBIT_FACTOR
;
1004 SetTileOwner(tile
, new_owner
);
1010 case TT_MISC_AQUEDUCT
: {
1011 if (!IsTileOwner(tile
, old_owner
)) return;
1013 TileIndex other_end
= GetOtherTunnelBridgeEnd(tile
);
1014 /* Set number of pieces to zero if it's the southern tile as we
1015 * don't want to update the infrastructure counts twice. */
1016 uint num_pieces
= tile
< other_end
? (GetTunnelBridgeLength(tile
, other_end
) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
: 0;
1018 /* Update company infrastructure counts.
1019 * No need to dirty windows here, we'll redraw the whole screen anyway. */
1020 Company::Get(old_owner
)->infrastructure
.water
-= num_pieces
;
1021 if (new_owner
!= INVALID_OWNER
) {
1022 Company::Get(new_owner
)->infrastructure
.water
+= num_pieces
;
1023 SetTileOwner(tile
, new_owner
);
1025 SetTileOwner(tile
, OWNER_NONE
);
1030 case TT_MISC_TUNNEL
: {
1031 TileIndex other_end
= GetOtherTunnelEnd(tile
);
1032 /* Set number of pieces to zero if it's the southern tile as we
1033 * don't want to update the infrastructure counts twice. */
1034 uint num_pieces
= tile
< other_end
? (GetTunnelBridgeLength(tile
, other_end
) + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR
: 0;
1036 if (GetTunnelTransportType(tile
) != TRANSPORT_RAIL
) {
1037 /* A full diagonal road tile has two road bits. */
1039 if (new_owner
== INVALID_OWNER
) new_owner
= OWNER_NONE
;
1041 for (RoadType rt
= ROADTYPE_ROAD
; rt
< ROADTYPE_END
; rt
++) {
1042 /* Update all roadtypes, no matter if they are present */
1043 if (GetRoadOwner(tile
, rt
) == old_owner
) {
1044 if (HasBit(GetRoadTypes(tile
), rt
)) {
1045 /* Update company infrastructure counts.
1046 * No need to dirty windows here, we'll redraw the whole screen anyway. */
1047 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= num_pieces
;
1048 if (new_owner
!= OWNER_NONE
) Company::Get(new_owner
)->infrastructure
.road
[rt
] += num_pieces
;
1051 SetRoadOwner(tile
, rt
, new_owner
);
1055 if (IsTileOwner(tile
, old_owner
)) {
1056 SetTileOwner (tile
, new_owner
);
1059 } else if (IsTileOwner(tile
, old_owner
)) {
1060 /* No need to dirty windows here, we'll redraw the whole screen anyway. */
1061 Company::Get(old_owner
)->infrastructure
.rail
[GetRailType(tile
)] -= num_pieces
;
1063 if (new_owner
!= INVALID_OWNER
) {
1064 Company::Get(new_owner
)->infrastructure
.rail
[GetRailType(tile
)] += num_pieces
;
1065 SetTileOwner(tile
, new_owner
);
1067 /* Since all of our vehicles have been removed,
1068 * it is safe to remove the rail tunnel. */
1069 CommandCost ret
= DoCommand(tile
, 0, 0, DC_EXEC
| DC_BANKRUPT
, CMD_LANDSCAPE_CLEAR
);
1070 assert(ret
.Succeeded());
1078 if (!IsTileOwner(tile
, old_owner
)) return;
1080 if (new_owner
!= INVALID_OWNER
) {
1081 /* Update company infrastructure counts. No need to dirty windows here, we'll redraw the whole screen anyway. */
1082 if (IsRailDepot(tile
)) {
1083 RailType rt
= GetRailType(tile
);
1084 Company::Get(old_owner
)->infrastructure
.rail
[rt
]--;
1085 Company::Get(new_owner
)->infrastructure
.rail
[rt
]++;
1087 /* A road depot has two road bits. */
1088 RoadType rt
= (RoadType
)FIND_FIRST_BIT(GetRoadTypes(tile
));
1089 Company::Get(old_owner
)->infrastructure
.road
[rt
] -= 2;
1090 Company::Get(new_owner
)->infrastructure
.road
[rt
] += 2;
1093 SetTileOwner(tile
, new_owner
);
1095 DoCommand(tile
, 0, 0, DC_EXEC
| DC_BANKRUPT
, CMD_LANDSCAPE_CLEAR
);
1103 * Frame when a vehicle should be hidden in a tunnel with a certain direction.
1104 * This differs per direction, because of visibility / bounding box issues.
1105 * Note that direction, in this case, is the direction leading into the tunnel.
1106 * When entering a tunnel, hide the vehicle when it reaches the given frame.
1107 * When leaving a tunnel, show the vehicle when it is one frame further
1108 * to the 'outside', i.e. at (TILE_SIZE-1) - (frame) + 1
1110 extern const byte _tunnel_visibility_frame
[DIAGDIR_END
] = {12, 8, 8, 12};
1113 static Foundation
GetFoundation_Misc(TileIndex tile
, Slope tileh
)
1115 switch (GetTileSubtype(tile
)) {
1116 case TT_MISC_AQUEDUCT
: return GetBridgeFoundation(tileh
, DiagDirToAxis(GetTunnelBridgeDirection(tile
)));
1117 case TT_MISC_TUNNEL
: return FOUNDATION_NONE
;
1118 default: return FlatteningFoundation(tileh
);
1123 static CommandCost
TerraformTile_Misc(TileIndex tile
, DoCommandFlag flags
, int z_new
, Slope tileh_new
)
1125 if (_settings_game
.construction
.build_on_slopes
&& AutoslopeEnabled()) {
1126 switch (GetTileSubtype(tile
)) {
1129 case TT_MISC_CROSSING
:
1130 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
]);
1134 if (AutoslopeCheckForEntranceEdge(tile
, z_new
, tileh_new
, GetGroundDepotDirection(tile
))) {
1135 return CommandCost(EXPENSES_CONSTRUCTION
, _price
[PR_BUILD_FOUNDATION
]);
1141 return DoCommand(tile
, 0, 0, flags
, CMD_LANDSCAPE_CLEAR
);
1145 extern const TileTypeProcs _tile_type_misc_procs
= {
1146 DrawTile_Misc
, // draw_tile_proc
1147 GetSlopePixelZ_Misc
, // get_slope_z_proc
1148 ClearTile_Misc
, // clear_tile_proc
1149 NULL
, // add_accepted_cargo_proc
1150 GetTileDesc_Misc
, // get_tile_desc_proc
1151 GetTileRailwayStatus_Misc
, // get_tile_railway_status_proc
1152 GetTileRoadStatus_Misc
, // get_tile_road_status_proc
1153 GetTileWaterwayStatus_Misc
, // get_tile_waterway_status_proc
1154 ClickTile_Misc
, // click_tile_proc
1155 NULL
, // animate_tile_proc
1156 TileLoop_Misc
, // tile_loop_proc
1157 ChangeTileOwner_Misc
, // change_tile_owner_proc
1158 NULL
, // add_produced_cargo_proc
1159 GetFoundation_Misc
, // get_foundation_proc
1160 TerraformTile_Misc
, // terraform_tile_proc