Changeset - r19572:c5d4369f5c6d
[Not reviewed]
master
0 1 0
terkhen - 12 years ago 2012-09-01 14:58:36
terkhen@openttd.org
(svn r24503) -Change [FS#5228]: When building long roads or tramways, only build the roadbits at the beginning and the end if they can connect to something.
1 file changed with 31 insertions and 4 deletions:
0 comments (0 inline, 0 general)
src/road_cmd.cpp
Show inline comments
 
@@ -777,35 +777,50 @@ do_clear:;
 
		if (rt != ROADTYPE_TRAM && IsNormalRoadTile(tile)) {
 
			existing |= pieces;
 
			SetDisallowedRoadDirections(tile, IsStraightRoad(existing) ?
 
					GetDisallowedRoadDirections(tile) ^ toggle_drd : DRD_NONE);
 
		}
 

	
 
		MarkTileDirtyByTile(tile);
 
	}
 
	return cost;
 
}
 

	
 
/**
 
 * Checks whether a road or tram connection can be found when building a new road or tram.
 
 * @param tile Tile at which the road being built will end.
 
 * @param rt Roadtype of the road being built.
 
 * @param dir Direction that the road is following.
 
 * @return True if the next tile at dir direction is suitable for being connected directly by a second roadbit at the end of the road being built.
 
 */
 
static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
 
{
 
	RoadBits bits = GetAnyRoadBits(tile + TileOffsByDiagDir(dir), rt, false);
 
	return (bits & DiagDirToRoadBits(ReverseDiagDir(dir)));
 
}
 

	
 
/**
 
 * Build a long piece of road.
 
 * @param start_tile start tile of drag (the building cost will appear over this tile)
 
 * @param flags operation to perform
 
 * @param p1 end tile of drag
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
 
 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
 
 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1). Only used if bit 6 is set or if we are building a single tile
 
 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2). Only used if bit 6 is set or if we are building a single tile
 
 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
 
 * - p2 = (bit 3 + 4) - road type
 
 * - p2 = (bit 5) - set road direction
 
 * - p2 = (bit 6) - 0 = build up to an obstacle, 1 = fail if an obstacle is found (used for AIs).
 
 * - p2 = (bit 6) - defines two different behaviors for this command:
 
 *      - 0 = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile
 
 *      - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	DisallowedRoadDirections drd = DRD_NORTHBOUND;
 

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

	
 
	TileIndex end_tile = p1;
 
	RoadType rt = Extract<RoadType, 3, 2>(p2);
 
	if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR;
 
@@ -828,37 +843,49 @@ CommandCost CmdBuildLongRoad(TileIndex s
 
	 * will be interpreted correctly in the GTTS. Furthermore
 
	 * when you just 'click' on one tile to build them. */
 
	if ((axis == AXIS_Y) == (start_tile == end_tile && HasBit(p2, 0) == HasBit(p2, 1))) drd ^= DRD_BOTH;
 
	/* No disallowed direction bits have to be toggled */
 
	if (!HasBit(p2, 5)) drd = DRD_NONE;
 

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	CommandCost last_error = CMD_ERROR;
 
	TileIndex tile = start_tile;
 
	bool had_bridge = false;
 
	bool had_tunnel = false;
 
	bool had_success = false;
 
	bool is_ai = HasBit(p2, 6);
 

	
 
	/* Start tile is the first tile clicked by the user. */
 
	for (;;) {
 
		RoadBits bits = AxisToRoadBits(axis);
 

	
 
		/* Determine which road parts should be built. */
 
		if (!is_ai && start_tile != end_tile) {
 
			/* Only build the first and last roadbit if they can connect to something. */
 
			if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
 
				bits = DiagDirToRoadBits(ReverseDiagDir(dir));
 
			} else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
 
				bits = DiagDirToRoadBits(dir);
 
			}
 
		} else {
 
		/* Road parts only have to be built at the start tile or at the end tile. */
 
		if (tile == end_tile && !HasBit(p2, 1)) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
 
		if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir);
 
		}
 

	
 
		CommandCost ret = DoCommand(tile, drd << 6 | rt << 4 | bits, 0, flags, CMD_BUILD_ROAD);
 
		if (ret.Failed()) {
 
			last_error = ret;
 
			if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
 
				if (HasBit(p2, 6)) return last_error;
 
				if (is_ai) return last_error;
 
				break;
 
			}
 
		} else {
 
			had_success = true;
 
			/* Only pay for the upgrade on one side of the bridges and tunnels */
 
			if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
				if (IsBridge(tile)) {
 
					if (!had_bridge || GetTunnelBridgeDirection(tile) == dir) {
 
						cost.AddCost(ret);
 
					}
 
					had_bridge = true;
 
				} else { // IsTunnel(tile)
0 comments (0 inline, 0 general)