~ubuntu-branches/debian/squeeze/openttd/squeeze

« back to all changes in this revision

Viewing changes to src/tunnelbridge_cmd.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Matthijs Kooijman, Jordi Mallach
  • Date: 2009-04-15 18:22:10 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090415182210-22ktb8kdbp2tf3bm
[ Matthijs Kooijman ]
* New upstream release.
* Remove Debian specific desktop file, upstream provides one now. 
* Add debian/watch file.

[ Jordi Mallach ]
* Bump Standards-Version to 3.8.1, with no changes required.
* Move to debhelper compat 7. Bump Build-Depends accordingly.
* Use dh_prep.
* Add "set -e" to config script.
* Remove a few extra doc files that get installed by upstream Makefile.
* Add more complete copyright information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: tunnelbridge_cmd.cpp 14259 2008-09-07 11:54:00Z rubidium $ */
 
1
/* $Id: tunnelbridge_cmd.cpp 15718 2009-03-15 00:32:18Z rubidium $ */
2
2
 
3
3
/** @file tunnelbridge_cmd.cpp
4
4
 * This file deals with tunnels and bridges (non-gui stuff)
7
7
 
8
8
#include "stdafx.h"
9
9
#include "openttd.h"
10
 
#include "bridge_map.h"
11
10
#include "rail_map.h"
12
 
#include "road_map.h"
13
 
#include "tile_cmd.h"
14
11
#include "landscape.h"
15
 
#include "tunnel_map.h"
16
12
#include "unmovable_map.h"
17
13
#include "viewport_func.h"
18
14
#include "command_func.h"
19
15
#include "town.h"
20
16
#include "variables.h"
21
 
#include "bridge.h"
22
17
#include "train.h"
23
18
#include "water_map.h"
24
19
#include "yapf/yapf.h"
25
20
#include "newgrf_sound.h"
26
21
#include "autoslope.h"
27
 
#include "transparency.h"
28
22
#include "tunnelbridge_map.h"
29
23
#include "strings_func.h"
30
24
#include "date_func.h"
31
25
#include "functions.h"
32
26
#include "vehicle_func.h"
33
27
#include "sound_func.h"
34
 
#include "signal_func.h"
35
28
#include "tunnelbridge.h"
36
 
#include "player_base.h"
 
29
#include "engine_base.h"
 
30
#include "cheat_type.h"
 
31
#include "elrail_func.h"
 
32
#include "landscape_type.h"
37
33
 
38
34
#include "table/sprites.h"
39
35
#include "table/strings.h"
40
36
#include "table/bridge_land.h"
41
37
 
42
38
BridgeSpec _bridge[MAX_BRIDGES];
 
39
TileIndex _build_tunnel_endtile;
43
40
 
44
41
/** Reset the data been eventually changed by the grf loaded. */
45
42
void ResetBridges()
47
44
        /* First, free sprite table data */
48
45
        for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
49
46
                if (_bridge[i].sprite_table != NULL) {
50
 
                        for (uint j = 0; j < 7; j++) free(_bridge[i].sprite_table[j]);
 
47
                        for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
51
48
                        free(_bridge[i].sprite_table);
52
49
                }
53
50
        }
98
95
        return (tileh != SLOPE_FLAT);
99
96
}
100
97
 
101
 
static inline const PalSpriteID *GetBridgeSpriteTable(int index, byte table)
 
98
static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
102
99
{
103
100
        const BridgeSpec *bridge = GetBridgeSpec(index);
104
 
        assert(table < 7);
 
101
        assert(table < BRIDGE_PIECE_INVALID);
105
102
        if (bridge->sprite_table == NULL || bridge->sprite_table[table] == NULL) {
106
103
                return _bridge_sprite_table[index][table];
107
104
        } else {
152
149
        return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
153
150
}
154
151
 
155
 
bool CheckBridge_Stuff(BridgeType bridge_type, uint bridge_len, uint32 flags)
 
152
bool CheckBridge_Stuff(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags)
156
153
{
157
154
        if (flags & DC_QUERY_COST) {
158
 
                return bridge_len <= (_patches.longbridges ? 100U : 16U);
 
155
                return bridge_len <= (_settings_game.construction.longbridges ? 100U : 16U);
159
156
        }
160
157
 
161
158
        if (bridge_type >= MAX_BRIDGES) return false;
164
161
        if (b->avail_year > _cur_year) return false;
165
162
 
166
163
        uint max = b->max_length;
167
 
        if (max >= 16 && _patches.longbridges) max = 100;
 
164
        if (max >= 16 && _settings_game.construction.longbridges) max = 100;
168
165
 
169
166
        return b->min_length <= bridge_len && bridge_len <= max;
170
167
}
174
171
 * @param flags type of operation
175
172
 * @param p1 packed start tile coords (~ dx)
176
173
 * @param p2 various bitstuffed elements
177
 
 * - p2 = (bit 0- 7) - bridge type (hi bh)
178
 
 * - p2 = (bit 8-..) - rail type or road types.
179
 
 * - p2 = (bit 15  ) - set means road bridge.
 
174
 * - p2 = (bit  0- 7) - bridge type (hi bh)
 
175
 * - p2 = (bit  8-14) - rail type or road types.
 
176
 * - p2 = (bit 15-16) - transport type.
180
177
 */
181
 
CommandCost CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2)
 
178
CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
182
179
{
183
180
        BridgeType bridge_type;
184
181
        RailType railtype = INVALID_RAILTYPE;
213
210
        /* type of bridge */
214
211
        switch (transport_type) {
215
212
                case TRANSPORT_ROAD:
216
 
                        roadtypes = (RoadTypes)GB(p2, 8, 3);
217
 
                        if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_player, roadtypes)) return CMD_ERROR;
 
213
                        roadtypes = (RoadTypes)GB(p2, 8, 2);
 
214
                        if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
218
215
                        break;
219
216
 
220
217
                case TRANSPORT_RAIL:
221
 
                        railtype = (RailType)GB(p2, 8, 8);
 
218
                        railtype = (RailType)GB(p2, 8, 7);
222
219
                        if (!ValParamRailtype(railtype)) return CMD_ERROR;
223
220
                        break;
224
221
 
 
222
                case TRANSPORT_WATER:
 
