mirror of https://github.com/OpenTTD/OpenTTD
(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.
parent
8141fe0898
commit
91a49cee55
|
@ -778,6 +778,7 @@ static inline bool TracksOverlap(TrackBits bits)
|
||||||
return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT;
|
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 DrawTrainDepotSprite(int x, int y, int image, RailType railtype);
|
||||||
void DrawDefaultWaypointSprite(int x, int y, RailType railtype);
|
void DrawDefaultWaypointSprite(int x, int y, RailType railtype);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "railtypes.h" // include table for railtypes
|
#include "railtypes.h" // include table for railtypes
|
||||||
#include "newgrf.h"
|
#include "newgrf.h"
|
||||||
#include "yapf/yapf.h"
|
#include "yapf/yapf.h"
|
||||||
|
#include "newgrf_engine.h"
|
||||||
#include "newgrf_callbacks.h"
|
#include "newgrf_callbacks.h"
|
||||||
#include "newgrf_station.h"
|
#include "newgrf_station.h"
|
||||||
#include "train.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);
|
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.
|
* Switches the rail type.
|
||||||
* Railtypes are stored on a per-tile basis, not on a per-track basis, so
|
* 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)
|
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. */
|
/* change type. */
|
||||||
if (exec) {
|
if (exec) {
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
|
@ -1057,18 +1061,12 @@ static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
|
if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
|
||||||
Vehicle *v;
|
|
||||||
|
|
||||||
/* Update build vehicle window related to this depot */
|
/* Update build vehicle window related to this depot */
|
||||||
InvalidateWindowData(WC_BUILD_VEHICLE, tile);
|
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);
|
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 (x = sx; x <= ex; ++x) {
|
||||||
for (y = sy; y <= ey; ++y) {
|
for (y = sy; y <= ey; ++y) {
|
||||||
TileIndex tile = TileXY(x, y);
|
TileIndex tile = TileXY(x, y);
|
||||||
DoConvertRailProc* proc;
|
DoConvertRailProc *proc;
|
||||||
|
RailType totype = (RailType)p2;
|
||||||
|
|
||||||
switch (GetTileType(tile)) {
|
switch (GetTileType(tile)) {
|
||||||
case MP_RAILWAY: proc = DoConvertRail; break;
|
case MP_RAILWAY: proc = DoConvertRail; break;
|
||||||
|
@ -1121,7 +1120,22 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||||
default: continue;
|
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 (CmdFailed(ret)) continue;
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
|
@ -1130,7 +1144,7 @@ CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||||
_additional_cash_required = ret.GetCost();
|
_additional_cash_required = ret.GetCost();
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
proc(tile, (RailType)p2, true);
|
proc(tile, totype, true);
|
||||||
}
|
}
|
||||||
cost.AddCost(ret);
|
cost.AddCost(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -543,18 +543,11 @@ CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec)
|
||||||
/* not a railroad crossing? */
|
/* not a railroad crossing? */
|
||||||
if (!IsLevelCrossing(tile)) return CMD_ERROR;
|
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) {
|
if (exec) {
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
|
YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile)));
|
||||||
|
VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost(_price.build_rail / 2);
|
return CommandCost(_price.build_rail / 2);
|
||||||
|
|
|
@ -1227,22 +1227,14 @@ static CommandCost RemoveRailroadStation(Station *st, TileIndex tile, uint32 fla
|
||||||
*/
|
*/
|
||||||
CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
|
CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
|
||||||
{
|
{
|
||||||
const Station* st = GetStationByTile(tile);
|
/* Tile is not a railroad station? */
|
||||||
|
|
||||||
if (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile)) return CMD_ERROR;
|
|
||||||
|
|
||||||
// tile is not a railroad station?
|
|
||||||
if (!IsRailwayStation(tile)) return CMD_ERROR;
|
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) {
|
if (exec) {
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
|
YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
|
||||||
|
VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost(_price.build_rail / 2);
|
return CommandCost(_price.build_rail / 2);
|
||||||
|
|
|
@ -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 (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_power = total_power;
|
||||||
v->u.rail.cached_max_te = max_te;
|
v->u.rail.cached_max_te = max_te;
|
||||||
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
||||||
|
|
|
@ -749,68 +749,67 @@ static CommandCost ClearTile_TunnelBridge(TileIndex tile, byte flags)
|
||||||
*/
|
*/
|
||||||
CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
|
CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec)
|
||||||
{
|
{
|
||||||
TileIndex endtile;
|
|
||||||
|
|
||||||
if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
|
if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) {
|
||||||
uint length;
|
uint length;
|
||||||
|
TileIndex endtile;
|
||||||
|
|
||||||
if (!CheckTileOwnership(tile)) return CMD_ERROR;
|
/* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel */
|
||||||
|
if (!IsCompatibleRail(GetRailType(tile), totype)) {
|
||||||
if (GetRailType(tile) == totype) return CMD_ERROR;
|
endtile = CheckTunnelBusy(tile, &length);
|
||||||
|
if (endtile == INVALID_TILE) return CMD_ERROR;
|
||||||
/* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */
|
} else {
|
||||||
if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR;
|
endtile = GetOtherTunnelEnd(tile);
|
||||||
|
length = DistanceManhattan(tile, endtile);
|
||||||
endtile = CheckTunnelBusy(tile, &length);
|
}
|
||||||
if (endtile == INVALID_TILE) return CMD_ERROR;
|
|
||||||
|
|
||||||
if (exec) {
|
if (exec) {
|
||||||
Track track;
|
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
SetRailType(endtile, totype);
|
SetRailType(endtile, totype);
|
||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
MarkTileDirtyByTile(endtile);
|
MarkTileDirtyByTile(endtile);
|
||||||
|
|
||||||
track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile)));
|
Track track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile)));
|
||||||
|
|
||||||
YapfNotifyTrackLayoutChange(tile, track);
|
YapfNotifyTrackLayoutChange(tile, track);
|
||||||
YapfNotifyTrackLayoutChange(endtile, track);
|
YapfNotifyTrackLayoutChange(endtile, track);
|
||||||
|
|
||||||
|
VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
|
||||||
|
VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc);
|
||||||
}
|
}
|
||||||
return CommandCost((length + 1) * (_price.build_rail / 2));
|
|
||||||
|
return CommandCost((length + 1) * (_price.build_rail >> 1));
|
||||||
} else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
|
} else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) {
|
||||||
|
TileIndex endtile = GetOtherBridgeEnd(tile);
|
||||||
if (!CheckTileOwnership(tile)) return CMD_ERROR;
|
|
||||||
|
|
||||||
endtile = GetOtherBridgeEnd(tile);
|
|
||||||
byte bridge_height = GetBridgeHeight(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 ||
|
FindVehicleOnTileZ(endtile, bridge_height) != NULL ||
|
||||||
IsVehicleOnBridge(tile, endtile, bridge_height)) {
|
IsVehicleOnBridge(tile, endtile, bridge_height))) {
|
||||||
return CMD_ERROR;
|
return CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetRailType(tile) == totype) return CMD_ERROR;
|
|
||||||
|
|
||||||
if (exec) {
|
if (exec) {
|
||||||
TileIndexDiff delta;
|
|
||||||
Track track;
|
|
||||||
|
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
SetRailType(endtile, totype);
|
SetRailType(endtile, totype);
|
||||||
MarkTileDirtyByTile(tile);
|
MarkTileDirtyByTile(tile);
|
||||||
MarkTileDirtyByTile(endtile);
|
MarkTileDirtyByTile(endtile);
|
||||||
|
|
||||||
track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile)));
|
Track track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile)));
|
||||||
|
TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
|
||||||
|
|
||||||
YapfNotifyTrackLayoutChange(tile, track);
|
YapfNotifyTrackLayoutChange(tile, track);
|
||||||
YapfNotifyTrackLayoutChange(endtile, track);
|
YapfNotifyTrackLayoutChange(endtile, track);
|
||||||
|
|
||||||
delta = TileOffsByDiagDir(GetBridgeRampDirection(tile));
|
VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
|
||||||
|
VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc);
|
||||||
|
|
||||||
for (tile += delta; tile != endtile; tile += delta) {
|
for (tile += delta; tile != endtile; tile += delta) {
|
||||||
MarkTileDirtyByTile(tile); // TODO encapsulate this into a function
|
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 {
|
} else {
|
||||||
return CMD_ERROR;
|
return CMD_ERROR;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue