/** * Remove a lock. * @param tile Central tile of the lock. * @param flags Operation to perform. * @return The cost in case of success, or an error code if it failed. */ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags) { if (GetTileOwner(tile) != OWNER_NONE) { CommandCost ret = CheckTileOwnership(tile); if (ret.Failed()) return ret; } TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile)); /* make sure no vehicle is on the tile. */ CommandCost ret = EnsureNoVehicleOnGround(tile); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta); if (ret.Failed()) return ret; if (flags & DC_EXEC) { DoClearSquare(tile); MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta)); MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta)); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]); }
/** * Builds a lock. * @param tile Central tile of the lock. * @param dir Uphill direction. * @param flags Operation to perform. * @return The cost in case of success, or an error code if it failed. */ static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags) { CommandCost cost(EXPENSES_CONSTRUCTION); int delta = TileOffsByDiagDir(dir); CommandCost ret = EnsureNoVehicleOnGround(tile); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta); if (ret.Failed()) return ret; /* middle tile */ ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); /* lower tile */ WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL; if (!IsWaterTile(tile - delta)) { ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); cost.AddCost(_price[PR_BUILD_CANAL]); } if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } /* upper tile */ WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL; if (!IsWaterTile(tile + delta)) { ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); cost.AddCost(_price[PR_BUILD_CANAL]); } if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) || (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) || (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) { return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); } if (flags & DC_EXEC) { MakeLock(tile, _current_company, dir, wc_lower, wc_upper); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile - delta); MarkTileDirtyByTile(tile + delta); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } cost.AddCost(_price[PR_BUILD_LOCK]); return cost; }
/** build a shiplift */ static CommandCost DoBuildShiplift(TileIndex tile, DiagDirection dir, DoCommandFlag flags) { CommandCost ret; int delta; /* middle tile */ ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return CMD_ERROR; delta = TileOffsByDiagDir(dir); /* lower tile */ WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL; ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return CMD_ERROR; if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } /* upper tile */ WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL; ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return CMD_ERROR; if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } if ((MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) || (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) || (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) { return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); } if (flags & DC_EXEC) { MakeLock(tile, _current_company, dir, wc_lower, wc_upper); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile - delta); MarkTileDirtyByTile(tile + delta); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER] * 22 >> 3); }
/** * Build a piece of canal. * @param tile end tile of stretch-dragging * @param flags type of operation * @param p1 start tile of stretch-dragging * @param p2 waterclass to build. sea and river can only be built in scenario editor * @param text unused * @return the cost of this operation or an error */ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { WaterClass wc = Extract<WaterClass, 0, 2>(p2); if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR; /* Outside of the editor you can only build canals, not oceans */ if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR; TileArea ta(tile, p1); /* Outside the editor you can only drag canals, and not areas */ if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR; CommandCost cost(EXPENSES_CONSTRUCTION); TILE_AREA_LOOP(tile, ta) { CommandCost ret; Slope slope = GetTileSlope(tile, NULL); if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); } /* can't make water of water! */ if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue; ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); if (flags & DC_EXEC) { switch (wc) { case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break; case WATER_CLASS_SEA: if (TileHeight(tile) == 0) { MakeSea(tile); break; } /* FALL THROUGH */ default: MakeCanal(tile, _current_company, Random()); break; } MarkTileDirtyByTile(tile); MarkCanalsAndRiversAroundDirty(tile); } cost.AddCost(_price[PR_BUILD_CANAL]); }
static CommandCost RemoveShiplift(TileIndex tile, DoCommandFlag flags) { TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile)); if (!CheckTileOwnership(tile) && GetTileOwner(tile) != OWNER_NONE) return CMD_ERROR; /* make sure no vehicle is on the tile. */ if (!EnsureNoVehicleOnGround(tile) || !EnsureNoVehicleOnGround(tile + delta) || !EnsureNoVehicleOnGround(tile - delta)) return CMD_ERROR; if (flags & DC_EXEC) { DoClearSquare(tile); MakeWaterKeepingClass(tile + delta, GetTileOwner(tile)); MakeWaterKeepingClass(tile - delta, GetTileOwner(tile)); MarkTileDirtyByTile(tile - delta); MarkTileDirtyByTile(tile + delta); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER] * 2); }
/** * Remove a lock. * @param tile Central tile of the lock. * @param flags Operation to perform. * @return The cost in case of success, or an error code if it failed. */ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags) { if (GetTileOwner(tile) != OWNER_NONE) { CommandCost ret = CheckTileOwnership(tile); if (ret.Failed()) return ret; } TileIndexDiff delta = TileOffsByDiagDir(GetLockDirection(tile)); /* make sure no vehicle is on the tile. */ CommandCost ret = EnsureNoVehicleOnGround(tile); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta); if (ret.Failed()) return ret; if (flags & DC_EXEC) { /* Remove middle part from company infrastructure count. */ Company *c = Company::GetIfValid(GetTileOwner(tile)); if (c != NULL) { c->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // three parts of the lock. DirtyCompanyInfrastructureWindows(c->index); } if (GetWaterClass(tile) == WATER_CLASS_RIVER) { MakeRiver(tile, Random()); } else { DoClearSquare(tile); } MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta)); MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta)); MarkCanalsAndRiversAroundDirty(tile); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]); }
/** Build a piece of canal. * @param tile end tile of stretch-dragging * @param flags type of operation * @param p1 start tile of stretch-dragging * @param p2 specifies canal (0), water (1) or river (2); last two can only be built in scenario editor * @param text unused * @return the cost of this operation or an error */ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost cost(EXPENSES_CONSTRUCTION); if (p1 >= MapSize()) return CMD_ERROR; /* Outside of the editor you can only build canals, not oceans */ if (p2 != 0 && _game_mode != GM_EDITOR) return CMD_ERROR; TileArea ta(tile, p1); /* Outside the editor you can only drag canals, and not areas */ if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR; TILE_AREA_LOOP(tile, ta) { CommandCost ret; Slope slope = GetTileSlope(tile, NULL); if (slope != SLOPE_FLAT && (p2 != 2 || !IsInclinedSlope(slope))) { return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED); } /* can't make water of water! */ if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || p2 == 1)) continue; ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) return ret; cost.AddCost(ret); if (flags & DC_EXEC) { if (TileHeight(tile) == 0 && p2 == 1) { MakeSea(tile); } else if (p2 == 2) { MakeRiver(tile, Random()); } else { MakeCanal(tile, _current_company, Random()); } MarkTileDirtyByTile(tile); MarkCanalsAndRiversAroundDirty(tile); } cost.AddCost(_price[PR_CLEAR_WATER]); }
/** * Builds a lock. * @param tile Central tile of the lock. * @param dir Uphill direction. * @param flags Operation to perform. * @return The cost in case of success, or an error code if it failed. */ static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags) { CommandCost cost(EXPENSES_CONSTRUCTION); int delta = TileOffsByDiagDir(dir); CommandCost ret = EnsureNoVehicleOnGround(tile); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta); if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta); if (ret.Failed()) return ret; /* middle tile */ WaterClass wc_middle = IsWaterTile(tile) ? GetWaterClass(tile) : WATER_CLASS_CANAL; ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); /* lower tile */ if (!IsWaterTile(tile - delta)) { ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); cost.AddCost(_price[PR_BUILD_CANAL]); } if (!IsTileFlat(tile - delta)) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL; /* upper tile */ if (!IsWaterTile(tile + delta)) { ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return ret; cost.AddCost(ret); cost.AddCost(_price[PR_BUILD_CANAL]); } if (!IsTileFlat(tile + delta)) { return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL; if (IsBridgeAbove(tile) || IsBridgeAbove(tile - delta) || IsBridgeAbove(tile + delta)) { return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); } if (flags & DC_EXEC) { /* Update company infrastructure counts. */ Company *c = Company::GetIfValid(_current_company); if (c != NULL) { /* Counts for the water. */ if (!IsWaterTile(tile - delta)) c->infrastructure.water++; if (!IsWaterTile(tile + delta)) c->infrastructure.water++; /* Count for the lock itself. */ c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock is three tiles. DirtyCompanyInfrastructureWindows(_current_company); } MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle); MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile - delta); MarkTileDirtyByTile(tile + delta); MarkCanalsAndRiversAroundDirty(tile - delta); MarkCanalsAndRiversAroundDirty(tile + delta); } cost.AddCost(_price[PR_BUILD_LOCK]); return cost; }