mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-12 10:30:28 +00:00
(svn r21481) -Codechange: make rail conversion make use of TILE_AREA_LOOP as well
This commit is contained in:
parent
90e247c84d
commit
a1d923700f
267
src/rail_cmd.cpp
267
src/rail_cmd.cpp
@ -1397,73 +1397,126 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
if (!ValParamRailtype(totype)) return CMD_ERROR;
|
if (!ValParamRailtype(totype)) return CMD_ERROR;
|
||||||
if (p1 >= MapSize()) return CMD_ERROR;
|
if (p1 >= MapSize()) return CMD_ERROR;
|
||||||
|
|
||||||
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 */
|
|
||||||
if (ex < sx) Swap(ex, sx);
|
|
||||||
if (ey < sy) Swap(ey, sy);
|
|
||||||
|
|
||||||
TrainList affected_trains;
|
TrainList affected_trains;
|
||||||
|
|
||||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||||
CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert.
|
CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert.
|
||||||
for (uint x = sx; x <= ex; ++x) {
|
TileArea ta(tile, p1);
|
||||||
for (uint y = sy; y <= ey; ++y) {
|
TILE_AREA_LOOP(tile, ta) {
|
||||||
TileIndex tile = TileXY(x, y);
|
TileType tt = GetTileType(tile);
|
||||||
TileType tt = GetTileType(tile);
|
|
||||||
|
|
||||||
/* Check if there is any track on tile */
|
/* Check if there is any track on tile */
|
||||||
switch (tt) {
|
switch (tt) {
|
||||||
case MP_RAILWAY:
|
case MP_RAILWAY:
|
||||||
break;
|
break;
|
||||||
case MP_STATION:
|
case MP_STATION:
|
||||||
if (!HasStationRail(tile)) continue;
|
if (!HasStationRail(tile)) continue;
|
||||||
break;
|
break;
|
||||||
case MP_ROAD:
|
case MP_ROAD:
|
||||||
if (!IsLevelCrossing(tile)) continue;
|
if (!IsLevelCrossing(tile)) continue;
|
||||||
if (RailNoLevelCrossings(totype)) {
|
if (RailNoLevelCrossings(totype)) {
|
||||||
error.MakeError(STR_ERROR_CROSSING_DISALLOWED);
|
error.MakeError(STR_ERROR_CROSSING_DISALLOWED);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MP_TUNNELBRIDGE:
|
||||||
|
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
|
||||||
|
break;
|
||||||
|
default: continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Original railtype we are converting from */
|
||||||
|
RailType type = GetRailType(tile);
|
||||||
|
|
||||||
|
/* Converting to the same type or converting 'hidden' elrail -> rail */
|
||||||
|
if (type == totype || (_settings_game.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
|
||||||
|
|
||||||
|
/* Trying to convert other's rail */
|
||||||
|
CommandCost ret = CheckTileOwnership(tile);
|
||||||
|
if (ret.Failed()) {
|
||||||
|
error = ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallVector<Train *, 2> vehicles_affected;
|
||||||
|
|
||||||
|
/* Vehicle on the tile when not converting Rail <-> ElRail
|
||||||
|
* Tunnels and bridges have special check later */
|
||||||
|
if (tt != MP_TUNNELBRIDGE) {
|
||||||
|
if (!IsCompatibleRail(type, totype)) {
|
||||||
|
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
||||||
|
if (ret.Failed()) {
|
||||||
|
error = ret;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flags & DC_EXEC) { // we can safely convert, too
|
||||||
|
TrackBits reserved = GetReservedTrackbits(tile);
|
||||||
|
Track track;
|
||||||
|
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
|
||||||
|
Train *v = GetTrainForReservation(tile, track);
|
||||||
|
if (v != NULL && !HasPowerOnRail(v->railtype, totype)) {
|
||||||
|
/* No power on new rail type, reroute. */
|
||||||
|
FreeTrainTrackReservation(v);
|
||||||
|
*vehicles_affected.Append() = v;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case MP_TUNNELBRIDGE:
|
|
||||||
if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
|
SetRailType(tile, totype);
|
||||||
break;
|
MarkTileDirtyByTile(tile);
|
||||||
default: continue;
|
/* update power of train on this tile */
|
||||||
|
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Original railtype we are converting from */
|
switch (tt) {
|
||||||
RailType type = GetRailType(tile);
|
case MP_RAILWAY:
|
||||||
|
switch (GetRailTileType(tile)) {
|
||||||
|
case RAIL_TILE_DEPOT:
|
||||||
|
if (flags & DC_EXEC) {
|
||||||
|
/* notify YAPF about the track layout change */
|
||||||
|
YapfNotifyTrackLayoutChange(tile, GetRailDepotTrack(tile));
|
||||||
|
|
||||||
/* Converting to the same type or converting 'hidden' elrail -> rail */
|
/* Update build vehicle window related to this depot */
|
||||||
if (type == totype || (_settings_game.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
|
InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
|
||||||
|
InvalidateWindowData(WC_BUILD_VEHICLE, tile);
|
||||||
|
}
|
||||||
|
cost.AddCost(RailConvertCost(type, totype));
|
||||||
|
break;
|
||||||
|
|
||||||
/* Trying to convert other's rail */
|
default: // RAIL_TILE_NORMAL, RAIL_TILE_SIGNALS
|
||||||
CommandCost ret = CheckTileOwnership(tile);
|
if (flags & DC_EXEC) {
|
||||||
if (ret.Failed()) {
|
/* notify YAPF about the track layout change */
|
||||||
error = ret;
|
TrackBits tracks = GetTrackBits(tile);
|
||||||
continue;
|
while (tracks != TRACK_BIT_NONE) {
|
||||||
}
|
YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
SmallVector<Train *, 2> vehicles_affected;
|
case MP_TUNNELBRIDGE: {
|
||||||
|
TileIndex endtile = GetOtherTunnelBridgeEnd(tile);
|
||||||
|
|
||||||
/* Vehicle on the tile when not converting Rail <-> ElRail
|
/* If both ends of tunnel/bridge are in the range, do not try to convert twice -
|
||||||
* Tunnels and bridges have special check later */
|
* it would cause assert because of different test and exec runs */
|
||||||
if (tt != MP_TUNNELBRIDGE) {
|
if (endtile < tile && TileX(endtile) >= TileX(ta.tile) && TileX(endtile) < TileX(ta.tile) + ta.w &&
|
||||||
if (!IsCompatibleRail(type, totype)) {
|
TileY(endtile) >= TileY(ta.tile) && TileY(endtile) < TileY(ta.tile) + ta.h) continue;
|
||||||
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
|
||||||
|
/* When not coverting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */
|
||||||
|
if (!IsCompatibleRail(GetRailType(tile), totype)) {
|
||||||
|
CommandCost ret = TunnelBridgeIsFree(tile, endtile);
|
||||||
if (ret.Failed()) {
|
if (ret.Failed()) {
|
||||||
error = ret;
|
error = ret;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags & DC_EXEC) { // we can safely convert, too
|
|
||||||
TrackBits reserved = GetReservedTrackbits(tile);
|
if (flags & DC_EXEC) {
|
||||||
Track track;
|
Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
|
||||||
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
|
if (HasTunnelBridgeReservation(tile)) {
|
||||||
Train *v = GetTrainForReservation(tile, track);
|
Train *v = GetTrainForReservation(tile, track);
|
||||||
if (v != NULL && !HasPowerOnRail(v->railtype, totype)) {
|
if (v != NULL && !HasPowerOnRail(v->railtype, totype)) {
|
||||||
/* No power on new rail type, reroute. */
|
/* No power on new rail type, reroute. */
|
||||||
@ -1471,105 +1524,41 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
*vehicles_affected.Append() = v;
|
*vehicles_affected.Append() = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetRailType(tile, totype);
|
SetRailType(tile, totype);
|
||||||
MarkTileDirtyByTile(tile);
|
SetRailType(endtile, totype);
|
||||||
/* update power of train on this tile */
|
|
||||||
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
||||||
}
|
FindVehicleOnPos(endtile, &affected_trains, &UpdateTrainPowerProc);
|
||||||
}
|
|
||||||
|
|
||||||
switch (tt) {
|
YapfNotifyTrackLayoutChange(tile, track);
|
||||||
case MP_RAILWAY:
|
YapfNotifyTrackLayoutChange(endtile, track);
|
||||||
switch (GetRailTileType(tile)) {
|
|
||||||
case RAIL_TILE_DEPOT:
|
|
||||||
if (flags & DC_EXEC) {
|
|
||||||
/* notify YAPF about the track layout change */
|
|
||||||
YapfNotifyTrackLayoutChange(tile, GetRailDepotTrack(tile));
|
|
||||||
|
|
||||||
/* Update build vehicle window related to this depot */
|
MarkTileDirtyByTile(tile);
|
||||||
InvalidateWindowData(WC_VEHICLE_DEPOT, tile);
|
MarkTileDirtyByTile(endtile);
|
||||||
InvalidateWindowData(WC_BUILD_VEHICLE, tile);
|
|
||||||
}
|
|
||||||
cost.AddCost(RailConvertCost(type, totype));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: // RAIL_TILE_NORMAL, RAIL_TILE_SIGNALS
|
if (IsBridge(tile)) {
|
||||||
if (flags & DC_EXEC) {
|
TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile));
|
||||||
/* notify YAPF about the track layout change */
|
TileIndex t = tile + delta;
|
||||||
TrackBits tracks = GetTrackBits(tile);
|
for (; t != endtile; t += delta) MarkTileDirtyByTile(t); // TODO encapsulate this into a function
|
||||||
while (tracks != TRACK_BIT_NONE) {
|
|
||||||
YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile)));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case MP_TUNNELBRIDGE: {
|
|
||||||
TileIndex endtile = GetOtherTunnelBridgeEnd(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)) {
|
|
||||||
CommandCost ret = TunnelBridgeIsFree(tile, endtile);
|
|
||||||
if (ret.Failed()) {
|
|
||||||
error = ret;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
|
||||||
Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
|
|
||||||
if (HasTunnelBridgeReservation(tile)) {
|
|
||||||
Train *v = GetTrainForReservation(tile, track);
|
|
||||||
if (v != NULL && !HasPowerOnRail(v->railtype, totype)) {
|
|
||||||
/* No power on new rail type, reroute. */
|
|
||||||
FreeTrainTrackReservation(v);
|
|
||||||
*vehicles_affected.Append() = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetRailType(tile, totype);
|
|
||||||
SetRailType(endtile, totype);
|
|
||||||
|
|
||||||
FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
|
|
||||||
FindVehicleOnPos(endtile, &affected_trains, &UpdateTrainPowerProc);
|
|
||||||
|
|
||||||
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((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // MP_STATION, MP_ROAD
|
cost.AddCost((GetTunnelBridgeLength(tile, endtile) + 2) * RailConvertCost(type, totype));
|
||||||
if (flags & DC_EXEC) {
|
break;
|
||||||
Track track = ((tt == MP_STATION) ? GetRailStationTrack(tile) : GetCrossingRailTrack(tile));
|
|
||||||
YapfNotifyTrackLayoutChange(tile, track);
|
|
||||||
}
|
|
||||||
|
|
||||||
cost.AddCost(RailConvertCost(type, totype));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint i = 0; i < vehicles_affected.Length(); ++i) {
|
default: // MP_STATION, MP_ROAD
|
||||||
TryPathReserve(vehicles_affected[i], true);
|
if (flags & DC_EXEC) {
|
||||||
}
|
Track track = ((tt == MP_STATION) ? GetRailStationTrack(tile) : GetCrossingRailTrack(tile));
|
||||||
|
YapfNotifyTrackLayoutChange(tile, track);
|
||||||
|
}
|
||||||
|
|
||||||
|
cost.AddCost(RailConvertCost(type, totype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < vehicles_affected.Length(); ++i) {
|
||||||
|
TryPathReserve(vehicles_affected[i], true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user