223
                        break;
 
224
 
225
225
                default:
226
 
                        /* For now, only TRANSPORT_RAIL and TRANSPORT_ROAD are allowed.
227
 
                         * But let not this stops us for preparing the future */
 
226
                        /* Airports don't have tunnels. */
228
227
                        return CMD_ERROR;
229
228
        }
230
229
 
245
244
                return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN);
246
245
        }
247
246
 
248
 
        /* set and test bridge length, availability */
249
247
        bridge_len = sx + sy - x - y - 1;
250
 
        if (!CheckBridge_Stuff(bridge_type, bridge_len, flags)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE);
 
248
        if (transport_type != TRANSPORT_WATER) {
 
249
                /* set and test bridge length, availability */
 
250
                if (!CheckBridge_Stuff(bridge_type, bridge_len, flags)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE);
 
251
        }
251
252
 
252
253
        /* retrieve landscape height and ensure it's on land */
253
254
        tile_start = TileXY(x, y);
292
293
                        return_cmd_error(STR_1007_ALREADY_BUILT);
293
294
                }
294
295
 
295
 
                /* Do not allow replacing another player's bridges. */
296
 
                if (!IsTileOwner(tile_start, _current_player) && !IsTileOwner(tile_start, OWNER_TOWN)) {
 
296
                /* Do not allow replacing another company's bridges. */
 
297
                if (!IsTileOwner(tile_start, _current_company) && !IsTileOwner(tile_start, OWNER_TOWN)) {
297
298
                        return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
298
299
                }
299
300
 
306
307
        } else {
307
308
                /* Build a new bridge. */
308
309
 
309
 
                bool allow_on_slopes = (!_is_old_ai_player && _patches.build_on_slopes);
 
310
                bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
310
311
 
311
312
                /* Try and clear the start landscape */
312
313
                ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
326
327
                if (CmdFailed(terraform_cost_south) || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes))
327
328
                        return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
328
329
                cost.AddCost(terraform_cost_south);
 
330
 
 
331
                if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
329
332
        }
330
333
 
331
334
        if (!replace_bridge) {
350
353
        /* do the drill? */
351
354
        if (flags & DC_EXEC) {
352
355
                DiagDirection dir = AxisToDiagDir(direction);
353
 
                Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_player;
 
356
                Owner owner = replace_bridge ? GetTileOwner(tile_start) : _current_company;
354
357
 
355
358
                switch (transport_type) {
356
359
                        case TRANSPORT_RAIL:
363
366
                                MakeRoadBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), roadtypes);
364
367
                                break;
365
368
 
 
369
                        case TRANSPORT_WATER:
 
370
                                MakeAqueductBridgeRamp(tile_start, owner, dir);
 
371
                                MakeAqueductBridgeRamp(tile_end,   owner, ReverseDiagDir(dir));
 
372
                                break;
 
373
 
366
374
                        default:
367
375
                                NOT_REACHED();
368
376
                                break;
382
390
 
383
391
                switch (GetTileType(tile)) {
384
392
                        case MP_WATER:
385
 
                                if (!EnsureNoVehicleOnGround(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY);
386
393
                                if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
387
394
                                break;
388
395
 
425
432
 
426
433
        if (flags & DC_EXEC && transport_type == TRANSPORT_RAIL) {
427
434
                Track track = AxisToTrack(direction);
428
 
                AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_player);
 
435
                AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_company);
429
436
                YapfNotifyTrackLayoutChange(tile_start, track);
430
437
        }
431
438
 
433
440
         * It's unnecessary to execute this command every time for every bridge. So it is done only
434
441
         * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
435
442
         */
436
 
        if (!(flags & DC_QUERY_COST) || (IsValidPlayer(_current_player) && GetPlayer(_current_player)->is_ai)) {
 
443
        if (!(flags & DC_QUERY_COST) || (IsValidCompanyID(_current_company) && GetCompany(_current_company)->is_ai)) {
437
444
                bridge_len += 2; // begin and end tiles/ramps
438
445
 
439
 
                if (IsValidPlayer(_current_player) && !_is_old_ai_player)
 
446
                if (IsValidCompanyID(_current_company))
440
447
                        bridge_len = CalcBridgeLenCostFactor(bridge_len);
441
448
 
442
449
                cost.AddCost((int64)bridge_len * _price.build_bridge * GetBridgeSpec(bridge_type)->price >> 8);
 
450
 
 
451
                /* Aqueducts are a little more expensive. */
 
452
                if (transport_type == TRANSPORT_WATER) cost.AddCost((int64)bridge_len * _price.clear_water);
443
453
        }
444
454
 
445
455
        return cost;
452
462
 * @param p1 railtype or roadtypes. bit 9 set means road tunnel
453
463
 * @param p2 unused
454
464
 */
455
 
CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2)
 
465
CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
456
466
{
457
467
        TileIndexDiff delta;
458
468
        TileIndex end_tile;
469
479
        if (transport_type == TRANSPORT_RAIL) {
470
480
                if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
471
481
        } else {
472
 
                const RoadTypes rts = (RoadTypes)GB(p1, 0, 3);
473
 
                if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
 
482
                const RoadTypes rts = (RoadTypes)GB(p1, 0, 2);
 
483
                if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
474
484
        }
475
485
 
476
486
        start_tileh = GetTileSlope(start_tile, &start_z);
489
499
 
490
500
        delta = TileOffsByDiagDir(direction);
491
501
        DiagDirection tunnel_in_way_dir;
492
 
        if (OtherAxis(DiagDirToAxis(direction)) == AXIS_X) {
 
502
        if (DiagDirToAxis(direction) == AXIS_Y) {
493
503
                tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
494
504
        } else {
495
505
                tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
506
516
 
507
517
        for (;;) {
508
518
                end_tile += delta;
 
519
                if (!IsValidTile(end_tile)) return_cmd_error(STR_TUNNEL_THROUGH_MAP_BORDER);
509
520
                end_tileh = GetTileSlope(end_tile, &end_z);
510
521
 
511
522
                if (start_z == end_z) break;
535
546
 
536
547
        /* slope of end tile must be complementary to the slope of the start tile */
537
548
        if (end_tileh != ComplementSlope(start_tileh)) {
538
 
                /* Check if there is a structure on the terraformed tile. Do not add the cost, that will be done by the terraforming */
 
549
                /* Check if there is a structure on the terraformed tile. Do not add the cost, that will be done by the terraforming
 
550
                 * Note: Currently the town rating is also affected by this clearing-test. So effectivly the player is punished twice for clearing
 
551
                 *       the tree on end_tile.
 
552
                 */
539
553
                ret = DoCommand(end_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR);
540
554
                if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
541
555
 
550
564
 
551
565
        if (flags & DC_EXEC) {
552
566
                if (transport_type == TRANSPORT_RAIL) {
553
 
                        MakeRailTunnel(start_tile, _current_player, direction,                 (RailType)GB(p1, 0, 4));
554
 
                        MakeRailTunnel(end_tile,   _current_player, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4));
555
 
                        AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_player);
556
 
                        YapfNotifyTrackLayoutChange(start_tile, AxisToTrack(DiagDirToAxis(direction)));
 
567
                        MakeRailTunnel(start_tile, _current_company, direction,                 (RailType)GB(p1, 0, 4));
 
568
                        MakeRailTunnel(end_tile,   _current_company, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4));
 
569
                        AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company);
 
570
                        YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
557
571
                } else {
558
 
                        MakeRoadTunnel(start_tile, _current_player, direction,                 (RoadTypes)GB(p1, 0, 3));
559
 
                        MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3));
 
572
                        MakeRoadTunnel(start_tile, _current_company, direction,                 (RoadTypes)GB(p1, 0, 2));
 
573
                        MakeRoadTunnel(end_tile,   _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 2));
560
574
                }
