Changeset - r8428:44e364e9d33f
[Not reviewed]
master
0 1 0
smatz - 16 years ago 2008-01-28 12:40:31
smatz@openttd.org
(svn r11998) -Fix [FS#1692](r10053): possible remote assert by setting bit 6 of p1 for CMD_REMOVE_ROAD
1 file changed with 29 insertions and 19 deletions:
0 comments (0 inline, 0 general)
src/road_cmd.cpp
Show inline comments
 
@@ -93,36 +93,29 @@ bool CheckAllowRemoveRoad(TileIndex tile
 

	
 
static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt)
 
{
 
	return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt);
 
}
 

	
 

	
 
/** Delete a piece of road.
 
 * @param tile tile where to remove road from
 
 * @param flags operation to perform
 
 * @param p1 bit 0..3 road pieces to remove (RoadBits)
 
 *           bit 4..5 road type
 
 *           bit    6 ignore the fact that the tram track has not been removed
 
 *                    yet when removing the road bits when not actually doing
 
 *                    it. Makes it possible to test whether the road bits can
 
 *                    be removed from a level crossing without physically
 
 *                    removing the tram bits before the test.
 
 * @param p2 unused
 
 * @param pieces roadbits to remove
 
 * @param rt roadtype to remove
 
 * @param crossing_check should we check if there is a tram track when we are removing road from crossing?
 
 */
 
CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check)
 
{
 
	/* cost for removing inner/edge -roads */
 
	static const uint16 road_remove_cost[2] = {50, 18};
 

	
 
	/* true if the roadpiece was always removeable,
 
	 * false if it was a center piece. Affects town ratings drop */
 
	bool edge_road;
 

	
 
	RoadType rt = (RoadType)GB(p1, 4, 2);
 
	if (!IsValidRoadType(rt)) return CMD_ERROR;
 

	
 
	Town *t = NULL;
 
	switch (GetTileType(tile)) {
 
		case MP_ROAD:
 
			if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile);
 
			if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
			break;
 
@@ -138,13 +131,12 @@ CommandCost CmdRemoveRoad(TileIndex tile
 
			break;
 

	
 
		default:
 
			return CMD_ERROR;
 
	}
 

	
 
	RoadBits pieces = Extract<RoadBits, 0>(p1);
 
	RoadTypes rts = GetRoadTypes(tile);
 
	/* The tile doesn't have the given road type */
 
	if (!HasBit(rts, rt)) return CMD_ERROR;
 

	
 
	if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR;
 

	
 
@@ -230,13 +222,13 @@ CommandCost CmdRemoveRoad(TileIndex tile
 
			if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) {
 
				return CMD_ERROR;
 
			}
 

	
 
			/* Don't allow road to be removed from the crossing when there is tram;
 
			 * we can't draw the crossing without trambits ;) */
 
			if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR;
 
			if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR;
 

	
 
			if (rt == ROADTYPE_ROAD) {
 
				ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM);
 
			}
 

	
 
			if (flags & DC_EXEC) {
 
@@ -256,12 +248,30 @@ CommandCost CmdRemoveRoad(TileIndex tile
 
		case ROAD_TILE_DEPOT:
 
			return CMD_ERROR;
 
	}
 
}
 

	
 

	
 
/** Delete a piece of road.
 
 * @param tile tile where to remove road from
 
 * @param flags operation to perform
 
 * @param p1 bit 0..3 road pieces to remove (RoadBits)
 
 *           bit 4..5 road type
 
 * @param p2 unused
 
 */
 
CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	RoadType rt = (RoadType)GB(p1, 4, 2);
 
	if (!IsValidRoadType(rt)) return CMD_ERROR;
 

	
 
	RoadBits pieces = Extract<RoadBits, 0>(p1);
 

	
 
	return RemoveRoad(tile, flags, pieces, rt, true);
 
}
 

	
 

	
 
static const RoadBits _valid_tileh_slopes_road[][15] = {
 
	/* set of normal ones */
 
	{
 
		ROAD_ALL,  // SLOPE_FLAT
 
		ROAD_NONE, // SLOPE_W
 
		ROAD_NONE, // SLOPE_S
 
@@ -731,21 +741,21 @@ CommandCost CmdRemoveLongRoad(TileIndex 
 

	
 
		if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
 
		if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
 

	
 
		/* try to remove the halves. */
 
		if (bits != 0) {
 
			ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD);
 
			ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true);
 
			if (CmdSucceeded(ret)) {
 
				if (flags & DC_EXEC) {
 
					money -= ret.GetCost();
 
					if (money < 0) {
 
						_additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost();
 
						return cost;
 
					}
 
					DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD);
 
					RemoveRoad(tile, flags, bits, rt, true);
 
				}
 
				cost.AddCost(ret);
 
			}
 
		}
 

	
 
		if (tile == end_tile) break;
 
@@ -832,13 +842,13 @@ static CommandCost ClearTile_Road(TileIn
 
			    !(flags & DC_AUTO)
 
				) {
 
				RoadTypes rts = GetRoadTypes(tile);
 
				CommandCost ret(EXPENSES_CONSTRUCTION);
 
				for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) {
 
					if (HasBit(rts, rt)) {
 
						CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD);
 
						CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true);
 
						if (CmdFailed(tmp_ret)) return tmp_ret;
 
						ret.AddCost(tmp_ret);
 
					}
 
				}
 
				return ret;
 
			}
 
@@ -852,13 +862,13 @@ static CommandCost ClearTile_Road(TileIn
 
			if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST);
 

	
 
			/* Must iterate over the roadtypes in a reverse manner because
 
			 * tram tracks must be removed before the road bits. */
 
			for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) {
 
				if (HasBit(rts, rt)) {
 
					CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD);
 
					CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false);
 
					if (CmdFailed(tmp_ret)) return tmp_ret;
 
					ret.AddCost(tmp_ret);
 
				}
 
			}
 

	
 
			if (flags & DC_EXEC) {
 
@@ -1273,13 +1283,13 @@ static void TileLoop_Road(TileIndex tile
 
		if (_patches.mod_road_rebuild) {
 
			/* Generate a nicer town surface */
 
			const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD);
 
			const RoadBits new_rb = CleanUpRoadBits(tile, old_rb);
 

	
 
			if (old_rb != new_rb) {
 
				DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD);
 
				RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true);
 
			}
 
		}
 

	
 
		MarkTileDirtyByTile(tile);
 
	}
 
}
0 comments (0 inline, 0 general)