Improve pathfinder support for multiple docks
The pathfinder can now find docks other than the Manhattan closest one. Based on Cirdan commits: afc7969c13d7ca59afe4dae4bf88122ba8d27df2 4067190dedcd3e5f668ea4f49b1dd8dfed10b2a7 d9be6b712d2ae4fb1b5ae844dde4919dd24c4fb2
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "station_type.h"
|
#include "station_type.h"
|
||||||
#include "tile_type.h"
|
#include "tile_type.h"
|
||||||
|
#include "map_func.h"
|
||||||
#include "core/pool_type.hpp"
|
#include "core/pool_type.hpp"
|
||||||
|
|
||||||
typedef Pool<Dock, DockID, 32, 64000> DockPool;
|
typedef Pool<Dock, DockID, 32, 64000> DockPool;
|
||||||
@@ -31,6 +32,11 @@ struct Dock : DockPool::PoolItem<&_dock_pool> {
|
|||||||
|
|
||||||
inline Dock *GetNextDock() const { return this->next; }
|
inline Dock *GetNextDock() const { return this->next; }
|
||||||
|
|
||||||
|
inline TileIndex GetDockingTile() const
|
||||||
|
{
|
||||||
|
return this->flat + TileOffsByDiagDir(DiagdirBetweenTiles(this->sloped, this->flat));
|
||||||
|
}
|
||||||
|
|
||||||
static Dock *GetByTile(TileIndex tile);
|
static Dock *GetByTile(TileIndex tile);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -160,8 +160,8 @@ static int32 NPFCalcStationOrTileHeuristic(AyStar *as, AyStarNode *current, Open
|
|||||||
uint dist;
|
uint dist;
|
||||||
AyStarUserData *user = (AyStarUserData *)as->user_data;
|
AyStarUserData *user = (AyStarUserData *)as->user_data;
|
||||||
|
|
||||||
/* for train-stations, we are going to aim for the closest station tile */
|
/* for stations, we are going to aim for the closest station tile */
|
||||||
if (user->type != TRANSPORT_WATER && fstd->station_index != INVALID_STATION) {
|
if (fstd->station_index != INVALID_STATION) {
|
||||||
to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);
|
to = CalcClosestStationTile(fstd->station_index, from, fstd->station_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,16 +558,16 @@ static int32 NPFFindStationOrTile(AyStar *as, OpenListNode *current)
|
|||||||
AyStarNode *node = ¤t->path.node;
|
AyStarNode *node = ¤t->path.node;
|
||||||
TileIndex tile = node->tile;
|
TileIndex tile = node->tile;
|
||||||
|
|
||||||
if (fstd->station_index == INVALID_STATION && tile == fstd->dest_coords) return AYSTAR_FOUND_END_NODE;
|
if (fstd->station_index == INVALID_STATION) {
|
||||||
|
return (tile == fstd->dest_coords) ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
|
||||||
if (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) {
|
}
|
||||||
if (fstd->v->type == VEH_TRAIN) return AYSTAR_FOUND_END_NODE;
|
|
||||||
|
switch (fstd->v->type) {
|
||||||
assert(fstd->v->type == VEH_ROAD);
|
default: NOT_REACHED();
|
||||||
/* Only if it is a valid station *and* we can stop there */
|
case VEH_TRAIN: return (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index) ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
|
||||||
if (GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) return AYSTAR_FOUND_END_NODE;
|
case VEH_ROAD: return (IsTileType(tile, MP_STATION) && GetStationIndex(tile) == fstd->station_index && GetStationType(tile) == fstd->station_type && (fstd->not_articulated || IsDriveThroughStopTile(tile))) ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
|
||||||
|
case VEH_SHIP: return Station::Get(fstd->station_index)->IsDockingTile(tile) ? AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
|
||||||
}
|
}
|
||||||
return AYSTAR_DONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1099,16 +1099,12 @@ void InitializeNPF()
|
|||||||
|
|
||||||
static void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool reserve_path = false)
|
static void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *v, bool reserve_path = false)
|
||||||
{
|
{
|
||||||
/* Ships don't really reach their stations, but the tile in front. So don't
|
/* Fill station_index for station orders, else only dest_coords. */
|
||||||
* save the station id for ships. For roadvehs we don't store it either,
|
if (v->current_order.IsType(OT_GOTO_STATION) || (v->type != VEH_SHIP && v->current_order.IsType(OT_GOTO_WAYPOINT))) {
|
||||||
* because multistop depends on vehicles actually reaching the exact
|
|
||||||
* dest_tile, not just any stop of that station.
|
|
||||||
* So only for train orders to stations we fill fstd->station_index, for all
|
|
||||||
* others only dest_coords */
|
|
||||||
if (v->type != VEH_SHIP && (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_WAYPOINT))) {
|
|
||||||
assert(v->IsGroundVehicle());
|
|
||||||
fstd->station_index = v->current_order.GetDestination();
|
fstd->station_index = v->current_order.GetDestination();
|
||||||
fstd->station_type = (v->type == VEH_TRAIN) ? (v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT) : (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK);
|
fstd->station_type = (v->type == VEH_SHIP) ? STATION_DOCK :
|
||||||
|
(v->type == VEH_TRAIN) ? (v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT) :
|
||||||
|
(RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK);
|
||||||
fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart();
|
fstd->not_articulated = v->type == VEH_ROAD && !RoadVehicle::From(v)->HasArticulatedPart();
|
||||||
/* Let's take the closest tile of the station as our target for vehicles */
|
/* Let's take the closest tile of the station as our target for vehicles */
|
||||||
fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type);
|
fstd->dest_coords = CalcClosestStationTile(fstd->station_index, v->tile, fstd->station_type);
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
#include "../../tunnelbridge_map.h"
|
#include "../../tunnelbridge_map.h"
|
||||||
#include "../../tunnelbridge.h"
|
#include "../../tunnelbridge.h"
|
||||||
#include "../../ship.h"
|
#include "../../ship.h"
|
||||||
|
#include "../../station_base.h"
|
||||||
#include "../../core/random_func.hpp"
|
#include "../../core/random_func.hpp"
|
||||||
|
|
||||||
#include "../../safeguards.h"
|
#include "../../safeguards.h"
|
||||||
@@ -25,6 +26,7 @@ struct RememberData {
|
|||||||
|
|
||||||
struct TrackPathFinder {
|
struct TrackPathFinder {
|
||||||
TileIndex skiptile;
|
TileIndex skiptile;
|
||||||
|
StationID dest_station;
|
||||||
TileIndex dest_coords;
|
TileIndex dest_coords;
|
||||||
uint best_bird_dist;
|
uint best_bird_dist;
|
||||||
uint best_length;
|
uint best_length;
|
||||||
@@ -35,7 +37,14 @@ struct TrackPathFinder {
|
|||||||
static bool ShipTrackFollower(TileIndex tile, TrackPathFinder *pfs, uint length)
|
static bool ShipTrackFollower(TileIndex tile, TrackPathFinder *pfs, uint length)
|
||||||
{
|
{
|
||||||
/* Found dest? */
|
/* Found dest? */
|
||||||
if (tile == pfs->dest_coords) {
|
if (pfs->dest_station != INVALID_STATION) {
|
||||||
|
if (Station::Get(pfs->dest_station)->IsDockingTile(tile)) {
|
||||||
|
pfs->best_bird_dist = 0;
|
||||||
|
|
||||||
|
pfs->best_length = minu(pfs->best_length, length);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (tile == pfs->dest_coords) {
|
||||||
pfs->best_bird_dist = 0;
|
pfs->best_bird_dist = 0;
|
||||||
|
|
||||||
pfs->best_length = minu(pfs->best_length, length);
|
pfs->best_length = minu(pfs->best_length, length);
|
||||||
@@ -140,6 +149,7 @@ static uint FindShipTrack(const Ship *v, TileIndex tile, DiagDirection dir, Trac
|
|||||||
uint best_length = 0;
|
uint best_length = 0;
|
||||||
byte ship_dir = v->direction & 3;
|
byte ship_dir = v->direction & 3;
|
||||||
|
|
||||||
|
pfs.dest_station = v->current_order.IsType(OT_GOTO_STATION) ? v->current_order.GetDestination() : INVALID_STATION;
|
||||||
pfs.dest_coords = v->dest_tile;
|
pfs.dest_coords = v->dest_tile;
|
||||||
pfs.skiptile = skiptile;
|
pfs.skiptile = skiptile;
|
||||||
|
|
||||||
|
@@ -110,72 +110,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** YAPF destination provider base class - used when destination is single tile / multiple trackdirs */
|
|
||||||
template <class Types>
|
|
||||||
class CYapfDestinationTileT
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
|
||||||
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
|
||||||
typedef typename Node::Key Key; ///< key to hash tables
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TileIndex m_destTile; ///< destination tile
|
|
||||||
TrackdirBits m_destTrackdirs; ///< destination trackdir mask
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** set the destination tile / more trackdirs */
|
|
||||||
void SetDestination(TileIndex tile, TrackdirBits trackdirs)
|
|
||||||
{
|
|
||||||
m_destTile = tile;
|
|
||||||
m_destTrackdirs = trackdirs;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** to access inherited path finder */
|
|
||||||
Tpf& Yapf()
|
|
||||||
{
|
|
||||||
return *static_cast<Tpf *>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Called by YAPF to detect if node ends in the desired destination */
|
|
||||||
inline bool PfDetectDestination(Node &n)
|
|
||||||
{
|
|
||||||
bool bDest = (n.m_key.m_tile == m_destTile) && ((m_destTrackdirs & TrackdirToTrackdirBits(n.GetTrackdir())) != TRACKDIR_BIT_NONE);
|
|
||||||
return bDest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
|
||||||
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
|
||||||
*/
|
|
||||||
inline bool PfCalcEstimate(Node &n)
|
|
||||||
{
|
|
||||||
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
|
||||||
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
|
||||||
if (PfDetectDestination(n)) {
|
|
||||||
n.m_estimate = n.m_cost;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileIndex tile = n.GetTile();
|
|
||||||
DiagDirection exitdir = TrackdirToExitdir(n.GetTrackdir());
|
|
||||||
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
|
||||||
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
|
||||||
int x2 = 2 * TileX(m_destTile);
|
|
||||||
int y2 = 2 * TileY(m_destTile);
|
|
||||||
int dx = abs(x1 - x2);
|
|
||||||
int dy = abs(y1 - y2);
|
|
||||||
int dmin = min(dx, dy);
|
|
||||||
int dxy = abs(dx - dy);
|
|
||||||
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
|
||||||
n.m_estimate = n.m_cost + d;
|
|
||||||
assert(n.m_estimate >= n.m_parent->m_estimate);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* YAPF template that uses Ttypes template argument to determine all YAPF
|
* YAPF template that uses Ttypes template argument to determine all YAPF
|
||||||
* components (base classes) from which the actual YAPF is composed.
|
* components (base classes) from which the actual YAPF is composed.
|
||||||
|
@@ -75,14 +75,12 @@ public:
|
|||||||
|
|
||||||
/* convert origin trackdir to TrackdirBits */
|
/* convert origin trackdir to TrackdirBits */
|
||||||
TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
|
TrackdirBits trackdirs = TrackdirToTrackdirBits(trackdir);
|
||||||
/* get available trackdirs on the destination tile */
|
|
||||||
TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
|
|
||||||
|
|
||||||
/* create pathfinder instance */
|
/* create pathfinder instance */
|
||||||
Tpf pf;
|
Tpf pf;
|
||||||
/* set origin and destination nodes */
|
/* set origin and destination nodes */
|
||||||
pf.SetOrigin(src_tile, trackdirs);
|
pf.SetOrigin(src_tile, trackdirs);
|
||||||
pf.SetDestination(v->dest_tile, dest_trackdirs);
|
pf.SetDestination(v);
|
||||||
/* find best path */
|
/* find best path */
|
||||||
path_found = pf.FindPath(v);
|
path_found = pf.FindPath(v);
|
||||||
|
|
||||||
@@ -115,14 +113,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2)
|
static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2)
|
||||||
{
|
{
|
||||||
/* get available trackdirs on the destination tile */
|
|
||||||
TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
|
|
||||||
|
|
||||||
/* create pathfinder instance */
|
/* create pathfinder instance */
|
||||||
Tpf pf;
|
Tpf pf;
|
||||||
/* set origin and destination nodes */
|
/* set origin and destination nodes */
|
||||||
pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2));
|
pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2));
|
||||||
pf.SetDestination(v->dest_tile, dest_trackdirs);
|
pf.SetDestination(v);
|
||||||
/* find best path */
|
/* find best path */
|
||||||
if (!pf.FindPath(v)) return false;
|
if (!pf.FindPath(v)) return false;
|
||||||
|
|
||||||
@@ -188,6 +183,80 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** YAPF destination provider for ships */
|
||||||
|
template <class Types>
|
||||||
|
class CYapfDestinationShipT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
||||||
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
||||||
|
typedef typename Node::Key Key; ///< key to hash tables
|
||||||
|
|
||||||
|
protected:
|
||||||
|
StationID m_destStation; ///< destinatin station
|
||||||
|
TileIndex m_destTile; ///< destination tile
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** set the destination */
|
||||||
|
void SetDestination(const Ship *v)
|
||||||
|
{
|
||||||
|
if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||||
|
m_destStation = v->current_order.GetDestination();
|
||||||
|
m_destTile = CalcClosestStationTile(m_destStation, v->tile, STATION_DOCK);
|
||||||
|
} else {
|
||||||
|
m_destStation = INVALID_STATION;
|
||||||
|
m_destTile = v->dest_tile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** to access inherited path finder */
|
||||||
|
Tpf& Yapf()
|
||||||
|
{
|
||||||
|
return *static_cast<Tpf *>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Called by YAPF to detect if node ends in the desired destination */
|
||||||
|
inline bool PfDetectDestination(Node &n)
|
||||||
|
{
|
||||||
|
if (m_destStation == INVALID_STATION) {
|
||||||
|
return n.m_key.m_tile == m_destTile;
|
||||||
|
} else {
|
||||||
|
return Station::Get(m_destStation)->IsDockingTile(n.m_key.m_tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||||
|
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
||||||
|
*/
|
||||||
|
inline bool PfCalcEstimate(Node &n)
|
||||||
|
{
|
||||||
|
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
||||||
|
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
||||||
|
if (PfDetectDestination(n)) {
|
||||||
|
n.m_estimate = n.m_cost;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileIndex tile = n.GetTile();
|
||||||
|
DiagDirection exitdir = TrackdirToExitdir(n.GetTrackdir());
|
||||||
|
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
||||||
|
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
||||||
|
int x2 = 2 * TileX(m_destTile);
|
||||||
|
int y2 = 2 * TileY(m_destTile);
|
||||||
|
int dx = abs(x1 - x2);
|
||||||
|
int dy = abs(y1 - y2);
|
||||||
|
int dmin = min(dx, dy);
|
||||||
|
int dxy = abs(dx - dy);
|
||||||
|
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||||
|
n.m_estimate = n.m_cost + d;
|
||||||
|
assert(n.m_estimate >= n.m_parent->m_estimate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config struct of YAPF for ships.
|
* Config struct of YAPF for ships.
|
||||||
* Defines all 6 base YAPF modules as classes providing services for CYapfBaseT.
|
* Defines all 6 base YAPF modules as classes providing services for CYapfBaseT.
|
||||||
@@ -209,7 +278,7 @@ struct CYapfShip_TypesT
|
|||||||
typedef CYapfBaseT<Types> PfBase; // base pathfinder class
|
typedef CYapfBaseT<Types> PfBase; // base pathfinder class
|
||||||
typedef CYapfFollowShipT<Types> PfFollow; // node follower
|
typedef CYapfFollowShipT<Types> PfFollow; // node follower
|
||||||
typedef CYapfOriginTileT<Types> PfOrigin; // origin provider
|
typedef CYapfOriginTileT<Types> PfOrigin; // origin provider
|
||||||
typedef CYapfDestinationTileT<Types> PfDestination; // destination/distance provider
|
typedef CYapfDestinationShipT<Types> PfDestination; // destination/distance provider
|
||||||
typedef CYapfSegmentCostCacheNoneT<Types> PfCache; // segment cost cache provider
|
typedef CYapfSegmentCostCacheNoneT<Types> PfCache; // segment cost cache provider
|
||||||
typedef CYapfCostShipT<Types> PfCost; // cost provider
|
typedef CYapfCostShipT<Types> PfCost; // cost provider
|
||||||
};
|
};
|
||||||
|
@@ -284,48 +284,13 @@ void Ship::PlayLeaveStationSound() const
|
|||||||
PlayShipSound(this);
|
PlayShipSound(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Of all the docks a station has, return the best destination for a ship.
|
|
||||||
* @param v The ship.
|
|
||||||
* @param st Station the ship \a v is heading for.
|
|
||||||
* @return The free and closest (if none is free, just closest) dock of station \a st to ship \a v.
|
|
||||||
*/
|
|
||||||
const Dock* GetBestDock(const Ship *v, const Station *st)
|
|
||||||
{
|
|
||||||
assert(st != NULL && st->HasFacilities(FACIL_DOCK) && st->docks != NULL);
|
|
||||||
if (st->docks->next == NULL) return st->docks;
|
|
||||||
|
|
||||||
Dock *best_dock = NULL;
|
|
||||||
uint best_distance = UINT_MAX;
|
|
||||||
|
|
||||||
for (Dock *dock = st->docks; dock != NULL; dock = dock->next) {
|
|
||||||
uint new_distance = DistanceManhattan(v->tile, dock->flat);
|
|
||||||
|
|
||||||
if (new_distance < best_distance) {
|
|
||||||
best_dock = dock;
|
|
||||||
best_distance = new_distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(best_dock != NULL);
|
|
||||||
|
|
||||||
return best_dock;
|
|
||||||
}
|
|
||||||
|
|
||||||
TileIndex Ship::GetOrderStationLocation(StationID station)
|
TileIndex Ship::GetOrderStationLocation(StationID station)
|
||||||
{
|
{
|
||||||
if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
|
if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
|
||||||
|
|
||||||
const Station *st = Station::Get(station);
|
const Station *st = Station::Get(station);
|
||||||
if (st->HasFacilities(FACIL_DOCK)) {
|
if (st->HasFacilities(FACIL_DOCK)) {
|
||||||
if (st->docks == NULL) {
|
return st->xy;
|
||||||
return st->xy; // A buoy
|
|
||||||
} else {
|
|
||||||
const Dock* dock = GetBestDock(this, st);
|
|
||||||
|
|
||||||
DiagDirection direction = DiagdirBetweenTiles(dock->sloped, dock->flat);
|
|
||||||
return dock->flat + TileOffsByDiagDir(direction);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this->IncrementRealOrderIndex();
|
this->IncrementRealOrderIndex();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -732,26 +697,23 @@ static void ShipController(Ship *v)
|
|||||||
UpdateVehicleTimetable(v, true);
|
UpdateVehicleTimetable(v, true);
|
||||||
v->IncrementRealOrderIndex();
|
v->IncrementRealOrderIndex();
|
||||||
v->current_order.MakeDummy();
|
v->current_order.MakeDummy();
|
||||||
} else {
|
} else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
||||||
/* Non-buoy orders really need to reach the tile */
|
if (v->dest_tile == gp.new_tile && (gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
|
||||||
if (v->dest_tile == gp.new_tile) {
|
VehicleEnterDepot(v);
|
||||||
if (v->current_order.IsType(OT_GOTO_DEPOT)) {
|
return;
|
||||||
if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
|
}
|
||||||
VehicleEnterDepot(v);
|
} else if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||||
return;
|
Station *st = Station::Get(v->current_order.GetDestination());
|
||||||
}
|
if (st->IsDockingTile(gp.new_tile)) {
|
||||||
} else if (v->current_order.IsType(OT_GOTO_STATION)) {
|
v->last_station_visited = v->current_order.GetDestination();
|
||||||
v->last_station_visited = v->current_order.GetDestination();
|
|
||||||
|
|
||||||
/* Process station in the orderlist. */
|
/* Process station in the orderlist. */
|
||||||
Station *st = Station::Get(v->current_order.GetDestination());
|
if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
|
||||||
if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
|
ShipArrivesAt(v, st);
|
||||||
ShipArrivesAt(v, st);
|
v->BeginLoading();
|
||||||
v->BeginLoading();
|
} else { // leave stations without docks right aways
|
||||||
} else { // leave stations without docks right aways
|
v->current_order.MakeLeaveStation();
|
||||||
v->current_order.MakeLeaveStation();
|
v->IncrementRealOrderIndex();
|
||||||
v->IncrementRealOrderIndex();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -313,6 +313,14 @@ Rect Station::GetCatchmentRectUsingRadius(uint catchment_radius) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Station::IsDockingTile(TileIndex tile) const
|
||||||
|
{
|
||||||
|
for (const Dock *d = this->docks; d != NULL; d = d->next) {
|
||||||
|
if (tile == d->GetDockingTile()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Rect and pointer to IndustryVector */
|
/** Rect and pointer to IndustryVector */
|
||||||
struct RectAndIndustryVector {
|
struct RectAndIndustryVector {
|
||||||
Rect rect; ///< The rectangle to search the industries in.
|
Rect rect; ///< The rectangle to search the industries in.
|
||||||
|
@@ -510,6 +510,8 @@ public:
|
|||||||
return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
|
return IsAirportTile(tile) && GetStationIndex(tile) == this->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsDockingTile(TileIndex tile) const;
|
||||||
|
|
||||||
/* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
|
/* virtual */ uint32 GetNewGRFVariable(const ResolverObject &object, byte variable, byte parameter, bool *available) const;
|
||||||
|
|
||||||
/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
|
/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
|
||||||
|
Reference in New Issue
Block a user