Fix old map array tunnel head conversion
[openttd/fttd.git] / src / misctile_cmd.cpp
blob0f29b1a4abba81feb65245c979936ce85d5575e0
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 misctile_cmd.cpp Handling of misc tiles. */
12 #include "stdafx.h"
13 #include "map/zoneheight.h"
14 #include "map/road.h"
15 #include "tile_cmd.h"
16 #include "bridge.h"
17 #include "signalbuffer.h"
18 #include "command_func.h"
19 #include "company_func.h"
20 #include "vehicle_func.h"
21 #include "pbs.h"
22 #include "train.h"
23 #include "roadveh.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"
30 #include "road_cmd.h"
31 #include "town.h"
32 #include "tunnelbridge.h"
33 #include "ship.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"
47 /**
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
61 * 1 3
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;
79 SpriteID image;
80 SpriteID railtype_overlay = 0;
81 if (rti != NULL) {
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.
88 } else {
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);
107 if (rti == NULL) {
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)) {
117 catenary = true;
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);
122 } else {
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);
132 catenary = true;
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;
160 if (sprite != 0) {
161 sprite += image;
162 } else {
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),
200 TILE_SEQ_END()
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),
206 TILE_SEQ_END()
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),
212 TILE_SEQ_END()
215 static const DrawTileSeqStruct _depot_gfx_NW[] = {
216 TILE_SEQ_LINE(SPR_RAIL_DEPOT_NW, 13, 2, 1, 13),
217 TILE_SEQ_END()
220 #undef TILE_SEQ_LINE
221 #undef TILE_SEQ_END
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));
243 /* draw depot */
245 DiagDirection dir = GetGroundDepotDirection (ti->tile);
247 const TrainDepotSprites *dts = &_depot_gfx_table[dir];
249 SpriteID image;
250 if (rti->UsesOverlay()) {
251 image = SPR_FLAT_GRASS_TILE;
252 } else {
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
263 } else {
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;
274 SpriteID overlay;
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;
286 reserved = true;
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)];
293 reserved = true;
295 if (reserved) {
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),
341 TILE_SEQ_END()
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),
347 TILE_SEQ_END()
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),
353 TILE_SEQ_END()
356 static const DrawTileSeqStruct _road_depot_NW[] = {
357 TILE_SEQ_LINE(0x585, PAL_NONE, 15, 0, 1, 16),
358 TILE_SEQ_END()
361 static const DrawTileSeqStruct _tram_depot_NE[] = {
362 TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x35, PAL_NONE, 0, 15, 16, 1),
363 TILE_SEQ_END()
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),
369 TILE_SEQ_END()
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),
375 TILE_SEQ_END()
378 static const DrawTileSeqStruct _tram_depot_NW[] = {
379 TILE_SEQ_LINE(SPR_TRAMWAY_BASE + 0x36, PAL_NONE, 15, 0, 1, 16),
380 TILE_SEQ_END()
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 },
388 #undef TILE_SEQ_LINE
389 #undef TILE_SEQ_END
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);
426 break;
428 case TT_MISC_AQUEDUCT:
429 DrawAqueductRamp(ti);
430 DrawBridgeMiddle(ti);
431 break;
433 case TT_MISC_TUNNEL:
434 DrawTunnel(ti);
435 break;
437 case TT_MISC_DEPOT:
438 if (ti->tileh != SLOPE_FLAT) {
439 DrawFoundation (ti, FOUNDATION_LEVELED);
442 if (IsRailDepot(ti->tile)) {
443 DrawTrainDepot(ti);
444 } else {
445 DrawRoadDepot(ti);
447 break;
451 static int GetSlopePixelZ_Misc(TileIndex tile, uint x, uint y)
453 switch (GetTileSubtype(tile)) {
454 case TT_MISC_AQUEDUCT: {
455 int z;
456 Slope tileh = GetTilePixelSlope(tile, &z);
458 x &= 0xF;
459 y &= 0xF;
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: {
475 int z;
476 Slope tileh = GetTilePixelSlope(tile, &z);
478 x &= 0xF;
479 y &= 0xF;
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;
508 } else {
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;
520 } else {
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;
539 Town *t = NULL;
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);
566 Train *v1 = NULL;
567 Train *v2 = NULL;
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);
582 DoClearSquare(tile);
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);
593 } else {
594 RoadType rt;
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));
598 if (c != NULL) {
599 c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR;
600 DirtyCompanyInfrastructureWindows(c->index);
604 DoClearSquare(tile);
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);
618 Train *v = NULL;
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);
628 DoClearSquare(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));
641 if (c != NULL) {
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);
648 DoClearSquare(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;
670 do {
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);
681 return ret;
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);
709 DoClearSquare(tile);
710 DoClearSquare(endtile);
713 return CommandCost(EXPENSES_CONSTRUCTION, len * _price[PR_CLEAR_AQUEDUCT]);
716 case TT_MISC_TUNNEL:
717 return RemoveTunnel(tile, flags);
719 case TT_MISC_DEPOT:
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);
760 if (mixed_owners) {
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;
768 } else {
769 /* One to rule them all */
770 td->owner[0] = first_owner;
773 break;
776 case TT_MISC_AQUEDUCT:
777 td->str = STR_LAI_BRIDGE_DESCRIPTION_AQUEDUCT;
778 td->owner[0] = GetTileOwner(tile);
779 break;
781 case TT_MISC_TUNNEL:
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;
789 } else {
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])) {
801 uint i = 1;
802 if (road_owner != INVALID_OWNER) {
803 td->owner_type[i] = STR_LAND_AREA_INFORMATION_ROAD_OWNER;
804 td->owner[i] = road_owner;
805 i++;
807 if (tram_owner != INVALID_OWNER) {
808 td->owner_type[i] = STR_LAND_AREA_INFORMATION_TRAM_OWNER;
809 td->owner[i] = tram_owner;
814 break;
816 case TT_MISC_DEPOT:
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);
830 } else {
831 td->rail[0].speed = 61;
834 } else {
835 td->str = STR_LAI_ROAD_DESCRIPTION_ROAD_VEHICLE_DEPOT;
838 break;
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:
852 return 0;
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;
867 case 1:
868 red_signals = maptile_get_tunnel_signal_state(tile, false) == SIGNAL_STATE_RED ? trackdirs :
869 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(dir));
870 break;
872 case 2:
873 red_signals = maptile_get_tunnel_signal_state(tile, true) == SIGNAL_STATE_RED ? trackdirs :
874 TrackdirToTrackdirBits(DiagDirToDiagTrackdir(ReverseDiagDir(dir)));
875 break;
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:
907 return 0;
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) {
920 return 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);
945 return true;
949 static void TileLoop_Misc(TileIndex tile)
951 switch (_settings_game.game_creation.landscape) {
952 case LT_ARCTIC: {
953 int z = IsTileSubtype(tile, TT_MISC_AQUEDUCT) ? GetTileMaxZ(tile) : GetTileZ(tile);
954 if (IsOnSnow(tile) != (z > GetSnowLine())) {
955 ToggleSnow(tile);
956 MarkTileDirtyByTile(tile);
958 break;
961 case LT_TROPIC:
962 if (GetTropicZone(tile) == TROPICZONE_DESERT && !IsOnDesert(tile)) {
963 SetDesert(tile, true);
964 MarkTileDirtyByTile(tile);
966 break;
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);
998 } else {
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);
1008 break;
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);
1024 } else {
1025 SetTileOwner(tile, OWNER_NONE);
1027 break;
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. */
1038 num_pieces *= 2;
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);
1066 } else {
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());
1074 break;
1077 case TT_MISC_DEPOT:
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]++;
1086 } else {
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);
1094 } else {
1095 DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
1097 break;
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)) {
1127 default: break;
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]);
1131 break;
1133 case TT_MISC_DEPOT:
1134 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetGroundDepotDirection(tile))) {
1135 return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
1137 break;
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