(svn r8623) [0.5] -Backport from trunk (8593, 8608, 8619, 8620) 0.5
authorrubidium
Thu, 08 Feb 2007 10:00:22 +0000
branch0.5
changeset 5427 63ce73145566
parent 5426 114316885a2e
child 5428 ef4e98d1a511
(svn r8623) [0.5] -Backport from trunk (8593, 8608, 8619, 8620)
-Fix (FS#564): bridges do not get destroyed when the bridge head gets flooded and there is a vehicle on the bridge.
-Fix: you were unable to build roads in the scenario editor when there is no town 0, even though there are other towns.
-Fix: store the ownership of a water tile in the buoy tile and set the ownership of the water tile when the buoy is removed. This solves the issue of removing ownership from canal tiles thus making is possible for other players to remove the canal tile.
-Fix: buoys on canal tiles do not flood anymore.
road_cmd.c
station_cmd.c
station_map.h
tunnelbridge_cmd.c
vehicle.c
vehicle.h
water_cmd.c
--- a/road_cmd.c	Wed Jan 31 22:08:23 2007 +0000
+++ b/road_cmd.c	Thu Feb 08 10:00:22 2007 +0000
@@ -293,7 +293,7 @@
 
 	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
 	 * if a non-player is building the road */
-	if ((p1 >> 4) || (IsValidPlayer(_current_player) && p2 != 0) || !IsValidTownID(p2)) return CMD_ERROR;
+	if ((p1 >> 4) || (IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR;
 	pieces = p1;
 
 	tileh = GetTileSlope(tile, NULL);
--- a/station_cmd.c	Wed Jan 31 22:08:23 2007 +0000
+++ b/station_cmd.c	Thu Feb 08 10:00:22 2007 +0000
@@ -1895,13 +1895,22 @@
 	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		Owner o;
 		st->dock_tile = 0;
 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
 		 * braindead.. */
 		st->facilities &= ~FACIL_DOCK;
 		st->had_vehicle_of_type &= ~HVOT_BUOY;
 
-		MakeWater(tile);
+		/* We have to set the water tile's state to the same state as before the
+		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
+		 * remove it and flood the land (if the canal edge is at level 0) */
+		o = GetTileOwner(tile);
+		if (o == OWNER_WATER) {
+			MakeWater(tile);
+		} else {
+			MakeCanal(tile, o);
+		}
 		MarkTileDirtyByTile(tile);
 
 		UpdateStationVirtCoordDirty(st);
--- a/station_map.h	Wed Jan 31 22:08:23 2007 +0000
+++ b/station_map.h	Thu Feb 08 10:00:22 2007 +0000
@@ -287,7 +287,10 @@
 
 static inline void MakeBuoy(TileIndex t, StationID sid)
 {
-	MakeStation(t, OWNER_NONE, sid, GFX_BUOY_BASE);
+	/* Make the owner of the buoy tile the same as the current owner of the
+	 * water tile. In this way, we can reset the owner of the water to its
+	 * original state when the buoy gets removed. */
+	MakeStation(t, GetTileOwner(t), sid, GFX_BUOY_BASE);
 }
 
 static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d)
--- a/tunnelbridge_cmd.c	Wed Jan 31 22:08:23 2007 +0000
+++ b/tunnelbridge_cmd.c	Thu Feb 08 10:00:22 2007 +0000
@@ -541,7 +541,7 @@
 		GetTileZ(tile) != z
 	);
 
-	v = FindVehicleBetween(starttile, tile, z);
+	v = FindVehicleBetween(starttile, tile, z, false);
 	if (v != NULL) {
 		_error_message = v->type == VEH_Train ?
 			STR_5000_TRAIN_IN_TUNNEL : STR_5001_ROAD_VEHICLE_IN_TUNNEL;
@@ -688,7 +688,7 @@
 	v = FindVehicleBetween(
 		tile    + delta,
 		endtile - delta,
-		GetBridgeHeightRamp(tile)
+		GetBridgeHeightRamp(tile), false
 	);
 	if (v != NULL) return_cmd_error(VehicleInTheWayErrMsg(v));
 
@@ -820,7 +820,7 @@
 
 		if (!EnsureNoVehicle(tile) ||
 				!EnsureNoVehicle(endtile) ||
-				FindVehicleBetween(tile, endtile, GetBridgeHeightRamp(tile)) != NULL) {
+				FindVehicleBetween(tile, endtile, GetBridgeHeightRamp(tile), false) != NULL) {
 			return_cmd_error(STR_8803_TRAIN_IN_THE_WAY);
 		}
 
--- a/vehicle.c	Wed Jan 31 22:08:23 2007 +0000
+++ b/vehicle.c	Thu Feb 08 10:00:22 2007 +0000
@@ -174,7 +174,7 @@
 	return 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);
@@ -188,6 +188,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/vehicle.h	Wed Jan 31 22:08:23 2007 +0000
+++ b/vehicle.h	Thu Feb 08 10:00:22 2007 +0000
@@ -299,7 +299,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);
 TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v);
 
 bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction);
--- a/water_cmd.c	Wed Jan 31 22:08:23 2007 +0000
+++ b/water_cmd.c	Thu Feb 08 10:00:22 2007 +0000
@@ -40,6 +40,7 @@
 };
 
 
+static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
 static void FloodVehicle(Vehicle *v);
 
 /** Build a ship depot.
@@ -593,7 +594,7 @@
 
 		_current_player = OWNER_WATER;
 		{
-			Vehicle *v = FindVehicleOnTileZ(target, 0);
+			Vehicle *v = FindFloodableVehicleOnTile(target);
 			if (v != NULL) FloodVehicle(v);
 		}
 
@@ -604,6 +605,36 @@
 	}
 }
 
+/**
+ * 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)
+{
+	TileIndex end;
+	byte z;
+	Vehicle *v;
+
+	if (!IsBridgeTile(tile)) return FindVehicleOnTileZ(tile, 0);
+
+	end = GetOtherBridgeEnd(tile);
+	z = GetBridgeHeight(tile);
+
+	/* 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)) {
@@ -628,6 +659,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;
@@ -661,9 +693,8 @@
 		{{ 0, -1}, {0, 0}, {1, 0}, { 0, -1}, { 1, -1}}
 	};
 
-	/* Ensure sea-level canals do not flood */
-	if ((IsTileType(tile, MP_WATER) || IsTileType(tile, MP_TUNNELBRIDGE)) &&
-			!IsTileOwner(tile, OWNER_WATER)) return;
+	/* Ensure sea-level canals and buoys on canal borders do not flood */
+	if ((IsTileType(tile, MP_WATER) || IsTileType(tile, MP_TUNNELBRIDGE) || IsBuoyTile(tile)) && !IsTileOwner(tile, OWNER_WATER)) return;
 
 	if (IS_INT_INSIDE(TileX(tile), 1, MapSizeX() - 3 + 1) &&
 			IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) {