changeset 5940:8518d27e667f draft

(svn r8593) -Fix (FS#564): bridges do not get destroyed when the bridge head gets flooded and there is a vehicle on the bridge. Original patch by KeeperofTheSoul.
author rubidium <rubidium@openttd.org>
date Mon, 05 Feb 2007 14:00:32 +0000
parents 1347bd144518
children d0e1f93e603a
files src/vehicle.cpp src/vehicle.h src/water_cmd.cpp
diffstat 3 files changed, 35 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -167,7 +167,7 @@
 	return (Vehicle*)VehicleFromPos(tile, &ti, EnsureNoVehicleProcZ);
 }
 
-Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z)
+Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z, bool without_crashed)
 {
 	int x1 = TileX(from);
 	int y1 = TileY(from);
@@ -181,6 +181,7 @@
 		intswap(y1,y2);
 	}
 	FOR_ALL_VEHICLES(veh) {
+		if (without_crashed && (veh->vehstatus & VS_CRASHED) != 0) continue;
 		if ((veh->type == VEH_Train || veh->type == VEH_Road) && (z==0xFF || veh->z_pos == z)) {
 			if ((veh->x_pos>>4) >= x1 && (veh->x_pos>>4) <= x2 &&
 					(veh->y_pos>>4) >= y1 && (veh->y_pos>>4) <= y2) {
--- a/src/vehicle.h
+++ b/src/vehicle.h
@@ -306,7 +306,7 @@
 uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y);
 
 StringID VehicleInTheWayErrMsg(const Vehicle* v);
-Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z);
+Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z, bool without_crashed = false);
 
 bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction);
 void SetSignalsOnBothDir(TileIndex tile, byte track);
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -40,6 +40,7 @@
 };
 
 
+static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
 static void FloodVehicle(Vehicle *v);
 
 /** Build a ship depot.
@@ -564,10 +565,9 @@
 		}
 	} else {
 		_current_player = OWNER_WATER;
-		{
-			Vehicle *v = FindVehicleOnTileZ(target, 0);
-			if (v != NULL) FloodVehicle(v);
-		}
+
+		Vehicle *v = FindFloodableVehicleOnTile(target);
+		if (v != NULL) FloodVehicle(v);
 
 		if (!CmdFailed(DoCommand(target, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR))) {
 			MakeWater(target);
@@ -576,6 +576,33 @@
 	}
 }
 
+/**
+ * Finds a vehicle to flood.
+ * It does not find vehicles that are already crashed on bridges, i.e. flooded.
+ * @param tile the tile where to find a vehicle to flood
+ * @return a vehicle too flood or NULL when there is no vehicle too flood.
+ */
+static Vehicle *FindFloodableVehicleOnTile(TileIndex tile)
+{
+	if (!IsBridgeTile(tile)) return FindVehicleOnTileZ(tile, 0);
+
+	TileIndex end = GetOtherBridgeEnd(tile);
+	byte z = GetBridgeHeight(tile);
+	Vehicle *v;
+
+	/* check the start tile first since as this is closest to the water */
+	v = FindVehicleOnTileZ(tile, z);
+	if (v != NULL && (v->vehstatus & VS_CRASHED) == 0) return v;
+
+	/* check a vehicle in between both bridge heads */
+	v = FindVehicleBetween(tile, end, z, true);
+	if (v != NULL) return v;
+
+	/* check the end tile last to give fleeing vehicles a chance to escape */
+	v = FindVehicleOnTileZ(end, z);
+	return (v != NULL && (v->vehstatus & VS_CRASHED) == 0) ? v : NULL;
+}
+
 static void FloodVehicle(Vehicle *v)
 {
 	if (!(v->vehstatus & VS_CRASHED)) {
@@ -600,6 +627,7 @@
 			BEGIN_ENUM_WAGONS(v)
 				if (v->cargo_type == CT_PASSENGERS) pass += v->cargo_count;
 				v->vehstatus |= VS_CRASHED;
+				MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
 			END_ENUM_WAGONS(v)
 
 			v = u;