|
@@ -274,182 +274,182 @@ CommandCost CmdBuildRailWaypoint(TileInd
|
|
|
if (flags & DC_EXEC) {
|
|
|
if (wp == NULL) {
|
|
|
wp = new Waypoint(start_tile);
|
|
|
} else if (!wp->IsInUse()) {
|
|
|
/* Move existing (recently deleted) waypoint to the new location */
|
|
|
wp->xy = start_tile;
|
|
|
}
|
|
|
wp->owner = GetTileOwner(start_tile);
|
|
|
|
|
|
wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY);
|
|
|
|
|
|
wp->delete_ctr = 0;
|
|
|
wp->facilities |= FACIL_TRAIN;
|
|
|
wp->build_date = _date;
|
|
|
wp->string_id = STR_SV_STNAME_WAYPOINT;
|
|
|
wp->train_station = new_location;
|
|
|
|
|
|
if (wp->town == NULL) MakeDefaultWaypointName(wp);
|
|
|
|
|
|
wp->UpdateVirtCoord();
|
|
|
|
|
|
const StationSpec *spec = GetCustomStationSpec(spec_class, spec_index);
|
|
|
byte *layout_ptr = AllocaM(byte, count);
|
|
|
if (spec == NULL) {
|
|
|
/* The layout must be 0 for the 'normal' waypoints by design. */
|
|
|
memset(layout_ptr, 0, count);
|
|
|
} else {
|
|
|
/* But for NewGRF waypoints we like to have their style. */
|
|
|
GetStationLayout(layout_ptr, count, 1, spec);
|
|
|
}
|
|
|
byte map_spec_index = AllocateSpecToStation(spec, wp, true);
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
TileIndex tile = start_tile + i * offset;
|
|
|
byte old_specindex = IsTileType(tile, MP_STATION) ? GetCustomStationSpecIndex(tile) : 0;
|
|
|
bool reserved = IsTileType(tile, MP_RAILWAY) ?
|
|
|
HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis)) :
|
|
|
HasStationReservation(tile);
|
|
|
MakeRailWaypoint(tile, wp->owner, wp->index, axis, layout_ptr[i], GetRailType(tile));
|
|
|
SetCustomStationSpecIndex(tile, map_spec_index);
|
|
|
SetRailStationReservation(tile, reserved);
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
|
|
|
DeallocateSpecFromStation(wp, old_specindex);
|
|
|
YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, count * _price[PR_BUILD_DEPOT_TRAIN]);
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, count * _price[PR_BUILD_WAYPOINT_RAIL]);
|
|
|
}
|
|
|
|
|
|
/** Build a buoy.
|
|
|
* @param tile tile where to place the bouy
|
|
|
* @param flags operation to perform
|
|
|
* @param p1 unused
|
|
|
* @param p2 unused
|
|
|
* @param text unused
|
|
|
* @return the cost of this operation or an error
|
|
|
*/
|
|
|
CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
|
|
{
|
|
|
if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
|
|
|
if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
|
|
|
|
|
if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
|
|
|
|
|
|
/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
|
|
|
Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY);
|
|
|
if (wp == NULL && !Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
if (wp == NULL) {
|
|
|
wp = new Waypoint(tile);
|
|
|
} else {
|
|
|
/* Move existing (recently deleted) buoy to the new location */
|
|
|
wp->xy = tile;
|
|
|
InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
|
|
|
}
|
|
|
wp->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
|
|
|
|
|
|
wp->string_id = STR_SV_STNAME_BUOY;
|
|
|
|
|
|
wp->facilities |= FACIL_DOCK;
|
|
|
wp->owner = OWNER_NONE;
|
|
|
|
|
|
wp->build_date = _date;
|
|
|
|
|
|
if (wp->town == NULL) MakeDefaultWaypointName(wp);
|
|
|
|
|
|
MakeBuoy(tile, wp->index, GetWaterClass(tile));
|
|
|
|
|
|
wp->UpdateVirtCoord();
|
|
|
InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_STATION_DOCK]);
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_WAYPOINT_BUOY]);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Remove a buoy
|
|
|
* @param tile TileIndex been queried
|
|
|
* @param flags operation to perform
|
|
|
* @pre IsBuoyTile(tile)
|
|
|
* @return cost or failure of operation
|
|
|
*/
|
|
|
CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
|
|
|
{
|
|
|
/* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
|
|
|
if (!Company::IsValidID(_current_company) && !(flags & DC_BANKRUPT)) return_cmd_error(INVALID_STRING_ID);
|
|
|
|
|
|
Waypoint *wp = Waypoint::GetByTile(tile);
|
|
|
|
|
|
if (HasStationInUse(wp->index, INVALID_COMPANY)) return_cmd_error(STR_ERROR_BUOY_IS_IN_USE);
|
|
|
/* remove the buoy if there is a ship on tile when company goes bankrupt... */
|
|
|
if (!(flags & DC_BANKRUPT) && !EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
wp->facilities &= ~FACIL_DOCK;
|
|
|
|
|
|
InvalidateWindowData(WC_WAYPOINT_VIEW, wp->index);
|
|
|
|
|
|
/* We have to set the water tile's state to the same state as before the
|
|
|
* buoy was placed. Otherwise one could plant a buoy on a canal edge,
|
|
|
* remove it and flood the land (if the canal edge is at level 0) */
|
|
|
MakeWaterKeepingClass(tile, GetTileOwner(tile));
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
|
|
|
wp->rect.AfterRemoveTile(wp, tile);
|
|
|
|
|
|
wp->UpdateVirtCoord();
|
|
|
wp->delete_ctr = 0;
|
|
|
}
|
|
|
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_TRUCK]);
|
|
|
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WAYPOINT_BUOY]);
|
|
|
}
|
|
|
|
|
|
|
|
|
static bool IsUniqueWaypointName(const char *name)
|
|
|
{
|
|
|
const Waypoint *wp;
|
|
|
|
|
|
FOR_ALL_WAYPOINTS(wp) {
|
|
|
if (wp->name != NULL && strcmp(wp->name, name) == 0) return false;
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Rename a waypoint.
|
|
|
* @param tile unused
|
|
|
* @param flags type of operation
|
|
|
* @param p1 id of waypoint
|
|
|
* @param p2 unused
|
|
|
* @param text the new name or an empty string when resetting to the default
|
|
|
* @return the cost of this operation or an error
|
|
|
*/
|
|
|
CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
|
|
{
|
|
|
Waypoint *wp = Waypoint::GetIfValid(p1);
|
|
|
if (wp == NULL || !(CheckOwnership(wp->owner) || wp->owner == OWNER_NONE)) return CMD_ERROR;
|
|
|
|
|
|
bool reset = StrEmpty(text);
|
|
|
|
|
|
if (!reset) {
|
|
|
if (strlen(text) >= MAX_LENGTH_STATION_NAME_BYTES) return CMD_ERROR;
|
|
|
if (!IsUniqueWaypointName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
|
|
|
}
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
free(wp->name);
|
|
|
|
|
|
if (reset) {
|
|
|
MakeDefaultWaypointName(wp); // sets wp->name = NULL
|
|
|
} else {
|
|
|
wp->name = strdup(text);
|
|
|
}
|
|
|
|
|
|
wp->UpdateVirtCoord();
|
|
|
}
|
|
|
return CommandCost();
|
|
|
}
|