mirror of https://github.com/OpenTTD/OpenTTD
Add: Add and adapt some functions for extended depots.
parent
2ddb3bf2d7
commit
08f4ae4b3d
|
@ -112,19 +112,29 @@ void Depot::Disuse()
|
|||
* Of all the depot parts a depot has, return the best destination for a vehicle.
|
||||
* @param v The vehicle.
|
||||
* @param dep The depot vehicle \a v is heading for.
|
||||
* @return The closest part of depot to vehicle v.
|
||||
* @return The free and closest (if none is free, just closest) part of depot to vehicle v.
|
||||
*/
|
||||
TileIndex Depot::GetBestDepotTile(Vehicle *v) const
|
||||
{
|
||||
assert(this->veh_type == v->type);
|
||||
TileIndex best_depot = INVALID_TILE;
|
||||
DepotReservation best_found_type = DEPOT_RESERVATION_END;
|
||||
uint best_distance = UINT_MAX;
|
||||
|
||||
for (const auto &tile : this->depot_tiles) {
|
||||
bool check_south = v->type == VEH_ROAD;
|
||||
uint new_distance = DistanceManhattan(v->tile, tile);
|
||||
if (new_distance < best_distance) {
|
||||
again:
|
||||
DepotReservation depot_reservation = GetDepotReservation(tile, check_south);
|
||||
if (((best_found_type == depot_reservation) && new_distance < best_distance) || (depot_reservation < best_found_type)) {
|
||||
best_depot = tile;
|
||||
best_distance = new_distance;
|
||||
best_found_type = depot_reservation;
|
||||
}
|
||||
if (check_south) {
|
||||
/* For road vehicles, check north direction as well. */
|
||||
check_south = false;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,4 +83,96 @@ inline VehicleType GetDepotVehicleType(Tile t)
|
|||
}
|
||||
}
|
||||
|
||||
/** Return true if a tile belongs to an extended depot. */
|
||||
static inline bool IsExtendedDepot(Tile tile) {
|
||||
assert(IsValidTile(tile));
|
||||
assert(IsDepotTile(tile));
|
||||
if (IsAirportTile(tile)) return false;
|
||||
return HasBit(tile.m5(), 5);
|
||||
}
|
||||
|
||||
/** Return true if a tile belongs to an extended depot. */
|
||||
static inline bool IsExtendedDepotTile(TileIndex tile) {
|
||||
if (!IsValidTile(tile)) return false;
|
||||
if (!IsDepotTile(tile)) return false;
|
||||
return IsExtendedDepot(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has this depot some vehicle servicing or stopped inside?
|
||||
* @param tile tile of the depot.
|
||||
* @param south_dir In case of road transport, return reservation facing south if true.
|
||||
* @return The type of reservation on this tile (empty, servicing or occupied).
|
||||
* @pre is a depot tile
|
||||
*/
|
||||
static inline DepotReservation GetDepotReservation(Tile t, bool south_dir = false)
|
||||
{
|
||||
assert(IsDepotTile(t));
|
||||
if (!IsExtendedDepot(t)) return DEPOT_RESERVATION_EMPTY;
|
||||
if (south_dir) {
|
||||
assert(GetDepotVehicleType(t) == VEH_ROAD);
|
||||
return (DepotReservation)GB(t.m6(), 4, 2);
|
||||
}
|
||||
return (DepotReservation)GB(t.m4(), 6, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a platform/depot tile full with stopped vehicles?
|
||||
* @param tile tile of the depot.
|
||||
* @param south_dir In case of road transport, check reservation facing south if true.
|
||||
* @return the type of reservation of the depot.
|
||||
* @pre is a depot tile
|
||||
*/
|
||||
static inline bool IsDepotFullWithStoppedVehicles(TileIndex t, bool south_dir = false)
|
||||
{
|
||||
assert(IsDepotTile(t));
|
||||
if (!IsExtendedDepot(t)) return false;
|
||||
return GetDepotReservation(t, south_dir) == DEPOT_RESERVATION_FULL_STOPPED_VEH;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Has this depot tile/platform some vehicle inside?
|
||||
* @param tile tile of the depot.
|
||||
* @param south_dir In case of road transport, check reservation facing south if true.
|
||||
* @return true iff depot tile/platform has no vehicle.
|
||||
* @pre IsExtendedDepotTile
|
||||
*/
|
||||
static inline bool IsExtendedDepotEmpty(TileIndex t, bool south_dir = false)
|
||||
{
|
||||
assert(IsExtendedDepotTile(t));
|
||||
return GetDepotReservation(t, south_dir) == DEPOT_RESERVATION_EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark whether this depot has a ship inside.
|
||||
* @param tile of the depot.
|
||||
* @param reservation type of reservation
|
||||
* @param south_dir Whether to set south direction reservation.
|
||||
* @pre tile is an extended ship depot.
|
||||
*/
|
||||
static inline void SetDepotReservation(Tile t, DepotReservation reservation, bool south_dir = false)
|
||||
{
|
||||
assert(IsDepotTile(t));
|
||||
if (!IsExtendedDepot(t)) return;
|
||||
switch (GetTileType(t)) {
|
||||
default: NOT_REACHED();
|
||||
case MP_RAILWAY:
|
||||
break;
|
||||
case MP_ROAD:
|
||||
if (south_dir) {
|
||||
SB(t.m6(), 4, 2, reservation);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case MP_WATER:
|
||||
assert(GetDepotReservation(t) == GetDepotReservation(GetOtherShipDepotTile(t)));
|
||||
SB(Tile(GetOtherShipDepotTile(t)).m4(), 6, 2, reservation);
|
||||
break;
|
||||
case MP_STATION: return;
|
||||
}
|
||||
|
||||
SB(t.m4(), 6, 2, reservation);
|
||||
}
|
||||
|
||||
#endif /* DEPOT_MAP_H */
|
||||
|
|
|
@ -18,4 +18,12 @@ static const DepotID NEW_DEPOT = INVALID_DEPOT - 1;
|
|||
|
||||
static const uint MAX_LENGTH_DEPOT_NAME_CHARS = 32; ///< The maximum length of a depot name in characters including '\0'
|
||||
|
||||
/** Type of reservation of extended ship depots. */
|
||||
enum DepotReservation {
|
||||
DEPOT_RESERVATION_EMPTY = 0, ///< No vehicle servicing/stopped on depot tile/platform.
|
||||
DEPOT_RESERVATION_IN_USE = 1, ///< At least a vehicle is in the depot, but the depot tile is not full of stopped vehicles.
|
||||
DEPOT_RESERVATION_FULL_STOPPED_VEH = 2, ///< The depot tile/platform is full with stopped vehicles.
|
||||
DEPOT_RESERVATION_END
|
||||
};
|
||||
|
||||
#endif /* DEPOT_TYPE_H */
|
||||
|
|
|
@ -910,6 +910,7 @@ STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE
|
|||
STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} is lost
|
||||
STR_NEWS_VEHICLE_UNPROFITABLE_YEAR :{WHITE}{VEHICLE}'s profit last year was {CURRENCY_LONG}
|
||||
STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD :{WHITE}{VEHICLE}'s profit last period was {CURRENCY_LONG}
|
||||
STR_NEWS_VEHICLE_CAN_T_FIND_FREE_DEPOT :{WHITE}{VEHICLE} can't find a free depot
|
||||
STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} can't get to the next destination because it is out of range
|
||||
|
||||
STR_NEWS_ORDER_REFIT_FAILED :{WHITE}{VEHICLE} stopped because an ordered refit failed
|
||||
|
|
|
@ -66,13 +66,22 @@ static inline TileIndex CalcClosestDepotTile(DepotID depot_id, TileIndex tile)
|
|||
}
|
||||
|
||||
TileIndex best_tile = INVALID_TILE;
|
||||
DepotReservation best_found_type = dep->veh_type == VEH_SHIP ? DEPOT_RESERVATION_END : DEPOT_RESERVATION_EMPTY;
|
||||
uint best_distance = UINT_MAX;
|
||||
|
||||
for (auto const &depot_tile : dep->depot_tiles) {
|
||||
uint new_distance = DistanceManhattan(depot_tile, tile);
|
||||
if (new_distance < best_distance) {
|
||||
bool check_south_direction = dep->veh_type == VEH_ROAD;
|
||||
again:
|
||||
DepotReservation depot_reservation = GetDepotReservation(depot_tile, check_south_direction);
|
||||
if (((best_found_type == depot_reservation) && new_distance < best_distance) || (depot_reservation < best_found_type)) {
|
||||
best_tile = depot_tile;
|
||||
best_distance = new_distance;
|
||||
best_found_type = depot_reservation;
|
||||
}
|
||||
if (check_south_direction) {
|
||||
check_south_direction = false;
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -790,6 +790,22 @@ void Vehicle::ShiftDates(TimerGameEconomy::Date interval)
|
|||
*/
|
||||
void Vehicle::HandlePathfindingResult(bool path_found)
|
||||
{
|
||||
if (this->dest_tile != INVALID_TILE && IsDepotTypeTile(this->dest_tile, (TransportType)this->type) && IsDepotFullWithStoppedVehicles(this->dest_tile)) {
|
||||
/* Vehicle cannot find a free depot. */
|
||||
/* Were we already lost? */
|
||||
if (HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
|
||||
|
||||
/* It is first time the problem occurred, set the "lost" flag. */
|
||||
SetBit(this->vehicle_flags, VF_PATHFINDER_LOST);
|
||||
/* Notify user about the event. */
|
||||
AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
|
||||
if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
|
||||
SetDParam(0, this->index);
|
||||
AddVehicleAdviceNewsItem(STR_NEWS_VEHICLE_CAN_T_FIND_FREE_DEPOT, this->index);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (path_found) {
|
||||
/* Route found, is the vehicle marked with "lost" flag? */
|
||||
if (!HasBit(this->vehicle_flags, VF_PATHFINDER_LOST)) return;
|
||||
|
|
Loading…
Reference in New Issue