561
575
        }
562
576
 
567
581
static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
568
582
{
569
583
        /* Floods can remove anything as well as the scenario editor */
570
 
        if (_current_player == OWNER_WATER || _game_mode == GM_EDITOR) return true;
571
 
        /* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
572
 
        if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
573
 
        /* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
574
 
        if (IsTileOwner(tile, OWNER_TOWN) && (_patches.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
575
 
        return false;
 
584
        if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return true;
 
585
 
 
586
        switch (GetTunnelBridgeTransportType(tile)) {
 
587
                case TRANSPORT_ROAD: {
 
588
                        RoadTypes rts = GetRoadTypes(tile);
 
589
                        Owner road_owner = _current_company;
 
590
                        Owner tram_owner = _current_company;
 
591
 
 
592
                        if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
 
593
                        if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
 
594
 
 
595
                        /* We can remove unowned road and if the town allows it */
 
596
                        if (road_owner == OWNER_TOWN && !(_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return CheckTileOwnership(tile);
 
597
                        if (road_owner == OWNER_NONE || road_owner == OWNER_TOWN) road_owner = _current_company;
 
598
                        if (tram_owner == OWNER_NONE) tram_owner = _current_company;
 
599
 
 
600
                        return CheckOwnership(road_owner) && CheckOwnership(tram_owner);
 
601
                }
 
602
 
 
603
                case TRANSPORT_RAIL:
 
604
                case TRANSPORT_WATER:
 
605
                        return CheckOwnership(GetTileOwner(tile));
 
606
 
 
607
                default: NOT_REACHED();
 
608
        }
576
609
}
577
610
 
578
 
static CommandCost DoClearTunnel(TileIndex tile, uint32 flags)
 
611
static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlag flags)
579
612
{
580
613
        Town *t = NULL;
581
614
        TileIndex endtile;
589
622
        _build_tunnel_endtile = endtile;
590
623
 
591
624
        if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
592
 
                t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
 
625
                t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
593
626
 
594
627
                /* Check if you are allowed to remove the tunnel owned by a town
595
628
                 * Removal depends on difficulty settings */
602
635
        /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
603
636
         * you have a "Poor" (0) town rating */
604
637
        if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
605
 
                ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
 
638
                ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
606
639
        }
607
640
 
608
641
        if (flags & DC_EXEC) {
609
642
                if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
610
643
                        /* We first need to request values before calling DoClearSquare */
611
644
                        DiagDirection dir = GetTunnelBridgeDirection(tile);
 
645
                        Track track = DiagDirToDiagTrack(dir);
612
646
                        Owner owner = GetTileOwner(tile);
613
647
 
 
648
                        Vehicle *v = NULL;
 
649
                        if (GetTunnelBridgeReservation(tile)) {
 
650
                                v = GetTrainForReservation(tile, track);
 
651
                                if (v != NULL) FreeTrainTrackReservation(v);
 
652
                        }
 
653
 
614
654
                        DoClearSquare(tile);
615
655
                        DoClearSquare(endtile);
616
656
 
618
658
                        AddSideToSignalBuffer(tile,    ReverseDiagDir(dir), owner);
619
659
                        AddSideToSignalBuffer(endtile, dir,                 owner);
620
660
 
621
 
                        Track track = AxisToTrack(DiagDirToAxis(dir));
622
661
                        YapfNotifyTrackLayoutChange(tile,    track);
623
662
                        YapfNotifyTrackLayoutChange(endtile, track);
 
663
 
 
664
                        if (v != NULL) TryPathReserve(v);
624
665
                } else {
625
666
                        DoClearSquare(tile);
626
667
                        DoClearSquare(endtile);
630
671
}
631
672
 
632
673
 
633
 
static CommandCost DoClearBridge(TileIndex tile, uint32 flags)
 
674
static CommandCost DoClearBridge(TileIndex tile, DoCommandFlag flags)
634
675
{
635
676
        DiagDirection direction;
636
677
        TileIndexDiff delta;
647
688
        delta = TileOffsByDiagDir(direction);
648
689
 
649
690
        if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
650
 
                t = ClosestTownFromTile(tile, (uint)-1); // town penalty rating
 
691
                t = ClosestTownFromTile(tile, UINT_MAX); // town penalty rating
651
692
 
652
693
                /* Check if you are allowed to remove the bridge owned by a town
653
694
                 * Removal depends on difficulty settings */
660
701
        /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until
661
702
         * you have a "Poor" (0) town rating */
662
703
        if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
663
 
                ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
 
704
                ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM, flags);
664
705
        }
665
706
 
