Only in work/OTTD-source-nightly-r12366/bin/data: autorun.inf Only in work/OTTD-source-nightly-r12366/bin/data: awe Only in work/OTTD-source-nightly-r12366/bin/data: demo1e.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo1f.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo2e.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo2f.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo3e.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo3f.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo4e.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo4f.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo5e.dat Only in work/OTTD-source-nightly-r12366/bin/data: demo5f.dat Only in work/OTTD-source-nightly-r12366/bin/data: dsetup6e.dll Only in work/OTTD-source-nightly-r12366/bin/data: dsetup6j.dll Only in work/OTTD-source-nightly-r12366/bin/data: dsetup.dll Only in work/OTTD-source-nightly-r12366/bin/data: dsetupe.dll Only in work/OTTD-source-nightly-r12366/bin/data: dsetupj.dll Only in work/OTTD-source-nightly-r12366/bin/data: fm Only in work/OTTD-source-nightly-r12366/bin/data: GameGFX.exe Only in work/OTTD-source-nightly-r12366/bin/data: gm Only in work/OTTD-source-nightly-r12366/bin/data: logo.bmp Only in work/OTTD-source-nightly-r12366/bin/data: mkpttxt.exe Only in work/OTTD-source-nightly-r12366/bin/data: mpssnd_c.dll Only in work/OTTD-source-nightly-r12366/bin/data: opt.dat Only in work/OTTD-source-nightly-r12366/bin/data: sample.cat Only in work/OTTD-source-nightly-r12366/bin/data: setup.bat Only in work/OTTD-source-nightly-r12366/bin/data: slogo.bmp Only in work/OTTD-source-nightly-r12366/bin/data: title.dat Only in work/OTTD-source-nightly-r12366/bin/data: Transport Tycoon Deluxe.exe Only in work/OTTD-source-nightly-r12366/bin/data: trc00.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc01.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc02.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc03.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc04.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc05.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc06.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc07.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc08.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc10.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trc12.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trg1r.grf Only in work/OTTD-source-nightly-r12366/bin/data: trgcr.grf Only in work/OTTD-source-nightly-r12366/bin/data: trghr.grf Only in work/OTTD-source-nightly-r12366/bin/data: trgir.grf Only in work/OTTD-source-nightly-r12366/bin/data: trgtr.grf Only in work/OTTD-source-nightly-r12366/bin/data: trh00.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh00.ss1 Only in work/OTTD-source-nightly-r12366/bin/data: trh01.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh02.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh03.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh04.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh05.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh06.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh07.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trh08.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt00.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt00.ss1 Only in work/OTTD-source-nightly-r12366/bin/data: trt00.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt01.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt02.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt02.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt03.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt03.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt04.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt04.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt05.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt05.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt06.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt06.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt07.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt07.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt08.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt08.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt09.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt10.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: trt10.sv1 Only in work/OTTD-source-nightly-r12366/bin/data: trt11.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try00.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try01.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try02.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try03.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try05.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try06.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try07.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try08.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try09.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: try10.ss0 Only in work/OTTD-source-nightly-r12366/bin/data: TTconfig.EXE Only in work/OTTD-source-nightly-r12366/bin/data: TTDLOADW.OVL Only in work/OTTD-source-nightly-r12366/bin/data: ttdpatch.cfg Only in work/OTTD-source-nightly-r12366/bin/data: TTDX Configurator.exe Only in work/OTTD-source-nightly-r12366/bin/data: UniFISH.exe Only in work/OTTD-source-nightly-r12366/bin: lang Only in work/OTTD-source-nightly-r12366/bin: openttd Only in work/OTTD-source-nightly-r12366: config.cache Only in work/OTTD-source-nightly-r12366: config.cache.source.list Only in work/OTTD-source-nightly-r12366: config.log Only in work/OTTD-source-nightly-r12366: Makefile Only in work/OTTD-source-nightly-r12366: Makefile.am Only in work/OTTD-source-nightly-r12366: objs diff -rup orig/OTTD-source-nightly-r12366/src/rail_cmd.cpp work/OTTD-source-nightly-r12366/src/rail_cmd.cpp --- orig/OTTD-source-nightly-r12366/src/rail_cmd.cpp 2008-03-05 22:11:26.000000000 +1030 +++ work/OTTD-source-nightly-r12366/src/rail_cmd.cpp 2008-03-19 18:58:49.000000000 +1030 @@ -1171,6 +1171,154 @@ void *UpdateTrainPowerProc(Vehicle *v, v return NULL; } +/* Is there a suitable conversion depot at this tile? */ +/* Yes, it's a really simple func at the moment, but who knows what could */ +/* happen to it later. */ +bool IsSecondaryConversionDepotSuitable(TileIndex tile, RailType totype) +{ + return (GetTileType(tile) == MP_RAILWAY) + && (GetRailTileType(tile) == RAIL_TILE_DEPOT) + && (GetRailType(tile) == totype); +} + +/* Search for a suitable secondary depot of the specified type. */ +/* Returns tile if found, or INVALID_TILE if not. */ +/* Does not check the orgin tile, deliberately. */ +TileIndex FindSecondaryDepot(TileIndex origin, uint32 flags, RailType totype) +{ + uint rx = TileX(origin); + uint ry = TileY(origin); + + /* Scan outwards until we find a suitable secondary depot. */ + /* Ideally this would work with some kind of rail distance (ie. */ + /* closest distance by rail), but I don't know how to do that, */ + /* so I'll just scan outwards in a square with an increasing range. */ + uint x = 0; + uint y = 0; + for (int sr=1; sr<=128; sr++) { + for (int oy=-sr; oy<=sr; oy += sr*2) { + int ty = ((int)ry) + oy; + if ((ty < 0) || ((uint)ty >= MapSizeY())) + continue; + y = (uint)ty; + for (int ox=-sr; ox<=sr; ox++) { + int tx = ((int)rx) + ox; + if ((tx < 0) || ((uint)tx >= MapSizeX())) + continue; + x = (uint)tx; + if (IsSecondaryConversionDepotSuitable(TileXY(x, y), totype)) + return TileXY(x, y); + } + } + for (int ox=-sr; ox<=sr; ox += sr*2) { + int tx = ((int)rx) + ox; + x = (uint)tx; + if ((tx < 0) || ((uint)tx >= MapSizeX())) + continue; + for (int oy=-sr+1; oy<=sr-1; oy++) { + int ty = ((int)ry) + oy; + if ((ty < 0) || ((uint)ty >= MapSizeY())) + continue; + y = (uint)ty; + if (IsSecondaryConversionDepotSuitable(TileXY(x, y), totype)) + return TileXY(x, y); + } + } + } + + return INVALID_TILE; +} + +/* Converts all vehicles in a single depot at . */ +/* Returns cost. */ +/* in_place: Perform upgrade in-place, ie. without a secondary depot. */ +CommandCost ConvertAllVehiclesInDepot(TileIndex primary_tile, uint32 flags, RailType totype, bool in_place = true) +{ + /* TODO */ + /* Always fail if patch is not enabled. */ + /* if (!patch-is-enabled) */ + /* return CMD_ERROR; */ + + Vehicle **vl = NULL; + uint16 engine_list_length = 0; + uint16 engine_count = 0; + uint i, x = 0, y = 0, z = 0; + CommandCost cost; + + if (!IsDepotTile(primary_tile) || !IsTileOwner(primary_tile, _current_player)) + return CMD_ERROR; + + /* Get the list of vehicles in the depot */ + BuildDepotVehicleList(VEH_TRAIN, primary_tile, &vl, &engine_list_length, &engine_count, NULL, NULL, NULL); + + /* Fast fail. Don't search for secondary depot if there is nothing to do.*/ + if (engine_count == 0) + return CommandCost(0); /* No cost to convert zero trains! */ + + RailType orig_rail_type = GetRailType(primary_tile); + + TileIndex secondary_tile = primary_tile; + if (!in_place) + secondary_tile = FindSecondaryDepot(primary_tile, flags, totype); + + if (secondary_tile == INVALID_TILE) { + free(vl); + return CMD_ERROR; + } + + uint sx = TileX(secondary_tile); + uint sy = TileY(secondary_tile); + + for (i = 0; i < engine_count; i++) { + Vehicle *v = vl[i]; + bool stopped = (v->vehstatus & VS_STOPPED); + CommandCost ret; + + /* Fail if train not stopped, or not fully in depot. */ + if ((!stopped) || (!v->IsInDepot())) { + free(vl); + return CMD_ERROR; + } + + x = v->x_pos; + y = v->y_pos; + z = v->z_pos; + + if (in_place) { + /* Temporarily change rail type to allow us to build. */ + SetRailType(secondary_tile, totype); + } + + /* Clone the vehicle. */ + ret = DoCommand(secondary_tile, v->index, 0, flags, CMD_CLONE_VEHICLE); + + if (in_place) { + /* Now restore it. */ + SetRailType(secondary_tile, orig_rail_type); + } + + if (CmdSucceeded(ret)) { + cost.AddCost(ret); + } else { + free(vl); + return CMD_ERROR; + } + + /* Sell the old one. */ + ret = DoCommand(primary_tile, v->index, 1, flags, CMD_SELL_RAIL_WAGON); + + if (CmdSucceeded(ret)) { + cost.AddCost(ret); + } else { + free(vl); + return CMD_ERROR; + } + } + + free(vl); + return cost; +} + /** 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 @@ -1230,7 +1378,25 @@ CommandCost CmdConvertRail(TileIndex til /* 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; + + bool depot_upgrade_success = false; + + if ((tt == MP_RAILWAY) && (GetRailTileType(tile) == RAIL_TILE_DEPOT)) { + CommandCost ret = ConvertAllVehiclesInDepot(tile, flags, totype); + /* If we failed, we can't convert the depot. */ + if (CmdSucceeded(ret)) { + depot_upgrade_success = true; + cost.AddCost(ret); + } else { + continue; + } + + /* If we reach here, it is now fine to convert the depot. */ + } + + if (!depot_upgrade_success && !IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile)) + continue; + if (flags & DC_EXEC) { // we can safely convert, too SetRailType(tile, totype); MarkTileDirtyByTile(tile); Only in work/OTTD-source-nightly-r12366/src: rev.cpp diff -rup orig/OTTD-source-nightly-r12366/src/vehicle.cpp work/OTTD-source-nightly-r12366/src/vehicle.cpp --- orig/OTTD-source-nightly-r12366/src/vehicle.cpp 2008-03-05 08:19:40.000000000 +1030 +++ work/OTTD-source-nightly-r12366/src/vehicle.cpp 2008-03-19 18:52:23.000000000 +1030 @@ -1751,6 +1751,60 @@ CommandCost CmdDepotMassAutoReplace(Tile return cost; } +/* Given the specified engine , suggest a suitable replacement if it must run */ +/* on rail type . Assumes player . */ +static EngineID SuggestEngineReplacement(EngineID oe, PlayerID player, RailType totype) +{ + EngineID e; + EngineID best_e = INVALID_ENGINE; + int best_score = 0; + FOR_ALL_ENGINEIDS_OF_TYPE(e, VEH_TRAIN) { + const RailVehicleInfo *rvi = RailVehInfo(e); + const RailVehicleInfo *orvi = RailVehInfo(oe); + /* Wagons for wagons, locos for locos. */ + if ((orvi->railveh_type & RAILVEH_WAGON) != (rvi->railveh_type & RAILVEH_WAGON)) + continue; + /* The engine must be suitable for the new type. */ + if (!IsCompatibleRail(rvi->railtype, totype)) + continue; + /* And being able to move is definitely a plus. */ + if (!HasPowerOnRail(rvi->railtype, totype)) + continue; + /* Must be allowed to build it. */ + if (!IsEngineBuildable(e, VEH_TRAIN, player)) + continue; + + /* Give preference to the fastest locos, and greatest capacity wagons. */ + int score = (rvi->railveh_type & RAILVEH_WAGON) ? rvi->capacity : rvi->max_speed; + + /* If old has a cargo type, the new one should as well. */ + if ((orvi->cargo_type != CT_INVALID) && (orvi->cargo_type != rvi->cargo_type)) { + /* If it's a wagon, fail right now. */ + if (orvi->railveh_type & RAILVEH_WAGON) + continue; + /* Otherwise we've got a loco with the wrong cargo type. */ + /* Punish the score somewhat, because we'd rather have a */ + /* matching one. */ + score = score / 4; + } + + /* We have a candidate. */ + if (best_e == INVALID_ENGINE) { + best_e = e; + best_score = score; + } else if (score > best_score) { + best_score = score; + best_e = e; + } + } + + if (best_e != INVALID_ENGINE) { + return best_e; + } + + return INVALID_RAILTYPE; +} + /** Clone a vehicle. If it is a train, it will clone all the cars too * @param tile tile of the depot where the cloned vehicle is build * @param flags type of operation @@ -1771,7 +1825,11 @@ CommandCost CmdCloneVehicle(TileIndex ti w_front = NULL; w_rear = NULL; - + /* If not INVALID_RAILTYPE, specifies the new rail type that we intend to use. */ + RailType new_rail_type = INVALID_RAILTYPE; + /* Set to true if we have or intend to change any engines whilst cloning. */ + bool changed_engines = false; + /* * v_front is the front engine in the original vehicle * v is the car/vehicle of the original vehicle, that is currently being copied @@ -1784,6 +1842,15 @@ CommandCost CmdCloneVehicle(TileIndex ti if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR; + if ((v->type == VEH_TRAIN)) { + RailType v_rail_type = RailVehInfo(v->engine_type)->railtype; + RailType w_rail_type = GetRailType(tile); + if (v_rail_type != w_rail_type) { + new_rail_type = w_rail_type; + changed_engines = true; + } + } + /* check that we can allocate enough vehicles */ if (!(flags & DC_EXEC)) { int veh_counter = 0; @@ -1804,7 +1871,13 @@ CommandCost CmdCloneVehicle(TileIndex ti continue; } - cost = DoCommand(tile, v->engine_type, build_argument, flags, GetCmdBuildVeh(v)); + EngineID new_engine_type = v->engine_type; + + /* If we are building for a new rail type, suggest a replacement. */ + if (new_rail_type != INVALID_RAILTYPE) + new_engine_type = SuggestEngineReplacement(new_engine_type, _current_player, new_rail_type); + + cost = DoCommand(tile, new_engine_type, build_argument, flags, GetCmdBuildVeh(v)); build_argument = 3; // ensure that we only assign a number to the first engine if (CmdFailed(cost)) return cost; @@ -1819,7 +1892,7 @@ CommandCost CmdCloneVehicle(TileIndex ti } if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { - /* this s a train car + /* this is a train car * add this unit to the end of the train */ CommandCost result = DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE); if (CmdFailed(result)) { @@ -1862,6 +1935,13 @@ CommandCost CmdCloneVehicle(TileIndex ti do { do { if (flags & DC_EXEC) { + + /* If we've changed engines at all, the new train may be shorter. */ + /* eg. if we go from a dual- to single-head loco. */ + /* if ((changed_engines) && (w == NULL)) */ + if (w == NULL) + break; + assert(w != NULL); if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) { @@ -1893,6 +1973,10 @@ CommandCost CmdCloneVehicle(TileIndex ti } } while (v != NULL); + /* If we've changed engines at all, the new train may be shorter. */ + if (w == NULL) + break; + if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w); } while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL); diff -rup orig/OTTD-source-nightly-r12366/src/vehicle_func.h work/OTTD-source-nightly-r12366/src/vehicle_func.h --- orig/OTTD-source-nightly-r12366/src/vehicle_func.h 2008-01-18 23:32:47.000000000 +1030 +++ work/OTTD-source-nightly-r12366/src/vehicle_func.h 2008-03-16 16:33:16.000000000 +1030 @@ -12,6 +12,7 @@ #include "cargo_type.h" #include "command_type.h" #include "vehicle_type.h" +#include "rail_type.h" #define is_custom_sprite(x) (x >= 0xFD) #define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD)