src/road_cmd.cpp
branchnoai
changeset 9722 ebf0ece7d8f6
parent 9718 f82a4facea8b
child 9723 eee46cb39750
equal deleted inserted replaced
9721:9a27928bcd5e 9722:ebf0ece7d8f6
    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 */
   364 		return CommandCost(); // no extra cost
   365 		return CommandCost(); // no extra cost
   365 	}
   366 	}
   366 
   367 
   367 	/* foundation is used. Whole tile is leveled up */
   368 	/* foundation is used. Whole tile is leveled up */
   368 	if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) {
   369 	if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) {
   369 		return CommandCost(existing != ROAD_NONE ? 0 : _price.terraform);
   370 		return CommandCost(existing != ROAD_NONE ? (Money)0 : _price.terraform);
   370 	}
   371 	}
   371 
   372 
   372 	/* Force straight roads. */
   373 	/* Force straight roads. */
   373 	*pieces |= MirrorRoadBits(*pieces);
   374 	*pieces |= MirrorRoadBits(*pieces);
   374 
   375 
   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) {
   442 						return_cmd_error(STR_1007_ALREADY_BUILT);
   443 						return_cmd_error(STR_1007_ALREADY_BUILT);
   443 					}
   444 					}
   444 				} break;
   445 				} break;
   445 
   446 
   446 				case ROAD_TILE_CROSSING:
   447 				case ROAD_TILE_CROSSING:
   447 					if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   448 					if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT);
   448 					all_bits = GetCrossingRoadBits(tile);
   449 					all_bits = GetCrossingRoadBits(tile);
   449 					if (pieces & ComplementRoadBits(all_bits)) goto do_clear;
   450 					if (pieces & ComplementRoadBits(all_bits)) goto do_clear;
   450 					break;
   451 					break;
   451 
   452 
   452 				default:
   453 				default:
   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;
   689 			}
   690 			}
   690 		}
   691 		}
   691 
   692 
   692 		if (tile == end_tile) break;
   693 		if (tile == end_tile) break;
   693 
   694 
   694 		tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   695 		tile += HasBit(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   695 	}
   696 	}
   696 
   697 
   697 	return !had_success ? CMD_ERROR : cost;
   698 	return !had_success ? CMD_ERROR : cost;
   698 }
   699 }
   699 
   700 
   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)) {
   757 			}
   758 			}
   758 		}
   759 		}
   759 
   760 
   760 		if (tile == end_tile) break;
   761 		if (tile == end_tile) break;
   761 
   762 
   762 		tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   763 		tile += HasBit(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0);
   763 	}
   764 	}
   764 
   765 
   765 	return (cost.GetCost() == 0) ? CMD_ERROR : cost;
   766 	return (cost.GetCost() == 0) ? CMD_ERROR : cost;
   766 }
   767 }
   767 
   768 
   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);
   943  * @param tram the roadbits for the tram
   944  * @param tram the roadbits for the tram
   944  */
   945  */
   945 void DrawTramCatenary(TileInfo *ti, RoadBits tram)
   946 void DrawTramCatenary(TileInfo *ti, RoadBits tram)
   946 {
   947 {
   947 	/* Don't draw the catenary under a low bridge */
   948 	/* Don't draw the catenary under a low bridge */
   948 	if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !HASBIT(_transparent_opt, TO_BUILDINGS)) {
   949 	if (MayHaveBridgeAbove(ti->tile) && IsBridgeAbove(ti->tile) && !IsTransparencySet(TO_BUILDINGS)) {
   949 		uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   950 		uint height = GetBridgeHeight(GetNorthernBridgeEnd(ti->tile));
   950 
   951 
   951 		if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
   952 		if (height <= GetTileMaxZ(ti->tile) + TILE_HEIGHT) return;
   952 	}
   953 	}
   953 
   954 
   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;
  1105 
  1106 
  1106 			if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
  1107 			if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
  1107 
  1108 
  1108 			palette = PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile));
  1109 			palette = PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile));
  1109 
  1110 
  1110 			if (HASBIT(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) {
  1111 			if (HasBit(GetRoadTypes(ti->tile), ROADTYPE_TRAM)) {
  1111 				dts =  &_tram_depot[GetRoadDepotDirection(ti->tile)];
  1112 				dts =  &_tram_depot[GetRoadDepotDirection(ti->tile)];
  1112 			} else {
  1113 			} else {
  1113 				dts =  &_road_depot[GetRoadDepotDirection(ti->tile)];
  1114 				dts =  &_road_depot[GetRoadDepotDirection(ti->tile)];
  1114 			}
  1115 			}
  1115 
  1116 
  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(
  1413 		}
  1414 		}
  1414 		return;
  1415 		return;
  1415 	}
  1416 	}
  1416 
  1417 
  1417 	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
  1418 	for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
  1418 		if (!HASBIT(GetRoadTypes(tile), rt)) continue;
  1419 		if (!HasBit(GetRoadTypes(tile), rt)) continue;
  1419 
  1420 
  1420 		if (GetRoadOwner(tile, rt) == old_player) {
  1421 		if (GetRoadOwner(tile, rt) == old_player) {
  1421 			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1422 			SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player);
  1422 		}
  1423 		}
  1423 	}
  1424 	}
  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;