666
707
        if (flags & DC_EXEC) {
668
709
                bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
669
710
                Owner owner = GetTileOwner(tile);
670
711
                uint height = GetBridgeHeight(tile);
 
712
                Vehicle *v = NULL;
 
713
 
 
714
                if (rail && GetTunnelBridgeReservation(tile)) {
 
715
                        v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
 
716
                        if (v != NULL) FreeTrainTrackReservation(v);
 
717
                }
671
718
 
672
719
                DoClearSquare(tile);
673
720
                DoClearSquare(endtile);
686
733
                        AddSideToSignalBuffer(tile,    ReverseDiagDir(direction), owner);
687
734
                        AddSideToSignalBuffer(endtile, direction,                 owner);
688
735
 
689
 
                        Track track = AxisToTrack(DiagDirToAxis(direction));
 
736
                        Track track = DiagDirToDiagTrack(direction);
690
737
                        YapfNotifyTrackLayoutChange(tile,    track);
691
738
                        YapfNotifyTrackLayoutChange(endtile, track);
 
739
 
 
740
                        if (v != NULL) TryPathReserve(v, true);
692
741
                }
693
742
        }
694
743
 
695
744
        return CommandCost(EXPENSES_CONSTRUCTION, (GetTunnelBridgeLength(tile, endtile) + 2) * _price.clear_bridge);
696
745
}
697
746
 
698
 
static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags)
 
747
static CommandCost ClearTile_TunnelBridge(TileIndex tile, DoCommandFlag flags)
699
748
{
700
749
        if (IsTunnel(tile)) {
701
750
                if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
719
768
 * @param y Sprite Y position of front pillar.
720
769
 * @param z_bridge Absolute height of bridge bottom.
721
770
 */
722
 
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, BridgeType type, int x, int y, int z_bridge)
 
771
static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo *ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
723
772
{
 
773
        /* Do not draw bridge pillars if they are invisible */
 
774
        if (IsInvisibilitySet(TO_BRIDGES)) return;
 
775
 
724
776
        SpriteID image = psid->sprite;
 
777
 
725
778
        if (image != 0) {
726
 
                bool drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
727
 
 
728
779
                /* "side" specifies the side the pillars stand on.
729
780
                 * The length of the pillars is then set to the height of the bridge over the corners of this edge.
730
781
                 *
773
824
 * @param z       the z of the bridge
774
825
 * @param offset  number representing whether to level or sloped and the direction
775
826
 * @param overlay do we want to still see the road?
 
827
 * @param head    are we drawing bridge head?
776
828
 */
777
 
static void DrawBridgeTramBits(int x, int y, byte z, int offset, bool overlay)
 
829
static void DrawBridgeTramBits(int x, int y, byte z, int offset, bool overlay, bool head)
778
830
{
779
831
        static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
780
832
        static const SpriteID back_offsets[6]    =   {  95,  96,  99, 102, 100, 101 };
787
839
 
788
840
        /* The sprites under the vehicles are drawn as SpriteCombine. StartSpriteCombine() has already been called
789
841
         * The bounding boxes here are the same as for bridge front/roof */
790
 
        AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE, x, y, size_x[offset], size_y[offset], 0x28, z, IsTransparencySet(TO_BRIDGES));
 
842
        if (head || !IsInvisibilitySet(TO_BRIDGES)) {
 
843
                AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
 
844
                        x, y, size_x[offset], size_y[offset], 0x28, z,
 
845
                        !head && IsTransparencySet(TO_BRIDGES));
 
846
        }
791
847
 
792
 
        AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset],  PAL_NONE, x, y, size_x[offset], size_y[offset], 0x28, z, IsTransparencySet(TO_CATENARY));
 
848
        /* Do not draw catenary if it is set invisible */
 
849
        if (!IsInvisibilitySet(TO_CATENARY)) {
 
850
                AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NONE,
 
851
                        x, y, size_x[offset], size_y[offset], 0x28, z,
 
852
                        IsTransparencySet(TO_CATENARY));
 
853
        }
793
854
 
794
855
        /* Start a new SpriteCombine for the front part */
795
856
        EndSpriteCombine();
796
857
        StartSpriteCombine();
797
858
 
798
859
        /* For sloped sprites the bounding box needs to be higher, as the pylons stop on a higher point */
799
 
        AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE, x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z, IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
 
860
        if (!IsInvisibilitySet(TO_CATENARY)) {
 
861
                AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + front_offsets[offset], PAL_NONE,
 
862
                        x, y, size_x[offset] + front_bb_offset_x[offset], size_y[offset] + front_bb_offset_y[offset], 0x28, z,
 
863
                        IsTransparencySet(TO_CATENARY), front_bb_offset_x[offset], front_bb_offset_y[offset]);
 
864
        }
800
865
}
801
866
 
802
867
/**
850
915
 
851
916
                image += tunnelbridge_direction * 2;
852
917
                DrawGroundSprite(image, PAL_NONE);
 
918
 
 
919
                /* PBS debugging, draw reserved tracks darker */
 
920
                if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && (transport_type == TRANSPORT_RAIL && GetTunnelBridgeReservation(ti->tile))) {
 
921
                        const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
922
                        DrawGroundSprite(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH);
 
923
                }
 
924
 
853
925
                if (transport_type == TRANSPORT_ROAD) {
854
926
                        RoadTypes rts = GetRoadTypes(ti->tile);
855
927
 
858
930
 
859
931
                                DrawGroundSprite(SPR_TRAMWAY_BASE + tunnel_sprites[rts - ROADTYPES_TRAM][tunnelbridge_direction], PAL_NONE);
860
932
 
861
 
                                catenary = true;
862
 
                                StartSpriteCombine();
863
 
                                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);
 
933
                                /* Do not draw wires if they are invisible */
 
934
                                if (!IsInvisibilitySet(TO_CATENARY)) {
 
935
                                        catenary = true;
 
936
                                        StartSpriteCombine();
 
937
                                        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);
 
938
                                }
864
939
                        }
865
 
                } else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
 
940
                } else if (HasCatenaryDrawn(GetRailType(ti->tile))) {
 
941
                        /* Maybe draw pylons on the entry side */
866
942
                        DrawCatenary(ti);
867
943
 
868
944
                        catenary = true;
869
945
                        StartSpriteCombine();
 
946
                        /* Draw wire above the ramp */
870
947
                        DrawCatenaryOnTunnel(ti);
871
948
                }
