(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.
This commit is contained in:
rubidium 2007-02-08 10:00:22 +00:00
parent 5467635bf9
commit 03bfa6e525
7 changed files with 56 additions and 12 deletions

View File

@ -293,7 +293,7 @@ int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
/* 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);

View File

@ -1895,13 +1895,22 @@ static int32 RemoveBuoy(Station *st, uint32 flags)
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);

View File

@ -287,7 +287,10 @@ static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section
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)

View File

@ -541,7 +541,7 @@ TileIndex CheckTunnelBusy(TileIndex tile, uint *length)
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 @@ static int32 DoClearBridge(TileIndex tile, uint32 flags)
v = FindVehicleBetween(
tile + delta,
endtile - delta,
GetBridgeHeightRamp(tile)
GetBridgeHeightRamp(tile), false
);
if (v != NULL) return_cmd_error(VehicleInTheWayErrMsg(v));
@ -820,7 +820,7 @@ int32 DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
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);
}

View File

@ -174,7 +174,7 @@ Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z)
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 @@ Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z)
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) {

View File

@ -299,7 +299,7 @@ Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVeh
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);

View File

@ -40,6 +40,7 @@ const SpriteID _water_shore_sprites[15] = {
};
static Vehicle *FindFloodableVehicleOnTile(TileIndex tile);
static void FloodVehicle(Vehicle *v);
/** Build a ship depot.
@ -593,7 +594,7 @@ static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
_current_player = OWNER_WATER;
{
Vehicle *v = FindVehicleOnTileZ(target, 0);
Vehicle *v = FindFloodableVehicleOnTile(target);
if (v != NULL) FloodVehicle(v);
}
@ -604,6 +605,36 @@ static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs)
}
}
/**
* 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 @@ static void FloodVehicle(Vehicle *v)
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 @@ void TileLoop_Water(TileIndex tile)
{{ 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)) {