Changeset - r15811:b2ad31854a1f
[Not reviewed]
master
0 1 0
frosch - 14 years ago 2010-08-15 15:47:07
frosch@openttd.org
(svn r20500) -Fix: When converting rail all trains with a part on the converted rails need updating. Not only engines, which have power afterwards. Also update Acceleration after updating Power.
1 file changed with 19 insertions and 10 deletions:
0 comments (0 inline, 0 general)
src/rail_cmd.cpp
Show inline comments
 
@@ -34,24 +34,27 @@
 
#include "elrail_func.h"
 
#include "town.h"
 
#include "pbs.h"
 
#include "company_base.h"
 
#include "core/backup_type.hpp"
 
#include "date_func.h"
 

	
 
#include "table/strings.h"
 
#include "table/sprites.h"
 
#include "table/railtypes.h"
 
#include "table/track_land.h"
 

	
 
/** Helper type for lists/vectors of trains */
 
typedef SmallVector<Train *, 16> TrainList;
 

	
 
RailtypeInfo _railtypes[RAILTYPE_END];
 

	
 
assert_compile(sizeof(_original_railtypes) <= sizeof(_railtypes));
 

	
 
/**
 
 * Initialize rail type information.
 
 */
 
void ResetRailTypes()
 
{
 
	memset(_railtypes, 0, sizeof(_railtypes));
 
	memcpy(_railtypes, _original_railtypes, sizeof(_original_railtypes));
 
}
 
@@ -1369,30 +1372,26 @@ CommandCost CmdRemoveSingleSignal(TileIn
 
 */
 
CommandCost CmdRemoveSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	return CmdSignalTrackHelper(tile, flags, p1, SetBit(p2, 5), text); // bit 5 is remove bit
 
}
 

	
 
/** Update power of train under which is the railtype being converted */
 
static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data)
 
{
 
	if (v->type != VEH_TRAIN) return NULL;
 

	
 
	/* Similar checks as in Train::PowerChanged() */
 

	
 
	Train *t = Train::From(v);
 
	if (t->IsArticulatedPart()) return NULL;
 

	
 
	const RailVehicleInfo *rvi = RailVehInfo(t->engine_type);
 
	if (GetVehicleProperty(t, PROP_TRAIN_POWER, rvi->power) != 0) t->First()->PowerChanged();
 
	TrainList *affected_trains = static_cast<TrainList*>(data);
 
	affected_trains->Include(Train::From(v)->First());
 

	
 
	return NULL;
 
}
 

	
 
/**
 
 * 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
 
 * @param flags operation to perform
 
 * @param p1 start tile of drag
 
 * @param p2 new railtype to convert to
 
 * @param text unused
 
@@ -1405,24 +1404,26 @@ CommandCost CmdConvertRail(TileIndex til
 
	if (!ValParamRailtype(totype)) 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;
 

	
 
	CommandCost cost(EXPENSES_CONSTRUCTION);
 
	CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert.
 
	for (uint x = sx; x <= ex; ++x) {
 
		for (uint y = sy; y <= ey; ++y) {
 
			TileIndex tile = TileXY(x, y);
 
			TileType tt = GetTileType(tile);
 

	
 
			/* Check if there is any track on tile */
 
			switch (tt) {
 
				case MP_RAILWAY:
 
					break;
 
				case MP_STATION:
 
@@ -1471,26 +1472,26 @@ CommandCost CmdConvertRail(TileIndex til
 
					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;
 
						}
 
					}
 

	
 
					SetRailType(tile, totype);
 
					MarkTileDirtyByTile(tile);
 
					/* update power of train engines on this tile */
 
					FindVehicleOnPos(tile, NULL, &UpdateTrainPowerProc);
 
					/* update power of train on this tile */
 
					FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc);
 
				}
 
			}
 

	
 
			switch (tt) {
 
				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));
 

	
 
								/* Update build vehicle window related to this depot */
 
@@ -1534,26 +1535,26 @@ CommandCost CmdConvertRail(TileIndex til
 
						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, NULL, &UpdateTrainPowerProc);
 
						FindVehicleOnPos(endtile, NULL, &UpdateTrainPowerProc);
 
						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
 
						}
 
@@ -1570,24 +1571,32 @@ CommandCost CmdConvertRail(TileIndex til
 
					}
 

	
 
					cost.AddCost(RailConvertCost(type, totype));
 
					break;
 
			}
 

	
 
			for (uint i = 0; i < vehicles_affected.Length(); ++i) {
 
				TryPathReserve(vehicles_affected[i], true);
 
			}
 
		}
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		/* Railtype changed, update trains as when entering different track */
 
		for (Train **v = affected_trains.Begin(); v != affected_trains.End(); v++) {
 
			(*v)->PowerChanged();
 
			(*v)->UpdateAcceleration();
 
		}
 
	}
 

	
 
	return (cost.GetCost() == 0) ? error : cost;
 
}
 

	
 
static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlag flags)
 
{
 
	if (_current_company != OWNER_WATER) {
 
		CommandCost ret = CheckTileOwnership(tile);
 
		if (ret.Failed()) return ret;
 
	}
 

	
 
	CommandCost ret = EnsureNoVehicleOnGround(tile);
 
	if (ret.Failed()) return ret;
0 comments (0 inline, 0 general)