diff --git a/regression/regression/main.nut b/regression/regression/main.nut index 7621c49c6f..f6fe45cc2e 100644 --- a/regression/regression/main.nut +++ b/regression/regression/main.nut @@ -1107,6 +1107,7 @@ function Regression::Rail() print(" IsRailTile(): " + AIRail.IsRailTile(33411)); print(" BuildRailDepot(): " + AIRail.BuildRailDepot(0, 1)); print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33411)); + print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33410)); print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33414)); print(" BuildRailDepot(): " + AIRail.BuildRailDepot(33411, 33412)); print(" GetRailDepotFrontTile(): " + AIRail.GetRailDepotFrontTile(33411)); @@ -1203,6 +1204,7 @@ function Regression::Road() print(" IsRoadTile(): " + AIRoad.IsRoadTile(33411)); print(" BuildRoadDepot(): " + AIRoad.BuildRoadDepot(0, 1)); print(" BuildRoadDepot(): " + AIRoad.BuildRoadDepot(33411, 33411)); + print(" BuildRoadDepot(): " + AIRoad.BuildRoadDepot(33411, 33410)); print(" BuildRoadDepot(): " + AIRoad.BuildRoadDepot(33411, 33414)); print(" BuildRoadDepot(): " + AIRoad.BuildRoadDepot(33411, 33412)); print(" HasRoadType(Road): " + AIRoad.HasRoadType(33411, AIRoad.ROADTYPE_ROAD)); diff --git a/regression/regression/result.txt b/regression/regression/result.txt index 3dd8b60746..59ecd46fb0 100644 --- a/regression/regression/result.txt +++ b/regression/regression/result.txt @@ -7498,6 +7498,7 @@ ERROR: IsEnd() is invalid as Begin() is never called BuildRailDepot(): false BuildRailDepot(): false BuildRailDepot(): true + BuildRailDepot(): true BuildRailDepot(): false GetRailDepotFrontTile(): 33412 IsBuildable(): false @@ -7591,11 +7592,12 @@ ERROR: IsEnd() is invalid as Begin() is never called BuildRoadDepot(): false BuildRoadDepot(): false BuildRoadDepot(): true + BuildRoadDepot(): true BuildRoadDepot(): false HasRoadType(Road): true HasRoadType(Tram): false - GetLastError(): 260 - GetLastErrorString(): ERR_AREA_NOT_CLEAR + GetLastError(): 259 + GetLastErrorString(): ERR_ALREADY_BUILT GetErrorCategory(): 1 IsRoadTile(): false GetRoadDepotFrontTile(): 33412 @@ -9311,7 +9313,7 @@ ERROR: IsEnd() is invalid as Begin() is never called IsStoppedInDepot(): false --Accounting-- GetCosts(): -5947 - Should be: -5947 + Should be: -5946 GetName(): Road Vehicle #1 SetName(): true GetName(): MyVehicleName @@ -9408,11 +9410,11 @@ ERROR: IsEnd() is invalid as Begin() is never called 14 => 1 12 => 1 Age ListDump: - 14 => 1 - 13 => 1 12 => 1 17 => 0 16 => 0 + 14 => 0 + 13 => 0 MaxAge ListDump: 16 => 10980 14 => 10980 @@ -9421,9 +9423,9 @@ ERROR: IsEnd() is invalid as Begin() is never called 12 => 5490 AgeLeft ListDump: 16 => 10980 - 14 => 10979 + 14 => 10980 17 => 7320 - 13 => 5489 + 13 => 5490 12 => 5489 CurrentSpeed ListDump: 12 => 27 diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index eee3856a24..7e1ec01ee3 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -989,24 +989,44 @@ CommandCost CmdBuildTrainDepot(DoCommandFlag flags, TileIndex tile, RailType rai cost.AddCost(_price[PR_BUILD_FOUNDATION]); } - cost.AddCost(Command::Do(flags, tile)); - if (cost.Failed()) return cost; + /* Allow the user to rotate the depot instead of having to destroy it and build it again */ + bool rotate_existing_depot = false; + if (IsRailDepotTile(tile) && railtype == GetRailType(tile)) { + CommandCost ret = CheckTileOwnership(tile); + if (ret.Failed()) return ret; + + if (dir == GetRailDepotDirection(tile)) return_cmd_error(STR_ERROR_ALREADY_BUILT); + + ret = EnsureNoVehicleOnGround(tile); + if (ret.Failed()) return ret; + + rotate_existing_depot = true; + } - if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (!rotate_existing_depot) { + cost.AddCost(Command::Do(flags, tile)); + if (cost.Failed()) return cost; - if (!Depot::CanAllocateItem()) return CMD_ERROR; + if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + + if (!Depot::CanAllocateItem()) return CMD_ERROR; + } if (flags & DC_EXEC) { - Depot *d = new Depot(tile); - d->build_date = TimerGameCalendar::date; + if (rotate_existing_depot) { + SetRailDepotExitDirection(tile, dir); + } else { + Depot *d = new Depot(tile); + d->build_date = TimerGameCalendar::date; - MakeRailDepot(tile, _current_company, d->index, dir, railtype); - MarkTileDirtyByTile(tile); - MakeDefaultName(d); + MakeRailDepot(tile, _current_company, d->index, dir, railtype); + MakeDefaultName(d); - Company::Get(_current_company)->infrastructure.rail[railtype]++; - DirtyCompanyInfrastructureWindows(_current_company); + Company::Get(_current_company)->infrastructure.rail[railtype]++; + DirtyCompanyInfrastructureWindows(_current_company); + } + MarkTileDirtyByTile(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company); YapfNotifyTrackLayoutChange(tile, DiagDirToDiagTrack(dir)); } diff --git a/src/rail_map.h b/src/rail_map.h index 25f61339eb..0626eb47cb 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -530,19 +530,37 @@ static inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r) t.m8() = r; } +/** + * Sets the exit direction of a rail depot. + * @param tile Tile of the depot. + * @param dir Direction of the depot exit. + */ +static inline void SetRailDepotExitDirection(Tile tile, DiagDirection dir) +{ + assert(IsRailDepotTile(tile)); + SB(tile.m5(), 0, 2, dir); +} -static inline void MakeRailDepot(Tile t, Owner o, DepotID did, DiagDirection d, RailType r) +/** + * Make a rail depot. + * @param tile Tile to make a depot on. + * @param owner New owner of the depot. + * @param depot_id New depot ID. + * @param dir Direction of the depot exit. + * @param rail_type Rail type of the depot. + */ +static inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RailType rail_type) { - SetTileType(t, MP_RAILWAY); - SetTileOwner(t, o); - SetDockingTile(t, false); - t.m2() = did; - t.m3() = 0; - t.m4() = 0; - t.m5() = RAIL_TILE_DEPOT << 6 | d; - SB(t.m6(), 2, 4, 0); - t.m7() = 0; - t.m8() = r; + SetTileType(tile, MP_RAILWAY); + SetTileOwner(tile, owner); + SetDockingTile(tile, false); + tile.m2() = depot_id; + tile.m3() = 0; + tile.m4() = 0; + tile.m5() = RAIL_TILE_DEPOT << 6 | dir; + SB(tile.m6(), 2, 4, 0); + tile.m7() = 0; + tile.m8() = rail_type; } #endif /* RAIL_MAP_H */ diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index b7049ebac4..3802f884e3 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1163,24 +1163,46 @@ CommandCost CmdBuildRoadDepot(DoCommandFlag flags, TileIndex tile, RoadType rt, cost.AddCost(_price[PR_BUILD_FOUNDATION]); } - cost.AddCost(Command::Do(flags, tile)); - if (cost.Failed()) return cost; + /* Allow the user to rotate the depot instead of having to destroy it and build it again */ + bool rotate_existing_depot = false; + if (IsRoadDepotTile(tile) && (HasRoadTypeTram(tile) ? rt == GetRoadTypeTram(tile) : rt == GetRoadTypeRoad(tile))) + { + CommandCost ret = CheckTileOwnership(tile); + if (ret.Failed()) return ret; - if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + if (dir == GetRoadDepotDirection(tile)) return_cmd_error(STR_ERROR_ALREADY_BUILT); - if (!Depot::CanAllocateItem()) return CMD_ERROR; + ret = EnsureNoVehicleOnGround(tile); + if (ret.Failed()) return ret; + + rotate_existing_depot = true; + } + + if (!rotate_existing_depot) { + cost.AddCost(Command::Do(flags, tile)); + if (cost.Failed()) return cost; + + if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + + if (!Depot::CanAllocateItem()) return CMD_ERROR; + } if (flags & DC_EXEC) { - Depot *dep = new Depot(tile); - dep->build_date = TimerGameCalendar::date; + if (rotate_existing_depot) { + SetRoadDepotExitDirection(tile, dir); + } else { + Depot *dep = new Depot(tile); + dep->build_date = TimerGameCalendar::date; + MakeRoadDepot(tile, _current_company, dep->index, dir, rt); + MakeDefaultName(dep); + } + + MarkTileDirtyByTile(tile); /* A road depot has two road bits. */ UpdateCompanyRoadInfrastructure(rt, _current_company, ROAD_DEPOT_TRACKBIT_FACTOR); - - MakeRoadDepot(tile, _current_company, dep->index, dir, rt); - MarkTileDirtyByTile(tile); - MakeDefaultName(dep); } + cost.AddCost(_price[PR_BUILD_DEPOT_ROAD]); return cost; } diff --git a/src/road_map.h b/src/road_map.h index 2b95993aa7..51882189ed 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -673,26 +673,37 @@ static inline void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, } /** - * Make a road depot. - * @param t Tile to make a level crossing. - * @param owner New owner of the depot. - * @param did New depot ID. - * @param dir Direction of the depot exit.* - * @param rt Road type of the depot. + * Sets the exit direction of a road depot. + * @param tile Tile of the depot. + * @param dir Direction of the depot exit. */ -static inline void MakeRoadDepot(Tile t, Owner owner, DepotID did, DiagDirection dir, RoadType rt) +static inline void SetRoadDepotExitDirection(Tile tile, DiagDirection dir) { - SetTileType(t, MP_ROAD); - SetTileOwner(t, owner); - t.m2() = did; - t.m3() = 0; - t.m4() = INVALID_ROADTYPE; - t.m5() = ROAD_TILE_DEPOT << 6 | dir; - SB(t.m6(), 2, 4, 0); - t.m7() = owner; - t.m8() = INVALID_ROADTYPE << 6; - SetRoadType(t, GetRoadTramType(rt), rt); - SetRoadOwner(t, RTT_TRAM, owner); + assert(IsRoadDepotTile(tile)); + SB(tile.m5(), 0, 2, dir); +} + +/** + * Make a road depot. + * @param tile Tile to make a depot on. + * @param owner New owner of the depot. + * @param depot_id New depot ID. + * @param dir Direction of the depot exit. + * @param rail_type Road type of the depot. + */ +static inline void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RoadType rail_type) +{ + SetTileType(tile, MP_ROAD); + SetTileOwner(tile, owner); + tile.m2() = depot_id; + tile.m3() = 0; + tile.m4() = INVALID_ROADTYPE; + tile.m5() = ROAD_TILE_DEPOT << 6 | dir; + SB(tile.m6(), 2, 4, 0); + tile.m7() = owner; + tile.m8() = INVALID_ROADTYPE << 6; + SetRoadType(tile, GetRoadTramType(rail_type), rail_type); + SetRoadOwner(tile, RTT_TRAM, owner); } #endif /* ROAD_MAP_H */