mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Adapt some functions that located the depot with its tile.
parent
373f9fe5ef
commit
f8bc259ec0
|
@ -519,6 +519,7 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
|||
{
|
||||
Vehicle *old_head = *chain;
|
||||
assert(old_head->IsPrimaryVehicle());
|
||||
TileIndex tile = old_head->tile;
|
||||
|
||||
CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES, (Money)0);
|
||||
|
||||
|
@ -661,6 +662,9 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon
|
|||
if ((flags & DC_EXEC) != 0) CheckCargoCapacity(new_head);
|
||||
}
|
||||
|
||||
assert(IsValidTile(tile));
|
||||
if (!HasCompatibleDepotTile(tile, Train::From(new_head))) cost.MakeError(STR_ERROR_UNABLE_TO_FIND_APPROPRIATE_DEPOT_TILE);
|
||||
|
||||
/* If we are not in DC_EXEC undo everything, i.e. rearrange old vehicles.
|
||||
* We do this from back to front, so that the head of the temporary vehicle chain does not change all the time.
|
||||
* Note: The vehicle attach callback is disabled here :) */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "vehicle_gui.h"
|
||||
#include "vehiclelist.h"
|
||||
#include "command_func.h"
|
||||
#include "vehicle_base.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
@ -41,6 +42,15 @@ Depot::~Depot()
|
|||
/* Clear the order backup. */
|
||||
OrderBackup::Reset(this->index, false);
|
||||
|
||||
/* Make sure no vehicle is going to the old depot. */
|
||||
for (Vehicle *v : Vehicle::Iterate()) {
|
||||
if (v->First() != v) continue;
|
||||
if (!v->current_order.IsType(OT_GOTO_DEPOT)) continue;
|
||||
if (v->current_order.GetDestination() != this->index) continue;
|
||||
|
||||
v->current_order.MakeDummy();
|
||||
}
|
||||
|
||||
/* Clear the depot from all order-lists */
|
||||
RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->index);
|
||||
|
||||
|
@ -53,6 +63,29 @@ Depot::~Depot()
|
|||
this->veh_type, this->owner, this->index).Pack());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
TileIndex Depot::GetBestDepotTile(Vehicle *v) const
|
||||
{
|
||||
assert(this->veh_type == v->type);
|
||||
TileIndex best_depot = INVALID_TILE;
|
||||
uint best_distance = UINT_MAX;
|
||||
|
||||
for (const auto &tile : this->depot_tiles) {
|
||||
uint new_distance = DistanceManhattan(v->tile, tile);
|
||||
if (new_distance < best_distance) {
|
||||
best_depot = tile;
|
||||
best_distance = new_distance;
|
||||
}
|
||||
}
|
||||
|
||||
return best_depot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check we can add some tiles to this depot.
|
||||
* @param ta The affected tile area.
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef Pool<Depot, DepotID, 64, MAX_DEPOTS> DepotPool;
|
|||
extern DepotPool _depot_pool;
|
||||
|
||||
class CommandCost;
|
||||
struct Vehicle;
|
||||
|
||||
struct Depot : DepotPool::PoolItem<&_depot_pool> {
|
||||
/* DepotID index member of DepotPool is 2 bytes. */
|
||||
|
@ -64,6 +65,8 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> {
|
|||
return Depot::Get(GetDepotIndex(tile));
|
||||
}
|
||||
|
||||
TileIndex GetBestDepotTile(Vehicle *v) const;
|
||||
|
||||
/**
|
||||
* Is the "type" of depot the same as the given depot,
|
||||
* i.e. are both a rail, road or ship depots?
|
||||
|
|
|
@ -5146,6 +5146,7 @@ STR_ERROR_CAN_T_MOVE_VEHICLE :{WHITE}Can't mo
|
|||
STR_ERROR_REAR_ENGINE_FOLLOW_FRONT :{WHITE}The rear engine will always follow its front counterpart
|
||||
STR_ERROR_UNABLE_TO_FIND_ROUTE_TO :{WHITE}Unable to find route to local depot
|
||||
STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT :{WHITE}Unable to find local depot
|
||||
STR_ERROR_UNABLE_TO_FIND_APPROPRIATE_DEPOT_TILE :{WHITE}Unable to find appropriate depot tile
|
||||
|
||||
STR_ERROR_DEPOT_TOO_SPREAD_OUT :{WHITE}... depot too spread out
|
||||
STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :Wrong depot type
|
||||
|
|
|
@ -2033,7 +2033,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
|
|||
v->IncrementRealOrderIndex();
|
||||
} else {
|
||||
if (v->type != VEH_AIRCRAFT) {
|
||||
v->SetDestTile(Depot::Get(order->GetDestination())->xy);
|
||||
v->SetDestTile(Depot::Get(order->GetDestination())->GetBestDepotTile(v));
|
||||
} else {
|
||||
Aircraft *a = Aircraft::From(v);
|
||||
DestinationID destination_depot = a->current_order.GetDestination();
|
||||
|
|
|
@ -1056,7 +1056,9 @@ bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
|
|||
|
||||
if (first) {
|
||||
/* We are leaving a depot, but have to go to the exact same one; re-enter */
|
||||
if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
|
||||
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
||||
IsRoadDepotTile(v->tile) &&
|
||||
v->current_order.GetDestination() == GetDepotIndex(v->tile)) {
|
||||
VehicleEnterDepot(v);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -187,8 +187,9 @@ static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
|
|||
const Depot *best_depot = nullptr;
|
||||
uint best_dist_sq = std::numeric_limits<uint>::max();
|
||||
for (const Depot *depot : Depot::Iterate()) {
|
||||
if (depot->veh_type != VEH_SHIP || depot->owner != v->owner) continue;
|
||||
|
||||
const TileIndex tile = depot->xy;
|
||||
if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
|
||||
const uint dist_sq = DistanceSquare(tile, v->tile);
|
||||
if (dist_sq < best_dist_sq && dist_sq <= max_distance * max_distance &&
|
||||
visited_patch_hashes.count(CalculateWaterRegionPatchHash(GetWaterRegionPatchInfo(tile))) > 0) {
|
||||
|
@ -196,7 +197,6 @@ static const Depot *FindClosestShipDepot(const Vehicle *v, uint max_distance)
|
|||
best_depot = depot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return best_depot;
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ static void CheckIfShipNeedsService(Vehicle *v)
|
|||
}
|
||||
|
||||
v->current_order.MakeGoToDepot(depot->index, ODTFB_SERVICE);
|
||||
v->SetDestTile(depot->xy);
|
||||
v->SetDestTile(depot->GetBestDepotTile(v));
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
}
|
||||
|
||||
|
@ -962,5 +962,5 @@ ClosestDepot Ship::FindClosestDepot()
|
|||
const Depot *depot = FindClosestShipDepot(this, MAX_SHIP_DEPOT_SEARCH_DISTANCE);
|
||||
if (depot == nullptr) return ClosestDepot();
|
||||
|
||||
return ClosestDepot(depot->xy, depot->index);
|
||||
return ClosestDepot(depot->GetBestDepotTile(this), depot->index);
|
||||
}
|
||||
|
|
|
@ -353,4 +353,6 @@ protected: // These functions should not be called outside acceleration code.
|
|||
}
|
||||
};
|
||||
|
||||
bool HasCompatibleDepotTile(TileIndex tile, const Train *t);
|
||||
|
||||
#endif /* TRAIN_H */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
/** @file train_cmd.cpp Handling of trains. */
|
||||
|
||||
#include "depot_map.h"
|
||||
#include "stdafx.h"
|
||||
#include "error.h"
|
||||
#include "articulated_vehicles.h"
|
||||
|
@ -38,6 +39,7 @@
|
|||
#include "misc_cmd.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "timer/timer_game_economy.h"
|
||||
#include "depot_base.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/train_sprites.h"
|
||||
|
@ -604,6 +606,65 @@ void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if a train chain is compatible with a depot tile.
|
||||
* @param tile Tile to check.
|
||||
* @param t Train chain to check.
|
||||
* @return Whether the full train chain is compatible with this tile.
|
||||
*/
|
||||
bool IsVehicleCompatibleWithDepotTile(TileIndex tile, const Train *t)
|
||||
{
|
||||
assert(IsRailDepotTile(tile));
|
||||
for (const Train *u = t; u != nullptr; u = u->Next()) {
|
||||
RailType rail_type = Engine::Get(u->engine_type)->u.rail.railtype;
|
||||
if (!IsCompatibleRail(rail_type, GetRailType(tile))) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a depot has a tile where a train chain can be stored.
|
||||
* @param tile A tile of the depot.
|
||||
* @param t The train to check.
|
||||
* @return True iff the depot has a tile compatible with the chain.
|
||||
*/
|
||||
bool HasCompatibleDepotTile(TileIndex tile, const Train *t)
|
||||
{
|
||||
assert(IsRailDepotTile(tile));
|
||||
Depot *dep = Depot::GetByTile(tile);
|
||||
|
||||
for (auto &depot_tile : dep->depot_tiles) {
|
||||
if (IsVehicleCompatibleWithDepotTile(depot_tile, t)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a tile of a depot compatible with the rail type of a rail vehicle.
|
||||
* @param depot_id Index of the depot.
|
||||
* @param rail_type Rail type of the new vehicle.
|
||||
* @param is_engine Whether the vehicle is an engine.
|
||||
* @return A compatible tile of the depot or INVALID_TILE if no compatible tile is found.
|
||||
*/
|
||||
TileIndex FindCompatibleDepotTile(DepotID depot_id, RailType rail_type, bool is_engine)
|
||||
{
|
||||
assert(Depot::IsValidID(depot_id));
|
||||
Depot *depot = Depot::Get(depot_id);
|
||||
|
||||
for (auto &dep_tile : depot->depot_tiles) {
|
||||
if (is_engine) {
|
||||
if (HasPowerOnRail(rail_type, GetRailType(dep_tile))) return dep_tile;
|
||||
} else {
|
||||
if (IsCompatibleRail(rail_type, GetRailType(dep_tile))) return dep_tile;
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_TILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a railroad wagon.
|
||||
* @param flags type of operation.
|
||||
|
@ -616,9 +677,11 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
|
|||
{
|
||||
const RailVehicleInfo *rvi = &e->u.rail;
|
||||
assert(IsRailDepotTile(tile));
|
||||
DepotID depot_id = GetDepotIndex(tile);
|
||||
|
||||
/* Check that the wagon can drive on the track in question */
|
||||
if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
|
||||
/* Find a good tile to place the wagon. */
|
||||
tile = FindCompatibleDepotTile(depot_id, rvi->railtype, false);
|
||||
if (tile == INVALID_TILE) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
Train *v = new Train();
|
||||
|
@ -646,7 +709,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
|
|||
v->SetWagon();
|
||||
|
||||
v->SetFreeWagon();
|
||||
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(tile));
|
||||
InvalidateWindowData(WC_VEHICLE_DEPOT, depot_id);
|
||||
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
|
@ -674,7 +737,8 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
|
|||
|
||||
/* Try to connect the vehicle to one of free chains of wagons. */
|
||||
for (Train *w : Train::Iterate()) {
|
||||
if (w->tile == tile && ///< Same depot
|
||||
if (!IsRailDepotTile(w->tile)) continue;
|
||||
if (GetDepotIndex(w->tile) == depot_id && ///< Same depot
|
||||
w->IsFreeWagon() && ///< A free wagon chain
|
||||
w->engine_type == e->index && ///< Same type
|
||||
w->First() != v && ///< Don't connect to ourself
|
||||
|
@ -693,9 +757,10 @@ static CommandCost CmdBuildRailWagon(DoCommandFlag flags, TileIndex tile, const
|
|||
void NormalizeTrainVehInDepot(const Train *u)
|
||||
{
|
||||
assert(u->IsEngine());
|
||||
DepotID dep_id = GetDepotIndex(u->tile);
|
||||
for (const Train *v : Train::Iterate()) {
|
||||
if (v->IsFreeWagon() && v->tile == u->tile &&
|
||||
v->track == TRACK_BIT_DEPOT) {
|
||||
if (v->IsFreeWagon() && v->IsInDepot() &&
|
||||
GetDepotIndex(v->tile) == dep_id) {
|
||||
if (Command<CMD_MOVE_RAIL_VEHICLE>::Do(DC_EXEC, v->index, u->index, true).Failed()) {
|
||||
break;
|
||||
}
|
||||
|
@ -749,13 +814,14 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
|
|||
*/
|
||||
CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
|
||||
{
|
||||
assert(IsRailDepotTile(tile));
|
||||
const RailVehicleInfo *rvi = &e->u.rail;
|
||||
|
||||
if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(flags, tile, e, ret);
|
||||
|
||||
/* Check if depot and new engine uses the same kind of tracks *
|
||||
* We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
|
||||
if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
|
||||
/* Find a good tile to place the engine and get power on it. */
|
||||
tile = FindCompatibleDepotTile(GetDepotIndex(tile), rvi->railtype, true);
|
||||
if (tile == INVALID_TILE) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
DiagDirection dir = GetRailDepotDirection(tile);
|
||||
|
@ -825,10 +891,10 @@ CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engin
|
|||
static Train *FindGoodVehiclePos(const Train *src)
|
||||
{
|
||||
EngineID eng = src->engine_type;
|
||||
TileIndex tile = src->tile;
|
||||
DepotID dep_id = GetDepotIndex(src->tile);
|
||||
|
||||
for (Train *dst : Train::Iterate()) {
|
||||
if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED)) {
|
||||
if (dst->IsFreeWagon() && !(dst->vehstatus & VS_CRASHED) && GetDepotIndex(dst->tile) == dep_id) {
|
||||
/* check so all vehicles in the line have the same engine. */
|
||||
Train *t = dst;
|
||||
while (t->engine_type == eng) {
|
||||
|
@ -1230,7 +1296,7 @@ CommandCost CmdMoveRailVehicle(DoCommandFlag flags, VehicleID src_veh, VehicleID
|
|||
Train *dst_head;
|
||||
if (dst != nullptr) {
|
||||
dst_head = dst->First();
|
||||
if (dst_head->tile != src_head->tile) return CMD_ERROR;
|
||||
if (GetDepotIndex(dst_head->tile) != GetDepotIndex(src_head->tile)) return CMD_ERROR;
|
||||
/* Now deal with articulated part of destination wagon */
|
||||
dst = dst->GetLastEnginePart();
|
||||
} else {
|
||||
|
@ -2303,7 +2369,9 @@ static bool CheckTrainStayInDepot(Train *v)
|
|||
}
|
||||
|
||||
/* We are leaving a depot, but have to go to the exact same one; re-enter. */
|
||||
if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) {
|
||||
if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
||||
IsRailDepotTile(v->tile) &&
|
||||
v->current_order.GetDestination() == GetDepotIndex(v->tile)) {
|
||||
/* Service when depot has no reservation. */
|
||||
if (!HasDepotReservation(v->tile)) VehicleEnterDepot(v);
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue