mirror of https://github.com/OpenTTD/OpenTTD
Change: Add additional rules for placing trains in depots according to railtypes.
parent
8d5eca7097
commit
b5e04974be
|
@ -5138,6 +5138,7 @@ STR_ERROR_AIRCRAFT_MUST_BE_STOPPED_INSIDE_HANGAR :{WHITE}... must
|
|||
|
||||
STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT :{WHITE}Trains can only be altered when stopped inside a depot
|
||||
STR_ERROR_TRAIN_TOO_LONG :{WHITE}Train too long
|
||||
STR_ERROR_INCOMPATIBLE_RAILTYPES_WITH_DEPOT :{WHITE}Train chain is incompatible with any tile of this depot
|
||||
STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE :{WHITE}Can't reverse direction of vehicle...
|
||||
STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE_MULTIPLE_UNITS :{WHITE}... consists of multiple units
|
||||
STR_ERROR_INCOMPATIBLE_RAIL_TYPES :Incompatible rail types
|
||||
|
|
|
@ -1050,6 +1050,82 @@ static CommandCost CheckNewTrain(Train *original_dst, Train *dst, Train *origina
|
|||
return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a train can be placed in a depot tile.
|
||||
* @param train The train.
|
||||
* @param tile The tile to check whether it is possible to place the train.
|
||||
* @return whether it found a depot tile in which to place the train.
|
||||
*/
|
||||
bool CheckPlacement(const Train *train, TileIndex tile)
|
||||
{
|
||||
assert(train != nullptr);
|
||||
assert(IsRailDepotTile(tile));
|
||||
|
||||
RailType rt = GetRailType(tile);
|
||||
for (const Train *t = train; t != nullptr; t = t->Next()) {
|
||||
RailType rail_type = Engine::Get(t->engine_type)->u.rail.railtype;
|
||||
if (!IsCompatibleRail(rail_type, rt)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a valid tile before placing a train in the depot.
|
||||
* @param t The train to place in a rail depot tile.
|
||||
* @return a compatible tile, if any, preferabily the one the first vehicle is or INVALID_TILE if none found.
|
||||
*/
|
||||
TileIndex LookForTileInDepot(const Train *train)
|
||||
{
|
||||
assert(train != nullptr);
|
||||
assert(IsRailDepotTile(train->tile));
|
||||
TileIndex best_tile = INVALID_TILE;
|
||||
|
||||
/* First candidate is the original position of the train. */
|
||||
if (CheckPlacement(train, train->tile)) {
|
||||
if (HasPowerOnRail(train->railtype, GetRailType(train->tile))) return train->tile;
|
||||
best_tile = train->tile;
|
||||
}
|
||||
|
||||
/* Check all depot tiles. */
|
||||
Depot *depot = Depot::GetByTile(train->tile);
|
||||
for (std::vector<TileIndex>::iterator it = depot->depot_tiles.begin(); it != depot->depot_tiles.end(); ++it) {
|
||||
if (CheckPlacement(train, *it)) {
|
||||
if (HasPowerOnRail(train->railtype, GetRailType(*it))) return *it;
|
||||
if (best_tile == INVALID_TILE) best_tile = *it;
|
||||
}
|
||||
}
|
||||
|
||||
return best_tile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an appropriate depot tile for a train and place
|
||||
* all the vehicle chain in the same depot tile.
|
||||
* @param train The train to place.
|
||||
*/
|
||||
void PlaceOnRailDepot(Train *train)
|
||||
{
|
||||
assert(train->First() == train);
|
||||
|
||||
TileIndex depot_tile = LookForTileInDepot(train);
|
||||
assert(depot_tile != INVALID_TILE);
|
||||
|
||||
DiagDirection diag_dir = GetRailDepotDirection(depot_tile);
|
||||
int x = TileX(depot_tile) * TILE_SIZE + _vehicle_initial_x_fract[diag_dir];
|
||||
int y = TileY(depot_tile) * TILE_SIZE + _vehicle_initial_y_fract[diag_dir];
|
||||
for (Train *t = train; t != nullptr; t = t->Next()) {
|
||||
t->tile = depot_tile;
|
||||
t->direction = DiagDirToDir(diag_dir);
|
||||
t->vehstatus |= VS_HIDDEN;
|
||||
t->track = TRACK_BIT_DEPOT;
|
||||
t->x_pos = x;
|
||||
t->y_pos = y;
|
||||
t->z_pos = GetSlopePixelZ(x, y);
|
||||
t->UpdatePosition();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the train parts can be attached.
|
||||
* @param t the train to check
|
||||
|
@ -1060,6 +1136,8 @@ static CommandCost CheckTrainAttachment(Train *t)
|
|||
/* No multi-part train, no need to check. */
|
||||
if (t == nullptr || t->Next() == nullptr) return CommandCost();
|
||||
|
||||
if (LookForTileInDepot(t) == INVALID_TILE) return_cmd_error(STR_ERROR_INCOMPATIBLE_RAILTYPES_WITH_DEPOT);
|
||||
|
||||
/* The maximum length for a train. For each part we decrease this by one
|
||||
* and if the result is negative the train is simply too long. */
|
||||
int allowed_len = _settings_game.vehicle.max_train_length * TILE_SIZE - t->gcache.cached_veh_length;
|
||||
|
@ -1425,8 +1503,15 @@ CommandCost CmdMoveRailVehicle(DoCommandFlag flags, VehicleID src_veh, VehicleID
|
|||
CheckCargoCapacity(dst_head);
|
||||
}
|
||||
|
||||
if (src_head != nullptr) src_head->First()->MarkDirty();
|
||||
if (dst_head != nullptr) dst_head->First()->MarkDirty();
|
||||
if (src_head != nullptr) {
|
||||
PlaceOnRailDepot(src_head->First());
|
||||
src_head->First()->MarkDirty();
|
||||
}
|
||||
|
||||
if (dst_head != nullptr) {
|
||||
PlaceOnRailDepot(dst_head->First());
|
||||
dst_head->First()->MarkDirty();
|
||||
}
|
||||
|
||||
/* We are undoubtedly changing something in the depot and train list. */
|
||||
InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(src->tile));
|
||||
|
|
Loading…
Reference in New Issue