diff --git a/src/command.cpp b/src/command.cpp index 23500fefe5..706f080ad7 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -54,6 +54,7 @@ CommandProc CmdRemoveSingleSignal; CommandProc CmdTerraformLand; CommandProc CmdBuildObject; +CommandProc CmdPurchaseLandArea; CommandProc CmdBuildHouse; CommandProc CmdSellLandArea; @@ -280,6 +281,7 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdRemoveSingleSignal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_SIGNALS DEF_CMD(CmdTerraformLand, CMD_ALL_TILES | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_TERRAFORM_LAND DEF_CMD(CmdBuildObject, CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_OBJECT + DEF_CMD(CmdPurchaseLandArea, CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_PURCHASE_LAND_AREA DEF_CMD(CmdBuildHouse, CMD_DEITY | CMD_NO_WATER | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_HOUSE DEF_CMD(CmdBuildTunnel, CMD_DEITY | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_TUNNEL DEF_CMD(CmdRemoveFromRailStation, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_FROM_RAIL_STATION diff --git a/src/command_type.h b/src/command_type.h index c130633963..fad1f5739d 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -225,6 +225,7 @@ enum Commands { CMD_REMOVE_SIGNALS, ///< remove a signal CMD_TERRAFORM_LAND, ///< terraform a tile CMD_BUILD_OBJECT, ///< build an object + CMD_PURCHASE_LAND_AREA, ///< purchase an area of landscape CMD_BUILD_HOUSE, ///< build a house CMD_BUILD_TUNNEL, ///< build a tunnel diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 244faec5e6..dad7ef50f7 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -362,6 +362,60 @@ CommandCost CmdBuildObject(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 return cost; } +/** + * Buy a big piece of landscape + * @param tile end tile of area dragging + * @param flags of operation to conduct + * @param p1 start tile of area dragging + * @param p2 various bitstuffed data. + * bit 0: Whether to use the Orthogonal (0) or Diagonal (1) iterator. + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdPurchaseLandArea(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (p1 >= MapSize()) return CMD_ERROR; + + Money money = GetAvailableMoneyForCommand(); + CommandCost cost(EXPENSES_CONSTRUCTION); + CommandCost last_error = CMD_ERROR; + bool had_success = false; + + const Company *c = Company::GetIfValid(_current_company); + int limit = (c == NULL ? INT32_MAX : GB(c->purchase_land_limit, 16, 16)); + + TileIterator *iter = HasBit(p2, 0) ? (TileIterator *)new DiagonalTileIterator(tile, p1) : new OrthogonalTileIterator(tile, p1); + for (; *iter != INVALID_TILE; ++(*iter)) { + TileIndex t = *iter; + CommandCost ret = DoCommand(t, OBJECT_OWNED_LAND, 0, flags & ~DC_EXEC, CMD_BUILD_OBJECT); + if (ret.Failed()) { + last_error = ret; + + /* We may not clear more tiles. */ + if (c != NULL && GB(c->purchase_land_limit, 16, 16) < 1) break; + continue; + } + + had_success = true; + if (flags & DC_EXEC) { + money -= ret.GetCost(); + if (ret.GetCost() > 0 && money < 0) { + _additional_cash_required = ret.GetCost(); + delete iter; + return cost; + } + DoCommand(t, OBJECT_OWNED_LAND, 0, flags, CMD_BUILD_OBJECT); + } else { + /* When we're at the clearing limit we better bail (unneed) testing as well. */ + if (ret.GetCost() != 0 && --limit <= 0) break; + } + cost.AddCost(ret); + } + + delete iter; + return had_success ? cost : last_error; +} + static Foundation GetFoundation_Object(TileIndex tile, Slope tileh); diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index 9d282964d1..9df8866f24 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -134,6 +134,9 @@ bool GUIPlaceProcDragXY(ViewportDragDropSelectionProcess proc, TileIndex start_t case DDSP_CREATE_DESERT: GenerateDesertArea(end_tile, start_tile); break; + case DDSP_BUY_LAND: + DoCommandP(end_tile, start_tile, _ctrl_pressed ? 1 : 0, CMD_PURCHASE_LAND_AREA | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_SPLAT_RAIL); + break; default: return false; } @@ -204,7 +207,7 @@ struct TerraformToolbarWindow : Window { break; case WID_TT_BUY_LAND: // Buy land button - HandlePlacePushButton(this, WID_TT_BUY_LAND, SPR_CURSOR_BUY_LAND, HT_RECT); + HandlePlacePushButton(this, WID_TT_BUY_LAND, SPR_CURSOR_BUY_LAND, HT_RECT | HT_DIAGONAL); this->last_user_action = widget; break; @@ -250,7 +253,7 @@ struct TerraformToolbarWindow : Window { break; case WID_TT_BUY_LAND: // Buy land button - DoCommandP(tile, OBJECT_OWNED_LAND, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_PURCHASE_THIS_LAND), CcPlaySound_SPLAT_RAIL); + VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_BUY_LAND); break; case WID_TT_MEASUREMENT_TOOL: @@ -286,6 +289,7 @@ struct TerraformToolbarWindow : Window { case DDSP_RAISE_AND_LEVEL_AREA: case DDSP_LOWER_AND_LEVEL_AREA: case DDSP_LEVEL_AREA: + case DDSP_BUY_LAND: GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; case DDSP_MEASURE: @@ -724,6 +728,7 @@ struct ScenarioEditorLandscapeGenerationWindow : Window { case DDSP_LOWER_AND_LEVEL_AREA: case DDSP_LEVEL_AREA: case DDSP_DEMOLISH_AREA: + case DDSP_BUY_LAND: GUIPlaceProcDragXY(select_proc, start_tile, end_tile); break; } diff --git a/src/viewport_type.h b/src/viewport_type.h index 7b9ce33c80..7892b3199c 100644 --- a/src/viewport_type.h +++ b/src/viewport_type.h @@ -121,6 +121,7 @@ enum ViewportDragDropSelectionProcess { DDSP_BUILD_BRIDGE, ///< Bridge placement DDSP_MEASURE, ///< Measurement tool DDSP_DRAW_PLANLINE, ///< Draw a line for a plan + DDSP_BUY_LAND, ///< Purchase land /* Rail specific actions */ DDSP_PLACE_RAIL, ///< Rail placement