summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2007-12-17 22:29:27 +0000
committersmatz <smatz@openttd.org>2007-12-17 22:29:27 +0000
commit0b08f7370ddd778da13ed5426c8c4d24fe0d5432 (patch)
tree4b515d99becc25cc7fb8461375ce7ffa41682f47
parentbda9d4a23633c4ebb6ad18c29218deaf1a92d55d (diff)
downloadopenttd-0b08f7370ddd778da13ed5426c8c4d24fe0d5432.tar.xz
(svn r11657) -Fix: show better error message when trying to convert rail
-Codechange: merge DoConvert functions into one, make test and exec runs the same for tunnels/bridges
-rw-r--r--src/command.cpp1
-rw-r--r--src/rail_cmd.cpp196
-rw-r--r--src/road_cmd.cpp24
-rw-r--r--src/station_cmd.cpp23
-rw-r--r--src/tunnelbridge_cmd.cpp48
5 files changed, 110 insertions, 182 deletions
diff --git a/src/command.cpp b/src/command.cpp
index b09d43318..e65b8a4b2 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -549,7 +549,6 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback,
* estimate the cost of cloning a vehicle. */
notest =
(cmd & 0xFF) == CMD_CLEAR_AREA ||
- (cmd & 0xFF) == CMD_CONVERT_RAIL ||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD ||
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index 454e4b30e..15146f5e5 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -1143,8 +1143,7 @@ CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32
return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5)); // bit 5 is remove bit
}
-typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec);
-
+/** Update power of train under which is the railtype being converted */
void *UpdateTrainPowerProc(Vehicle *v, void *data)
{
/* Similiar checks as in TrainPowerChanged() */
@@ -1157,46 +1156,6 @@ void *UpdateTrainPowerProc(Vehicle *v, void *data)
return NULL;
}
-/**
- * Switches the rail type.
- * Railtypes are stored on a per-tile basis, not on a per-track basis, so
- * all the tracks in the given tile will be converted.
- * @param tile The tile on which the railtype is to be convert.
- * @param totype The railtype we want to convert to
- * @param exec Switches between test and execute mode
- * @return The cost and state of the operation
- * @retval CMD_ERROR An error occured during the operation.
- */
-static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec)
-{
- /* change type. */
- if (exec) {
- SetRailType(tile, totype);
- MarkTileDirtyByTile(tile);
-
- /* notify YAPF about the track layout change */
- TrackBits tracks = GetTrackBits(tile);
- while (tracks != TRACK_BIT_NONE) {
- YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
- }
-
- if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
- /* Update build vehicle window related to this depot */
- InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
- InvalidateWindowData(WC_BUILD_VEHICLE, tile);
- }
-
- /* update power of train engines on this tile */
- VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
- }
-
- return CommandCost(RailConvertCost(GetRailType(tile), totype) * CountBits(GetTrackBits(tile)));
-}
-
-extern CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec);
-extern CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec);
-extern CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec);
-
/** Convert one rail type to the other. You can convert normal rail to
* monorail/maglev easily or vice-versa.
* @param tile end tile of rail conversion drag
@@ -1206,72 +1165,137 @@ extern CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bo
*/
CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{
- CommandCost ret, cost;
- Money money;
- int ex;
- int ey;
- int sx, sy, x, y;
-
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
+ CommandCost cost;
if (!ValParamRailtype(p2)) return CMD_ERROR;
if (p1 >= MapSize()) return CMD_ERROR;
+ RailType totype = (RailType)p2;
+
+ uint ex = TileX(tile);
+ uint ey = TileY(tile);
+ uint sx = TileX(p1);
+ uint sy = TileY(p1);
+
/* make sure sx,sy are smaller than ex,ey */
- ex = TileX(tile);
- ey = TileY(tile);
- sx = TileX(p1);
- sy = TileY(p1);
if (ex < sx) Swap(ex, sx);
if (ey < sy) Swap(ey, sy);
- money = GetAvailableMoneyForCommand();
+ SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
+
+ _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert
- for (x = sx; x <= ex; ++x) {
- for (y = sy; y <= ey; ++y) {
+ for (uint x = sx; x <= ex; ++x) {
+ for (uint y = sy; y <= ey; ++y) {
TileIndex tile = TileXY(x, y);
- DoConvertRailProc *proc;
- RailType totype = (RailType)p2;
-
- switch (GetTileType(tile)) {
- case MP_RAILWAY: proc = DoConvertRail; break;
- case MP_STATION: proc = DoConvertStationRail; break;
- case MP_ROAD: proc = DoConvertStreetRail; break;
- case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break;
+ TileType tt = GetTileType(tile);
+
+ /* Check if there is any track on tile */
+ switch (tt) {
+ case MP_RAILWAY:
+ break;
+ case MP_STATION:
+ if (!IsRailwayStation(tile)) continue;
+ break;
+ case MP_ROAD:
+ if (!IsLevelCrossing(tile)) continue;
+ break;
+ case MP_TUNNELBRIDGE:
+ if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
+ break;
default: continue;
}
- /* It is possible that 'type' is invalid when there is no rail on the tile,
- * but this situation will be detected in proc()
- */
+ /* Original railtype we are converting from */
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;
+ /* Converting to the same type or converting 'hidden' elrail -> rail */
+ if (type == totype || (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
+
+ /* Trying to convert other's rail */
+ if (!CheckTileOwnership(tile)) continue;
+
+ /* Vehicle on the tile when not converting Rail <-> ElRail
+ * Tunnels and bridges have special check later */
+ if (tt != MP_TUNNELBRIDGE) {
+ if (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile)) continue;
+ if (flags & DC_EXEC) { // we can safely convert, too
+ SetRailType(tile, totype);
+ MarkTileDirtyByTile(tile);
+ /* update power of train engines on this tile */
+ VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
+ }
}
- ret = proc(tile, totype, false);
- if (CmdFailed(ret)) continue;
+ switch (tt) {
+ case MP_RAILWAY:
+ if (flags & DC_EXEC) {
+ /* notify YAPF about the track layout change */
+ TrackBits tracks = GetTrackBits(tile);
+ while (tracks != TRACK_BIT_NONE) {
+ YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
+ }
+
+ if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
+ /* Update build vehicle window related to this depot */
+ InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
+ InvalidateWindowData(WC_BUILD_VEHICLE, tile);
+ }
+ }
- if (flags & DC_EXEC) {
- money -= ret.GetCost();
- if (money < 0) {
- _additional_cash_required = ret.GetCost();
- return cost;
- }
- proc(tile, totype, true);
+ cost.AddCost(CommandCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile))));
+ break;
+
+ case MP_TUNNELBRIDGE: {
+ TileIndex endtile = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
+
+ /* If both ends of tunnel/bridge are in the range, do not try to convert twice -
+ * it would cause assert because of different test and exec runs */
+ if (endtile < tile && TileX(endtile) >= sx && TileX(endtile) <= ex &&
+ TileY(endtile) >= sy && TileY(endtile) <= ey) continue;
+
+ /* When not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
+ if (!IsCompatibleRail(GetRailType(tile), totype) &&
+ GetVehicleTunnelBridge(tile, endtile) != NULL) continue;
+
+ if (flags & DC_EXEC) {
+ SetRailType(tile, totype);
+ SetRailType(endtile, totype);
+
+ VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
+ VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc);
+
+ Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile)));
+
+ YapfNotifyTrackLayoutChange(tile, track);
+ YapfNotifyTrackLayoutChange(endtile, track);
+
+ MarkTileDirtyByTile(tile);
+ MarkTileDirtyByTile(endtile);
+
+ if (IsBridge(tile)) {
+ TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
+ TileIndex t = tile + delta;
+ for (; t != endtile; t += delta) MarkTileDirtyByTile(t); // TODO encapsulate this into a function
+ }
+ }
+
+ cost.AddCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(type, totype));
+ } break;
+
+ default: // MP_STATION, MP_ROAD
+ if (flags & DC_EXEC) {
+ Track track = (tt == MP_STATION) ? GetRailStationTrack(tile) : AxisToTrack(OtherAxis(GetCrossingRoadAxis(tile)));
+ YapfNotifyTrackLayoutChange(tile, track);
+ }
+
+ cost.AddCost(RailConvertCost(type, totype));
+ break;
}
- cost.AddCost(ret);
}
}
- return (cost.GetCost() == 0) ? ret : cost;
+ return (cost.GetCost() == 0) ? CMD_ERROR : cost;
}
static CommandCost RemoveTrainDepot(TileIndex tile, uint32 flags)
diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp
index 58ad42208..f6a2a8694 100644
--- a/src/road_cmd.cpp
+++ b/src/road_cmd.cpp
@@ -593,30 +593,6 @@ do_clear:;
return cost;
}
-/**
- * Switches the rail type on a level crossing.
- * @param tile The tile on which the railtype is to be convert.
- * @param totype The railtype we want to convert to
- * @param exec Switches between test and execute mode
- * @return The cost and state of the operation
- * @retval CMD_ERROR An error occured during the operation.
- */
-CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
-{
- /* not a railroad crossing? */
- if (!IsLevelCrossing(tile)) return CMD_ERROR;
-
- if (exec) {
- SetRailType(tile, totype);
- MarkTileDirtyByTile(tile);
- YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
- VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
- }
-
- return CommandCost(RailConvertCost(GetRailType(tile), totype));
-}
-
-
/** Build a long piece of road.
* @param end_tile end tile of drag
* @param flags operation to perform
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 0e189bd05..dc077e27f 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1290,29 +1290,6 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 fla
}
/**
- * Switches the rail type at a railway station tile.
- * @param tile The tile on which the railtype is to be convert.
- * @param totype The railtype we want to convert to
- * @param exec Switches between test and execute mode
- * @return The cost and state of the operation
- * @retval CMD_ERROR An error occured during the operation.
- */
-CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
-{
- /* Tile is not a railroad station? */
- if (!IsRailwayStation(tile)) return CMD_ERROR;
-
- if (exec) {
- SetRailType(tile, totype);
- MarkTileDirtyByTile(tile);
- YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
- VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
- }
-
- return CommandCost(RailConvertCost(GetRailType(tile), totype));
-}
-
-/**
* @param truck_station Determines whether a stop is RoadStop::BUS or RoadStop::TRUCK
* @param st The Station to do the whole procedure for
* @return a pointer to where to link a new RoadStop*
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 68be57389..95fc6f980 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -691,54 +691,6 @@ static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags)
}
/**
- * Switches the rail type for a tunnel or a bridgehead. As the railtype
- * on the bridge are determined by the one of the bridgehead, this
- * functions converts the railtype on the entire bridge.
- * @param tile The tile on which the railtype is to be convert.
- * @param totype The railtype we want to convert to
- * @param exec Switches between test and execute mode
- * @return The cost and state of the operation
- * @retval CMD_ERROR An error occured during the operation.
- */
-CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
-{
- if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) return CMD_ERROR;
-
- TileIndex endtile = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile);
-
- /* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
- if (!IsCompatibleRail(GetRailType(tile), totype) &&
- GetVehicleTunnelBridge(tile, endtile) != NULL) {
- return CMD_ERROR;
- }
-
- if (exec) {
- SetRailType(tile, totype);
- SetRailType(endtile, totype);
-
- Track track = AxisToTrack(DiagDirToAxis(GetTunnelBridgeDirection(tile)));
-
- YapfNotifyTrackLayoutChange(tile, track);
- YapfNotifyTrackLayoutChange(endtile, track);
-
- VehicleFromPos(tile, NULL, &UpdateTrainPowerProc);
- VehicleFromPos(endtile, NULL, &UpdateTrainPowerProc);
-
- MarkTileDirtyByTile(tile);
- MarkTileDirtyByTile(endtile);
-
- if (IsBridge(tile)) {
- TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
- TileIndex t = tile + delta;
- for (; t != endtile; t += delta) MarkTileDirtyByTile(t); // TODO encapsulate this into a function
- }
- }
-
- return CommandCost((DistanceManhattan(tile, endtile) + 1) * RailConvertCost(GetRailType(tile), totype));
-}
-
-
-/**
* Draws the pillars under high bridges.
*
* @param psid Image and palette of a bridge pillar.