summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-09-08 09:52:02 +0000
committerrubidium <rubidium@openttd.org>2007-09-08 09:52:02 +0000
commit91a49cee55bd2162099ef7bd35c318b7e77ab590 (patch)
treed8567cb4c3be776942b6892104b1373991293490 /src
parent8141fe0898de18d0f6a5e8da7231a1adbe7790da (diff)
downloadopenttd-91a49cee55bd2162099ef7bd35c318b7e77ab590.tar.xz
(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.
Diffstat (limited to 'src')
-rw-r--r--src/rail.h1
-rw-r--r--src/rail_cmd.cpp56
-rw-r--r--src/road_cmd.cpp9
-rw-r--r--src/station_cmd.cpp12
-rw-r--r--src/train_cmd.cpp3
-rw-r--r--src/tunnelbridge_cmd.cpp55
6 files changed, 69 insertions, 67 deletions
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;
}