Allow building multiple docks per station.

(cherry picked from commit 0110c4a35d383e0be2cbb53cbe9cbe6784abb3e9)

# Conflicts:
#	src/station_cmd.cpp
This commit is contained in:
keldorkatarn
2017-09-11 22:48:19 +02:00
committed by Jonathan G Rennison
parent d486d58d86
commit 1d3cf59d8a
26 changed files with 412 additions and 62 deletions

View File

@@ -38,6 +38,7 @@
#include "elrail_func.h"
#include "station_base.h"
#include "roadstop_base.h"
#include "dock_base.h"
#include "newgrf_railtype.h"
#include "waypoint_base.h"
#include "waypoint_func.h"
@@ -399,7 +400,7 @@ void Station::GetTileArea(TileArea *ta, StationType type) const
case STATION_DOCK:
case STATION_OILRIG:
ta->tile = this->dock_tile;
*ta = this->dock_station;
break;
default: NOT_REACHED();
@@ -2599,41 +2600,43 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile));
TileIndex slope_tile = tile;
DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(slope_tile));
if (direction == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
direction = ReverseDiagDir(direction);
TileIndex flat_tile = slope_tile + TileOffsByDiagDir(direction);
/* Docks cannot be placed on rapids */
if (HasTileWaterGround(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
if (HasTileWaterGround(slope_tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
CommandCost ret = CheckIfAuthorityAllowsNewStation(slope_tile, flags);
if (ret.Failed()) return ret;
if (IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
if (IsBridgeAbove(slope_tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
ret = DoCommand(slope_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (ret.Failed()) return ret;
TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
if (!IsTileType(flat_tile, MP_WATER) || !IsTileFlat(flat_tile)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
if (IsBridgeAbove(tile_cur)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
if (IsBridgeAbove(flat_tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
/* Get the water class of the water tile before it is cleared.*/
WaterClass wc = GetWaterClass(tile_cur);
WaterClass wc = GetWaterClass(flat_tile);
ret = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
ret = DoCommand(flat_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (ret.Failed()) return ret;
tile_cur += TileOffsByDiagDir(direction);
if (!IsTileType(tile_cur, MP_WATER) || !IsTileFlat(tile_cur)) {
TileIndex adjacent_tile = flat_tile + TileOffsByDiagDir(direction);
if (!IsTileType(adjacent_tile, MP_WATER) || !IsTileFlat(adjacent_tile)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
TileArea dock_area = TileArea(tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
TileArea dock_area = TileArea(slope_tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
_dock_w_chk[direction], _dock_h_chk[direction]);
/* middle */
@@ -2644,14 +2647,20 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
/* Distant join */
if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
if (!Dock::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_DOCKS);
ret = BuildStationPart(&st, flags, reuse, dock_area, STATIONNAMING_DOCK);
if (ret.Failed()) return ret;
if (st != NULL && st->dock_tile != INVALID_TILE) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK);
if (flags & DC_EXEC) {
st->dock_tile = tile;
st->AddFacility(FACIL_DOCK, tile);
/* Create the dock and insert it into the list of docks. */
Dock *dock = new Dock(slope_tile, flat_tile);
dock->next = st->docks;
st->docks = dock;
st->dock_station.Add(slope_tile);
st->dock_station.Add(flat_tile);
st->AddFacility(FACIL_DOCK, slope_tile);
st->rect.BeforeAddRect(dock_area.tile, dock_area.w, dock_area.h, StationRect::ADD_TRY);
@@ -2663,7 +2672,7 @@ CommandCost CmdBuildDock(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
Company::Get(st->owner)->infrastructure.station += 2;
DirtyCompanyInfrastructureWindows(st->owner);
MakeDock(tile, st->owner, st->index, direction, wc);
MakeDock(slope_tile, st->owner, st->index, direction, wc);
st->UpdateVirtCoord();
UpdateStationAcceptance(st, false);
@@ -2689,10 +2698,16 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
CommandCost ret = CheckOwnership(st->owner);
if (ret.Failed()) return ret;
TileIndex docking_location = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
Dock *removing_dock = Dock::GetByTile(tile);
assert(removing_dock != NULL);
TileIndex tile1 = st->dock_tile;
TileIndex tile2 = tile1 + TileOffsByDiagDir(GetDockDirection(tile1));
TileIndex tile1 = removing_dock->sloped;
TileIndex tile2 = removing_dock->flat;
DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(removing_dock->sloped));
direction = ReverseDiagDir(direction);
TileIndex docking_location = removing_dock->flat + TileOffsByDiagDir(direction);
ret = EnsureNoVehicleOnGround(tile1);
if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
@@ -2700,6 +2715,26 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
if (flags & DC_EXEC) {
ZoningMarkDirtyStationCoverageArea(st);
st->catchment.AfterRemoveTile(tile1, CA_DOCK);
st->catchment.AfterRemoveTile(tile2, CA_DOCK);
if (st->docks == removing_dock) {
/* The first dock in the list is removed. */
st->docks = removing_dock->next;
/* Last dock is removed. */
if (st->docks == NULL) {
st->facilities &= ~FACIL_DOCK;
}
} else {
/* Tell the predecessor in the list to skip this dock. */
Dock *pred = st->docks;
while (pred->next != removing_dock) pred = pred->next;
pred->next = removing_dock->next;
}
delete removing_dock;
DoClearSquare(tile1);
MarkTileDirtyByTile(tile1);
MakeWaterKeepingClass(tile2, st->owner);
@@ -2707,8 +2742,11 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
st->rect.AfterRemoveTile(st, tile1);
st->rect.AfterRemoveTile(st, tile2);
st->dock_tile = INVALID_TILE;
st->facilities &= ~FACIL_DOCK;
st->dock_station.Clear();
for (Dock *dock = st->docks; dock != NULL; dock = dock->next) {
st->dock_station.Add(dock->flat);
st->dock_station.Add(dock->sloped);
}
Company::Get(st->owner)->infrastructure.station -= 2;
DirtyCompanyInfrastructureWindows(st->owner);
@@ -4028,8 +4066,17 @@ void BuildOilRig(TileIndex tile)
st->owner = OWNER_NONE;
st->airport.type = AT_OILRIG;
st->airport.Add(tile);
st->dock_tile = tile;
st->facilities = FACIL_AIRPORT | FACIL_DOCK;
st->dock_station.tile = tile;
st->facilities = FACIL_AIRPORT;
if (!Dock::CanAllocateItem()) {
DEBUG(misc, 0, "Can't allocate dock for oilrig at 0x%X, reverting to oilrig with airport only", tile);
} else {
st->docks = new Dock(tile, tile + ToTileIndexDiff({1, 0}));
st->dock_station.tile = tile;
st->facilities |= FACIL_DOCK;
}
st->build_date = _date;
st->rect.BeforeAddTile(tile, StationRect::ADD_FORCE);
@@ -4047,7 +4094,11 @@ void DeleteOilRig(TileIndex tile)
MakeWaterKeepingClass(tile, OWNER_NONE);
st->dock_tile = INVALID_TILE;
st->dock_station.tile = INVALID_TILE;
if (st->docks != NULL) {
delete st->docks;
st->docks = NULL;
}
st->airport.Clear();
st->facilities &= ~(FACIL_AIRPORT | FACIL_DOCK);
st->airport.flags = 0;