872
949
 
901
978
 
902
979
                if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head
903
980
 
904
 
                /* Table number 6 always refers to the bridge heads for any bridge type */
905
 
                psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset];
 
981
                /* Table number BRIDGE_PIECE_HEAD always refers to the bridge heads for any bridge type */
 
982
                if (transport_type != TRANSPORT_WATER) {
 
983
                        psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD)[base_offset];
 
984
                } else {
 
985
                        psid = _aqueduct_sprites + base_offset;
 
986
                }
906
987
 
907
988
                if (!ice) {
908
989
                        DrawClearLandTile(ti, 3);
918
999
                /* HACK set the height of the BB of a sloped ramp to 1 so a vehicle on
919
1000
                 * it doesn't disappear behind it
920
1001
                 */
921
 
                AddSortableSpriteToDraw(
922
 
                        psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z, IsTransparencySet(TO_BRIDGES)
923
 
                );
 
1002
                /* Bridge heads are drawn solid no matter how invisibility/transparency is set */
 
1003
                AddSortableSpriteToDraw(psid->sprite, psid->pal, ti->x, ti->y, 16, 16, ti->tileh == SLOPE_FLAT ? 0 : 8, ti->z);
 
1004
 
 
1005
                if (_settings_client.gui.show_track_reservation && transport_type == TRANSPORT_RAIL && GetTunnelBridgeReservation(ti->tile)) {
 
1006
                        const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 
1007
                        if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) {
 
1008
                                AddSortableSpriteToDraw(DiagDirToAxis(tunnelbridge_direction) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH, ti->x, ti->y, 16, 16, 0, ti->z + 8);
 
1009
                        } else {
 
1010
                                AddSortableSpriteToDraw(rti->base_sprites.single_sloped + tunnelbridge_direction, PALETTE_CRASH, ti->x, ti->y, 16, 16, 8, ti->z);
 
1011
                        }
 
1012
                }
924
1013
 
925
1014
                if (transport_type == TRANSPORT_ROAD) {
926
1015
                        RoadTypes rts = GetRoadTypes(ti->tile);
935
1024
                                        offset += 2;
936
1025
                                }
937
1026
                                /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
938
 
                                DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD));
 
1027
                                DrawBridgeTramBits(ti->x, ti->y, z, offset, HasBit(rts, ROADTYPE_ROAD), true);
939
1028
                        }
940
1029
                        EndSpriteCombine();
941
 
                } else if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) {
942
 
                        DrawCatenary(ti);
 
1030
                } else if (transport_type == TRANSPORT_RAIL) {
 
1031
                        if (HasCatenaryDrawn(GetRailType(ti->tile))) {
 
1032
                                DrawCatenary(ti);
 
1033
                        }
943
1034
                }
944
1035
 
945
1036
                DrawBridgeMiddle(ti);
948
1039
 
949
1040
 
950
1041
/** Compute bridge piece. Computes the bridge piece to display depending on the position inside the bridge.
951
 
 * bridges pieces sequence (middle parts)
952
 
 * bridge len 1: 0
953
 
 * bridge len 2: 0 1
954
 
 * bridge len 3: 0 4 1
955
 
 * bridge len 4: 0 2 3 1
956
 
 * bridge len 5: 0 2 5 3 1
957
 
 * bridge len 6: 0 2 3 2 3 1
958
 
 * bridge len 7: 0 2 3 4 2 3 1
 
1042
 * bridges pieces sequence (middle parts).
 
1043
 * Note that it is not covering the bridge heads, which are always referenced by the same sprite table.
 
1044
 * bridge len 1: BRIDGE_PIECE_NORTH
 
1045
 * bridge len 2: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_SOUTH
 
1046
 * bridge len 3: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_MIDDLE_ODD   BRIDGE_PIECE_SOUTH
 
1047
 * bridge len 4: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
 
1048
 * bridge len 5: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_MIDDLE_EVEN  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
 
1049
 * bridge len 6: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
 
1050
 * bridge len 7: BRIDGE_PIECE_NORTH  BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_MIDDLE_ODD   BRIDGE_PIECE_INNER_NORTH  BRIDGE_PIECE_INNER_SOUTH  BRIDGE_PIECE_SOUTH
959
1051
 * #0 - always as first, #1 - always as last (if len>1)
960
1052
 * #2,#3 are to pair in order
961
1053
 * for odd bridges: #5 is going in the bridge middle if on even position, #4 on odd (counting from 0)
963
1055
 * @param south Southernmost tile of bridge
964
1056
 * @return Index of bridge piece
965
1057
 */
966
 
static uint CalcBridgePiece(uint north, uint south)
 
1058
static BridgePieces CalcBridgePiece(uint north, uint south)
967
1059
{
968
1060
        if (north == 1) {
969
 
                return 0;
 
1061
                return BRIDGE_PIECE_NORTH;
970
1062
        } else if (south == 1) {
971
 
                return 1;
 
1063
                return BRIDGE_PIECE_SOUTH;
972
1064
        } else if (north < south) {
973
 
                return north & 1 ? 3 : 2;
 
1065
                return north & 1 ? BRIDGE_PIECE_INNER_SOUTH : BRIDGE_PIECE_INNER_NORTH;
974
1066
        } else if (north > south) {
975
 
                return south & 1 ? 2 : 3;
 
1067
                return south & 1 ? BRIDGE_PIECE_INNER_NORTH : BRIDGE_PIECE_INNER_SOUTH;
976
1068
        } else {
977
 
                return north & 1 ? 5 : 4;
 
1069
                return north & 1 ? BRIDGE_PIECE_MIDDLE_EVEN : BRIDGE_PIECE_MIDDLE_ODD;
978
1070
        }
979
1071
}
980
1072
 
981
1073
 
982
 
void DrawBridgeMiddle(const TileInfo* ti)
 
