1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-27 00:34:46 +01:00

Merge pull request #22490 from AaronVanGeffen/rework-landrights

Integrate Map window's land ownership tool in LandRights window
This commit is contained in:
Aaron van Geffen
2024-08-11 12:26:29 +02:00
committed by GitHub
7 changed files with 317 additions and 367 deletions

View File

@@ -3728,6 +3728,8 @@ STR_6653 :All sources shown
STR_6654 :Showing {POP16}{UINT16} sources
STR_6655 :Only {POP16}{STRINGID}
STR_6656 :Remove all fences from the park
STR_6657 :Land Not Owned
STR_6658 :Set land to be not owned by the park, nor available for purchase
#############
# Scenarios #

View File

@@ -6,6 +6,8 @@
- Feature: [#22414] Finance graphs can be resized.
- Change: [#21659] Increase the Hybrid Roller Coasters maximum lift speed to 17 km/h (11 mph).
- Change: [#22466] The Clear Scenery tool now uses a bulldozer cursor instead of a generic crosshair.
- Change: [#22490] The tool to change land and construction rights has been moved out of the Map window.
- Change: [#22490] In sandbox mode, changing land or construction rights now acts as buying or selling.
- Change: [#22491] Scrollbars are now hidden if the scrollable widget is not actually overflowing.
- Fix: [#21908] Errors showing up when placing/moving track design previews.
- Fix: [#22307] Hover tooltips in financial charts are not invalidated properly.

View File

@@ -819,9 +819,19 @@ namespace OpenRCT2
STR_ADJUST_SMALLER_LAND_RIGHTS_TIP = 5133,
STR_BUY_CONSTRUCTION_RIGHTS_TIP = 2326,
STR_BUY_LAND_RIGHTS_TIP = 2325,
STR_CONSTRUCTION_RIGHTS_OWNED = 3218,
STR_CONSTRUCTION_RIGHTS_SALE = 3220,
STR_LAND_NOT_OWNED = 6657,
STR_LAND_OWNED = 3217,
STR_LAND_RIGHTS = 5136,
STR_LAND_SALE = 3219,
STR_NO_CONSTRUCTION_RIGHTS_FOR_SALE_TIP = 5989,
STR_NO_LAND_RIGHTS_FOR_SALE_TIP = 5988,
STR_SET_CONSTRUCTION_RIGHTS_TO_BE_AVAILABLE_TIP = 3224,
STR_SET_CONSTRUCTION_RIGHTS_TO_BE_OWNED_TIP = 3222,
STR_SET_LAND_TO_BE_AVAILABLE_TIP = 3223,
STR_SET_LAND_TO_BE_NOT_OWNED_TIP = 6658,
STR_SET_LAND_TO_BE_OWNED_TIP = 3221,
// Window: LoadSave
STR_DATE = 5374,
@@ -859,10 +869,6 @@ namespace OpenRCT2
// Window: Map
STR_BUILD_PARK_ENTRANCE_TIP = 3226,
STR_CONSTRUCTION_RIGHTS_OWNED = 3218,
STR_CONSTRUCTION_RIGHTS_SALE = 3220,
STR_LAND_OWNED = 3217,
STR_LAND_SALE = 3219,
STR_MAP_CASH_MACHINE = 3372,
STR_MAP_DRINK_STALL = 3368,
STR_MAP_FIRST_AID = 3371,
@@ -876,10 +882,6 @@ namespace OpenRCT2
STR_MAP_SOUVENIR_STALL = 3369,
STR_MAP_TOILET = 3373,
STR_SELECT_PARK_OWNED_LAND_TIP = 3216,
STR_SET_CONSTRUCTION_RIGHTS_TO_BE_AVAILABLE_TIP = 3224,
STR_SET_CONSTRUCTION_RIGHTS_TO_BE_OWNED_TIP = 3222,
STR_SET_LAND_TO_BE_AVAILABLE_TIP = 3223,
STR_SET_LAND_TO_BE_OWNED_TIP = 3221,
STR_SET_STARTING_POSITIONS_TIP = 3228,
STR_SHOW_PEOPLE_ON_MAP_TIP = 3143,
STR_SHOW_RIDES_STALLS_ON_MAP_TIP = 3144,

View File

@@ -8,6 +8,7 @@
*****************************************************************************/
#include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Theme.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/Widget.h>
#include <openrct2-ui/windows/Window.h>
@@ -15,18 +16,24 @@
#include <openrct2/Game.h>
#include <openrct2/GameState.h>
#include <openrct2/Input.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/actions/LandBuyRightsAction.h>
#include <openrct2/actions/LandSetRightsAction.h>
#include <openrct2/core/String.hpp>
#include <openrct2/drawing/Drawing.h>
#include <openrct2/localisation/Formatter.h>
#include <openrct2/sprites.h>
#include <openrct2/world/Park.h>
#include <openrct2/world/Surface.h>
namespace OpenRCT2::Ui::Windows
{
static constexpr ScreenCoordsXY kInGameSize = { 94, 94 };
static constexpr ScreenCoordsXY kEditorSize = { 280, 104 };
static constexpr StringId WINDOW_TITLE = STR_LAND_RIGHTS;
static constexpr int32_t WH = 94;
static constexpr int32_t WW = 98;
static constexpr int32_t WW = kInGameSize.x;
static constexpr int32_t WH = kInGameSize.y;
// clang-format off
enum WindowLandRightsWidgetIdx {
@@ -36,26 +43,80 @@ enum WindowLandRightsWidgetIdx {
WIDX_PREVIEW,
WIDX_DECREMENT,
WIDX_INCREMENT,
// In-game widgets
WIDX_BUY_LAND_RIGHTS,
WIDX_BUY_CONSTRUCTION_RIGHTS
WIDX_BUY_CONSTRUCTION_RIGHTS,
// Editor/sandbox widgets
WIDX_UNOWNED_LAND_CHECKBOX,
WIDX_LAND_SALE_CHECKBOX,
WIDX_LAND_OWNED_CHECKBOX,
WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX,
WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX,
};
static Widget window_land_rights_widgets[] = {
WINDOW_SHIM(WINDOW_TITLE, WW, WH),
MakeWidget ({27, 17}, {44, 32}, WindowWidgetType::ImgBtn, WindowColour::Primary , ImageId(SPR_LAND_TOOL_SIZE_0) ), // preview box
MakeRemapWidget({28, 18}, {16, 16}, WindowWidgetType::TrnBtn, WindowColour::Tertiary, SPR_LAND_TOOL_DECREASE, STR_ADJUST_SMALLER_LAND_RIGHTS_TIP), // decrement size
MakeRemapWidget({54, 32}, {16, 16}, WindowWidgetType::TrnBtn, WindowColour::Tertiary, SPR_LAND_TOOL_INCREASE, STR_ADJUST_LARGER_LAND_RIGHTS_TIP ), // increment size
MakeRemapWidget({22, 53}, {24, 24}, WindowWidgetType::FlatBtn, WindowColour::Tertiary, SPR_BUY_LAND_RIGHTS, STR_BUY_LAND_RIGHTS_TIP ), // land rights
MakeRemapWidget({52, 53}, {24, 24}, WindowWidgetType::FlatBtn, WindowColour::Tertiary, SPR_BUY_CONSTRUCTION_RIGHTS, STR_BUY_CONSTRUCTION_RIGHTS_TIP ), // construction rights
MakeWidget ({ 27, 17}, { 44, 32}, WindowWidgetType::ImgBtn, WindowColour::Primary, ImageId(SPR_LAND_TOOL_SIZE_0) ), // preview box
MakeRemapWidget({ 28, 18}, { 16, 16}, WindowWidgetType::TrnBtn, WindowColour::Primary, SPR_LAND_TOOL_DECREASE, STR_ADJUST_SMALLER_LAND_RIGHTS_TIP ), // decrement size
MakeRemapWidget({ 54, 32}, { 16, 16}, WindowWidgetType::TrnBtn, WindowColour::Primary, SPR_LAND_TOOL_INCREASE, STR_ADJUST_LARGER_LAND_RIGHTS_TIP ), // increment size
MakeRemapWidget({ 22, 53}, { 24, 24}, WindowWidgetType::ImgBtn, WindowColour::Primary, SPR_BUY_LAND_RIGHTS, STR_BUY_LAND_RIGHTS_TIP ), // land rights
MakeRemapWidget({ 52, 53}, { 24, 24}, WindowWidgetType::ImgBtn, WindowColour::Primary, SPR_BUY_CONSTRUCTION_RIGHTS, STR_BUY_CONSTRUCTION_RIGHTS_TIP ), // construction rights
MakeWidget ({100, 22}, {100, 12}, WindowWidgetType::Empty, WindowColour::Primary, STR_LAND_NOT_OWNED, STR_SET_LAND_TO_BE_NOT_OWNED_TIP ),
MakeWidget ({100, 38}, {100, 12}, WindowWidgetType::Empty, WindowColour::Primary, STR_LAND_SALE, STR_SET_LAND_TO_BE_AVAILABLE_TIP ),
MakeWidget ({100, 54}, {100, 12}, WindowWidgetType::Empty, WindowColour::Primary, STR_LAND_OWNED, STR_SET_LAND_TO_BE_OWNED_TIP ),
MakeWidget ({100, 70}, {100, 12}, WindowWidgetType::Empty, WindowColour::Primary, STR_CONSTRUCTION_RIGHTS_SALE, STR_SET_CONSTRUCTION_RIGHTS_TO_BE_AVAILABLE_TIP),
MakeWidget ({100, 86}, {100, 12}, WindowWidgetType::Empty, WindowColour::Primary, STR_CONSTRUCTION_RIGHTS_OWNED, STR_SET_CONSTRUCTION_RIGHTS_TO_BE_OWNED_TIP ),
kWidgetsEnd,
};
// clang-format on
constexpr uint8_t LAND_RIGHTS_MODE_BUY_CONSTRUCTION_RIGHTS = 0;
constexpr uint8_t LAND_RIGHTS_MODE_BUY_LAND = 1;
enum class LandRightsMode : uint8_t
{
// In-game
BuyLand,
BuyConstructionRights,
// Sandbox/editor mode
SetLandUnowned,
SetLandForSale,
SetLandOwned,
SetConstructionRightsForSale,
SetConstructionRightsOwned,
};
static const bool kLandRightsVisibleByMode[] = { true, false, true, true, true, false, false };
static const bool kConstructionRightsVisibleByMode[] = { false, true, true, false, false, true, true };
class LandRightsWindow final : public Window
{
private:
LandRightsMode _landRightsMode;
money64 _landRightsCost;
void SwitchToMode(LandRightsMode mode)
{
auto widgetIndex = WIDX_BUY_LAND_RIGHTS + EnumValue(mode);
pressed_widgets = (1uLL << widgetIndex);
_landRightsMode = mode;
ToolSet(*this, widgetIndex, Tool::UpArrow);
InputSetFlag(INPUT_FLAG_6, true);
if (kLandRightsVisibleByMode[EnumValue(mode)])
ShowLandRights();
else
HideLandRights();
if (kConstructionRightsVisibleByMode[EnumValue(mode)])
ShowConstructionRights();
else
HideConstructionRights();
Invalidate();
}
public:
void OnOpen() override
{
@@ -63,32 +124,28 @@ static Widget window_land_rights_widgets[] = {
hold_down_widgets = (1uLL << WIDX_INCREMENT) | (1uLL << WIDX_DECREMENT);
WindowInitScrollWidgets(*this);
WindowPushOthersBelow(*this);
_landRightsMode = LAND_RIGHTS_MODE_BUY_LAND;
pressed_widgets = (1uLL << WIDX_BUY_LAND_RIGHTS);
gLandToolSize = 1;
gLandToolSize = kLandToolMinimumSize;
ShowGridlines();
ToolSet(*this, WIDX_BUY_LAND_RIGHTS, Tool::UpArrow);
InputSetFlag(INPUT_FLAG_6, true);
ShowLandRights();
if (gLandRemainingConstructionSales == 0)
if (!GetGameState().Cheats.SandboxMode)
{
ShowConstructionRights();
if (gLandRemainingOwnershipSales > 0)
SwitchToMode(LandRightsMode::BuyLand);
else
SwitchToMode(LandRightsMode::BuyConstructionRights);
}
else
{
SwitchToMode(LandRightsMode::SetLandUnowned);
}
}
void OnClose() override
{
HideGridlines();
if (gLandRemainingConstructionSales == 0)
{
HideConstructionRights();
}
HideConstructionRights();
// If the tool wasn't changed, turn tool off
if (isToolActive(WindowClass::LandRights))
ToolCancel();
}
@@ -103,23 +160,41 @@ static Widget window_land_rights_widgets[] = {
case WIDX_PREVIEW:
InputSize();
break;
// In-game mode widgets
case WIDX_BUY_LAND_RIGHTS:
if (_landRightsMode != LAND_RIGHTS_MODE_BUY_LAND)
{
ToolSet(*this, WIDX_BUY_LAND_RIGHTS, Tool::UpArrow);
_landRightsMode = LAND_RIGHTS_MODE_BUY_LAND;
ShowLandRights();
Invalidate();
}
if (_landRightsMode != LandRightsMode::BuyLand)
SwitchToMode(LandRightsMode::BuyLand);
break;
case WIDX_BUY_CONSTRUCTION_RIGHTS:
if (_landRightsMode != LAND_RIGHTS_MODE_BUY_CONSTRUCTION_RIGHTS)
{
ToolSet(*this, WIDX_BUY_CONSTRUCTION_RIGHTS, Tool::UpArrow);
_landRightsMode = LAND_RIGHTS_MODE_BUY_CONSTRUCTION_RIGHTS;
ShowConstructionRights();
Invalidate();
}
if (_landRightsMode != LandRightsMode::BuyConstructionRights)
SwitchToMode(LandRightsMode::BuyConstructionRights);
break;
// Sandbox/editor mode widgets
case WIDX_UNOWNED_LAND_CHECKBOX:
if (_landRightsMode != LandRightsMode::SetLandUnowned)
SwitchToMode(LandRightsMode::SetLandUnowned);
break;
case WIDX_LAND_SALE_CHECKBOX:
if (_landRightsMode != LandRightsMode::SetLandForSale)
SwitchToMode(LandRightsMode::SetLandForSale);
break;
case WIDX_LAND_OWNED_CHECKBOX:
if (_landRightsMode != LandRightsMode::SetLandOwned)
SwitchToMode(LandRightsMode::SetLandOwned);
break;
case WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX:
if (_landRightsMode != LandRightsMode::SetConstructionRightsForSale)
SwitchToMode(LandRightsMode::SetConstructionRightsForSale);
break;
case WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX:
if (_landRightsMode != LandRightsMode::SetConstructionRightsOwned)
SwitchToMode(LandRightsMode::SetConstructionRightsOwned);
break;
}
}
@@ -173,22 +248,19 @@ static Widget window_land_rights_widgets[] = {
Close();
}
void OnPrepareDraw() override
void PrepareDrawInGame()
{
SetWidgetPressed(WIDX_PREVIEW, true);
if (_landRightsMode == LAND_RIGHTS_MODE_BUY_LAND)
if (_landRightsMode == LandRightsMode::BuyLand)
{
SetWidgetPressed(WIDX_BUY_LAND_RIGHTS, true);
SetWidgetPressed(WIDX_BUY_CONSTRUCTION_RIGHTS, false);
}
else if (_landRightsMode == LAND_RIGHTS_MODE_BUY_CONSTRUCTION_RIGHTS)
else if (_landRightsMode == LandRightsMode::BuyConstructionRights)
{
SetWidgetPressed(WIDX_BUY_LAND_RIGHTS, false);
SetWidgetPressed(WIDX_BUY_CONSTRUCTION_RIGHTS, true);
}
window_land_rights_widgets[WIDX_PREVIEW].image = ImageId(LandTool::SizeToSpriteIndex(gLandToolSize));
if (gLandRemainingOwnershipSales == 0)
{
SetWidgetDisabled(WIDX_BUY_LAND_RIGHTS, true);
@@ -210,6 +282,90 @@ static Widget window_land_rights_widgets[] = {
SetWidgetDisabled(WIDX_BUY_CONSTRUCTION_RIGHTS, false);
window_land_rights_widgets[WIDX_BUY_CONSTRUCTION_RIGHTS].tooltip = STR_BUY_CONSTRUCTION_RIGHTS_TIP;
}
// Position land size tool
widgets[WIDX_PREVIEW].top = 17;
widgets[WIDX_PREVIEW].bottom = widgets[WIDX_PREVIEW].top + 32;
widgets[WIDX_DECREMENT].top = 18;
widgets[WIDX_DECREMENT].bottom = widgets[WIDX_DECREMENT].top + 16;
widgets[WIDX_INCREMENT].top = 32;
widgets[WIDX_INCREMENT].bottom = widgets[WIDX_INCREMENT].top + 16;
// Show in-game mode widgets
widgets[WIDX_BUY_LAND_RIGHTS].type = WindowWidgetType::ImgBtn;
widgets[WIDX_BUY_CONSTRUCTION_RIGHTS].type = WindowWidgetType::ImgBtn;
// Hide editor/sandbox mode widgets
widgets[WIDX_UNOWNED_LAND_CHECKBOX].type = WindowWidgetType::Empty;
widgets[WIDX_LAND_OWNED_CHECKBOX].type = WindowWidgetType::Empty;
widgets[WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX].type = WindowWidgetType::Empty;
widgets[WIDX_LAND_SALE_CHECKBOX].type = WindowWidgetType::Empty;
widgets[WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX].type = WindowWidgetType::Empty;
}
void PrepareDrawSandbox()
{
// Position land size tool
widgets[WIDX_PREVIEW].top = 17 + 24;
widgets[WIDX_PREVIEW].bottom = widgets[WIDX_PREVIEW].top + 32;
widgets[WIDX_DECREMENT].top = 18 + 24;
widgets[WIDX_DECREMENT].bottom = widgets[WIDX_DECREMENT].top + 16;
widgets[WIDX_INCREMENT].top = 32 + 24;
widgets[WIDX_INCREMENT].bottom = widgets[WIDX_INCREMENT].top + 16;
// Hide in-game mode widgets
widgets[WIDX_BUY_LAND_RIGHTS].type = WindowWidgetType::Empty;
widgets[WIDX_BUY_CONSTRUCTION_RIGHTS].type = WindowWidgetType::Empty;
// Show editor/sandbox mode widgets
widgets[WIDX_UNOWNED_LAND_CHECKBOX].type = WindowWidgetType::Checkbox;
widgets[WIDX_LAND_OWNED_CHECKBOX].type = WindowWidgetType::Checkbox;
widgets[WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX].type = WindowWidgetType::Checkbox;
widgets[WIDX_LAND_SALE_CHECKBOX].type = WindowWidgetType::Checkbox;
widgets[WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX].type = WindowWidgetType::Checkbox;
}
ScreenCoordsXY GetModeDimensions() const
{
if ((gScreenFlags & SCREEN_FLAGS_EDITOR) != 0 || GetGameState().Cheats.SandboxMode)
return kEditorSize;
else
return kInGameSize;
}
void OnPrepareDraw() override
{
SetWidgetPressed(WIDX_PREVIEW, true);
window_land_rights_widgets[WIDX_PREVIEW].image = ImageId(LandTool::SizeToSpriteIndex(gLandToolSize));
if (width != GetModeDimensions().x)
OnResize();
if ((gScreenFlags & SCREEN_FLAGS_EDITOR) != 0 || GetGameState().Cheats.SandboxMode)
{
PrepareDrawSandbox();
ColourSchemeUpdateByClass(this, WindowClass::Map);
}
else
{
PrepareDrawInGame();
ColourSchemeUpdateByClass(this, WindowClass::LandRights);
}
}
void OnResize() override
{
Invalidate();
auto dimensions = GetModeDimensions();
width = dimensions.x;
height = dimensions.y;
if (windowPos.x + width > ContextGetWidth())
windowPos.x = ContextGetWidth() - width;
ResizeFrame();
Invalidate();
}
void OnDraw(DrawPixelInfo& dpi) override
@@ -233,12 +389,49 @@ static Widget window_land_rights_widgets[] = {
{
auto ft = Formatter();
ft.Add<money64>(_landRightsCost);
auto offset = widgets[WIDX_BUY_LAND_RIGHTS].type != WindowWidgetType::Empty ? 32 : 8;
screenCoords = { window_land_rights_widgets[WIDX_PREVIEW].midX() + windowPos.x,
window_land_rights_widgets[WIDX_PREVIEW].bottom + windowPos.y + 32 };
window_land_rights_widgets[WIDX_PREVIEW].bottom + windowPos.y + offset };
DrawTextBasic(dpi, screenCoords, STR_COST_AMOUNT, ft, { TextAlignment::CENTRE });
}
}
LandBuyRightsAction GetLandBuyAction()
{
auto mode = (_landRightsMode == LandRightsMode::BuyLand) ? LandBuyRightSetting::BuyLand
: LandBuyRightSetting::BuyConstructionRights;
return LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y }, mode);
}
uint8_t GetDesiredOwnership()
{
switch (_landRightsMode)
{
case LandRightsMode::SetLandForSale:
return OWNERSHIP_AVAILABLE;
case LandRightsMode::SetLandOwned:
return OWNERSHIP_OWNED;
case LandRightsMode::SetConstructionRightsForSale:
return OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE;
case LandRightsMode::SetConstructionRightsOwned:
return OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED;
case LandRightsMode::SetLandUnowned:
default:
return OWNERSHIP_UNOWNED;
}
}
LandSetRightsAction GetLandSetAction()
{
return LandSetRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandSetRightSetting::SetOwnershipWithChecks, GetDesiredOwnership());
}
void OnToolUpdate(WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords) override
{
MapInvalidateSelectionRect();
@@ -313,84 +506,52 @@ static Widget window_land_rights_widgets[] = {
if (!state_changed)
return;
auto landBuyRightsAction = LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
(_landRightsMode == LAND_RIGHTS_MODE_BUY_LAND) ? LandBuyRightSetting::BuyLand
: LandBuyRightSetting::BuyConstructionRights);
auto res = GameActions::Query(&landBuyRightsAction);
_landRightsCost = res.Error == GameActions::Status::Ok ? res.Cost : kMoney64Undefined;
if ((gScreenFlags & SCREEN_FLAGS_EDITOR) != 0 || GetGameState().Cheats.SandboxMode)
{
auto landSetRightsAction = GetLandSetAction();
auto res = GameActions::Query(&landSetRightsAction);
_landRightsCost = res.Error == GameActions::Status::Ok ? res.Cost : kMoney64Undefined;
}
else
{
auto landBuyRightsAction = GetLandBuyAction();
auto res = GameActions::Query(&landBuyRightsAction);
_landRightsCost = res.Error == GameActions::Status::Ok ? res.Cost : kMoney64Undefined;
}
}
void OnToolAbort(WidgetIndex widgetIndex) override
{
if (_landRightsMode == LAND_RIGHTS_MODE_BUY_LAND)
{
if (kLandRightsVisibleByMode[EnumValue(_landRightsMode)])
HideLandRights();
}
else
{
if (kConstructionRightsVisibleByMode[EnumValue(_landRightsMode)])
HideConstructionRights();
}
}
void OnToolDown(WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords) override
{
if (_landRightsMode == LAND_RIGHTS_MODE_BUY_LAND)
if (screenCoords.x == kLocationNull)
return;
if ((gScreenFlags & SCREEN_FLAGS_EDITOR) != 0 || GetGameState().Cheats.SandboxMode)
{
if (screenCoords.x != kLocationNull)
{
auto landBuyRightsAction = LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandBuyRightSetting::BuyLand);
GameActions::Execute(&landBuyRightsAction);
}
auto landSetRightsAction = GetLandSetAction();
GameActions::Execute(&landSetRightsAction);
}
else
{
if (screenCoords.x != kLocationNull)
{
auto landBuyRightsAction = LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandBuyRightSetting::BuyConstructionRights);
GameActions::Execute(&landBuyRightsAction);
}
auto landBuyRightsAction = GetLandBuyAction();
GameActions::Execute(&landBuyRightsAction);
}
}
void OnToolDrag(WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords) override
{
if (_landRightsMode == LAND_RIGHTS_MODE_BUY_LAND)
{
if (screenCoords.x != kLocationNull)
{
auto landBuyRightsAction = LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandBuyRightSetting::BuyLand);
GameActions::Execute(&landBuyRightsAction);
}
}
else
{
if (screenCoords.x != kLocationNull)
{
auto landBuyRightsAction = LandBuyRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandBuyRightSetting::BuyConstructionRights);
GameActions::Execute(&landBuyRightsAction);
}
}
}
void OnResize() override
{
ResizeFrame();
OnToolDown(widgetIndex, screenCoords);
}
private:
uint8_t _landRightsMode;
money64 _landRightsCost;
void InputSize()
{
Formatter ft;

View File

@@ -7,7 +7,6 @@
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include <openrct2-ui/interface/LandTool.h>
#include <openrct2-ui/interface/Viewport.h>
#include <openrct2-ui/interface/ViewportInteraction.h>
#include <openrct2-ui/interface/ViewportQuery.h>
@@ -19,7 +18,6 @@
#include <openrct2/GameState.h>
#include <openrct2/Input.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/actions/LandSetRightsAction.h>
#include <openrct2/actions/MapChangeSizeAction.h>
#include <openrct2/actions/PeepSpawnPlaceAction.h>
#include <openrct2/actions/SurfaceSetStyleAction.h>
@@ -115,13 +113,6 @@ namespace OpenRCT2::Ui::Windows
WIDX_SET_LAND_RIGHTS,
WIDX_BUILD_PARK_ENTRANCE,
WIDX_PEOPLE_STARTING_POSITION,
WIDX_LAND_TOOL,
WIDX_LAND_TOOL_SMALLER,
WIDX_LAND_TOOL_LARGER,
WIDX_LAND_OWNED_CHECKBOX,
WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX,
WIDX_LAND_SALE_CHECKBOX,
WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX,
WIDX_MAP_GENERATOR
};
@@ -138,13 +129,6 @@ static Widget window_map_widgets[] = {
MakeWidget ({ 4, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_BUY_LAND_RIGHTS), STR_SELECT_PARK_OWNED_LAND_TIP ),
MakeWidget ({ 4, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, ImageId(SPR_PARK_ENTRANCE), STR_BUILD_PARK_ENTRANCE_TIP ),
MakeWidget ({ 28, 1}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, 0xFFFFFFFF, STR_SET_STARTING_POSITIONS_TIP ),
MakeWidget ({ 4, 17}, { 44, 32}, WindowWidgetType::ImgBtn, WindowColour::Secondary, ImageId(SPR_LAND_TOOL_SIZE_0) ),
MakeRemapWidget ({ 5, 18}, { 16, 16}, WindowWidgetType::TrnBtn, WindowColour::Secondary, SPR_LAND_TOOL_DECREASE, STR_ADJUST_SMALLER_LAND_TIP ),
MakeRemapWidget ({ 31, 32}, { 16, 16}, WindowWidgetType::TrnBtn, WindowColour::Secondary, SPR_LAND_TOOL_INCREASE, STR_ADJUST_LARGER_LAND_TIP ),
MakeWidget ({ 58, 197}, {184, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_LAND_OWNED, STR_SET_LAND_TO_BE_OWNED_TIP ),
MakeWidget ({ 58, 197}, {184, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_CONSTRUCTION_RIGHTS_OWNED, STR_SET_CONSTRUCTION_RIGHTS_TO_BE_OWNED_TIP ),
MakeWidget ({ 58, 197}, {184, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_LAND_SALE, STR_SET_LAND_TO_BE_AVAILABLE_TIP ),
MakeWidget ({ 58, 197}, {174, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_CONSTRUCTION_RIGHTS_SALE, STR_SET_CONSTRUCTION_RIGHTS_TO_BE_AVAILABLE_TIP),
MakeWidget ({110, 189}, {131, 14}, WindowWidgetType::Button, WindowColour::Secondary, STR_MAPGEN_WINDOW_TITLE, STR_MAP_GENERATOR_TIP ),
kWidgetsEnd,
};
@@ -216,7 +200,6 @@ static Widget window_map_widgets[] = {
class MapWindow final : public Window
{
uint8_t _rotation;
uint8_t _activeTool;
uint32_t _currentLine;
uint16_t _landRightsToolSize;
int32_t _firstColumnWidth;
@@ -237,8 +220,7 @@ static Widget window_map_widgets[] = {
widgets = window_map_widgets;
hold_down_widgets = (1uLL << WIDX_MAP_SIZE_SPINNER_Y_UP) | (1uLL << WIDX_MAP_SIZE_SPINNER_Y_DOWN)
| (1uLL << WIDX_MAP_SIZE_SPINNER_X_UP) | (1uLL << WIDX_MAP_SIZE_SPINNER_X_DOWN)
| (1uLL << WIDX_LAND_TOOL_LARGER) | (1uLL << WIDX_LAND_TOOL_SMALLER);
| (1uLL << WIDX_MAP_SIZE_SPINNER_X_UP) | (1uLL << WIDX_MAP_SIZE_SPINNER_X_DOWN);
flags |= WF_RESIZABLE;
min_width = WW;
@@ -283,48 +265,13 @@ static Widget window_map_widgets[] = {
Close();
break;
case WIDX_SET_LAND_RIGHTS:
Invalidate();
if (ToolSet(*this, widgetIndex, Tool::UpArrow))
break;
_activeTool = 2;
// Prevent mountain tool size.
_landRightsToolSize = std::max<uint16_t>(kLandToolMinimumSize, _landRightsToolSize);
ShowGridlines();
ShowLandRights();
ShowConstructionRights();
break;
case WIDX_LAND_OWNED_CHECKBOX:
_activeTool ^= 2;
if (_activeTool & 2)
_activeTool &= 0xF2;
Invalidate();
break;
case WIDX_LAND_SALE_CHECKBOX:
_activeTool ^= 8;
if (_activeTool & 8)
_activeTool &= 0xF8;
Invalidate();
break;
case WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX:
_activeTool ^= 1;
if (_activeTool & 1)
_activeTool &= 0xF1;
Invalidate();
break;
case WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX:
_activeTool ^= 4;
if (_activeTool & 4)
_activeTool &= 0xF4;
Invalidate();
{
if (!WindowFindByClass(WindowClass::LandRights))
ContextOpenWindow(WindowClass::LandRights);
else
WindowCloseByClass(WindowClass::LandRights);
break;
}
case WIDX_BUILD_PARK_ENTRANCE:
{
if (!WindowFindByClass(WindowClass::EditorParkEntrance))
@@ -341,9 +288,6 @@ static Widget window_map_widgets[] = {
ShowLandRights();
ShowConstructionRights();
break;
case WIDX_LAND_TOOL:
InputLandSize();
break;
case WIDX_MAP_SIZE_SPINNER_Y:
case WIDX_MAP_SIZE_SPINNER_X:
InputMapSize(widgetIndex);
@@ -389,18 +333,6 @@ static Widget window_map_widgets[] = {
_resizeDirection = ResizeDirection::X;
DecreaseMapSize();
break;
case WIDX_LAND_TOOL_SMALLER:
// Decrement land rights tool size
_landRightsToolSize = std::max<uint16_t>(kLandToolMinimumSize, _landRightsToolSize - 1);
Invalidate();
break;
case WIDX_LAND_TOOL_LARGER:
// Increment land rights tool size
_landRightsToolSize = std::min<uint16_t>(kLandToolMaximumSize, _landRightsToolSize + 1);
Invalidate();
break;
}
}
@@ -457,9 +389,6 @@ static Widget window_map_widgets[] = {
{
switch (widgetIndex)
{
case WIDX_SET_LAND_RIGHTS:
SetLandRightsToolUpdate(screenCoords);
break;
case WIDX_PEOPLE_STARTING_POSITION:
SetPeepSpawnToolUpdate(screenCoords);
break;
@@ -476,32 +405,10 @@ static Widget window_map_widgets[] = {
}
}
void OnToolDrag(WidgetIndex widgetIndex, const ScreenCoordsXY& screenCoords) override
{
switch (widgetIndex)
{
case WIDX_SET_LAND_RIGHTS:
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
{
auto landSetRightsAction = LandSetRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandSetRightSetting::SetOwnershipWithChecks, _activeTool << 4);
GameActions::Execute(&landSetRightsAction);
}
break;
}
}
void OnToolAbort(WidgetIndex widgetIndex) override
{
switch (widgetIndex)
{
case WIDX_SET_LAND_RIGHTS:
Invalidate();
HideGridlines();
HideLandRights();
HideConstructionRights();
break;
case WIDX_PEOPLE_STARTING_POSITION:
Invalidate();
HideGridlines();
@@ -511,36 +418,6 @@ static Widget window_map_widgets[] = {
}
}
void SetLandRightsToolUpdate(const ScreenCoordsXY& screenCoords)
{
MapInvalidateSelectionRect();
gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE;
auto info = GetMapCoordinatesFromPos(
screenCoords, EnumsToFlags(ViewportInteractionItem::Terrain, ViewportInteractionItem::Water));
if (info.SpriteType == ViewportInteractionItem::None)
return;
auto mapCoords = info.Loc;
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectType = MAP_SELECT_TYPE_FULL_LAND_RIGHTS;
int32_t landRightsToolSize = _landRightsToolSize;
if (landRightsToolSize == 0)
landRightsToolSize = 1;
int32_t size = (landRightsToolSize * 32) - 32;
int32_t radius = (landRightsToolSize * 16) - 16;
mapCoords.x -= radius;
mapCoords.y -= radius;
mapCoords = mapCoords.ToTileStart();
gMapSelectPositionA = mapCoords;
gMapSelectPositionB.x = mapCoords.x + size;
gMapSelectPositionB.y = mapCoords.y + size;
MapInvalidateSelectionRect();
}
void SetPeepSpawnToolUpdate(const ScreenCoordsXY& screenCoords)
{
int32_t direction;
@@ -597,19 +474,6 @@ static Widget window_map_widgets[] = {
switch (widgetIndex)
{
case WIDX_LAND_TOOL:
{
char* end;
std::string textStr = std::string(text);
int32_t size = strtol(textStr.c_str(), &end, 10);
if (*end == '\0')
{
size = std::clamp<uint16_t>(size, kLandToolMinimumSize, kLandToolMaximumSize);
_landRightsToolSize = size;
Invalidate();
}
break;
}
case WIDX_MAP_SIZE_SPINNER_Y:
case WIDX_MAP_SIZE_SPINNER_X:
{
@@ -663,47 +527,6 @@ static Widget window_map_widgets[] = {
{
WindowScrollToLocation(*mainWindow, { mapCoords, mapZ });
}
if (isToolActive(WindowClass::Land))
{
// Set land terrain
int32_t landToolSize = std::max<int32_t>(1, gLandToolSize);
int32_t size = (landToolSize * 32) - 32;
int32_t radius = (landToolSize * 16) - 16;
mapCoords = (mapCoords - CoordsXY{ radius, radius }).ToTileStart();
MapInvalidateSelectionRect();
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectType = MAP_SELECT_TYPE_FULL;
gMapSelectPositionA = mapCoords;
gMapSelectPositionB = mapCoords + CoordsXY{ size, size };
MapInvalidateSelectionRect();
auto surfaceSetStyleAction = SurfaceSetStyleAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
gLandToolTerrainSurface, gLandToolTerrainEdge);
GameActions::Execute(&surfaceSetStyleAction);
}
else if (isToolActive(*this, WIDX_SET_LAND_RIGHTS))
{
// Set land rights
int32_t landRightsToolSize = std::max<int32_t>(1, _landRightsToolSize);
int32_t size = (landRightsToolSize * 32) - 32;
int32_t radius = (landRightsToolSize * 16) - 16;
mapCoords = (mapCoords - CoordsXY{ radius, radius }).ToTileStart();
MapInvalidateSelectionRect();
gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE;
gMapSelectType = MAP_SELECT_TYPE_FULL_LAND_RIGHTS;
gMapSelectPositionA = mapCoords;
gMapSelectPositionB = mapCoords + CoordsXY{ size, size };
MapInvalidateSelectionRect();
auto landSetRightsAction = LandSetRightsAction(
{ gMapSelectPositionA.x, gMapSelectPositionA.y, gMapSelectPositionB.x, gMapSelectPositionB.y },
LandSetRightSetting::SetOwnershipWithChecks, _activeTool << 4);
GameActions::Execute(&landSetRightsAction);
}
}
void OnScrollMouseDrag(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override
@@ -746,23 +569,13 @@ static Widget window_map_widgets[] = {
pressed_widgets = 0;
SetWidgetPressed(WIDX_MAP_SIZE_LINK, _mapWidthAndHeightLinked);
pressed_widgets |= (1uLL << (WIDX_PEOPLE_TAB + selected_tab));
pressed_widgets |= (1uLL << WIDX_LAND_TOOL);
if (_activeTool & (1 << 3))
pressed_widgets |= (1uLL << WIDX_LAND_SALE_CHECKBOX);
if (_activeTool & (1 << 2))
pressed_widgets |= (1uLL << WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX);
if (_activeTool & (1 << 1))
pressed_widgets |= (1uLL << WIDX_LAND_OWNED_CHECKBOX);
if (_activeTool & (1 << 0))
pressed_widgets |= (1uLL << WIDX_CONSTRUCTION_RIGHTS_OWNED_CHECKBOX);
if (WindowFindByClass(WindowClass::EditorParkEntrance))
pressed_widgets |= (1uLL << WIDX_BUILD_PARK_ENTRANCE);
if (WindowFindByClass(WindowClass::LandRights))
pressed_widgets |= (1uLL << WIDX_SET_LAND_RIGHTS);
// Set disabled widgets
auto& gameState = GetGameState();
SetWidgetDisabled(WIDX_MAP_SIZE_LINK, gameState.MapSize.x != gameState.MapSize.y);
@@ -793,26 +606,9 @@ static Widget window_map_widgets[] = {
widgets[WIDX_PEOPLE_STARTING_POSITION].top = height - 46;
widgets[WIDX_PEOPLE_STARTING_POSITION].bottom = height - 46 + 23;
widgets[WIDX_LAND_TOOL].top = height - 42;
widgets[WIDX_LAND_TOOL].bottom = height - 42 + 30;
widgets[WIDX_LAND_TOOL_SMALLER].top = height - 41;
widgets[WIDX_LAND_TOOL_SMALLER].bottom = height - 41 + 15;
widgets[WIDX_LAND_TOOL_LARGER].top = height - 27;
widgets[WIDX_LAND_TOOL_LARGER].bottom = height - 27 + 15;
widgets[WIDX_MAP_GENERATOR].top = height - 69;
widgets[WIDX_MAP_GENERATOR].bottom = height - 69 + 13;
// Land tool mode (4 checkboxes)
int checkboxY = height - 55;
for (int32_t i = WIDX_LAND_OWNED_CHECKBOX; i <= WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX; i++)
{
widgets[i].top = checkboxY;
checkboxY += 11;
widgets[i].bottom = checkboxY;
checkboxY += 2;
}
// Disable all scenario editor related widgets
for (int32_t i = WIDX_MAP_SIZE_SPINNER_Y; i <= WIDX_MAP_GENERATOR; i++)
{
@@ -823,24 +619,7 @@ static Widget window_map_widgets[] = {
{
// Always show set land rights button
widgets[WIDX_SET_LAND_RIGHTS].type = WindowWidgetType::FlatBtn;
if (isToolActive(WindowClass::Map, WIDX_SET_LAND_RIGHTS))
{
// Show land tool buttons + modes
widgets[WIDX_LAND_TOOL].type = WindowWidgetType::ImgBtn;
widgets[WIDX_LAND_TOOL_SMALLER].type = WindowWidgetType::TrnBtn;
widgets[WIDX_LAND_TOOL_LARGER].type = WindowWidgetType::TrnBtn;
for (int32_t i = WIDX_LAND_OWNED_CHECKBOX; i <= WIDX_CONSTRUCTION_RIGHTS_SALE_CHECKBOX; i++)
widgets[i].type = WindowWidgetType::Checkbox;
widgets[WIDX_LAND_TOOL].image = ImageId(LandTool::SizeToSpriteIndex(_landRightsToolSize));
}
else
{
// Show the default scenario editor buttons
ShowDefaultScenarioEditorButtons();
}
ShowDefaultScenarioEditorButtons();
}
if (_recalculateScrollbars)
{
@@ -854,23 +633,10 @@ static Widget window_map_widgets[] = {
DrawWidgets(dpi);
DrawTabImages(dpi);
auto screenCoords = windowPos
+ ScreenCoordsXY{ window_map_widgets[WIDX_LAND_TOOL].midX(), window_map_widgets[WIDX_LAND_TOOL].midY() };
// Draw land tool size
if (isToolActive(*this, WIDX_SET_LAND_RIGHTS) && _landRightsToolSize > kLandToolMaximumSizeWithSprite)
{
auto ft = Formatter();
ft.Add<uint16_t>(_landRightsToolSize);
DrawTextBasic(
dpi, screenCoords - ScreenCoordsXY{ 0, 2 }, STR_LAND_TOOL_SIZE_VALUE, ft, { TextAlignment::CENTRE });
}
screenCoords.y = windowPos.y + window_map_widgets[WIDX_LAND_TOOL].bottom + 5;
// People starting position (scenario editor only)
if (widgets[WIDX_PEOPLE_STARTING_POSITION].type != WindowWidgetType::Empty)
{
screenCoords = windowPos
auto screenCoords = windowPos
+ ScreenCoordsXY{ widgets[WIDX_PEOPLE_STARTING_POSITION].left + 12,
widgets[WIDX_PEOPLE_STARTING_POSITION].top + 18 };
GfxDrawSprite(dpi, ImageId(SPR_6410, COLOUR_BRIGHT_RED, COLOUR_LIGHT_BROWN), screenCoords);
@@ -881,7 +647,7 @@ static Widget window_map_widgets[] = {
// Render the map legend
if (selected_tab == PAGE_RIDES)
{
screenCoords = windowPos + ScreenCoordsXY{ 4, widgets[WIDX_MAP].bottom + 2 };
auto screenCoords = windowPos + ScreenCoordsXY{ 4, widgets[WIDX_MAP].bottom + 2 };
static_assert(std::size(RideKeyColours) == std::size(MapLabels));
@@ -1323,14 +1089,6 @@ static Widget window_map_widgets[] = {
ft.Add<uint16_t>(gameState.MapSize.x - 2);
}
void InputLandSize()
{
Formatter ft;
ft.Add<uint16_t>(kLandToolMinimumSize);
ft.Add<uint16_t>(kLandToolMaximumSize);
TextInputOpen(WIDX_LAND_TOOL, STR_SELECTION_SIZE, STR_ENTER_SELECTION_SIZE, ft, STR_NONE, STR_NONE, 3);
}
void InputMapSize(WidgetIndex callingWidget)
{
if (IsWidgetPressed(WIDX_MAP_SIZE_LINK))

View File

@@ -185,7 +185,32 @@ GameActions::Result LandSetRightsAction::MapBuyLandRightsForTile(const CoordsXY&
}
auto& gameState = GetGameState();
res.Cost = gameState.LandPrice;
const uint8_t currentOwnership = surfaceElement->GetOwnership();
// Are land rights or construction rights currently owned?
if (!(currentOwnership & (OWNERSHIP_OWNED | OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)))
{
// Buying land
if (!(currentOwnership & OWNERSHIP_OWNED) && (_ownership & OWNERSHIP_OWNED))
res.Cost = gameState.LandPrice;
// Buying construction rights
if (!(currentOwnership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)
&& (_ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED))
res.Cost = gameState.ConstructionRightsPrice;
}
else
{
// Selling land
if ((currentOwnership & OWNERSHIP_OWNED) && !(_ownership & OWNERSHIP_OWNED))
res.Cost = -gameState.LandPrice;
// Selling construction rights
if ((currentOwnership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)
&& !(_ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED))
res.Cost = -gameState.ConstructionRightsPrice;
}
if (isExecuting)
{
if (_ownership != OWNERSHIP_UNOWNED)

View File

@@ -49,7 +49,7 @@ using namespace OpenRCT2;
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
constexpr uint8_t kNetworkStreamVersion = 2;
constexpr uint8_t kNetworkStreamVersion = 3;
const std::string kNetworkStreamID = std::string(OPENRCT2_VERSION) + "-" + std::to_string(kNetworkStreamVersion);