# HG changeset patch # User rubidium # Date 1170684032 0 # Node ID 3bb99a7ad58fdd355ac59345b5a430df9c99f4bd # Parent 395ebd3ec312cf085b170b5c90195c9fd613dc00 (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. diff -r 395ebd3ec312 -r 3bb99a7ad58f src/vehicle.cpp --- a/src/vehicle.cpp Sun Feb 04 18:36:43 2007 +0000 +++ b/src/vehicle.cpp Mon Feb 05 14:00:32 2007 +0000 @@ -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) { diff -r 395ebd3ec312 -r 3bb99a7ad58f src/vehicle.h --- a/src/vehicle.h Sun Feb 04 18:36:43 2007 +0000 +++ b/src/vehicle.h Mon Feb 05 14:00:32 2007 +0000 @@ -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); diff -r 395ebd3ec312 -r 3bb99a7ad58f src/water_cmd.cpp --- a/src/water_cmd.cpp Sun Feb 04 18:36:43 2007 +0000 +++ b/src/water_cmd.cpp Mon Feb 05 14:00:32 2007 +0000 @@ -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;