1074
void DrawBridgeMiddle(const TileInfo *ti)
983
1075
{
984
1076
        /* Sectional view of bridge bounding boxes:
985
1077
         *
1000
1092
        /* Z position of the bridge sprites relative to bridge height (downwards) */
1001
1093
        static const int BRIDGE_Z_START = 3;
1002
1094
 
1003
 
        const PalSpriteID* psid;
1004
 
        uint base_offset;
1005
 
        TileIndex rampnorth;
1006
 
        TileIndex rampsouth;
1007
 
        TransportType transport_type;
1008
 
        Axis axis;
1009
 
        uint piece;
1010
 
        BridgeType type;
1011
 
        int x;
1012
 
        int y;
1013
 
        uint z;
1014
 
 
1015
1095
        if (!IsBridgeAbove(ti->tile)) return;
1016
1096
 
1017
 
        rampnorth = GetNorthernBridgeEnd(ti->tile);
1018
 
        rampsouth = GetSouthernBridgeEnd(ti->tile);
1019
 
        transport_type = GetTunnelBridgeTransportType(rampsouth);
 
1097
        TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile);
 
1098
        TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile);
 
1099
        TransportType transport_type = GetTunnelBridgeTransportType(rampsouth);
1020
1100
 
1021
 
        axis = GetBridgeAxis(ti->tile);
1022
 
        piece = CalcBridgePiece(
 
1101
        Axis axis = GetBridgeAxis(ti->tile);
 
1102
        BridgePieces piece = CalcBridgePiece(
1023
1103
                GetTunnelBridgeLength(ti->tile, rampnorth) + 1,
1024
1104
                GetTunnelBridgeLength(ti->tile, rampsouth) + 1
1025
1105
        );
1026
 
        type = GetBridgeType(rampsouth);
1027
 
 
1028
 
        if (transport_type == TRANSPORT_RAIL) {
1029
 
                base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
 
1106
 
 
1107
        const PalSpriteID *psid;
 
1108
        bool drawfarpillar;
 
1109
        if (transport_type != TRANSPORT_WATER) {
 
1110
                BridgeType type =  GetBridgeType(rampsouth);
 
1111
                drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0);
 
1112
 
 
1113
                uint base_offset;
 
1114
                if (transport_type == TRANSPORT_RAIL) {
 
1115
                        base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset;
 
1116
                } else {
 
1117
                        base_offset = 8;
 
1118
                }
 
1119
 
 
1120
                psid = base_offset + GetBridgeSpriteTable(type, piece);
1030
1121
        } else {
1031
 
                base_offset = 8;
 
1122
                drawfarpillar = true;
 
1123
                psid = _aqueduct_sprites;
1032
1124
        }
1033
1125
 
1034
 
        psid = base_offset + GetBridgeSpriteTable(type, piece);
1035
1126
        if (axis != AXIS_X) psid += 4;
1036
1127
 
1037
 
        x = ti->x;
1038
 
        y = ti->y;
 
1128
        int x = ti->x;
 
1129
        int y = ti->y;
1039
1130
        uint bridge_z = GetBridgeHeight(rampsouth);
1040
 
        z = bridge_z - BRIDGE_Z_START;
 
1131
        uint z = bridge_z - BRIDGE_Z_START;
1041
1132
 
1042
1133
        /* Add a bounding box, that separates the bridge from things below it. */
1043
1134
        AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR);
1046
1137
        if (transport_type == TRANSPORT_ROAD) StartSpriteCombine();
1047
1138
 
1048
1139
        /* Draw floor and far part of bridge*/
1049
 
        if (axis == AXIS_X) {
1050
 
                AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
1051
 
        } else {
1052
 
                AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
 
1140
        if (!IsInvisibilitySet(TO_BRIDGES)) {
 
1141
                if (axis == AXIS_X) {
 
1142
                        AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 1, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
 
1143
                } else {
 
1144
                        AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 1, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 0, BRIDGE_Z_START);
 
1145
                }
1053
1146
        }
1054
1147
 
1055
1148
        psid++;
1059
1152
 
1060
1153
                if (HasBit(rts, ROADTYPE_TRAM)) {
1061
1154
                        /* DrawBridgeTramBits() calls EndSpriteCombine() and StartSpriteCombine() */
1062
 
                        DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD));
 
1155
                        DrawBridgeTramBits(x, y, bridge_z, axis ^ 1, HasBit(rts, ROADTYPE_ROAD), false);
1063
1156
                } else {
1064
1157
                        EndSpriteCombine();
1065
1158
                        StartSpriteCombine();
1066
1159
                }
1067
 
        } else if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) {
1068
 
                DrawCatenary(ti);
 
1160
        } else if (transport_type == TRANSPORT_RAIL) {
 
1161
                if (HasCatenaryDrawn(GetRailType(rampsouth))) {
 
1162
                        DrawCatenaryOnBridge(ti);
 
1163
                }
1069
1164
        }
1070
1165
 
1071
1166
        /* draw roof, the component of the bridge which is logically between the vehicle and the camera */
1072
 
        if (axis == AXIS_X) {
1073
 
                y += 12;
1074
 
                if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
1075
 
        } else {
1076
 
                x += 12;
1077
 
                if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
 
1167
        if (!IsInvisibilitySet(TO_BRIDGES)) {
 
1168
                if (axis == AXIS_X) {
 
1169
                        y += 12;
 
1170
                        if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 16, 4, 0x28, z, IsTransparencySet(TO_BRIDGES), 0, 3, BRIDGE_Z_START);
 
1171
                } else {
 
1172
                        x += 12;
 
1173
                        if (psid->sprite & SPRITE_MASK) AddSortableSpriteToDraw(psid->sprite, psid->pal, x, y, 4, 16, 0x28, z, IsTransparencySet(TO_BRIDGES), 3, 0, BRIDGE_Z_START);
 
1174
                }
1078
1175
        }
1079
1176
 
1080
1177
        /* Draw TramFront as SpriteCombine */
1081
1178
        if (transport_type == TRANSPORT_ROAD) EndSpriteCombine();
1082
1179
 
 
1180
        /* Do not draw anything more if bridges are invisible */
 
1181
        if (IsInvisibilitySet(TO_BRIDGES)) return;
 
1182
 
1083
1183
        psid++;
1084
1184
        if (ti->z + 5 == z) {
1085
1185
                /* draw poles below for small bridges */
1093
1193
 
1094
1194
                        DrawGroundSpriteAt(image, pal, x, y, z);
1095
1195
                }
