From c97804461eb696393a9bf4acc2f9b57738349066 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 8 Sep 2007 09:52:02 +0000 Subject: (svn r11059) -Fix [FS#1182]: inconsistency between Rail<->ElRail conversions of different kinds of rail containing tiles (normal rail, stations, depots, etc). Patch by SmatZ. --- src/rail.h | 1 + src/rail_cmd.cpp | 56 ++++++++++++++++++++++++++++++------------------ src/road_cmd.cpp | 9 +------- src/station_cmd.cpp | 12 ++--------- src/train_cmd.cpp | 3 +++ src/tunnelbridge_cmd.cpp | 55 +++++++++++++++++++++++------------------------ 6 files changed, 69 insertions(+), 67 deletions(-) (limited to 'src') diff --git a/src/rail.h b/src/rail.h index ab6ea3b9f..1bd014d17 100644 --- a/src/rail.h +++ b/src/rail.h @@ -778,6 +778,7 @@ static inline bool TracksOverlap(TrackBits bits) return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT; } +void *UpdateTrainPowerProc(Vehicle *v, void *data); void DrawTrainDepotSprite(int x, int y, int image, RailType railtype); void DrawDefaultWaypointSprite(int x, int y, RailType railtype); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 27ce47cf5..f708fe02f 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -34,6 +34,7 @@ #include "railtypes.h" // include table for railtypes #include "newgrf.h" #include "yapf/yapf.h" +#include "newgrf_engine.h" #include "newgrf_callbacks.h" #include "newgrf_station.h" #include "train.h" @@ -1024,6 +1025,18 @@ CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); +void *UpdateTrainPowerProc(Vehicle *v, void *data) +{ + /* Similiar checks as in TrainPowerChanged() */ + + if (v->type == VEH_TRAIN && v->tile == *(TileIndex*)data && !IsArticulatedPart(v)) { + const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); + if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First()); + } + + return NULL; +} + /** * Switches the rail type. * Railtypes are stored on a per-tile basis, not on a per-track basis, so @@ -1036,15 +1049,6 @@ typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec */ static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec) { - if (!CheckTileOwnership(tile)) return CMD_ERROR; - - if (GetRailType(tile) == totype) return CMD_ERROR; - - if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR; - - /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ - if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; - /* change type. */ if (exec) { SetRailType(tile, totype); @@ -1057,18 +1061,12 @@ static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec) } if (IsTileDepotType(tile, TRANSPORT_RAIL)) { - Vehicle *v; - /* Update build vehicle window related to this depot */ InvalidateWindowData(WC_BUILD_VEHICLE, tile); - - /* update power of trains in this depot */ - FOR_ALL_VEHICLES(v) { - if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == tile && v->u.rail.track == 0x80) { - TrainPowerChanged(v); - } - } } + + /* update power of train engines on this tile */ + VehicleFromPos(tile, &tile, UpdateTrainPowerProc); } return CommandCost(_price.build_rail / 2); @@ -1111,7 +1109,8 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) for (x = sx; x <= ex; ++x) { for (y = sy; y <= ey; ++y) { TileIndex tile = TileXY(x, y); - DoConvertRailProc* proc; + DoConvertRailProc *proc; + RailType totype = (RailType)p2; switch (GetTileType(tile)) { case MP_RAILWAY: proc = DoConvertRail; break; @@ -1121,7 +1120,22 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) default: continue; } - ret = proc(tile, (RailType)p2, false); + /* It is possible that 'type' is invalid when there is no rail on the tile, + * but this situation will be detected in proc() + */ + RailType type = GetRailType(tile); + + /* Not own tile or track is already converted */ + if ((!CheckTileOwnership(tile) || type == totype) || + /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ + (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC) || + /* Vehicle on a tile while not converting Rail <-> ElRail */ + (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile))) { + ret = CMD_ERROR; + continue; + } + + ret = proc(tile, totype, false); if (CmdFailed(ret)) continue; if (flags & DC_EXEC) { @@ -1130,7 +1144,7 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) _additional_cash_required = ret.GetCost(); return cost; } - proc(tile, (RailType)p2, true); + proc(tile, totype, true); } cost.AddCost(ret); } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 3dadf9e5d..cf2ae3638 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -543,18 +543,11 @@ CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec) /* not a railroad crossing? */ if (!IsLevelCrossing(tile)) return CMD_ERROR; - /* not owned by me? */ - if (!CheckTileOwnership(tile) || !EnsureNoVehicleOnGround(tile)) return CMD_ERROR; - - if (GetRailType(tile) == totype) return CMD_ERROR; - - /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ - if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; - if (exec) { SetRailType(tile, totype); MarkTileDirtyByTile(tile); YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile))); + VehicleFromPos(tile, &tile, UpdateTrainPowerProc); } return CommandCost(_price.build_rail / 2); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 19d838b0c..4f75d932f 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1227,22 +1227,14 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 fla */ CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec) { - const Station* st = GetStationByTile(tile); - - if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR; - - // tile is not a railroad station? + /* Tile is not a railroad station? */ if (!IsRailwayStation(tile)) return CMD_ERROR; - if (GetRailType(tile) == totype) return CMD_ERROR; - - // 'hidden' elrails can't be downgraded to normal rail when elrails are disabled - if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; - if (exec) { SetRailType(tile, totype); MarkTileDirtyByTile(tile); YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile)); + VehicleFromPos(tile, &tile, UpdateTrainPowerProc); } return CommandCost(_price.build_rail / 2); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index a475c61ec..f850f7c42 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -95,6 +95,9 @@ void TrainPowerChanged(Vehicle* v) } if (v->u.rail.cached_power != total_power || v->u.rail.cached_max_te != max_te) { + /* If it has no power (no catenary), stop the train */ + if (total_power == 0) v->vehstatus |= VS_STOPPED; + v->u.rail.cached_power = total_power; v->u.rail.cached_max_te = max_te; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 7c625126a..33f28a540 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -749,68 +749,67 @@ static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags) */ CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec) { - TileIndex endtile; - if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) { uint length; + TileIndex endtile; - if (!CheckTileOwnership(tile)) return CMD_ERROR; - - if (GetRailType(tile) == totype) return CMD_ERROR; - - /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ - if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; - - endtile = CheckTunnelBusy(tile, &length); - if (endtile == INVALID_TILE) return CMD_ERROR; + /* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel */ + if (!IsCompatibleRail(GetRailType(tile), totype)) { + endtile = CheckTunnelBusy(tile, &length); + if (endtile == INVALID_TILE) return CMD_ERROR; + } else { + endtile = GetOtherTunnelEnd(tile); + length = DistanceManhattan(tile, endtile); + } if (exec) { - Track track; SetRailType(tile, totype); SetRailType(endtile, totype); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(endtile); - track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile))); + Track track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile))); + YapfNotifyTrackLayoutChange(tile, track); YapfNotifyTrackLayoutChange(endtile, track); - } - return CommandCost((length + 1) * (_price.build_rail / 2)); - } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { - if (!CheckTileOwnership(tile)) return CMD_ERROR; + VehicleFromPos(tile, &tile, UpdateTrainPowerProc); + VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc); + } - endtile = GetOtherBridgeEnd(tile); + return CommandCost((length + 1) * (_price.build_rail >> 1)); + } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { + TileIndex endtile = GetOtherBridgeEnd(tile); byte bridge_height = GetBridgeHeight(tile); - if (FindVehicleOnTileZ(tile, bridge_height) != NULL || + if (!IsCompatibleRail(GetRailType(tile), totype) && + (FindVehicleOnTileZ(tile, bridge_height) != NULL || FindVehicleOnTileZ(endtile, bridge_height) != NULL || - IsVehicleOnBridge(tile, endtile, bridge_height)) { + IsVehicleOnBridge(tile, endtile, bridge_height))) { return CMD_ERROR; } - if (GetRailType(tile) == totype) return CMD_ERROR; - if (exec) { - TileIndexDiff delta; - Track track; - SetRailType(tile, totype); SetRailType(endtile, totype); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(endtile); - track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile))); + Track track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile))); + TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); + YapfNotifyTrackLayoutChange(tile, track); YapfNotifyTrackLayoutChange(endtile, track); - delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); + VehicleFromPos(tile, &tile, UpdateTrainPowerProc); + VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc); + for (tile += delta; tile != endtile; tile += delta) { MarkTileDirtyByTile(tile); // TODO encapsulate this into a function } } - return CommandCost((DistanceManhattan(tile, endtile) + 1) * (_price.build_rail / 2)); + return CommandCost((DistanceManhattan(tile, endtile) + 1) * (_price.build_rail >> 1)); } else { return CMD_ERROR; } -- cgit v1.2.3-54-g00ecf