00001
00002
00008 #include "stdafx.h"
00009 #include "openttd.h"
00010 #include "bridge_map.h"
00011 #include "rail_map.h"
00012 #include "road_map.h"
00013 #include "tile_cmd.h"
00014 #include "landscape.h"
00015 #include "tunnel_map.h"
00016 #include "unmovable_map.h"
00017 #include "viewport_func.h"
00018 #include "command_func.h"
00019 #include "town.h"
00020 #include "variables.h"
00021 #include "bridge.h"
00022 #include "train.h"
00023 #include "water_map.h"
00024 #include "yapf/yapf.h"
00025 #include "newgrf_sound.h"
00026 #include "autoslope.h"
00027 #include "transparency.h"
00028 #include "tunnelbridge_map.h"
00029 #include "strings_func.h"
00030 #include "date_func.h"
00031 #include "functions.h"
00032 #include "vehicle_func.h"
00033 #include "sound_func.h"
00034 #include "signal_func.h"
00035 #include "tunnelbridge.h"
00036 #include "company_base.h"
00037 #include "engine_func.h"
00038 #include "engine_base.h"
00039 #include "economy_func.h"
00040 #include "rail.h"
00041 #include "cheat_func.h"
00042 #include "elrail_func.h"
00043 #include "landscape_type.h"
00044
00045 #include "table/sprites.h"
00046 #include "table/strings.h"
00047 #include "table/bridge_land.h"
00048
00049 BridgeSpec _bridge[MAX_BRIDGES];
00050 TileIndex _build_tunnel_endtile;
00051
00053 void ResetBridges()
00054 {
00055
00056 for (BridgeType i = 0; i < MAX_BRIDGES; i++) {
00057 if (_bridge[i].sprite_table != NULL) {
00058 for (BridgePieces j = BRIDGE_PIECE_NORTH; j < BRIDGE_PIECE_INVALID; j++) free(_bridge[i].sprite_table[j]);
00059 free(_bridge[i].sprite_table);
00060 }
00061 }
00062
00063
00064 memset(&_bridge, 0, sizeof(_bridge));
00065
00066 memcpy(&_bridge, &_orig_bridge, sizeof(_orig_bridge));
00067 }
00068
00072 int CalcBridgeLenCostFactor(int x)
00073 {
00074 int n;
00075 int r;
00076
00077 if (x < 2) return x;
00078 x -= 2;
00079 for (n = 0, r = 2;; n++) {
00080 if (x <= n) return r + x * n;
00081 r += n * n;
00082 x -= n;
00083 }
00084 }
00085
00086 Foundation GetBridgeFoundation(Slope tileh, Axis axis)
00087 {
00088 if ((tileh == SLOPE_FLAT) ||
00089 (((tileh == SLOPE_NE) || (tileh == SLOPE_SW)) && (axis == AXIS_X)) ||
00090 (((tileh == SLOPE_NW) || (tileh == SLOPE_SE)) && (axis == AXIS_Y))) return FOUNDATION_NONE;
00091
00092 return (HasSlopeHighestCorner(tileh) ? InclinedFoundation(axis) : FlatteningFoundation(tileh));
00093 }
00094
00102 bool HasBridgeFlatRamp(Slope tileh, Axis axis)
00103 {
00104 ApplyFoundationToSlope(GetBridgeFoundation(tileh, axis), &tileh);
00105
00106 return (tileh != SLOPE_FLAT);
00107 }
00108
00109 static inline const PalSpriteID *GetBridgeSpriteTable(int index, BridgePieces table)
00110 {
00111 const BridgeSpec *bridge = GetBridgeSpec(index);
00112 assert(table < BRIDGE_PIECE_INVALID);
00113 if (bridge->sprite_table == NULL || bridge->sprite_table[table] == NULL) {
00114 return _bridge_sprite_table[index][table];
00115 } else {
00116 return bridge->sprite_table[table];
00117 }
00118 }
00119
00120
00129 static CommandCost CheckBridgeSlopeNorth(Axis axis, Slope *tileh, uint *z)
00130 {
00131 Foundation f = GetBridgeFoundation(*tileh, axis);
00132 *z += ApplyFoundationToSlope(f, tileh);
00133
00134 Slope valid_inclined = (axis == AXIS_X ? SLOPE_NE : SLOPE_NW);
00135 if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
00136
00137 if (f == FOUNDATION_NONE) return CommandCost();
00138
00139 return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
00140 }
00141
00150 static CommandCost CheckBridgeSlopeSouth(Axis axis, Slope *tileh, uint *z)
00151 {
00152 Foundation f = GetBridgeFoundation(*tileh, axis);
00153 *z += ApplyFoundationToSlope(f, tileh);
00154
00155 Slope valid_inclined = (axis == AXIS_X ? SLOPE_SW : SLOPE_SE);
00156 if ((*tileh != SLOPE_FLAT) && (*tileh != valid_inclined)) return CMD_ERROR;
00157
00158 if (f == FOUNDATION_NONE) return CommandCost();
00159
00160 return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
00161 }
00162
00163 bool CheckBridge_Stuff(BridgeType bridge_type, uint bridge_len, uint32 flags)
00164 {
00165 if (flags & DC_QUERY_COST) {
00166 return bridge_len <= (_settings_game.construction.longbridges ? 100U : 16U);
00167 }
00168
00169 if (bridge_type >= MAX_BRIDGES) return false;
00170
00171 const BridgeSpec *b = GetBridgeSpec(bridge_type);
00172 if (b->avail_year > _cur_year) return false;
00173
00174 uint max = b->max_length;
00175 if (max >= 16 && _settings_game.construction.longbridges) max = 100;
00176
00177 return b->min_length <= bridge_len && bridge_len <= max;
00178 }
00179
00189 CommandCost CmdBuildBridge(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00190 {
00191 BridgeType bridge_type;
00192 RailType railtype = INVALID_RAILTYPE;
00193 RoadTypes roadtypes = ROADTYPES_NONE;
00194 uint x;
00195 uint y;
00196 uint sx;
00197 uint sy;
00198 TileIndex tile_start;
00199 TileIndex tile_end;
00200 Slope tileh_start;
00201 Slope tileh_end;
00202 uint z_start;
00203 uint z_end;
00204 TileIndex tile;
00205 TileIndexDiff delta;
00206 uint bridge_len;
00207 Axis direction;
00208 CommandCost cost(EXPENSES_CONSTRUCTION);
00209 CommandCost ret;
00210 bool replace_bridge = false;
00211 BridgeType replaced_bridge_type;
00212 TransportType transport_type;
00213
00214
00215 bridge_type = GB(p2, 0, 8);
00216
00217 if (p1 >= MapSize()) return CMD_ERROR;
00218
00219 transport_type = (TransportType)GB(p2, 15, 2);
00220
00221
00222 switch (transport_type) {
00223 case TRANSPORT_ROAD:
00224 roadtypes = (RoadTypes)GB(p2, 8, 3);
00225 if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
00226 break;
00227
00228 case TRANSPORT_RAIL:
00229 railtype = (RailType)GB(p2, 8, 7);
00230 if (!ValParamRailtype(railtype)) return CMD_ERROR;
00231 break;
00232
00233 case TRANSPORT_WATER:
00234 break;
00235
00236 default:
00237
00238 return CMD_ERROR;
00239 }
00240
00241 x = TileX(end_tile);
00242 y = TileY(end_tile);
00243 sx = TileX(p1);
00244 sy = TileY(p1);
00245
00246
00247 if (x == sx) {
00248 if (y == sy) return_cmd_error(STR_5008_CANNOT_START_AND_END_ON);
00249 direction = AXIS_Y;
00250 if (y > sy) Swap(y, sy);
00251 } else if (y == sy) {
00252 direction = AXIS_X;
00253 if (x > sx) Swap(x, sx);
00254 } else {
00255 return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN);
00256 }
00257
00258 bridge_len = sx + sy - x - y - 1;
00259 if (transport_type != TRANSPORT_WATER) {
00260
00261 if (!CheckBridge_Stuff(bridge_type, bridge_len, flags)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE);
00262 }
00263
00264
00265 tile_start = TileXY(x, y);
00266 tile_end = TileXY(sx, sy);
00267 if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) {
00268 return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH);
00269 }
00270
00271 tileh_start = GetTileSlope(tile_start, &z_start);
00272 tileh_end = GetTileSlope(tile_end, &z_end);
00273
00274 CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start);
00275 CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end, &z_end);
00276
00277 if (z_start != z_end) return_cmd_error(STR_BRIDGEHEADS_NOT_SAME_HEIGHT);
00278
00279 if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
00280 GetOtherBridgeEnd(tile_start) == tile_end &&
00281 GetTunnelBridgeTransportType(tile_start) == transport_type) {
00282
00283
00284
00285 if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
00286 return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
00287 }
00288
00289
00290 if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
00291 GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed) {
00292 Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
00293
00294 if (t == NULL) {
00295 return CMD_ERROR;
00296 } else {
00297 SetDParam(0, t->index);
00298 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
00299 }
00300 }
00301
00302
00303 if (!(flags & DC_QUERY_COST) && bridge_type == GetBridgeType(tile_start)) {
00304 return_cmd_error(STR_1007_ALREADY_BUILT);
00305 }
00306
00307
00308 if (!IsTileOwner(tile_start, _current_company) && !IsTileOwner(tile_start, OWNER_TOWN)) {
00309 return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
00310 }
00311
00312 cost.AddCost((bridge_len + 1) * _price.clear_bridge);
00313 replace_bridge = true;
00314 replaced_bridge_type = GetBridgeType(tile_start);
00315
00316
00317 roadtypes |= GetRoadTypes(tile_start);
00318 } else {
00319
00320
00321 bool allow_on_slopes = (!_is_old_ai_company && _settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
00322
00323
00324 ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00325 if (CmdFailed(ret)) return ret;
00326 cost = ret;
00327
00328 if (CmdFailed(terraform_cost_north) || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes))
00329 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
00330 cost.AddCost(terraform_cost_north);
00331
00332
00333 ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00334 if (CmdFailed(ret)) return ret;
00335 cost.AddCost(ret);
00336
00337
00338 if (CmdFailed(terraform_cost_south) || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes))
00339 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
00340 cost.AddCost(terraform_cost_south);
00341
00342 if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
00343 }
00344
00345 if (!replace_bridge) {
00346 TileIndex Heads[] = {tile_start, tile_end};
00347 int i;
00348
00349 for (i = 0; i < 2; i++) {
00350 if (MayHaveBridgeAbove(Heads[i])) {
00351 if (IsBridgeAbove(Heads[i])) {
00352 TileIndex north_head = GetNorthernBridgeEnd(Heads[i]);
00353
00354 if (direction == GetBridgeAxis(Heads[i])) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
00355
00356 if (z_start + TILE_HEIGHT == GetBridgeHeight(north_head)) {
00357 return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
00358 }
00359 }
00360 }
00361 }
00362 }
00363
00364
00365 if (flags & DC_EXEC) {
00366 DiagDirection dir = AxisToDiagDir(direction);
00367 Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_company;
00368
00369 switch (transport_type) {
00370 case TRANSPORT_RAIL:
00371 MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype);
00372 MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype);
00373 break;
00374
00375 case TRANSPORT_ROAD:
00376 MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes);
00377 MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes);
00378 break;
00379
00380 case TRANSPORT_WATER:
00381 MakeAqueductBridgeRamp(tile_start, owner, dir);
00382 MakeAqueductBridgeRamp(tile_end, owner, ReverseDiagDir(dir));
00383 break;
00384
00385 default:
00386 NOT_REACHED();
00387 break;
00388 }
00389 MarkTileDirtyByTile(tile_start);
00390 MarkTileDirtyByTile(tile_end);
00391 }
00392
00393 delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
00394 for (tile = tile_start + delta; tile != tile_end; tile += delta) {
00395 if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_BRIDGE_TOO_LOW_FOR_TERRAIN);
00396
00397 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) && !replace_bridge) {
00398
00399 return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
00400 }
00401
00402 switch (GetTileType(tile)) {
00403 case MP_WATER:
00404 if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
00405 break;
00406
00407 case MP_RAILWAY:
00408 if (!IsPlainRailTile(tile)) goto not_valid_below;
00409 break;
00410
00411 case MP_ROAD:
00412 if (IsRoadDepot(tile)) goto not_valid_below;
00413 break;
00414
00415 case MP_TUNNELBRIDGE:
00416 if (IsTunnel(tile)) break;
00417 if (replace_bridge) break;
00418 if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below;
00419 if (z_start < GetBridgeHeight(tile)) goto not_valid_below;
00420 break;
00421
00422 case MP_UNMOVABLE:
00423 if (!IsOwnedLand(tile)) goto not_valid_below;
00424 break;
00425
00426 case MP_CLEAR:
00427 break;
00428
00429 default:
00430 not_valid_below:;
00431
00432 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00433 if (CmdFailed(ret)) return ret;
00434 cost.AddCost(ret);
00435 break;
00436 }
00437
00438 if (flags & DC_EXEC) {
00439 SetBridgeMiddle(tile, direction);
00440 MarkTileDirtyByTile(tile);
00441 }
00442 }
00443
00444 if (flags & DC_EXEC && transport_type == TRANSPORT_RAIL) {
00445 Track track = AxisToTrack(direction);
00446 AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_company);
00447 YapfNotifyTrackLayoutChange(tile_start, track);
00448 }
00449
00450
00451
00452
00453
00454 if (!(flags & DC_QUERY_COST) || (IsValidCompanyID(_current_company) && GetCompany(_current_company)->is_ai)) {
00455 bridge_len += 2;
00456
00457 if (IsValidCompanyID(_current_company) && !_is_old_ai_company)
00458 bridge_len = CalcBridgeLenCostFactor(bridge_len);
00459
00460 cost.AddCost((int64)bridge_len * _price.build_bridge * GetBridgeSpec(bridge_type)->price >> 8);
00461
00462
00463 if (transport_type == TRANSPORT_WATER) cost.AddCost((int64)bridge_len * _price.clear_water);
00464 }
00465
00466 return cost;
00467 }
00468
00469
00476 CommandCost CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2, const char *text)
00477 {
00478 TileIndexDiff delta;
00479 TileIndex end_tile;
00480 DiagDirection direction;
00481 Slope start_tileh;
00482 Slope end_tileh;
00483 TransportType transport_type = (TransportType)GB(p1, 9, 1);
00484 uint start_z;
00485 uint end_z;
00486 CommandCost cost(EXPENSES_CONSTRUCTION);
00487 CommandCost ret;
00488
00489 _build_tunnel_endtile = 0;
00490 if (transport_type == TRANSPORT_RAIL) {
00491 if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
00492 } else {
00493 const RoadTypes rts = (RoadTypes)GB(p1, 0, 3);
00494 if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
00495 }
00496
00497 start_tileh = GetTileSlope(start_tile, &start_z);
00498 direction = GetInclinedSlopeDirection(start_tileh);
00499 if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
00500
00501 if (IsWaterTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
00502
00503 ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00504 if (CmdFailed(ret)) return ret;
00505
00506
00507
00508
00509
00510
00511 delta = TileOffsByDiagDir(direction);
00512 DiagDirection tunnel_in_way_dir;
00513 if (DiagDirToAxis(direction) == AXIS_Y) {
00514 tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE;
00515 } else {
00516 tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW;
00517 }
00518
00519 end_tile = start_tile;
00520
00522 int tiles_coef = 3;
00524 int tiles = 0;
00526 int tiles_bump = 25;
00527
00528 for (;;) {
00529 end_tile += delta;
00530 end_tileh = GetTileSlope(end_tile, &end_z);
00531
00532 if (start_z == end_z) break;
00533
00534 if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) {
00535 return_cmd_error(STR_5003_ANOTHER_TUNNEL_IN_THE_WAY);
00536 }
00537
00538 tiles++;
00539 if (tiles == tiles_bump) {
00540 tiles_coef++;
00541 tiles_bump *= 2;
00542 }
00543
00544 cost.AddCost(_price.build_tunnel);
00545 cost.AddCost(cost.GetCost() >> tiles_coef);
00546 }
00547
00548
00549 cost.AddCost(_price.build_tunnel);
00550 cost.AddCost(ret);
00551
00552
00553 _build_tunnel_endtile = end_tile;
00554
00555 if (IsWaterTile(end_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
00556
00557
00558 if (end_tileh != ComplementSlope(start_tileh)) {
00559
00560
00561
00562
00563 ret = DoCommand(end_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR);
00564 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
00565
00566 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
00567 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
00568 } else {
00569 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00570 if (CmdFailed(ret)) return ret;
00571 }
00572 cost.AddCost(_price.build_tunnel);
00573 cost.AddCost(ret);
00574
00575 if (flags & DC_EXEC) {
00576 if (transport_type == TRANSPORT_RAIL) {
00577 MakeRailTunnel(start_tile, _current_company, direction, (RailType)GB(p1, 0, 4));
00578 MakeRailTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4));
00579 AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company);
00580 YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
00581 } else {
00582 MakeRoadTunnel(start_tile, _current_company, direction, (RoadTypes)GB(p1, 0, 3));
00583 MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3));
00584 }
00585 }
00586
00587 return cost;
00588 }
00589
00590
00591 static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
00592 {
00593
00594 if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return true;
00595
00596 if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
00597
00598 if (IsTileOwner(tile, OWNER_TOWN) && (_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
00599 return false;
00600 }
00601
00602 static CommandCost DoClearTunnel(TileIndex tile, uint32 flags)
00603 {
00604 Town *t = NULL;
00605 TileIndex endtile;
00606
00607 if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR;
00608
00609 endtile = GetOtherTunnelEnd(tile);
00610
00611 if (HasVehicleOnTunnelBridge(tile, endtile)) return CMD_ERROR;
00612
00613 _build_tunnel_endtile = endtile;
00614
00615 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00616 t = ClosestTownFromTile(tile, UINT_MAX);
00617
00618
00619
00620 if (!CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE)) {
00621 SetDParam(0, t->index);
00622 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
00623 }
00624 }
00625
00626
00627
00628 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00629 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
00630 }
00631
00632 if (flags & DC_EXEC) {
00633 if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
00634
00635 DiagDirection dir = GetTunnelBridgeDirection(tile);
00636 Track track = DiagDirToDiagTrack(dir);
00637 Owner owner = GetTileOwner(tile);
00638
00639 Vehicle *v = NULL;
00640 if (GetTunnelBridgeReservation(tile)) {
00641 v = GetTrainForReservation(tile, track);
00642 if (v != NULL) FreeTrainTrackReservation(v);
00643 }
00644
00645 DoClearSquare(tile);
00646 DoClearSquare(endtile);
00647
00648
00649 AddSideToSignalBuffer(tile, ReverseDiagDir(dir), owner);
00650 AddSideToSignalBuffer(endtile, dir, owner);
00651
00652 YapfNotifyTrackLayoutChange(tile, track);
00653 YapfNotifyTrackLayoutChange(endtile, track);
00654
00655 if (v != NULL) TryPathReserve(v);
00656 } else {
00657 DoClearSquare(tile);
00658 DoClearSquare(endtile);
00659 }
00660 }
00661 return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_tunnel * (GetTunnelBridgeLength(tile, endtile) + 2));
00662 }
00663
00664
00665 static CommandCost DoClearBridge(TileIndex tile, uint32 flags)
00666 {
00667 DiagDirection direction;
00668 TileIndexDiff delta;
00669 TileIndex endtile;
00670 Town *t = NULL;
00671
00672 if (!CheckAllowRemoveTunnelBridge(tile)) return CMD_ERROR;
00673
00674 endtile = GetOtherBridgeEnd(tile);
00675
00676 if (HasVehicleOnTunnelBridge(tile, endtile)) return CMD_ERROR;
00677
00678 direction = GetTunnelBridgeDirection(tile);
00679 delta = TileOffsByDiagDir(direction);
00680
00681 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00682 t = ClosestTownFromTile(tile, UINT_MAX);
00683
00684
00685
00686 if (!CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE)) {
00687 SetDParam(0, t->index);
00688 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES);
00689 }
00690 }
00691
00692
00693
00694 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) {
00695 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM);
00696 }
00697
00698 if (flags & DC_EXEC) {
00699
00700 bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
00701 Owner owner = GetTileOwner(tile);
00702 uint height = GetBridgeHeight(tile);
00703 Vehicle *v = NULL;
00704
00705 if (rail && GetTunnelBridgeReservation(tile)) {
00706 v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
00707 if (v != NULL) FreeTrainTrackReservation(v);
00708 }
00709
00710 DoClearSquare(tile);
00711 DoClearSquare(endtile);
00712 for (TileIndex c = tile + delta; c != endtile; c += delta) {
00713
00714 if (IsNormalRoadTile(c) && GetRoadside(c) == ROADSIDE_TREES) {
00715 uint minz = GetTileMaxZ(c) + 3 * TILE_HEIGHT;
00716 if (height < minz) SetRoadside(c, ROADSIDE_PAVED);
00717 }
00718 ClearBridgeMiddle(c);
00719 MarkTileDirtyByTile(c);
00720 }
00721
00722 if (rail) {
00723
00724 AddSideToSignalBuffer(tile, ReverseDiagDir(direction), owner);
00725 AddSideToSignalBuffer(endtile, direction, owner);
00726
00727 Track track = DiagDirToDiagTrack(direction);
00728 YapfNotifyTrackLayoutChange(tile, track);
00729 YapfNotifyTrackLayoutChange(endtile, track);
00730
00731 if (v != NULL) TryPathReserve(v, true);
00732 }
00733 }
00734
00735 return CommandCost(EXPENSES_CONSTRUCTION, (GetTunnelBridgeLength(tile, endtile) + 2) * _price.clear_bridge);
00736 }
00737
00738 static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags)
00739 {
00740 if (IsTunnel(tile)) {
00741 if (flags & DC_AUTO) return_cmd_error(STR_5006_MUST_DEMOLISH_TUNNEL_FIRST);
00742 return DoClearTunnel(tile, flags);
00743 } else {
00744 if (flags & DC_AUTO) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
00745 return DoClearBridge(tile, flags);
00746 }
00747
00748 return CMD_ERROR;
00749 }
00750
00762 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge)
00763 {
00764
00765 if (IsInvisibilitySet(TO_BRIDGES)) return;
00766
00767 SpriteID image = psid->sprite;
00768
00769 if (image != 0) {
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 bool side = HasBit(image, 0);
00780
00781
00782 DiagDirection dir = AxisToDiagDir(axis);
00783 if (side != (axis == AXIS_Y)) dir = ReverseDiagDir(dir);
00784
00785
00786 int front_height = ti->z;
00787 int back_height = ti->z;
00788 GetSlopeZOnEdge(ti->tileh, dir, &front_height, &back_height);
00789
00790
00791 int w = (axis == AXIS_X ? 16 : 2);
00792 int h = (axis == AXIS_X ? 2 : 16);
00793
00794 int x_back = x - (axis == AXIS_X ? 0 : 9);
00795 int y_back = y - (axis == AXIS_X ? 9 : 0);
00796
00797 for (int cur_z = z_bridge; cur_z >= front_height || cur_z >= back_height; cur_z -= TILE_HEIGHT) {
00798
00799 if (cur_z >= front_height) {
00800 AddSortableSpriteToDraw(image, psid->pal, x, y, w, h, BB_HEIGHT_UNDER_BRIDGE - 5, cur_z, IsTransparencySet(TO_BRIDGES), 0, 0, -5);
00801 }
00802
00803
00804 if (drawfarpillar && cur_z >= back_height && cur_z < z_bridge - TILE_HEIGHT) {
00805 AddSortableSpriteToDraw(image, psid->pal, x_back, y_back, w, h, BB_HEIGHT_UNDER_BRIDGE - 5, cur_z, IsTransparencySet(TO_BRIDGES), 0, 0, -5);
00806 }
00807 }
00808 }
00809 }
00810
00820 static void DrawBridgeTramBits(int x, int y, byte z, int offset, bool overlay, bool head)
00821 {
00822 static const SpriteID tram_offsets[2][6] = { { 107, 108, 109, 110, 111, 112 }, { 4, 5, 15, 16, 17, 18 } };
00823 static const SpriteID back_offsets[6] = { 95, 96, 99, 102, 100, 101 };
00824 static const SpriteID front_offsets[6] = { 97, 98, 103, 106, 104, 105 };
00825
00826 static const uint size_x[6] = { 1, 16, 16, 1, 16, 1 };
00827 static const uint size_y[6] = { 16, 1, 1, 16, 1, 16 };
00828 static const uint front_bb_offset_x[6] = { 15, 0, 0, 15, 0, 15 };
00829 static const uint front_bb_offset_y[6] = { 0, 15, 15, 0, 15, 0 };
00830
00831
00832
00833 if (head || !IsInvisibilitySet(TO_BRIDGES)) {
00834 AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + tram_offsets[overlay][offset], PAL_NONE,
00835 x, y, size_x[offset], size_y[offset], 0x28, z,
00836 !head && IsTransparencySet(TO_BRIDGES));
00837 }
00838
00839
00840 if (!IsInvisibilitySet(TO_CATENARY)) {
00841 AddSortableSpriteToDraw(SPR_TRAMWAY_BASE + back_offsets[offset], PAL_NON