1096
 
        } else if (_patches.bridge_pillars) {
 
1196
        } else if (_settings_client.gui.bridge_pillars) {
1097
1197
                /* draw pillars below for high bridges */
1098
 
                DrawBridgePillars(psid, ti, axis, type, x, y, z);
 
1198
                DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z);
1099
1199
        }
1100
1200
}
1101
1201
 
1152
1252
 
1153
1253
static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td)
1154
1254
{
 
1255
        TransportType tt = GetTunnelBridgeTransportType(tile);
 
1256
 
1155
1257
        if (IsTunnel(tile)) {
1156
 
                td->str = (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) ?
1157
 
                        STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
1158
 
        } else { //so it must be a bridge
1159
 
                td->str = GetBridgeSpec(GetBridgeType(tile))->transport_name[GetTunnelBridgeTransportType(tile)];
1160
 
        }
1161
 
        td->owner = GetTileOwner(tile);
 
1258
                td->str = (tt == TRANSPORT_RAIL) ? STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL;
 
1259
        } else { // IsBridge(tile)
 
1260
                td->str = (tt == TRANSPORT_WATER) ? STR_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt];
 
1261
        }
 
1262
        td->owner[0] = GetTileOwner(tile);
 
1263
 
 
1264
        Owner road_owner = INVALID_OWNER;
 
1265
        Owner tram_owner = INVALID_OWNER;
 
1266
        RoadTypes rts = GetRoadTypes(tile);
 
1267
        if (HasBit(rts, ROADTYPE_ROAD)) road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
 
1268
        if (HasBit(rts, ROADTYPE_TRAM)) tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
 
1269
 
 
1270
        /* Is there a mix of owners? */
 
1271
        if ((tram_owner != INVALID_OWNER && tram_owner != td->owner[0]) ||
 
1272
                        (road_owner != INVALID_OWNER && road_owner != td->owner[0])) {
 
1273
                uint i = 1;
 
1274
                if (road_owner != INVALID_OWNER) {
 
1275
                        td->owner_type[i] = STR_ROAD_OWNER;
 
1276
                        td->owner[i] = road_owner;
 
1277
                        i++;
 
1278
                }
 
1279
                if (tram_owner != INVALID_OWNER) {
 
1280
                        td->owner_type[i] = STR_TRAM_OWNER;
 
1281
                        td->owner[i] = tram_owner;
 
1282
                }
 
1283
        }
1162
1284
}
1163
1285
 
1164
1286
 
1170
1292
static void TileLoop_TunnelBridge(TileIndex tile)
1171
1293
{
1172
1294
        bool snow_or_desert = HasTunnelBridgeSnowOrDesert(tile);
1173
 
        switch (_opt.landscape) {
 
1295
        switch (_settings_game.game_creation.landscape) {
1174
1296
                case LT_ARCTIC:
1175
1297
                        if (snow_or_desert != (GetTileZ(tile) > GetSnowLine())) {
1176
1298
                                SetTunnelBridgeSnowOrDesert(tile, !snow_or_desert);
1190
1312
        }
1191
1313
}
1192
1314
 
1193
 
static void ClickTile_TunnelBridge(TileIndex tile)
 
1315
static bool ClickTile_TunnelBridge(TileIndex tile)
1194
1316
{
1195
1317
        /* not used */
 
1318
        return false;
1196
1319
}
1197
1320
 
1198
1321
 
1203
1326
 
1204
1327
        DiagDirection dir = GetTunnelBridgeDirection(tile);
1205
1328
        if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
1206
 
        return CombineTrackStatus(TrackBitsToTrackdirBits(AxisToTrackBits(DiagDirToAxis(dir))), TRACKDIR_BIT_NONE);
 
1329
        return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
1207
1330
}
1208
1331
 
1209
 
static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
 
1332
static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
1210
1333
{
1211
 
        if (!IsTileOwner(tile, old_player)) return;
1212
 
 
1213
 
        if (new_player != PLAYER_SPECTATOR) {
1214
 
                SetTileOwner(tile, new_player);
 
1334
        for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 
1335
                /* Update all roadtypes, no matter if they are present */
 
1336
                if (GetRoadOwner(tile, rt) == old_owner) {
 
1337
                        SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner);
 
1338
                }
 
1339
        }
 
1340
 
 
1341
        if (!IsTileOwner(tile, old_owner)) return;
 
1342
 
 
1343
        if (new_owner != INVALID_OWNER) {
 
1344
                SetTileOwner(tile, new_owner);
1215
1345
        } else {
1216
1346
                if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR))) {
1217
1347
                        /* When clearing the bridge/tunnel failed there are still vehicles on/in
1218
1348
                         * the bridge/tunnel. As all *our* vehicles are already removed, they
1219
 
                         * must be of another owner. Therefor this must be a road bridge/tunnel.
 
1349
                         * must be of another owner. Therefore this can't be rail tunnel/bridge.
1220
1350
                         * In that case we can safely reassign the ownership to OWNER_NONE. */
1221
 
                        assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD);
 
1351
                        assert(GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL);
1222
1352
                        SetTileOwner(tile, OWNER_NONE);
1223
1353
                }
1224
1354
        }
1312
1442
                }
