31 #include "newgrf.h" |
31 #include "newgrf.h" |
32 #include "station_map.h" |
32 #include "station_map.h" |
33 #include "tunnel_map.h" |
33 #include "tunnel_map.h" |
34 #include "misc/autoptr.hpp" |
34 #include "misc/autoptr.hpp" |
35 #include "autoslope.h" |
35 #include "autoslope.h" |
|
36 #include "transparency.h" |
36 |
37 |
37 #define M(x) (1 << (x)) |
38 #define M(x) (1 << (x)) |
38 /* Level crossings may only be built on these slopes */ |
39 /* Level crossings may only be built on these slopes */ |
39 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT)); |
40 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT)); |
40 #undef M |
41 #undef M |
136 } |
137 } |
137 |
138 |
138 RoadBits pieces = Extract<RoadBits, 0>(p1); |
139 RoadBits pieces = Extract<RoadBits, 0>(p1); |
139 RoadTypes rts = GetRoadTypes(tile); |
140 RoadTypes rts = GetRoadTypes(tile); |
140 /* The tile doesn't have the given road type */ |
141 /* The tile doesn't have the given road type */ |
141 if (!HASBIT(rts, rt)) return CMD_ERROR; |
142 if (!HasBit(rts, rt)) return CMD_ERROR; |
142 |
143 |
143 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
144 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
144 |
145 |
145 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
146 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
146 |
147 |
218 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
219 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
219 SetRoadBits(tile, present, rt); |
220 SetRoadBits(tile, present, rt); |
220 MarkTileDirtyByTile(tile); |
221 MarkTileDirtyByTile(tile); |
221 } |
222 } |
222 } |
223 } |
223 return CommandCost(COUNTBITS(c) * _price.remove_road); |
224 return CommandCost(CountBits(c) * _price.remove_road); |
224 } |
225 } |
225 |
226 |
226 case ROAD_TILE_CROSSING: { |
227 case ROAD_TILE_CROSSING: { |
227 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
228 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
228 return CMD_ERROR; |
229 return CMD_ERROR; |
229 } |
230 } |
230 |
231 |
231 /* Don't allow road to be removed from the crossing when there is tram; |
232 /* Don't allow road to be removed from the crossing when there is tram; |
232 * we can't draw the crossing without trambits ;) */ |
233 * we can't draw the crossing without trambits ;) */ |
233 if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HASBIT(p1, 6))) return CMD_ERROR; |
234 if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR; |
234 |
235 |
235 if (flags & DC_EXEC) { |
236 if (flags & DC_EXEC) { |
236 if (rt == ROADTYPE_ROAD) { |
237 if (rt == ROADTYPE_ROAD) { |
237 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
238 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
238 } |
239 } |
350 RoadBits road_bits = *pieces | existing; |
351 RoadBits road_bits = *pieces | existing; |
351 |
352 |
352 /* Single bits on slopes. |
353 /* Single bits on slopes. |
353 * We check for the roads that need at least 2 bits */ |
354 * We check for the roads that need at least 2 bits */ |
354 if (_patches.build_on_slopes && |
355 if (_patches.build_on_slopes && |
355 existing == ROAD_NONE && COUNTBITS(*pieces) == 1 && |
356 existing == ROAD_NONE && CountBits(*pieces) == 1 && |
356 (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { |
357 (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { |
357 return CommandCost(_price.terraform); |
358 return CommandCost(_price.terraform); |
358 } |
359 } |
359 |
360 |
360 /* no special foundation */ |
361 /* no special foundation */ |
402 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
403 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
403 |
404 |
404 RoadBits pieces = Extract<RoadBits, 0>(p1); |
405 RoadBits pieces = Extract<RoadBits, 0>(p1); |
405 |
406 |
406 RoadType rt = (RoadType)GB(p1, 4, 2); |
407 RoadType rt = (RoadType)GB(p1, 4, 2); |
407 if (!IsValidRoadType(rt)) return CMD_ERROR; |
408 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
408 |
409 |
409 DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); |
410 DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); |
410 |
411 |
411 tileh = GetTileSlope(tile, NULL); |
412 tileh = GetTileSlope(tile, NULL); |
412 |
413 |
416 case ROAD_TILE_NORMAL: { |
417 case ROAD_TILE_NORMAL: { |
417 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
418 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
418 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
419 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
419 |
420 |
420 all_bits = GetAllRoadBits(tile); |
421 all_bits = GetAllRoadBits(tile); |
421 if (!HASBIT(GetRoadTypes(tile), rt)) break; |
422 if (!HasBit(GetRoadTypes(tile), rt)) break; |
422 |
423 |
423 existing = GetRoadBits(tile, rt); |
424 existing = GetRoadBits(tile, rt); |
424 RoadBits merged = existing | pieces; |
425 RoadBits merged = existing | pieces; |
425 bool crossing = (merged != ROAD_X && merged != ROAD_Y); |
426 bool crossing = (merged != ROAD_X && merged != ROAD_Y); |
426 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) { |
427 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) { |
461 if (IsSteepSlope(tileh)) { |
462 if (IsSteepSlope(tileh)) { |
462 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
463 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
463 } |
464 } |
464 |
465 |
465 /* Level crossings may only be built on these slopes */ |
466 /* Level crossings may only be built on these slopes */ |
466 if (!HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh)) { |
467 if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) { |
467 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
468 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
468 } |
469 } |
469 |
470 |
470 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear; |
471 if (GetRailTileType(tile) != RAIL_TILE_NORMAL) goto do_clear; |
471 switch (GetTrackBits(tile)) { |
472 switch (GetTrackBits(tile)) { |
493 return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); |
494 return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); |
494 } |
495 } |
495 |
496 |
496 case MP_STATION: |
497 case MP_STATION: |
497 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
498 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
498 if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
499 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
499 /* Don't allow "upgrading" the roadstop when vehicles are already driving on it */ |
500 /* Don't allow "upgrading" the roadstop when vehicles are already driving on it */ |
500 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
501 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
501 break; |
502 break; |
502 |
503 |
503 case MP_TUNNELBRIDGE: |
504 case MP_TUNNELBRIDGE: |
504 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
505 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
505 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
506 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
506 if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
507 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
507 /* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */ |
508 /* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */ |
508 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
509 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
509 break; |
510 break; |
510 |
511 |
511 default: |
512 default: |
529 if (IsTileType(tile, MP_ROAD)) { |
530 if (IsTileType(tile, MP_ROAD)) { |
530 /* Don't put the pieces that already exist */ |
531 /* Don't put the pieces that already exist */ |
531 pieces &= ComplementRoadBits(existing); |
532 pieces &= ComplementRoadBits(existing); |
532 } |
533 } |
533 |
534 |
534 cost.AddCost(COUNTBITS(pieces) * _price.build_road); |
535 cost.AddCost(CountBits(pieces) * _price.build_road); |
535 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
536 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
536 /* Pay for *every* tile of the bridge or tunnel */ |
537 /* Pay for *every* tile of the bridge or tunnel */ |
537 cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile)); |
538 cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile)); |
538 } |
539 } |
539 |
540 |
633 |
634 |
634 if (p1 >= MapSize()) return CMD_ERROR; |
635 if (p1 >= MapSize()) return CMD_ERROR; |
635 |
636 |
636 start_tile = p1; |
637 start_tile = p1; |
637 RoadType rt = (RoadType)GB(p2, 3, 2); |
638 RoadType rt = (RoadType)GB(p2, 3, 2); |
638 if (!IsValidRoadType(rt)) return CMD_ERROR; |
639 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
639 |
640 |
640 /* Only drag in X or Y direction dictated by the direction variable */ |
641 /* Only drag in X or Y direction dictated by the direction variable */ |
641 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
642 if (!HasBit(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
642 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
643 if (HasBit(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
643 |
644 |
644 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
645 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
645 if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) { |
646 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
646 TileIndex t = start_tile; |
647 TileIndex t = start_tile; |
647 start_tile = end_tile; |
648 start_tile = end_tile; |
648 end_tile = t; |
649 end_tile = t; |
649 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
650 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
650 drd = DRD_SOUTHBOUND; |
651 drd = DRD_SOUTHBOUND; |
651 } |
652 } |
652 |
653 |
653 /* On the X-axis, we have to swap the initial bits, so they |
654 /* On the X-axis, we have to swap the initial bits, so they |
654 * will be interpreted correctly in the GTTS. Futhermore |
655 * will be interpreted correctly in the GTTS. Futhermore |
655 * when you just 'click' on one tile to build them. */ |
656 * when you just 'click' on one tile to build them. */ |
656 if (HASBIT(p2, 2) == (start_tile == end_tile && HASBIT(p2, 0) == HASBIT(p2, 1))) drd ^= DRD_BOTH; |
657 if (HasBit(p2, 2) == (start_tile == end_tile && HasBit(p2, 0) == HasBit(p2, 1))) drd ^= DRD_BOTH; |
657 /* No disallowed direction bits have to be toggled */ |
658 /* No disallowed direction bits have to be toggled */ |
658 if (!HASBIT(p2, 5)) drd = DRD_NONE; |
659 if (!HasBit(p2, 5)) drd = DRD_NONE; |
659 |
660 |
660 tile = start_tile; |
661 tile = start_tile; |
661 /* Start tile is the small number. */ |
662 /* Start tile is the small number. */ |
662 for (;;) { |
663 for (;;) { |
663 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
664 RoadBits bits = HasBit(p2, 2) ? ROAD_Y : ROAD_X; |
664 |
665 |
665 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
666 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
666 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
667 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
667 |
668 |
668 ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD); |
669 ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD); |
669 if (CmdFailed(ret)) { |
670 if (CmdFailed(ret)) { |
670 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
671 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
671 _error_message = INVALID_STRING_ID; |
672 _error_message = INVALID_STRING_ID; |
719 start_tile = p1; |
720 start_tile = p1; |
720 RoadType rt = (RoadType)GB(p2, 3, 2); |
721 RoadType rt = (RoadType)GB(p2, 3, 2); |
721 if (!IsValidRoadType(rt)) return CMD_ERROR; |
722 if (!IsValidRoadType(rt)) return CMD_ERROR; |
722 |
723 |
723 /* Only drag in X or Y direction dictated by the direction variable */ |
724 /* Only drag in X or Y direction dictated by the direction variable */ |
724 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
725 if (!HasBit(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
725 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
726 if (HasBit(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
726 |
727 |
727 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
728 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
728 if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) { |
729 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
729 TileIndex t = start_tile; |
730 TileIndex t = start_tile; |
730 start_tile = end_tile; |
731 start_tile = end_tile; |
731 end_tile = t; |
732 end_tile = t; |
732 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
733 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
733 } |
734 } |
734 |
735 |
735 money.AddCost(GetAvailableMoneyForCommand()); |
736 money.AddCost(GetAvailableMoneyForCommand()); |
736 tile = start_tile; |
737 tile = start_tile; |
737 /* Start tile is the small number. */ |
738 /* Start tile is the small number. */ |
738 for (;;) { |
739 for (;;) { |
739 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
740 RoadBits bits = HasBit(p2, 2) ? ROAD_Y : ROAD_X; |
740 |
741 |
741 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
742 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
742 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
743 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
743 |
744 |
744 /* try to remove the halves. */ |
745 /* try to remove the halves. */ |
745 if (bits != 0) { |
746 if (bits != 0) { |
746 ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD); |
747 ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD); |
747 if (CmdSucceeded(ret)) { |
748 if (CmdSucceeded(ret)) { |
783 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
784 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
784 |
785 |
785 DiagDirection dir = Extract<DiagDirection, 0>(p1); |
786 DiagDirection dir = Extract<DiagDirection, 0>(p1); |
786 RoadType rt = (RoadType)GB(p1, 2, 2); |
787 RoadType rt = (RoadType)GB(p1, 2, 2); |
787 |
788 |
788 if (!IsValidRoadType(rt)) return CMD_ERROR; |
789 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
789 |
790 |
790 tileh = GetTileSlope(tile, NULL); |
791 tileh = GetTileSlope(tile, NULL); |
791 if (tileh != SLOPE_FLAT && ( |
792 if (tileh != SLOPE_FLAT && ( |
792 !_patches.build_on_slopes || |
793 !_patches.build_on_slopes || |
793 IsSteepSlope(tileh) || |
794 IsSteepSlope(tileh) || |
836 case ROAD_TILE_NORMAL: { |
837 case ROAD_TILE_NORMAL: { |
837 RoadBits b = GetAllRoadBits(tile); |
838 RoadBits b = GetAllRoadBits(tile); |
838 |
839 |
839 /* Clear the road if only one piece is on the tile OR the AI tries |
840 /* Clear the road if only one piece is on the tile OR the AI tries |
840 * to clear town road OR we are not using the DC_AUTO flag */ |
841 * to clear town road OR we are not using the DC_AUTO flag */ |
841 if ((COUNTBITS(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || |
842 if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || |
842 IsTileOwner(tile, OWNER_TOWN) || !(flags & DC_AUTO) |
843 IsTileOwner(tile, OWNER_TOWN) || !(flags & DC_AUTO) |
843 ) { |
844 ) { |
844 RoadTypes rts = GetRoadTypes(tile); |
845 RoadTypes rts = GetRoadTypes(tile); |
845 CommandCost ret; |
846 CommandCost ret; |
846 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
847 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
847 if (HASBIT(rts, rt)) { |
848 if (HasBit(rts, rt)) { |
848 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
849 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
849 if (CmdFailed(tmp_ret)) return tmp_ret; |
850 if (CmdFailed(tmp_ret)) return tmp_ret; |
850 ret.AddCost(tmp_ret); |
851 ret.AddCost(tmp_ret); |
851 } |
852 } |
852 } |
853 } |
862 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
863 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
863 |
864 |
864 /* Must iterate over the roadtypes in a reverse manner because |
865 /* Must iterate over the roadtypes in a reverse manner because |
865 * tram tracks must be removed before the road bits. */ |
866 * tram tracks must be removed before the road bits. */ |
866 for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) { |
867 for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) { |
867 if (HASBIT(rts, rt)) { |
868 if (HasBit(rts, rt)) { |
868 CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
869 CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
869 if (CmdFailed(tmp_ret)) return tmp_ret; |
870 if (CmdFailed(tmp_ret)) return tmp_ret; |
870 ret.AddCost(tmp_ret); |
871 ret.AddCost(tmp_ret); |
871 } |
872 } |
872 } |
873 } |
903 /* As one can remove a single road piece when in a corner on a foundation as |
904 /* As one can remove a single road piece when in a corner on a foundation as |
904 * it is on a sloped piece of landscape, one creates a state that cannot be |
905 * it is on a sloped piece of landscape, one creates a state that cannot be |
905 * created directly, but the state itself is still perfectly drawable. |
906 * created directly, but the state itself is still perfectly drawable. |
906 * However, as we do not want this to be build directly, we need to check |
907 * However, as we do not want this to be build directly, we need to check |
907 * for that situation in here. */ |
908 * for that situation in here. */ |
908 return (tileh != 0 && HAS_SINGLE_BIT(bits)) ? FOUNDATION_LEVELED : FOUNDATION_NONE; |
909 return (tileh != 0 && CountBits(bits) == 1) ? FOUNDATION_LEVELED : FOUNDATION_NONE; |
909 } |
910 } |
910 if ((~_valid_tileh_slopes_road[1][tileh] & bits) == 0) return FOUNDATION_LEVELED; |
911 if ((~_valid_tileh_slopes_road[1][tileh] & bits) == 0) return FOUNDATION_LEVELED; |
911 } |
912 } |
912 |
913 |
913 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y); |
914 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y); |
960 } else { |
961 } else { |
961 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[tram]; |
962 back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[tram]; |
962 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[tram]; |
963 front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[tram]; |
963 } |
964 } |
964 |
965 |
965 AddSortableSpriteToDraw(back, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, HASBIT(_transparent_opt, TO_BUILDINGS)); |
966 AddSortableSpriteToDraw(back, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_BUILDINGS)); |
966 AddSortableSpriteToDraw(front, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, HASBIT(_transparent_opt, TO_BUILDINGS)); |
967 AddSortableSpriteToDraw(front, PAL_NONE, ti->x, ti->y, 16, 16, TILE_HEIGHT + BB_HEIGHT_UNDER_BRIDGE, ti->z, IsTransparencySet(TO_BUILDINGS)); |
967 } |
968 } |
968 |
969 |
969 /** |
970 /** |
970 * Draws details on/around the road |
971 * Draws details on/around the road |
971 * @param img the sprite to draw |
972 * @param img the sprite to draw |
1049 } |
1050 } |
1050 |
1051 |
1051 if (tram != ROAD_NONE) DrawTramCatenary(ti, tram); |
1052 if (tram != ROAD_NONE) DrawTramCatenary(ti, tram); |
1052 |
1053 |
1053 /* Return if full detail is disabled, or we are zoomed fully out. */ |
1054 /* Return if full detail is disabled, or we are zoomed fully out. */ |
1054 if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return; |
1055 if (!HasBit(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return; |
1055 |
1056 |
1056 /* Draw extra details. */ |
1057 /* Draw extra details. */ |
1057 for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) { |
1058 for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) { |
1058 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10); |
1059 DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10); |
1059 } |
1060 } |
1087 default: image += 4; break; // Paved |
1088 default: image += 4; break; // Paved |
1088 } |
1089 } |
1089 } |
1090 } |
1090 |
1091 |
1091 DrawGroundSprite(image, pal); |
1092 DrawGroundSprite(image, pal); |
1092 if (HASBIT(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) { |
1093 if (HasBit(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) { |
1093 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal); |
1094 DrawGroundSprite(SPR_TRAMWAY_OVERLAY + (GetCrossingRoadAxis(ti->tile) ^ 1), pal); |
1094 DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile)); |
1095 DrawTramCatenary(ti, GetCrossingRoadBits(ti->tile)); |
1095 } |
1096 } |
1096 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1097 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1097 break; |
1098 break; |
1117 |
1118 |
1118 for (dtss = dts->seq; dtss->image != 0; dtss++) { |
1119 for (dtss = dts->seq; dtss->image != 0; dtss++) { |
1119 SpriteID image = dtss->image; |
1120 SpriteID image = dtss->image; |
1120 SpriteID pal; |
1121 SpriteID pal; |
1121 |
1122 |
1122 if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) { |
1123 if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
1123 pal = palette; |
1124 pal = palette; |
1124 } else { |
1125 } else { |
1125 pal = PAL_NONE; |
1126 pal = PAL_NONE; |
1126 } |
1127 } |
1127 |
1128 |
1128 AddSortableSpriteToDraw( |
1129 AddSortableSpriteToDraw( |
1129 image, pal, |
1130 image, pal, |
1130 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1131 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
1131 dtss->size_x, dtss->size_y, |
1132 dtss->size_x, dtss->size_y, |
1132 dtss->size_z, ti->z, |
1133 dtss->size_z, ti->z, |
1133 HASBIT(_transparent_opt, TO_BUILDINGS) |
1134 IsTransparencySet(TO_BUILDINGS) |
1134 ); |
1135 ); |
1135 } |
1136 } |
1136 break; |
1137 break; |
1137 } |
1138 } |
1138 } |
1139 } |
1152 |
1153 |
1153 for (dtss = dts->seq; dtss->image != 0; dtss++) { |
1154 for (dtss = dts->seq; dtss->image != 0; dtss++) { |
1154 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
1155 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
1155 SpriteID image = dtss->image; |
1156 SpriteID image = dtss->image; |
1156 |
1157 |
1157 DrawSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y); |
1158 DrawSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE, x + pt.x, y + pt.y); |
1158 } |
1159 } |
1159 } |
1160 } |
1160 |
1161 |
1161 static uint GetSlopeZ_Road(TileIndex tile, uint x, uint y) |
1162 static uint GetSlopeZ_Road(TileIndex tile, uint x, uint y) |
1162 { |
1163 { |
1238 grp = GetTownRadiusGroup(t, tile); |
1239 grp = GetTownRadiusGroup(t, tile); |
1239 |
1240 |
1240 /* Show an animation to indicate road work */ |
1241 /* Show an animation to indicate road work */ |
1241 if (t->road_build_months != 0 && |
1242 if (t->road_build_months != 0 && |
1242 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
1243 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
1243 GetRoadTileType(tile) == ROAD_TILE_NORMAL && COUNTBITS(GetAllRoadBits(tile)) > 1 ) { |
1244 GetRoadTileType(tile) == ROAD_TILE_NORMAL && CountBits(GetAllRoadBits(tile)) > 1 ) { |
1244 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { |
1245 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { |
1245 StartRoadWorks(tile); |
1246 StartRoadWorks(tile); |
1246 |
1247 |
1247 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
1248 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
1248 CreateEffectVehicleAbove( |
1249 CreateEffectVehicleAbove( |
1436 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1437 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1437 { |
1438 { |
1438 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
1439 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
1439 switch (GetRoadTileType(tile)) { |
1440 switch (GetRoadTileType(tile)) { |
1440 case ROAD_TILE_CROSSING: |
1441 case ROAD_TILE_CROSSING: |
1441 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HASBIT(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return _price.terraform; |
1442 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return _price.terraform; |
1442 break; |
1443 break; |
1443 |
1444 |
1444 case ROAD_TILE_DEPOT: |
1445 case ROAD_TILE_DEPOT: |
1445 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return _price.terraform; |
1446 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return _price.terraform; |
1446 break; |
1447 break; |