Changeset - r16725:b9041c857d37
[Not reviewed]
master
0 1 0
rubidium - 14 years ago 2010-12-11 18:28:34
rubidium@openttd.org
(svn r21468) -Change: make sure the end of a bridge is always a valid tile as well, and for aqueducts show "wrong land slope" when that would be more appropriate than "bridge heads not at same height"
1 file changed with 3 insertions and 3 deletions:
0 comments (0 inline, 0 general)
src/tunnelbridge_cmd.cpp
Show inline comments
 
@@ -190,49 +190,49 @@ CommandCost CheckBridgeAvailability(Brid
 
	if (bridge_len <= max) return CommandCost();
 
	return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
 
}
 

	
 
/**
 
 * Build a Bridge
 
 * @param end_tile end tile
 
 * @param flags type of operation
 
 * @param p1 packed start tile coords (~ dx)
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit  0- 7) - bridge type (hi bh)
 
 * - p2 = (bit  8-11) - rail type or road types.
 
 * - p2 = (bit 15-16) - transport type.
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	RailType railtype = INVALID_RAILTYPE;
 
	RoadTypes roadtypes = ROADTYPES_NONE;
 

	
 
	/* unpack parameters */
 
	BridgeType bridge_type = GB(p2, 0, 8);
 

	
 
	if (p1 >= MapSize()) return CMD_ERROR;
 
	if (!IsValidTile(p1)) return CMD_ERROR;
 

	
 
	TransportType transport_type = Extract<TransportType, 15, 2>(p2);
 

	
 
	/* type of bridge */
 
	switch (transport_type) {
 
		case TRANSPORT_ROAD:
 
			roadtypes = Extract<RoadTypes, 8, 2>(p2);
 
			if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
 
			break;
 

	
 
		case TRANSPORT_RAIL:
 
			railtype = Extract<RailType, 8, 4>(p2);
 
			if (!ValParamRailtype(railtype)) return CMD_ERROR;
 
			break;
 

	
 
		case TRANSPORT_WATER:
 
			break;
 

	
 
		default:
 
			/* Airports don't have bridges. */
 
			return CMD_ERROR;
 
	}
 
	TileIndex tile_start = p1;
 
	TileIndex tile_end = end_tile;
 
@@ -249,48 +249,50 @@ CommandCost CmdBuildBridge(TileIndex end
 
	} else {
 
		return_cmd_error(STR_ERROR_START_AND_END_MUST_BE_IN);
 
	}
 

	
 
	if (tile_end < tile_start) Swap(tile_start, tile_end);
 

	
 
	uint bridge_len = GetTunnelBridgeLength(tile_start, tile_end);
 
	if (transport_type != TRANSPORT_WATER) {
 
		/* set and test bridge length, availability */
 
		CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
 
		if (ret.Failed()) return ret;
 
	} else {
 
		if (bridge_len > (_settings_game.construction.longbridges ? MAX_BRIDGE_LENGTH_LONGBRIDGES : MAX_BRIDGE_LENGTH)) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
 
	}
 

	
 
	uint z_start;
 
	uint z_end;
 
	Slope tileh_start = GetTileSlope(tile_start, &z_start);
 
	Slope tileh_end = GetTileSlope(tile_end, &z_end);
 
	bool pbs_reservation = false;
 

	
 
	CommandCost terraform_cost_north = CheckBridgeSlopeNorth(direction, &tileh_start, &z_start);
 
	CommandCost terraform_cost_south = CheckBridgeSlopeSouth(direction, &tileh_end,   &z_end);
 

	
 
	/* Aqueducts can't be built of flat land. */
 
	if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 
	if (z_start != z_end) return_cmd_error(STR_ERROR_BRIDGEHEADS_NOT_SAME_HEIGHT);
 

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	Owner owner;
 
	if (IsBridgeTile(tile_start) && IsBridgeTile(tile_end) &&
 
			GetOtherBridgeEnd(tile_start) == tile_end &&
 
			GetTunnelBridgeTransportType(tile_start) == transport_type) {
 
		/* Replace a current bridge. */
 

	
 
		/* If this is a railway bridge, make sure the railtypes match. */
 
		if (transport_type == TRANSPORT_RAIL && GetRailType(tile_start) != railtype) {
 
			return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 
		}
 

	
 
		/* Do not replace town bridges with lower speed bridges. */
 
		if (!(flags & DC_QUERY_COST) && IsTileOwner(tile_start, OWNER_TOWN) &&
 
				GetBridgeSpec(bridge_type)->speed < GetBridgeSpec(GetBridgeType(tile_start))->speed) {
 
			Town *t = ClosestTownFromTile(tile_start, UINT_MAX);
 

	
 
			if (t == NULL) {
 
				return CMD_ERROR;
 
			} else {
 
				SetDParam(0, t->index);
 
				return_cmd_error(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS);
 
@@ -324,50 +326,48 @@ CommandCost CmdBuildBridge(TileIndex end
 
			default: break;
 
		}
 
	} else {
 
		/* Build a new bridge. */
 

	
 
		bool allow_on_slopes = (_settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
 

	
 
		/* Try and clear the start landscape */
 
		CommandCost ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
		if (ret.Failed()) return ret;
 
		cost = ret;
 

	
 
		if (terraform_cost_north.Failed() || (terraform_cost_north.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 
		cost.AddCost(terraform_cost_north);
 

	
 
		/* Try and clear the end landscape */
 
		ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
		if (ret.Failed()) return ret;
 
		cost.AddCost(ret);
 

	
 
		/* false - end tile slope check */
 
		if (terraform_cost_south.Failed() || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 
		cost.AddCost(terraform_cost_south);
 

	
 
		if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
 

	
 
		const TileIndex heads[] = {tile_start, tile_end};
 
		for (int i = 0; i < 2; i++) {
 
			if (MayHaveBridgeAbove(heads[i])) {
 
				if (IsBridgeAbove(heads[i])) {
 
					TileIndex north_head = GetNorthernBridgeEnd(heads[i]);
 

	
 
					if (direction == GetBridgeAxis(heads[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
					if (z_start + TILE_HEIGHT == GetBridgeHeight(north_head)) {
 
						return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 
					}
 
				}
 
			}
 
		}
 

	
 
		TileIndexDiff delta = (direction == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
 
		for (TileIndex tile = tile_start + delta; tile != tile_end; tile += delta) {
 
			if (GetTileMaxZ(tile) > z_start) return_cmd_error(STR_ERROR_BRIDGE_TOO_LOW_FOR_TERRAIN);
 

	
 
			if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) {
 
				/* Disallow crossing bridges for the time being */
 
				return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
 
			}
 

	
0 comments (0 inline, 0 general)