1313
1443
        } else { // IsBridge(tile)
1314
1444
 
1315
 
                if (v->IsPrimaryVehicle()) {
 
1445
                if (v->IsPrimaryVehicle() && v->type != VEH_SHIP) {
1316
1446
                        /* modify speed of vehicle */
1317
1447
                        uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed;
1318
1448
 
1328
1458
                                case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break;
1329
1459
                                case DIAGDIR_NW: if ((y & 0xF) != 0)             return VETSB_CONTINUE; break;
1330
1460
                        }
1331
 
                        if (v->type == VEH_TRAIN) {
1332
 
                                v->u.rail.track = TRACK_BIT_WORMHOLE;
1333
 
                                ClrBit(v->u.rail.flags, VRF_GOINGUP);
1334
 
                                ClrBit(v->u.rail.flags, VRF_GOINGDOWN);
1335
 
                        } else {
1336
 
                                v->u.road.state = RVSB_WORMHOLE;
 
1461
                        switch (v->type) {
 
1462
                                case VEH_TRAIN:
 
1463
                                        v->u.rail.track = TRACK_BIT_WORMHOLE;
 
1464
                                        ClrBit(v->u.rail.flags, VRF_GOINGUP);
 
1465
                                        ClrBit(v->u.rail.flags, VRF_GOINGDOWN);
 
1466
                                        break;
 
1467
 
 
1468
                                case VEH_ROAD:
 
1469
                                        v->u.road.state = RVSB_WORMHOLE;
 
1470
                                        break;
 
1471
 
 
1472
                                case VEH_SHIP:
 
1473
                                        v->u.ship.state = TRACK_BIT_WORMHOLE;
 
1474
                                        break;
 
1475
 
 
1476
                                default: NOT_REACHED();
1337
1477
                        }
1338
1478
                        return VETSB_ENTERED_WORMHOLE;
1339
1479
                } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
1340
1480
                        v->tile = tile;
1341
 
                        if (v->type == VEH_TRAIN) {
1342
 
                                if (v->u.rail.track == TRACK_BIT_WORMHOLE) {
1343
 
                                        v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
1344
 
                                        return VETSB_ENTERED_WORMHOLE;
1345
 
                                }
1346
 
                        } else {
1347
 
                                if (v->u.road.state == RVSB_WORMHOLE) {
1348
 
                                        v->u.road.state = _road_exit_tunnel_state[dir];
1349
 
                                        v->u.road.frame = 0;
1350
 
                                        return VETSB_ENTERED_WORMHOLE;
1351
 
                                }
 
1481
                        switch (v->type) {
 
1482
                                case VEH_TRAIN:
 
1483
                                        if (v->u.rail.track == TRACK_BIT_WORMHOLE) {
 
1484
                                                v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
 
1485
                                                return VETSB_ENTERED_WORMHOLE;
 
1486
                                        }
 
1487
                                        break;
 
1488
 
 
1489
                                case VEH_ROAD:
 
1490
                                        if (v->u.road.state == RVSB_WORMHOLE) {
 
1491
                                                v->u.road.state = _road_exit_tunnel_state[dir];
 
1492
                                                v->u.road.frame = 0;
 
1493
                                                return VETSB_ENTERED_WORMHOLE;
 
1494
                                        }
 
1495
                                        break;
 
1496
 
 
1497
                                case VEH_SHIP:
 
1498
                                        if (v->u.ship.state == TRACK_BIT_WORMHOLE) {
 
1499
                                                v->u.ship.state = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
 
1500
                                                return VETSB_ENTERED_WORMHOLE;
 
1501
                                        }
 
1502
                                        break;
 
1503
 
 
1504
                                default: NOT_REACHED();
1352
1505
                        }
1353
 
                        return VETSB_CONTINUE;
1354
1506
                }
1355
1507
        }
1356
1508
        return VETSB_CONTINUE;
1357
1509
}
1358
1510
 
1359
 
static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
 
1511
static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
1360
1512
{
1361
 
        if (_patches.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) {
 
1513
        if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile) && GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) {
1362
1514
                DiagDirection direction = GetTunnelBridgeDirection(tile);
1363
1515
                Axis axis = DiagDirToAxis(direction);
1364
1516
                CommandCost res;
1365
1517
                uint z_old;
1366
1518
                Slope tileh_old = GetTileSlope(tile, &z_old);
1367
1519
 
1368
 
                /* Check if new slope is valid for bridges in general (so we can savely call GetBridgeFoundation()) */
 
1520
                /* Check if new slope is valid for bridges in general (so we can safely call GetBridgeFoundation()) */
1369
1521
                if ((direction == DIAGDIR_NW) || (direction == DIAGDIR_NE)) {
1370
1522
                        CheckBridgeSlopeSouth(axis, &tileh_old, &z_old);
1371
1523
                        res = CheckBridgeSlopeSouth(axis, &tileh_new, &z_new);
1382
1534
}
1383
1535
 
1384
1536
extern const TileTypeProcs _tile_type_tunnelbridge_procs = {
1385
 
        DrawTile_TunnelBridge,           /* draw_tile_proc */
1386
 
        GetSlopeZ_TunnelBridge,          /* get_slope_z_proc */
1387
 
        ClearTile_TunnelBridge,          /* clear_tile_proc */
1388
 
        GetAcceptedCargo_TunnelBridge,   /* get_accepted_cargo_proc */
1389
 
        GetTileDesc_TunnelBridge,        /* get_tile_desc_proc */
1390
 
        GetTileTrackStatus_TunnelBridge, /* get_tile_track_status_proc */
1391
 
        ClickTile_TunnelBridge,          /* click_tile_proc */
1392
 
        AnimateTile_TunnelBridge,        /* animate_tile_proc */
1393
 
        TileLoop_TunnelBridge,           /* tile_loop_clear */
1394
 
        ChangeTileOwner_TunnelBridge,    /* change_tile_owner_clear */
1395
 
        NULL,                            /* get_produced_cargo_proc */
1396
 
        VehicleEnter_TunnelBridge,       /* vehicle_enter_tile_proc */
1397
 
        GetFoundation_TunnelBridge,      /* get_foundation_proc */
1398
 
        TerraformTile_TunnelBridge,      /* terraform_tile_proc */
 
1537
        DrawTile_TunnelBridge,           // draw_tile_proc
 
1538
        GetSlopeZ_TunnelBridge,          // get_slope_z_proc
 
1539
        ClearTile_TunnelBridge,          // clear_tile_proc
 
1540
        GetAcceptedCargo_TunnelBridge,   // get_accepted_cargo_proc
 
1541
        GetTileDesc_TunnelBridge,        // get_tile_desc_proc
 
1542
        GetTileTrackStatus_TunnelBridge, // get_tile_track_status_proc
 
1543
        ClickTile_TunnelBridge,          // click_tile_proc
 
1544
        AnimateTile_TunnelBridge,        // animate_tile_proc
 
1545
        TileLoop_TunnelBridge,           // tile_loop_clear
 
1546
        ChangeTileOwner_TunnelBridge,    // change_tile_owner_clear
 
1547
        NULL,                            // get_produced_cargo_proc
 
1548
        VehicleEnter_TunnelBridge,       // vehicle_enter_tile_proc
 
1549
        GetFoundation_TunnelBridge,      // get_foundation_proc
 
1550
        TerraformTile_TunnelBridge,      // terraform_tile_proc
1399
1551
};