mirror of https://github.com/OpenTTD/OpenTTD
Change: Buying and controlling road vehicles in extended road depots.
parent
861de832f6
commit
158c46fcd6
|
@ -5378,6 +5378,7 @@ STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a
|
||||||
STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger...
|
STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger...
|
||||||
STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train...
|
STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train...
|
||||||
STR_ERROR_TRAIN_START_NO_POWER :Train has no power
|
STR_ERROR_TRAIN_START_NO_POWER :Train has no power
|
||||||
|
STR_ERROR_ROAD_VEHICLE_START_NO_POWER :Road vehicle has no power
|
||||||
|
|
||||||
STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Can't make road vehicle turn around...
|
STR_ERROR_CAN_T_MAKE_ROAD_VEHICLE_TURN :{WHITE}Can't make road vehicle turn around...
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "road_cmd.h"
|
#include "road_cmd.h"
|
||||||
#include "landscape_cmd.h"
|
#include "landscape_cmd.h"
|
||||||
#include "rail_cmd.h"
|
#include "rail_cmd.h"
|
||||||
|
#include "platform_func.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "table/roadtypes.h"
|
#include "table/roadtypes.h"
|
||||||
|
@ -2476,10 +2477,40 @@ static const uint8_t _roadveh_enter_depot_dir[4] = {
|
||||||
TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE
|
TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE
|
||||||
};
|
};
|
||||||
|
|
||||||
static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int, int)
|
static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y)
|
||||||
{
|
{
|
||||||
if (GetRoadTileType(tile) != ROAD_TILE_DEPOT || v->type != VEH_ROAD) return VETSB_CONTINUE;
|
if (GetRoadTileType(tile) != ROAD_TILE_DEPOT || v->type != VEH_ROAD) return VETSB_CONTINUE;
|
||||||
|
|
||||||
|
if (IsExtendedRoadDepot(tile)) {
|
||||||
|
v = v->First();
|
||||||
|
if (!IsExtendedRoadDepotTile(v->tile)) return VETSB_CONTINUE;
|
||||||
|
DepotID depot_id = GetDepotIndex(v->tile);
|
||||||
|
if (!v->current_order.IsType(OT_GOTO_DEPOT) ||
|
||||||
|
v->current_order.GetDestination() != depot_id) {
|
||||||
|
return VETSB_CONTINUE;
|
||||||
|
}
|
||||||
|
for (Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||||
|
if (!IsExtendedRoadDepotTile(u->tile) || GetDepotIndex(u->tile) != depot_id) return VETSB_CONTINUE;
|
||||||
|
if (!IsDiagonalDirection(u->direction)) return VETSB_CONTINUE;
|
||||||
|
if (DiagDirToAxis(DirToDiagDir(u->direction)) !=
|
||||||
|
DiagDirToAxis(GetRoadDepotDirection(v->tile))) {
|
||||||
|
return VETSB_CONTINUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop position on platform is half the front vehicle length of the road vehicle. */
|
||||||
|
int stop_pos = RoadVehicle::From(v)->gcache.cached_veh_length / 2;
|
||||||
|
DiagDirection dir = DirToDiagDir(v->direction);
|
||||||
|
int depot_ahead = (GetPlatformLength(tile, dir, GetRoadTramType(RoadVehicle::From(v)->roadtype)) - 1) * TILE_SIZE;
|
||||||
|
if (depot_ahead > stop_pos) return VETSB_CONTINUE;
|
||||||
|
|
||||||
|
x = v->x_pos & 0xF;
|
||||||
|
y = v->y_pos & 0xF;
|
||||||
|
|
||||||
|
if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
|
||||||
|
if (dir == DIAGDIR_SE || dir == DIAGDIR_SW) x = TILE_SIZE - x;
|
||||||
|
if (abs(stop_pos - x) <= 1) return VETSB_ENTERED_DEPOT_PLATFORM;
|
||||||
|
} else {
|
||||||
RoadVehicle *rv = RoadVehicle::From(v);
|
RoadVehicle *rv = RoadVehicle::From(v);
|
||||||
if (rv->frame == RVC_DEPOT_STOP_FRAME &&
|
if (rv->frame == RVC_DEPOT_STOP_FRAME &&
|
||||||
_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == rv->state) {
|
_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == rv->state) {
|
||||||
|
@ -2488,10 +2519,10 @@ static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int,
|
||||||
rv->direction = ReverseDir(rv->direction);
|
rv->direction = ReverseDir(rv->direction);
|
||||||
if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
|
if (rv->Next() == nullptr) VehicleEnterDepot(rv->First());
|
||||||
rv->tile = tile;
|
rv->tile = tile;
|
||||||
|
|
||||||
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(rv->tile));
|
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(rv->tile));
|
||||||
return VETSB_ENTERED_WORMHOLE;
|
return VETSB_ENTERED_WORMHOLE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return VETSB_CONTINUE;
|
return VETSB_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,11 +254,12 @@ void RoadVehUpdateCache(RoadVehicle *v, bool same_length)
|
||||||
/**
|
/**
|
||||||
* Find an adequate tile for placing an engine.
|
* Find an adequate tile for placing an engine.
|
||||||
* @param[in,out] tile A tile of the depot.
|
* @param[in,out] tile A tile of the depot.
|
||||||
|
* @param[in,out] is_exit_facing_south Whether the depot tile is facing south.
|
||||||
* @param e Engine to be built.
|
* @param e Engine to be built.
|
||||||
* @param flags Flags of the command.
|
* @param already_built Whether the vehicle already exists (for vehicle replacement).
|
||||||
* @return CommandCost() or an error message if the depot is not appropriate.
|
* @return CommandCost() or an error message if the depot has no appropriate tiles.
|
||||||
*/
|
*/
|
||||||
CommandCost FindDepotTileForPlacingEngine(TileIndex &tile, const Engine *e, DoCommandFlag flags)
|
CommandCost FindDepotTileForPlacingEngine(TileIndex &tile, bool &is_exit_facing_south, const Engine *e, bool already_built)
|
||||||
{
|
{
|
||||||
assert(IsRoadDepotTile(tile));
|
assert(IsRoadDepotTile(tile));
|
||||||
|
|
||||||
|
@ -269,22 +270,42 @@ CommandCost FindDepotTileForPlacingEngine(TileIndex &tile, const Engine *e, DoCo
|
||||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||||
if ((dep->r_types.road_types & rti->powered_roadtypes) == 0) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
|
if ((dep->r_types.road_types & rti->powered_roadtypes) == 0) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
|
||||||
|
|
||||||
/* Use same tile if possible when replacing. */
|
/* Use same tile if possible when replacing or trying to leave the depot. */
|
||||||
if (flags & DC_AUTOREPLACE) {
|
if (HasTileAnyRoadType(tile, rti->powered_roadtypes) && already_built) return CommandCost();
|
||||||
/* Use same tile if possible when replacing. */
|
|
||||||
if (HasTileAnyRoadType(tile, rti->powered_roadtypes)) return CommandCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
tile = INVALID_TILE;
|
for (auto t : dep->depot_tiles) {
|
||||||
for (auto &depot_tile : dep->depot_tiles) {
|
if (!HasTileAnyRoadType(t, rti->powered_roadtypes)) continue;
|
||||||
if (!HasTileAnyRoadType(depot_tile, rti->powered_roadtypes)) continue;
|
if (!IsExtendedDepot(t)) return CommandCost();
|
||||||
tile = depot_tile;
|
if (GetDepotReservation(t, is_exit_facing_south) == DEPOT_RESERVATION_EMPTY) {
|
||||||
break;
|
tile = t;
|
||||||
}
|
return CommandCost();
|
||||||
|
} else if (GetDepotReservation(t, !is_exit_facing_south) == DEPOT_RESERVATION_EMPTY) {
|
||||||
assert(tile != INVALID_TILE);
|
is_exit_facing_south = !is_exit_facing_south;
|
||||||
|
tile = t;
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_cmd_error(STR_ERROR_DEPOT_FULL_DEPOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiagDirection GetRoadDepotExit(TileIndex tile, RoadTramType rtt, DiagDirection dir)
|
||||||
|
{
|
||||||
|
assert(IsRoadDepot(tile));
|
||||||
|
RoadBits rb = GetRoadBits(tile, rtt);
|
||||||
|
if ((rb & DiagDirToRoadBits(dir)) != ROAD_NONE) return dir;
|
||||||
|
if (rb & ROAD_SE) return DIAGDIR_SE;
|
||||||
|
if (rb & ROAD_SW) return DIAGDIR_SW;
|
||||||
|
if (rb & ROAD_NE) return DIAGDIR_NE;
|
||||||
|
if (rb & ROAD_NW) return DIAGDIR_NW;
|
||||||
|
return INVALID_DIAGDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RoadDriveEntry {
|
||||||
|
uint8_t x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "table/roadveh_movement.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a road vehicle.
|
* Build a road vehicle.
|
||||||
|
@ -299,24 +320,36 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
|
||||||
assert(IsRoadDepotTile(tile));
|
assert(IsRoadDepotTile(tile));
|
||||||
RoadType rt = e->u.road.roadtype;
|
RoadType rt = e->u.road.roadtype;
|
||||||
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||||
|
DiagDirection dir = GetRoadDepotExit(tile, RoadTramType(rt), GetRoadDepotDirection(tile));
|
||||||
|
bool facing_south = IsValidDiagDirection(dir) ? IsDiagDirFacingSouth(dir) : false;
|
||||||
|
|
||||||
CommandCost check = FindDepotTileForPlacingEngine(tile, e, flags);
|
if ((flags & DC_AUTOREPLACE) == 0) {
|
||||||
|
CommandCost check = FindDepotTileForPlacingEngine(tile, facing_south, e, false);
|
||||||
if (check.Failed()) return check;
|
if (check.Failed()) return check;
|
||||||
|
dir = GetRoadDepotExit(tile, RoadTramType(rt), GetRoadDepotDirection(tile));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsExtendedRoadDepotTile(tile) && facing_south != IsDiagDirFacingSouth(dir)) dir = ReverseDiagDir(dir);
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
const RoadVehicleInfo *rvi = &e->u.road;
|
const RoadVehicleInfo *rvi = &e->u.road;
|
||||||
|
|
||||||
RoadVehicle *v = new RoadVehicle();
|
RoadVehicle *v = new RoadVehicle();
|
||||||
*ret = v;
|
*ret = v;
|
||||||
v->direction = DiagDirToDir(GetRoadDepotDirection(tile));
|
v->direction = DiagDirToDir(dir);
|
||||||
v->owner = _current_company;
|
v->owner = _current_company;
|
||||||
|
|
||||||
v->tile = tile;
|
v->tile = tile;
|
||||||
int x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
|
if (IsExtendedRoadDepotTile(tile)) {
|
||||||
int y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
|
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(rt)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + DiagDirToDiagTrackdir(dir)];
|
||||||
v->x_pos = x;
|
v->frame = RVC_DEPOT_START_FRAME;
|
||||||
v->y_pos = y;
|
v->x_pos = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
|
||||||
v->z_pos = GetSlopePixelZ(x, y, true);
|
v->y_pos = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
|
||||||
|
} else {
|
||||||
|
v->x_pos = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
|
||||||
|
v->y_pos = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
|
||||||
|
}
|
||||||
|
v->z_pos = GetSlopePixelZ(v->x_pos, v->y_pos, true);
|
||||||
|
|
||||||
v->state = RVSB_IN_DEPOT;
|
v->state = RVSB_IN_DEPOT;
|
||||||
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
|
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
|
||||||
|
@ -360,6 +393,7 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
|
||||||
for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
|
for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
|
||||||
u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
|
u->cargo_cap = u->GetEngine()->DetermineCapacity(u);
|
||||||
u->refit_cap = 0;
|
u->refit_cap = 0;
|
||||||
|
u->state = RVSB_IN_DEPOT;
|
||||||
v->InvalidateNewGRFCache();
|
v->InvalidateNewGRFCache();
|
||||||
u->InvalidateNewGRFCache();
|
u->InvalidateNewGRFCache();
|
||||||
}
|
}
|
||||||
|
@ -369,6 +403,12 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engin
|
||||||
|
|
||||||
v->UpdatePosition();
|
v->UpdatePosition();
|
||||||
|
|
||||||
|
if (IsExtendedDepot(v->tile) && (flags & DC_AUTOREPLACE) == 0) {
|
||||||
|
v->vehstatus &= ~VS_HIDDEN;
|
||||||
|
UpdateExtendedDepotReservation(v, true);
|
||||||
|
v->UpdateViewport(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
CheckConsistencyOfArticulatedVehicle(v);
|
CheckConsistencyOfArticulatedVehicle(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +694,7 @@ struct RoadVehFindData {
|
||||||
|
|
||||||
static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
if (v->type != VEH_ROAD || v->IsInDepot()) return nullptr;
|
if (v->type != VEH_ROAD || (v->vehstatus & VS_HIDDEN) == 0) return nullptr;
|
||||||
|
|
||||||
RoadVehFindData *rvf = (RoadVehFindData*)data;
|
RoadVehFindData *rvf = (RoadVehFindData*)data;
|
||||||
|
|
||||||
|
@ -843,7 +883,7 @@ static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
|
||||||
{
|
{
|
||||||
const OvertakeData *od = (OvertakeData*)data;
|
const OvertakeData *od = (OvertakeData*)data;
|
||||||
|
|
||||||
return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v) ? v : nullptr;
|
return (v->type == VEH_ROAD && v->First() == v && v != od->u && v != od->v && ((v->vehstatus & VS_HIDDEN) == 0)) ? v : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -880,6 +920,9 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||||
/* Don't overtake in stations */
|
/* Don't overtake in stations */
|
||||||
if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
|
if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
|
||||||
|
|
||||||
|
/* Don't overtake in road depot platforms. */
|
||||||
|
if (IsExtendedRoadDepotTile(v->tile)) return;
|
||||||
|
|
||||||
/* For now, articulated road vehicles can't overtake anything. */
|
/* For now, articulated road vehicles can't overtake anything. */
|
||||||
if (v->HasArticulatedPart()) return;
|
if (v->HasArticulatedPart()) return;
|
||||||
|
|
||||||
|
@ -961,9 +1004,17 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
|
||||||
TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
|
TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
|
||||||
|
|
||||||
if (IsTileType(tile, MP_ROAD)) {
|
if (IsTileType(tile, MP_ROAD)) {
|
||||||
if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) {
|
if (IsRoadDepot(tile)) {
|
||||||
/* Road depot owned by another company or with the wrong orientation */
|
if (!IsTileOwner(tile, v->owner)) {
|
||||||
trackdirs = TRACKDIR_BIT_NONE;
|
trackdirs = TRACKDIR_BIT_NONE;
|
||||||
|
} else if (IsExtendedRoadDepotTile(tile)) {
|
||||||
|
if (tile != v->tile) {
|
||||||
|
RoadBits rb = GetRoadBits(tile, GetRoadTramType(v->roadtype)) & DiagDirToRoadBits(ReverseDiagDir(enterdir));
|
||||||
|
if (rb == ROAD_NONE) trackdirs = TRACKDIR_BIT_NONE;
|
||||||
|
}
|
||||||
|
} else if (GetRoadDepotDirection(tile) == enterdir) { // Standard depot
|
||||||
|
trackdirs = TRACKDIR_BIT_NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (IsTileType(tile, MP_STATION) && IsBayRoadStopTile(tile)) {
|
} else if (IsTileType(tile, MP_STATION) && IsBayRoadStopTile(tile)) {
|
||||||
/* Standard road stop (drive-through stops are treated as normal road) */
|
/* Standard road stop (drive-through stops are treated as normal road) */
|
||||||
|
@ -1065,60 +1116,118 @@ found_best_track:;
|
||||||
return best_track;
|
return best_track;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RoadDriveEntry {
|
void HandleRoadVehicleEnterDepot(RoadVehicle *v)
|
||||||
uint8_t x, y;
|
{
|
||||||
};
|
assert(IsRoadDepotTile(v->tile));
|
||||||
|
|
||||||
#include "table/roadveh_movement.h"
|
if (IsExtendedRoadDepot(v->tile)) {
|
||||||
|
assert(v == v->First());
|
||||||
|
for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
|
||||||
|
assert(u->direction == v->direction);
|
||||||
|
assert(IsExtendedRoadDepotTile(u->tile));
|
||||||
|
assert(GetDepotIndex(u->tile) == GetDepotIndex(v->tile));
|
||||||
|
u->state = RVSB_IN_DEPOT;
|
||||||
|
u->cur_speed = 0;
|
||||||
|
u->UpdateViewport(true, true); // revise: probably unneded
|
||||||
|
}
|
||||||
|
|
||||||
|
v->StartService();
|
||||||
|
UpdateExtendedDepotReservation(v, true);
|
||||||
|
|
||||||
|
SetWindowClassesDirty(WC_ROADVEH_LIST);
|
||||||
|
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
|
||||||
|
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile));
|
||||||
|
} else {
|
||||||
|
VehicleEnterDepot(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
|
bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
|
||||||
{
|
{
|
||||||
/* Don't leave unless v and following wagons are in the depot. */
|
/* Don't leave unless v and following wagons are in the depot. */
|
||||||
for (const RoadVehicle *u = v; u != nullptr; u = u->Next()) {
|
for (const RoadVehicle *u = v; u != nullptr; u = u->Next()) {
|
||||||
if (u->state != RVSB_IN_DEPOT || u->tile != v->tile) return false;
|
if (!u->IsInDepot()) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiagDirection dir = GetRoadDepotDirection(v->tile);
|
bool visible_vehicle = first && (v->vehstatus & VS_HIDDEN) == 0;
|
||||||
v->direction = DiagDirToDir(dir);
|
|
||||||
|
|
||||||
Trackdir tdir = DiagDirToDiagTrackdir(dir);
|
if (first && (v->vehstatus & VS_HIDDEN) != 0) {
|
||||||
|
TileIndex new_tile = v->tile;
|
||||||
|
bool facing_south = IsDiagDirFacingSouth(DirToDiagDir(v->direction));
|
||||||
|
if (FindDepotTileForPlacingEngine(new_tile, facing_south, Engine::Get(v->engine_type), true).Failed()) return false;
|
||||||
|
if (IsExtendedDepot(v->tile)) {
|
||||||
|
UpdateExtendedDepotReservation(v, false);
|
||||||
|
v->tile = new_tile;
|
||||||
|
UpdateExtendedDepotReservation(v, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DiagDirection dir = GetRoadDepotExit(v->tile, RoadTramType(v->roadtype), DirToDiagDir(v->direction));
|
||||||
|
if (facing_south != IsDiagDirFacingSouth(dir)) dir = ReverseDiagDir(dir);
|
||||||
|
assert(dir != INVALID_DIAGDIR);
|
||||||
|
for (Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||||
|
u->direction = DiagDirToDir(dir);
|
||||||
|
u->tile = v->tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x = v->x_pos;
|
||||||
|
int y = v->y_pos;
|
||||||
|
Trackdir tdir = v->GetVehicleTrackdir();
|
||||||
|
|
||||||
|
if ((v->vehstatus & VS_HIDDEN) != 0) {
|
||||||
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
|
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE) + tdir];
|
||||||
|
|
||||||
int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
|
x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
|
||||||
int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
|
y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
/* We are leaving a depot, but have to go to the exact same one; re-enter */
|
/* We are leaving a depot, but have to go to the exact same one; re-enter */
|
||||||
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
||||||
IsRoadDepotTile(v->tile) &&
|
IsRoadDepotTile(v->tile) &&
|
||||||
v->current_order.GetDestination() == GetDepotIndex(v->tile)) {
|
v->current_order.GetDestination() == GetDepotIndex(v->tile)) {
|
||||||
|
if (IsExtendedRoadDepot(v->tile)) {
|
||||||
|
v->StartService();
|
||||||
|
} else {
|
||||||
VehicleEnterDepot(v);
|
VehicleEnterDepot(v);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ((v->vehstatus & VS_HIDDEN) != 0 && RoadVehFindCloseTo(v, x, y, v->direction, false) != nullptr) return true;
|
||||||
if (RoadVehFindCloseTo(v, x, y, v->direction, false) != nullptr) return true;
|
|
||||||
|
|
||||||
VehicleServiceInDepot(v);
|
VehicleServiceInDepot(v);
|
||||||
|
|
||||||
v->LeaveUnbunchingDepot();
|
v->LeaveUnbunchingDepot();
|
||||||
|
|
||||||
StartRoadVehSound(v);
|
StartRoadVehSound(v);
|
||||||
|
/* Vehicle is about to leave a depot. */
|
||||||
/* Vehicle is about to leave a depot */
|
|
||||||
v->cur_speed = 0;
|
v->cur_speed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
v->vehstatus &= ~VS_HIDDEN;
|
|
||||||
v->state = tdir;
|
v->state = tdir;
|
||||||
v->frame = RVC_DEPOT_START_FRAME;
|
|
||||||
|
|
||||||
|
if ((v->vehstatus & VS_HIDDEN) != 0) {
|
||||||
|
v->vehstatus &= ~VS_HIDDEN;
|
||||||
v->x_pos = x;
|
v->x_pos = x;
|
||||||
v->y_pos = y;
|
v->y_pos = y;
|
||||||
|
v->frame = RVC_DEPOT_START_FRAME;
|
||||||
|
} else if (v->Next() != nullptr && (v->Next()->vehstatus & VS_HIDDEN) == 0){
|
||||||
|
for (RoadVehicle *u = v->Next(); u != nullptr; u = u->Next()) {
|
||||||
|
u->state = DiagDirToDiagTrackdir(DirToDiagDir(u->direction));
|
||||||
|
u->UpdatePosition();
|
||||||
|
u->UpdateInclination(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v->UpdatePosition();
|
v->UpdatePosition();
|
||||||
v->UpdateInclination(true, true);
|
v->UpdateInclination(true, true);
|
||||||
|
|
||||||
|
if (first && IsExtendedDepot(v->tile)) {
|
||||||
|
UpdateExtendedDepotReservation(v, false);
|
||||||
|
}
|
||||||
|
|
||||||
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile));
|
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile));
|
||||||
|
|
||||||
return true;
|
return !visible_vehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
|
static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicle *prev, TileIndex tile, DiagDirection entry_dir, bool already_reversed)
|
||||||
|
@ -1138,7 +1247,7 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
|
||||||
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
|
||||||
diag_dir = GetTunnelBridgeDirection(tile);
|
diag_dir = GetTunnelBridgeDirection(tile);
|
||||||
} else if (IsRoadDepotTile(tile)) {
|
} else if (IsRoadDepotTile(tile)) {
|
||||||
diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
|
diag_dir = ReverseDiagDir(IsExtendedRoadDepot(tile) ? DirToDiagDir(v->direction) : GetRoadDepotDirection(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
|
if (diag_dir == INVALID_DIAGDIR) return INVALID_TRACKDIR;
|
||||||
|
@ -1206,6 +1315,53 @@ static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadType rt, RoadB
|
||||||
return ret.Succeeded();
|
return ret.Succeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Check whether there is a close vehicle ahead and act as needed.
|
||||||
|
* @param v Moving vehicle
|
||||||
|
* @param x x coordinate to check
|
||||||
|
* @param y y coordinate to check
|
||||||
|
* @param dir direction of the vehicle
|
||||||
|
* @return whether a close vehicle is found.
|
||||||
|
*/
|
||||||
|
bool CheckCloseVehicle(RoadVehicle *v, int x, int y, Direction dir)
|
||||||
|
{
|
||||||
|
if (!v->IsFrontEngine() || IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) return false;
|
||||||
|
/* Vehicle is not in a road stop.
|
||||||
|
* Check for another vehicle to overtake */
|
||||||
|
RoadVehicle *u = RoadVehFindCloseTo(v, x, y, dir);
|
||||||
|
|
||||||
|
if (u == nullptr) return false;
|
||||||
|
assert(u == u->First());
|
||||||
|
|
||||||
|
/* There is a vehicle in front overtake it if possible */
|
||||||
|
if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
|
||||||
|
if (v->overtaking == 0) v->cur_speed = u->cur_speed;
|
||||||
|
|
||||||
|
/* In case we are in a road depot platform, why not try to start servicing? */
|
||||||
|
if (IsExtendedRoadDepotTile(v->tile) && v->current_order.IsType(OT_GOTO_DEPOT)) {
|
||||||
|
DepotID depot_id = GetDepotIndex(v->tile);
|
||||||
|
if (v->current_order.GetDestination() != depot_id) return true;
|
||||||
|
if (!u->IsInDepot() || GetDepotIndex(u->tile) != depot_id) return true;
|
||||||
|
for (u = v; u != nullptr; u = u->Next()) {
|
||||||
|
if (!IsExtendedRoadDepotTile(u->tile) || GetDepotIndex(u->tile) != depot_id) return true;
|
||||||
|
if (v->direction != u->direction) return true;
|
||||||
|
}
|
||||||
|
HandleRoadVehicleEnterDepot(v);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In case an RV is stopped in a road stop, why not try to load? */
|
||||||
|
if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
|
||||||
|
v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
|
||||||
|
v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
|
||||||
|
GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
|
||||||
|
Station *st = Station::GetByTile(v->tile);
|
||||||
|
v->last_station_visited = st->index;
|
||||||
|
RoadVehArrivesAt(v, st);
|
||||||
|
v->BeginLoading();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
||||||
{
|
{
|
||||||
if (v->overtaking != 0) {
|
if (v->overtaking != 0) {
|
||||||
|
@ -1264,18 +1420,21 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
||||||
(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
|
(_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)) ^ v->overtaking][v->frame + 1];
|
||||||
|
|
||||||
if (rd.x & RDE_NEXT_TILE) {
|
if (rd.x & RDE_NEXT_TILE) {
|
||||||
TileIndex tile = v->tile + TileOffsByDiagDir((DiagDirection)(rd.x & 3));
|
DiagDirection diag_dir = (DiagDirection)(rd.x & 3);
|
||||||
|
TileIndex tile = v->tile + TileOffsByDiagDir(diag_dir);
|
||||||
Trackdir dir;
|
Trackdir dir;
|
||||||
|
bool extended_depot_turn = IsExtendedRoadDepotTile(v->tile) &&
|
||||||
|
(GetRoadBits(v->tile, GetRoadTramType(v->roadtype)) & DiagDirToRoadBits(diag_dir)) == ROAD_NONE;
|
||||||
|
|
||||||
if (v->IsFrontEngine()) {
|
if (v->IsFrontEngine()) {
|
||||||
/* If this is the front engine, look for the right path. */
|
/* If this is the front engine, look for the right path. */
|
||||||
if (HasTileAnyRoadType(tile, v->compatible_roadtypes)) {
|
if (HasTileAnyRoadType(tile, v->compatible_roadtypes) && !extended_depot_turn) {
|
||||||
dir = RoadFindPathToDest(v, tile, (DiagDirection)(rd.x & 3));
|
dir = RoadFindPathToDest(v, tile, diag_dir);
|
||||||
} else {
|
} else {
|
||||||
dir = _road_reverse_table[(DiagDirection)(rd.x & 3)];
|
dir = _road_reverse_table[diag_dir];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dir = FollowPreviousRoadVehicle(v, prev, tile, (DiagDirection)(rd.x & 3), false);
|
dir = FollowPreviousRoadVehicle(v, prev, tile, diag_dir, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir == INVALID_TRACKDIR) {
|
if (dir == INVALID_TRACKDIR) {
|
||||||
|
@ -1302,7 +1461,10 @@ again:
|
||||||
case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
|
case TRACKDIR_RVREV_SW: needed = ROAD_NE; break;
|
||||||
case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
|
case TRACKDIR_RVREV_NW: needed = ROAD_SE; break;
|
||||||
}
|
}
|
||||||
if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
|
if (extended_depot_turn) {
|
||||||
|
tile = v->tile;
|
||||||
|
start_frame = RVC_TURN_AROUND_START_FRAME_SHORT_TRAM;
|
||||||
|
} else if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
|
||||||
(v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
|
(v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
|
||||||
HasTileAnyRoadType(tile, v->compatible_roadtypes) &&
|
HasTileAnyRoadType(tile, v->compatible_roadtypes) &&
|
||||||
(needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
|
(needed & GetRoadBits(tile, RTT_TRAM)) != ROAD_NONE)) {
|
||||||
|
@ -1319,8 +1481,9 @@ again:
|
||||||
} else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
|
} else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RTT_TRAM, false)) == ROAD_NONE)) {
|
||||||
/*
|
/*
|
||||||
* Taking the 'small' corner for trams only happens when:
|
* Taking the 'small' corner for trams only happens when:
|
||||||
* - We are not the from vehicle of an articulated tram.
|
* - We are not the front vehicle of an articulated tram.
|
||||||
* - Or when the company cannot build on the next tile.
|
* - Or when the company cannot build on the next tile.
|
||||||
|
* - Or when the extended depot doesn't have the appropriate tram bit to continue.
|
||||||
*
|
*
|
||||||
* The 'small' corner means that the vehicle is on the end of a
|
* The 'small' corner means that the vehicle is on the end of a
|
||||||
* tram track and needs to start turning there. To do this properly
|
* tram track and needs to start turning there. To do this properly
|
||||||
|
@ -1363,6 +1526,11 @@ again:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t r = VehicleEnterTile(v, tile, x, y);
|
uint32_t r = VehicleEnterTile(v, tile, x, y);
|
||||||
|
if (HasBit(r, VETS_ENTERED_DEPOT_PLATFORM) && v->Next() == nullptr && v == v->First()) {
|
||||||
|
HandleRoadVehicleEnterDepot(RoadVehicle::From(v));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (HasBit(r, VETS_CANNOT_ENTER)) {
|
if (HasBit(r, VETS_CANNOT_ENTER)) {
|
||||||
if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
|
if (!IsTileType(tile, MP_TUNNELBRIDGE)) {
|
||||||
v->cur_speed = 0;
|
v->cur_speed = 0;
|
||||||
|
@ -1419,6 +1587,9 @@ again:
|
||||||
}
|
}
|
||||||
v->x_pos = x;
|
v->x_pos = x;
|
||||||
v->y_pos = y;
|
v->y_pos = y;
|
||||||
|
if (prev != nullptr && prev->IsInDepot() && (prev->vehstatus & VS_HIDDEN) == 0) {
|
||||||
|
v->state = RVSB_IN_DEPOT;
|
||||||
|
}
|
||||||
v->UpdatePosition();
|
v->UpdatePosition();
|
||||||
RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
|
RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
|
||||||
return true;
|
return true;
|
||||||
|
@ -1429,7 +1600,7 @@ again:
|
||||||
Trackdir dir;
|
Trackdir dir;
|
||||||
uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
|
uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME;
|
||||||
|
|
||||||
if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
|
if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && !IsExtendedRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RTT_TRAM, true))) {
|
||||||
/*
|
/*
|
||||||
* The tram is turning around with one tram 'roadbit'. This means that
|
* The tram is turning around with one tram 'roadbit'. This means that
|
||||||
* it is using the 'big' corner 'drive data'. However, to support the
|
* it is using the 'big' corner 'drive data'. However, to support the
|
||||||
|
@ -1495,6 +1666,9 @@ again:
|
||||||
|
|
||||||
v->x_pos = x;
|
v->x_pos = x;
|
||||||
v->y_pos = y;
|
v->y_pos = y;
|
||||||
|
if (prev != nullptr && prev->IsInDepot() && (prev->vehstatus & VS_HIDDEN) == 0) {
|
||||||
|
v->state = RVSB_IN_DEPOT;
|
||||||
|
}
|
||||||
v->UpdatePosition();
|
v->UpdatePosition();
|
||||||
RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
|
RoadZPosAffectSpeed(v, v->UpdateInclination(true, true));
|
||||||
return true;
|
return true;
|
||||||
|
@ -1504,10 +1678,12 @@ again:
|
||||||
* it's on a depot tile, check if it's time to activate the next vehicle in
|
* it's on a depot tile, check if it's time to activate the next vehicle in
|
||||||
* the chain yet. */
|
* the chain yet. */
|
||||||
if (v->Next() != nullptr && IsRoadDepotTile(v->tile)) {
|
if (v->Next() != nullptr && IsRoadDepotTile(v->tile)) {
|
||||||
|
if ((v->Next()->vehstatus & VS_HIDDEN)) {
|
||||||
if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
|
if (v->frame == v->gcache.cached_veh_length + RVC_DEPOT_START_FRAME) {
|
||||||
RoadVehLeaveDepot(v->Next(), false);
|
RoadVehLeaveDepot(v->Next(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate new position for the vehicle */
|
/* Calculate new position for the vehicle */
|
||||||
int x = (v->x_pos & ~15) + (rd.x & 15);
|
int x = (v->x_pos & ~15) + (rd.x & 15);
|
||||||
|
@ -1515,30 +1691,7 @@ again:
|
||||||
|
|
||||||
Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
|
Direction new_dir = RoadVehGetSlidingDirection(v, x, y);
|
||||||
|
|
||||||
if (v->IsFrontEngine() && !IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
|
if (CheckCloseVehicle(v, x, y, new_dir)) return false;
|
||||||
/* Vehicle is not in a road stop.
|
|
||||||
* Check for another vehicle to overtake */
|
|
||||||
RoadVehicle *u = RoadVehFindCloseTo(v, x, y, new_dir);
|
|
||||||
|
|
||||||
if (u != nullptr) {
|
|
||||||
assert(u == u->First());
|
|
||||||
/* There is a vehicle in front overtake it if possible */
|
|
||||||
if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
|
|
||||||
if (v->overtaking == 0) v->cur_speed = u->cur_speed;
|
|
||||||
|
|
||||||
/* In case an RV is stopped in a road stop, why not try to load? */
|
|
||||||
if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
|
|
||||||
v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
|
|
||||||
v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
|
|
||||||
GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
|
|
||||||
Station *st = Station::GetByTile(v->tile);
|
|
||||||
v->last_station_visited = st->index;
|
|
||||||
RoadVehArrivesAt(v, st);
|
|
||||||
v->BeginLoading();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Direction old_dir = v->direction;
|
Direction old_dir = v->direction;
|
||||||
if (new_dir != old_dir) {
|
if (new_dir != old_dir) {
|
||||||
|
@ -1634,6 +1787,16 @@ again:
|
||||||
v->y_pos = y;
|
v->y_pos = y;
|
||||||
v->UpdatePosition();
|
v->UpdatePosition();
|
||||||
RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
|
RoadZPosAffectSpeed(v, v->UpdateInclination(false, true));
|
||||||
|
|
||||||
|
/* After updating the position, check whether the vehicle can stop in a depot platform. */
|
||||||
|
if (IsExtendedRoadDepotTile(v->tile) && v->Next() == nullptr) {
|
||||||
|
RoadVehicle *first = RoadVehicle::From(v)->First();
|
||||||
|
if (HasBit(VehicleEnterTile(first, first->tile, first->x_pos, first->y_pos), VETS_ENTERED_DEPOT_PLATFORM)) {
|
||||||
|
HandleRoadVehicleEnterDepot(first);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1655,6 +1818,8 @@ static bool RoadVehController(RoadVehicle *v)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v->ContinueServicing()) return true;
|
||||||
|
|
||||||
ProcessOrders(v);
|
ProcessOrders(v);
|
||||||
v->HandleLoading();
|
v->HandleLoading();
|
||||||
|
|
||||||
|
@ -1816,6 +1981,9 @@ Trackdir RoadVehicle::GetVehicleTrackdir() const
|
||||||
if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
|
if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
|
||||||
|
|
||||||
if (this->IsInDepot()) {
|
if (this->IsInDepot()) {
|
||||||
|
if (IsExtendedRoadDepot(this->tile)) {
|
||||||
|
return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
|
||||||
|
}
|
||||||
/* We'll assume the road vehicle is facing outwards */
|
/* We'll assume the road vehicle is facing outwards */
|
||||||
return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
|
return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,9 @@ CommandCost CmdSellVehicle(DoCommandFlag flags, VehicleID v_id, bool sell_chain,
|
||||||
ret = CommandCost(EXPENSES_NEW_VEHICLES, -front->value);
|
ret = CommandCost(EXPENSES_NEW_VEHICLES, -front->value);
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
|
if (front->type == VEH_ROAD && IsExtendedDepot(v->tile) && (flags & DC_AUTOREPLACE) == 0) {
|
||||||
|
UpdateExtendedDepotReservation(v, false);
|
||||||
|
}
|
||||||
if (front->IsPrimaryVehicle() && backup_order) OrderBackup::Backup(front, client_id);
|
if (front->IsPrimaryVehicle() && backup_order) OrderBackup::Backup(front, client_id);
|
||||||
delete front;
|
delete front;
|
||||||
}
|
}
|
||||||
|
@ -610,7 +613,16 @@ CommandCost CmdStartStopVehicle(DoCommandFlag flags, VehicleID veh_id, bool eval
|
||||||
}
|
}
|
||||||
|
|
||||||
case VEH_SHIP:
|
case VEH_SHIP:
|
||||||
|
break;
|
||||||
case VEH_ROAD:
|
case VEH_ROAD:
|
||||||
|
if ((v->vehstatus & VS_STOPPED) && !(flags & DC_AUTOREPLACE) && v->IsStoppedInDepot()) {
|
||||||
|
Depot *dep = Depot:: GetByTile(v->tile);
|
||||||
|
|
||||||
|
/* Check that the vehicle can drive on some tile of the depot */
|
||||||
|
RoadType rt = Engine::Get(v->engine_type)->u.road.roadtype;
|
||||||
|
const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
|
||||||
|
if ((dep->r_types.road_types & rti->powered_roadtypes) == 0) return_cmd_error(STR_ERROR_ROAD_VEHICLE_START_NO_POWER);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VEH_AIRCRAFT: {
|
case VEH_AIRCRAFT: {
|
||||||
|
|
Loading…
Reference in New Issue