diff --git a/src/openrct2-ui/UiStringIds.h b/src/openrct2-ui/UiStringIds.h index b760e3766a..681844dd29 100644 --- a/src/openrct2-ui/UiStringIds.h +++ b/src/openrct2-ui/UiStringIds.h @@ -522,48 +522,6 @@ namespace OpenRCT2 STR_UNABLE_TO_SELECT_THIS_OBJECT = 3176, STR_WARNING_TOO_MANY_OBJECTS_SELECTED = 3374, - // Window: EditorObjectiveOptions - STR_CHANGE = 3294, - STR_CHANGE_DETAIL_NOTES_ABOUT_PARK_SCENARIO_TIP = 3297, - STR_CHANGE_NAME_OF_PARK_TIP = 3295, - STR_CHANGE_NAME_OF_SCENARIO_TIP = 3296, - STR_ENTER_SCENARIO_DESCRIPTION = 3316, - STR_ENTER_SCENARIO_NAME = 3314, - STR_OBJECTIVE_DROPDOWN_NONE = 2397, - STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS = STR_OBJECTIVE_DROPDOWN_NONE + 5, - STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH = STR_OBJECTIVE_DROPDOWN_NONE + 8, - STR_OBJECTIVE_DROPDOWN_BUILD_THE_BEST_RIDE_YOU_CAN = STR_OBJECTIVE_DROPDOWN_NONE + 4, - STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS = STR_OBJECTIVE_DROPDOWN_NONE + 9, - STR_OBJECTIVE_DROPDOWN_HAVE_FUN = STR_OBJECTIVE_DROPDOWN_NONE + 3, - STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS = STR_OBJECTIVE_DROPDOWN_NONE + 7, - STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE = STR_OBJECTIVE_DROPDOWN_NONE + 11, - STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE = STR_OBJECTIVE_DROPDOWN_NONE + 1, - STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK = STR_OBJECTIVE_DROPDOWN_NONE + 6, - STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE = STR_OBJECTIVE_DROPDOWN_NONE + 2, - STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE = STR_OBJECTIVE_DROPDOWN_NONE + 10, - STR_OBJECTIVE_SELECTION = 3284, - STR_OBJECTIVE_WINDOW = 3287, - STR_PARK_SCENARIO_DETAILS = 3315, - STR_SCENARIO_NAME = 3313, - STR_SELECT_OBJECTIVE_AND_PARK_NAME_TIP = 3282, - STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP = 3286, - STR_SELECT_RIDES_TO_BE_PRESERVED_TIP = 3283, - STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN = 3318, - STR_WINDOW_COLOUR_2_LENGTH = 3310, - STR_WINDOW_OBJECTIVE_DATE = 3301, - STR_WINDOW_OBJECTIVE_EXCITEMENT_RATING = 3308, - STR_WINDOW_OBJECTIVE_GUEST_COUNT = 3303, - STR_WINDOW_OBJECTIVE_MINIMUM_LENGTH = 3307, - STR_WINDOW_OBJECTIVE_MONTHLY_INCOME = 3305, - STR_WINDOW_OBJECTIVE_MONTHLY_PROFIT = 3306, - STR_WINDOW_OBJECTIVE_PARK_VALUE = 3304, - STR_WINDOW_OBJECTIVE_VALUE_DATE = 3302, - STR_WINDOW_PARK_DETAILS = 3299, - STR_WINDOW_PARK_NAME = 3298, - STR_WINDOW_PRESERVATION_ORDER = 3312, - STR_WINDOW_SCENARIO_GROUP = 3319, - STR_WINDOW_SCENARIO_NAME = 3300, - // Window: EditorScenarioOptions STR_CANT_INCREASE_CASH = 3248, STR_CANT_INCREASE_INIT_LOAN = 3250, @@ -574,6 +532,12 @@ namespace OpenRCT2 STR_CANT_REDUCE_INTEREST_RATE = 3255, STR_CANT_REDUCE_MAX_LOAN = 3253, STR_CASH_PER_GUEST_LABEL = 3260, + STR_CHANGE = 3294, + STR_CHANGE_DETAIL_NOTES_ABOUT_PARK_SCENARIO_TIP = 3297, + STR_CHANGE_NAME_OF_PARK_TIP = 3295, + STR_CHANGE_NAME_OF_SCENARIO_TIP = 3296, + STR_ENTER_SCENARIO_DESCRIPTION = 3316, + STR_ENTER_SCENARIO_NAME = 3314, STR_ENTRY_PRICE_LABEL = 3281, STR_FORBID_HIGH_CONSTRUCTION = 3271, STR_FORBID_HIGH_CONSTRUCTION_TIP = 3272, @@ -603,13 +567,29 @@ namespace OpenRCT2 STR_LAND_COST_LABEL = 3277, STR_MAKE_PARK_NO_MONEY_TIP = 3239, STR_MAX_LOAN_LABEL = 3242, + STR_OBJECTIVE_DROPDOWN_NONE = 2397, + STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS = STR_OBJECTIVE_DROPDOWN_NONE + 5, + STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH = STR_OBJECTIVE_DROPDOWN_NONE + 8, + STR_OBJECTIVE_DROPDOWN_BUILD_THE_BEST_RIDE_YOU_CAN = STR_OBJECTIVE_DROPDOWN_NONE + 4, + STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS = STR_OBJECTIVE_DROPDOWN_NONE + 9, + STR_OBJECTIVE_DROPDOWN_HAVE_FUN = STR_OBJECTIVE_DROPDOWN_NONE + 3, + STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS = STR_OBJECTIVE_DROPDOWN_NONE + 7, + STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE = STR_OBJECTIVE_DROPDOWN_NONE + 11, + STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE = STR_OBJECTIVE_DROPDOWN_NONE + 1, + STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK = STR_OBJECTIVE_DROPDOWN_NONE + 6, + STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE = STR_OBJECTIVE_DROPDOWN_NONE + 2, + STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE = STR_OBJECTIVE_DROPDOWN_NONE + 10, + STR_OBJECTIVE_SELECTION = 3284, + STR_OBJECTIVE_WINDOW = 3287, STR_PAID_ENTRY_PAID_RIDES = 6153, + STR_PARK_SCENARIO_DETAILS = 3315, STR_PAY_FOR_PARK_PAY_FOR_RIDES_TIP = 3266, STR_PAY_PARK_ENTER = 3280, STR_PERCENT_FORMAT_LABEL = 3247, STR_RCT1_INTEREST = 6545, STR_RCT1_INTEREST_TIP = 6546, STR_RIGHTS_COST_LABEL = 3278, + STR_SCENARIO_NAME = 3313, STR_SCENARIO_OPTIONS_FINANCIAL = 3232, STR_SCENARIO_OPTIONS_FINANCIAL_TIP = 3235, STR_SCENARIO_OPTIONS_GUESTS = 3233, @@ -617,6 +597,24 @@ namespace OpenRCT2 STR_SCENARIO_OPTIONS_PARK = 3234, STR_SCENARIO_OPTIONS_PARK_TIP = 3237, STR_SELECT_CLIMATE_TIP = 3288, + STR_SELECT_OBJECTIVE_AND_PARK_NAME_TIP = 3282, + STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP = 3286, + STR_SELECT_RIDES_TO_BE_PRESERVED_TIP = 3283, + STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN = 3318, + STR_WINDOW_COLOUR_2_LENGTH = 3310, + STR_WINDOW_OBJECTIVE_DATE = 3301, + STR_WINDOW_OBJECTIVE_EXCITEMENT_RATING = 3308, + STR_WINDOW_OBJECTIVE_GUEST_COUNT = 3303, + STR_WINDOW_OBJECTIVE_MINIMUM_LENGTH = 3307, + STR_WINDOW_OBJECTIVE_MONTHLY_INCOME = 3305, + STR_WINDOW_OBJECTIVE_MONTHLY_PROFIT = 3306, + STR_WINDOW_OBJECTIVE_PARK_VALUE = 3304, + STR_WINDOW_OBJECTIVE_VALUE_DATE = 3302, + STR_WINDOW_PARK_DETAILS = 3299, + STR_WINDOW_PARK_NAME = 3298, + STR_WINDOW_PRESERVATION_ORDER = 3312, + STR_WINDOW_SCENARIO_GROUP = 3319, + STR_WINDOW_SCENARIO_NAME = 3300, // Window: Finances STR_1_WEEK_REMAINING = 5484, diff --git a/src/openrct2-ui/WindowManager.cpp b/src/openrct2-ui/WindowManager.cpp index db892c5860..2ef0d4fb90 100644 --- a/src/openrct2-ui/WindowManager.cpp +++ b/src/openrct2-ui/WindowManager.cpp @@ -80,8 +80,6 @@ public: return EditorInventionsListOpen(); case WindowClass::EditorObjectSelection: return EditorObjectSelectionOpen(); - case WindowClass::EditorObjectiveOptions: - return EditorObjectiveOptionsOpen(); case WindowClass::EditorScenarioOptions: return EditorScenarioOptionsOpen(); case WindowClass::Finances: diff --git a/src/openrct2-ui/interface/Theme.cpp b/src/openrct2-ui/interface/Theme.cpp index eb6118a7bd..471d5ebca1 100644 --- a/src/openrct2-ui/interface/Theme.cpp +++ b/src/openrct2-ui/interface/Theme.cpp @@ -166,7 +166,6 @@ static constexpr WindowThemeDesc WindowThemeDescriptors[] = { WindowClass::EditorObjectSelection, "WC_EDITOR_OBJECT_SELECTION", STR_THEMES_WINDOW_EDITOR_OBJECT_SELECTION, COLOURS_3(opaque(COLOUR_LIGHT_PURPLE), opaque(COLOUR_GREY), opaque(COLOUR_GREY) ) }, { WindowClass::EditorInventionList, "WC_EDITOR_INVENTION_LIST", STR_THEMES_WINDOW_EDITOR_INVENTION_LIST, COLOURS_3(opaque(COLOUR_LIGHT_PURPLE), opaque(COLOUR_GREY), opaque(COLOUR_GREY) ) }, { WindowClass::EditorScenarioOptions, "WC_EDITOR_SCENARIO_OPTIONS", STR_THEMES_WINDOW_EDITOR_SCENARIO_OPTIONS, COLOURS_3(opaque(COLOUR_LIGHT_PURPLE), opaque(COLOUR_GREY), opaque(COLOUR_GREY) ) }, - { WindowClass::EditorObjectiveOptions, "WC_EDITOR_OBJECTIVE_OPTIONS", STR_THEMES_WINDOW_EDITOR_OBJECTIVE_OPTIONS, COLOURS_3(opaque(COLOUR_LIGHT_PURPLE), opaque(COLOUR_GREY), opaque(COLOUR_GREY) ) }, { WindowClass::ManageTrackDesign, "WC_MANAGE_TRACK_DESIGN", STR_THEMES_WINDOW_MANAGE_TRACK_DESIGN, COLOURS_3(opaque(COLOUR_GREY), opaque(COLOUR_GREY), opaque(COLOUR_GREY) ) }, { WindowClass::TrackDeletePrompt, "WC_TRACK_DELETE_PROMPT", STR_THEMES_WINDOW_TRACK_DELETE_PROMPT, COLOURS_3(opaque(COLOUR_BORDEAUX_RED), opaque(COLOUR_BORDEAUX_RED), opaque(COLOUR_BORDEAUX_RED) ) }, { WindowClass::InstallTrack, "WC_INSTALL_TRACK", STR_THEMES_WINDOW_INSTALL_TRACK, COLOURS_3(opaque(COLOUR_BORDEAUX_RED), opaque(COLOUR_BORDEAUX_RED), opaque(COLOUR_BORDEAUX_RED) ) }, diff --git a/src/openrct2-ui/libopenrct2ui.vcxproj b/src/openrct2-ui/libopenrct2ui.vcxproj index 295c69b9d5..d96fa49e61 100644 --- a/src/openrct2-ui/libopenrct2ui.vcxproj +++ b/src/openrct2-ui/libopenrct2ui.vcxproj @@ -173,7 +173,6 @@ - diff --git a/src/openrct2-ui/title/TitleSequencePlayer.cpp b/src/openrct2-ui/title/TitleSequencePlayer.cpp index e5d3b361d0..0f767f5f6c 100644 --- a/src/openrct2-ui/title/TitleSequencePlayer.cpp +++ b/src/openrct2-ui/title/TitleSequencePlayer.cpp @@ -411,7 +411,6 @@ namespace OpenRCT2::Title windowMgr->CloseByClass(WindowClass::EditorInventionListDrag); windowMgr->CloseByClass(WindowClass::EditorInventionList); windowMgr->CloseByClass(WindowClass::EditorObjectSelection); - windowMgr->CloseByClass(WindowClass::EditorObjectiveOptions); windowMgr->CloseByClass(WindowClass::EditorScenarioOptions); windowMgr->CloseByClass(WindowClass::Finances); windowMgr->CloseByClass(WindowClass::FirePrompt); diff --git a/src/openrct2-ui/windows/EditorBottomToolbar.cpp b/src/openrct2-ui/windows/EditorBottomToolbar.cpp index 57c78d0150..20eb3374c2 100644 --- a/src/openrct2-ui/windows/EditorBottomToolbar.cpp +++ b/src/openrct2-ui/windows/EditorBottomToolbar.cpp @@ -247,7 +247,7 @@ namespace OpenRCT2::Ui::Windows auto* windowMgr = Ui::GetWindowManager(); windowMgr->CloseAll(); - ContextOpenWindow(WindowClass::EditorObjectiveOptions); + ContextOpenWindow(WindowClass::EditorScenarioOptions); getGameState().editorStep = EditorStep::ObjectiveSelection; GfxInvalidateScreen(); } diff --git a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp b/src/openrct2-ui/windows/EditorObjectiveOptions.cpp deleted file mode 100644 index 80eca6388a..0000000000 --- a/src/openrct2-ui/windows/EditorObjectiveOptions.cpp +++ /dev/null @@ -1,1185 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2025 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#include "../UiStringIds.h" -#include "../interface/Dropdown.h" -#include "../interface/Widget.h" -#include "Windows.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace OpenRCT2::Ui::Windows -{ - static constexpr StringId WINDOW_TITLE = STR_OBJECTIVE_SELECTION; - static constexpr int32_t WH = 229; - static constexpr int32_t WW = 450; - - static constexpr money64 kObjectiveCurrencyLoanAndValueMax = 2000000.00_GBP; - static constexpr money64 kObjectiveCurrencyLoanAndValueMin = 1000.00_GBP; - static constexpr money64 kObjectiveCurrencyLoanAndValueAdjustment = 1000.00_GBP; - - static constexpr money64 kObjectiveCurrencyFoodMax = 2000000.00_GBP; - static constexpr money64 kObjectiveCurrencyFoodMin = 1000.00_GBP; - static constexpr money64 kObjectiveCurrencyFoodAdjustment = 100.00_GBP; - - static constexpr uint16_t kObjectiveLengthMax = 5000; - static constexpr uint16_t kObjectiveLengthMin = 1000; - static constexpr uint16_t kObjectiveLengthAdjustment = 100; - - static constexpr ride_rating kObjectiveExcitementMax = MakeRideRating(9, 90); - static constexpr ride_rating kObjectiveExcitementMin = MakeRideRating(4, 00); - static constexpr ride_rating kObjectiveExcitementAdjustment = MakeRideRating(0, 10); - - // The number has to leave a bit of room for other entities like vehicles, litter and balloons. - static constexpr uint16_t kObjectiveGuestsMax = 50000; - static constexpr uint16_t kObjectiveGuestsMin = 250; - static constexpr uint16_t kObjectiveGuestsAdjustment = 50; - - static constexpr uint8_t kObjectiveYearMax = 25; - static constexpr uint8_t kObjectiveYearMin = 1; - static constexpr uint8_t kObjectiveYearAdjustment = 1; - -#pragma region Widgets - - enum - { - WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN, - WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES, - WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_COUNT - }; - - static constexpr StringId ObjectiveDropdownOptionNames[] = { - STR_OBJECTIVE_DROPDOWN_NONE, - STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE, - STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE, - STR_OBJECTIVE_DROPDOWN_HAVE_FUN, - STR_OBJECTIVE_DROPDOWN_BUILD_THE_BEST_RIDE_YOU_CAN, - STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS, - STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK, - STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS, - STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH, - STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS, - STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE, - STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE, - }; - - // clang-format off - enum - { - WIDX_BACKGROUND, - WIDX_TITLE, - WIDX_CLOSE, - WIDX_PAGE_BACKGROUND, - WIDX_TAB_1, - WIDX_TAB_2, - - WIDX_OBJECTIVE = 6, - WIDX_OBJECTIVE_DROPDOWN, - WIDX_OBJECTIVE_ARG_1, - WIDX_OBJECTIVE_ARG_1_INCREASE, - WIDX_OBJECTIVE_ARG_1_DECREASE, - WIDX_OBJECTIVE_ARG_2, - WIDX_OBJECTIVE_ARG_2_INCREASE, - WIDX_OBJECTIVE_ARG_2_DECREASE, - WIDX_PARK_NAME, - WIDX_SCENARIO_NAME, - WIDX_CATEGORY, - WIDX_CATEGORY_DROPDOWN, - WIDX_DETAILS, - - WIDX_RIDES = 6 - }; - - #define MAIN_OBJECTIVE_OPTIONS_WIDGETS \ - WINDOW_SHIM(WINDOW_TITLE, WW, WH), \ - MakeWidget({ 0, 43}, {280, 106}, WindowWidgetType::Resize, WindowColour::Secondary), \ - MakeTab ({ 3, 17}, STR_SELECT_OBJECTIVE_AND_PARK_NAME_TIP ), \ - MakeTab ({ 34, 17}, STR_SELECT_RIDES_TO_BE_PRESERVED_TIP ) - - static constexpr Widget window_editor_objective_options_main_widgets[] = { - MAIN_OBJECTIVE_OPTIONS_WIDGETS, - MakeWidget ({ 98, 48}, {344, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, kStringIdNone, STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP ), - MakeWidget ({430, 49}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP ), - MakeSpinnerWidgets({158, 65}, {120, 12}, WindowWidgetType::Button, WindowColour::Secondary ), // NB: 3 widgets - MakeSpinnerWidgets({158, 82}, {120, 12}, WindowWidgetType::Button, WindowColour::Secondary ), // NB: 3 widgets - MakeWidget ({370, 99}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_NAME_OF_PARK_TIP ), - MakeWidget ({370, 116}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_NAME_OF_SCENARIO_TIP ), - MakeWidget ({ 98, 133}, {180, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, kStringIdNone, STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN), - MakeWidget ({266, 134}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN), - MakeWidget ({370, 150}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_DETAIL_NOTES_ABOUT_PARK_SCENARIO_TIP), - }; - - static constexpr Widget window_editor_objective_options_rides_widgets[] = { - MAIN_OBJECTIVE_OPTIONS_WIDGETS, - MakeWidget({ 3, 60}, {374, 161}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL), - }; - - static constexpr std::span window_editor_objective_options_widgets[] = { - window_editor_objective_options_main_widgets, - window_editor_objective_options_rides_widgets, - }; - -#pragma endregion - -#pragma region Enabled widgets - - static uint64_t window_editor_objective_options_page_hold_down_widgets[] = { - (1uLL << WIDX_OBJECTIVE_ARG_1_INCREASE) | - (1uLL << WIDX_OBJECTIVE_ARG_1_DECREASE) | - (1uLL << WIDX_OBJECTIVE_ARG_2_INCREASE) | - (1uLL << WIDX_OBJECTIVE_ARG_2_DECREASE), - - 0, - }; - // clang-format on - -#pragma endregion - - class EditorObjectiveOptionsWindow final : public Window - { - private: - // Not shops or facilities - std::vector _rideableRides; - - public: - void OnOpen() override - { - SetPage(WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN); - } - - void OnMouseUp(WidgetIndex widgetIndex) override - { - switch (widgetIndex) - { - case WIDX_CLOSE: - Close(); - return; - case WIDX_TAB_1: - case WIDX_TAB_2: - SetPage(widgetIndex - WIDX_TAB_1); - return; - } - - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN) - { - OnMouseUpMain(widgetIndex); - } - } - - void OnResize() override - { - switch (page) - { - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN: - OnResizeMain(); - break; - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES: - OnResizeRides(); - break; - } - } - - void OnPrepareDraw() override - { - switch (page) - { - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN: - OnPrepareDrawMain(); - break; - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES: - OnPrepareDrawRides(); - break; - } - } - - void OnUpdate() override - { - switch (page) - { - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN: - OnUpdateMain(); - break; - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES: - OnUpdateRides(); - break; - } - } - - void OnDraw(DrawPixelInfo& dpi) override - { - switch (page) - { - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN: - OnDrawMain(dpi); - break; - case WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES: - OnDrawRides(dpi); - break; - } - } - - void OnMouseDown(WidgetIndex widgetIndex) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN) - { - OnMouseDownMain(widgetIndex); - } - } - - void OnDropdown(WidgetIndex widgetIndex, int32_t selectedIndex) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN) - { - OnDropdownMain(widgetIndex, selectedIndex); - } - } - - void OnTextInput(WidgetIndex widgetIndex, std::string_view text) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN) - { - OnTextInputMain(widgetIndex, text); - } - } - - void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES) - { - OnScrollMouseDownRides(scrollIndex, screenCoords); - } - } - - void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES) - { - OnScrollMouseOverRides(scrollIndex, screenCoords); - } - } - - void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES) - { - OnScrollDrawRides(dpi, scrollIndex); - } - } - - ScreenSize OnScrollGetSize(int32_t scrollIndex) override - { - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES) - { - return OnScrollGetSizeRides(scrollIndex); - } - - return {}; - } - - private: - /** - * - * rct2: 0x00668496 - */ - void SetPage(int32_t newPage) - { - // Skip setting page if we're already on this page, unless we're initialising the window - if (page == newPage && !widgets.empty()) - return; - - page = newPage; - frame_no = 0; - _rideableRides.clear(); - selected_list_item = -1; - hold_down_widgets = window_editor_objective_options_page_hold_down_widgets[newPage]; - SetWidgets(window_editor_objective_options_widgets[newPage]); - Invalidate(); - UpdateDisabledWidgets(); - OnResize(); - OnPrepareDraw(); - InitScrollWidgets(); - Invalidate(); - } - - /** - * - * rct2: 0x00672609 - */ - void UpdateDisabledWidgets() - { - // Check if there are any rides (not shops or facilities) - const auto& rideManager = GetRideManager(); - if (std::any_of( - rideManager.begin(), rideManager.end(), [](const Ride& rideToCheck) { return rideToCheck.isRide(); })) - { - disabled_widgets &= ~(1uLL << WIDX_TAB_2); - } - else - { - disabled_widgets |= (1uLL << WIDX_TAB_2); - } - } - - void SetPressedTab() - { - int32_t i; - for (i = WIDX_TAB_1; i <= WIDX_TAB_2; i++) - pressed_widgets &= ~(1 << i); - pressed_widgets |= 1LL << (WIDX_TAB_1 + page); - } - - void AnchorBorderWidgets() - { - ResizeFrameWithPage(); - } - - void DrawTabImages(DrawPixelInfo& dpi) - { - Widget* widget; - int32_t spriteIndex; - - // Tab 1 - widget = &widgets[WIDX_TAB_1]; - - spriteIndex = SPR_TAB_OBJECTIVE_0; - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_MAIN) - spriteIndex += (frame_no / 4) % 16; - - GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); - - // Tab 2 - if (!IsWidgetDisabled(WIDX_TAB_2)) - { - widget = &widgets[WIDX_TAB_2]; - spriteIndex = SPR_TAB_RIDE_0; - if (page == WINDOW_EDITOR_OBJECTIVE_OPTIONS_PAGE_RIDES) - spriteIndex += (frame_no / 4) % 16; - - GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); - } - } - - /** - * - * rct2: 0x0067201D - */ - void SetObjective(int32_t objective) - { - auto& gameState = getGameState(); - gameState.scenarioObjective.Type = objective; - Invalidate(); - - // Set default objective arguments - switch (objective) - { - case OBJECTIVE_NONE: - case OBJECTIVE_HAVE_FUN: - case OBJECTIVE_BUILD_THE_BEST: - case OBJECTIVE_10_ROLLERCOASTERS: - break; - case OBJECTIVE_GUESTS_BY: - gameState.scenarioObjective.Year = 3; - gameState.scenarioObjective.NumGuests = 1500; - break; - case OBJECTIVE_PARK_VALUE_BY: - gameState.scenarioObjective.Year = 3; - gameState.scenarioObjective.Currency = 50000.00_GBP; - break; - case OBJECTIVE_GUESTS_AND_RATING: - gameState.scenarioObjective.NumGuests = 2000; - break; - case OBJECTIVE_MONTHLY_RIDE_INCOME: - gameState.scenarioObjective.Currency = 10000.00_GBP; - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - gameState.scenarioObjective.MinimumLength = 1200; - break; - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - gameState.scenarioObjective.MinimumExcitement = MakeRideRating(6, 70); - break; - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - gameState.scenarioObjective.Currency = 50000.00_GBP; - break; - case OBJECTIVE_MONTHLY_FOOD_INCOME: - gameState.scenarioObjective.Currency = 1000.00_GBP; - break; - } - } - - void ShowObjectiveDropdown() - { - const auto& gameState = getGameState(); - int32_t numItems = 0, objectiveType; - Widget* dropdownWidget; - - dropdownWidget = &widgets[WIDX_OBJECTIVE]; - - for (auto i = 0; i < OBJECTIVE_COUNT; i++) - { - if (i == OBJECTIVE_NONE || i == OBJECTIVE_BUILD_THE_BEST) - continue; - - const bool objectiveAllowedByMoneyUsage = !(getGameState().park.Flags & PARK_FLAGS_NO_MONEY) - || !ObjectiveNeedsMoney(i); - // This objective can only work if the player can ask money for rides. - const bool objectiveAllowedByPaymentSettings = (i != OBJECTIVE_MONTHLY_RIDE_INCOME) - || Park::RidePricesUnlocked(); - if (objectiveAllowedByMoneyUsage && objectiveAllowedByPaymentSettings) - { - gDropdownItems[numItems].Format = STR_DROPDOWN_MENU_LABEL; - gDropdownItems[numItems].Args = ObjectiveDropdownOptionNames[i]; - numItems++; - } - } - - WindowDropdownShowTextCustomWidth( - { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, - colours[1], 0, Dropdown::Flag::StayOpen, numItems, dropdownWidget->width() - 3); - - objectiveType = gameState.scenarioObjective.Type; - for (int32_t j = 0; j < numItems; j++) - { - if (gDropdownItems[j].Args - STR_OBJECTIVE_DROPDOWN_NONE == objectiveType) - { - Dropdown::SetChecked(j, true); - break; - } - } - } - - void ShowCategoryDropdown() - { - int32_t i; - Widget* dropdownWidget; - - dropdownWidget = &widgets[WIDX_CATEGORY]; - - for (i = EnumValue(ScenarioCategory::beginner); i <= EnumValue(ScenarioCategory::other); i++) - { - gDropdownItems[i].Format = STR_DROPDOWN_MENU_LABEL; - gDropdownItems[i].Args = kScenarioCategoryStringIds[i]; - } - WindowDropdownShowTextCustomWidth( - { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, - colours[1], 0, Dropdown::Flag::StayOpen, 5, dropdownWidget->width() - 3); - Dropdown::SetChecked(EnumValue(getGameState().scenarioCategory), true); - } - - void Arg1Increase() - { - auto& gameState = getGameState(); - switch (gameState.scenarioObjective.Type) - { - case OBJECTIVE_PARK_VALUE_BY: - case OBJECTIVE_MONTHLY_RIDE_INCOME: - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - if (gameState.scenarioObjective.Currency >= kObjectiveCurrencyLoanAndValueMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Currency += kObjectiveCurrencyLoanAndValueAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_MONTHLY_FOOD_INCOME: - if (gameState.scenarioObjective.Currency >= kObjectiveCurrencyFoodMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Currency += kObjectiveCurrencyFoodAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - if (gameState.scenarioObjective.MinimumLength >= kObjectiveLengthMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.MinimumLength += kObjectiveLengthAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - if (gameState.scenarioObjective.MinimumExcitement >= kObjectiveExcitementMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.MinimumExcitement += kObjectiveExcitementAdjustment; - Invalidate(); - } - break; - default: - if (gameState.scenarioObjective.NumGuests >= kObjectiveGuestsMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.NumGuests += kObjectiveGuestsAdjustment; - Invalidate(); - } - break; - } - } - - void Arg1Decrease() - { - auto& gameState = getGameState(); - switch (gameState.scenarioObjective.Type) - { - case OBJECTIVE_PARK_VALUE_BY: - case OBJECTIVE_MONTHLY_RIDE_INCOME: - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - if (gameState.scenarioObjective.Currency <= kObjectiveCurrencyLoanAndValueMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Currency -= kObjectiveCurrencyLoanAndValueAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_MONTHLY_FOOD_INCOME: - if (gameState.scenarioObjective.Currency <= kObjectiveCurrencyFoodMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Currency -= kObjectiveCurrencyFoodAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - if (gameState.scenarioObjective.MinimumLength <= kObjectiveLengthMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.MinimumLength -= kObjectiveLengthAdjustment; - Invalidate(); - } - break; - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - if (gameState.scenarioObjective.MinimumExcitement <= kObjectiveExcitementMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.MinimumExcitement -= kObjectiveExcitementAdjustment; - Invalidate(); - } - break; - default: - if (gameState.scenarioObjective.NumGuests <= kObjectiveGuestsMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.NumGuests -= kObjectiveGuestsAdjustment; - Invalidate(); - } - break; - } - } - - void Arg2Increase() - { - auto& gameState = getGameState(); - if (gameState.scenarioObjective.Year >= kObjectiveYearMax) - { - ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Year += kObjectiveYearAdjustment; - Invalidate(); - } - } - - void Arg2Decrease() - { - auto& gameState = getGameState(); - if (gameState.scenarioObjective.Year <= kObjectiveYearMin) - { - ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); - } - else - { - gameState.scenarioObjective.Year -= kObjectiveYearAdjustment; - Invalidate(); - } - } - -#pragma region Main - - /** - * - * rct2: 0x006719CA - */ - void OnMouseUpMain(WidgetIndex widgetIndex) - { - const auto& gameState = getGameState(); - switch (widgetIndex) - { - case WIDX_PARK_NAME: - { - WindowTextInputRawOpen( - this, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, {}, gameState.park.Name.c_str(), - kParkNameMaxLength); - break; - } - case WIDX_SCENARIO_NAME: - WindowTextInputRawOpen( - this, WIDX_SCENARIO_NAME, STR_SCENARIO_NAME, STR_ENTER_SCENARIO_NAME, {}, - gameState.scenarioName.c_str(), kScenarioNameMaxLength); - break; - case WIDX_DETAILS: - WindowTextInputRawOpen( - this, WIDX_DETAILS, STR_PARK_SCENARIO_DETAILS, STR_ENTER_SCENARIO_DESCRIPTION, {}, - gameState.scenarioDetails.c_str(), kScenarioDetailsNameMaxLength); - break; - } - } - - /** - * - * rct2: 0x00672254 - */ - void OnResizeMain() - { - WindowSetResize(*this, { 450, 229 }, { 450, 229 }); - } - - /** - * - * rct2: 0x00671A0D - */ - void OnMouseDownMain(WidgetIndex widgetIndex) - { - switch (widgetIndex) - { - case WIDX_OBJECTIVE_DROPDOWN: - ShowObjectiveDropdown(); - break; - case WIDX_OBJECTIVE_ARG_1_INCREASE: - Arg1Increase(); - break; - case WIDX_OBJECTIVE_ARG_1_DECREASE: - Arg1Decrease(); - break; - case WIDX_OBJECTIVE_ARG_2_INCREASE: - Arg2Increase(); - break; - case WIDX_OBJECTIVE_ARG_2_DECREASE: - Arg2Decrease(); - break; - case WIDX_CATEGORY_DROPDOWN: - ShowCategoryDropdown(); - break; - } - } - - /** - * - * rct2: 0x00671A54 - */ - void OnDropdownMain(WidgetIndex widgetIndex, int32_t dropdownIndex) - { - auto& gameState = getGameState(); - uint8_t newObjectiveType; - - if (dropdownIndex == -1) - return; - - switch (widgetIndex) - { - case WIDX_OBJECTIVE_DROPDOWN: - // TODO: Don't rely on string ID order - newObjectiveType = static_cast(gDropdownItems[dropdownIndex].Args - STR_OBJECTIVE_DROPDOWN_NONE); - if (gameState.scenarioObjective.Type != newObjectiveType) - SetObjective(newObjectiveType); - break; - case WIDX_CATEGORY_DROPDOWN: - if (gameState.scenarioCategory != static_cast(dropdownIndex)) - { - gameState.scenarioCategory = static_cast(dropdownIndex); - Invalidate(); - } - break; - } - } - - /** - * - * rct2: 0x006721E7 - */ - void OnUpdateMain() - { - uint8_t objectiveType; - - frame_no++; - OnPrepareDraw(); - InvalidateWidget(WIDX_TAB_1); - - objectiveType = getGameState().scenarioObjective.Type; - - // Check if objective is allowed by money and pay-per-ride settings. - const bool objectiveAllowedByMoneyUsage = !(getGameState().park.Flags & PARK_FLAGS_NO_MONEY) - || !ObjectiveNeedsMoney(objectiveType); - // This objective can only work if the player can ask money for rides. - const bool objectiveAllowedByPaymentSettings = (objectiveType != OBJECTIVE_MONTHLY_RIDE_INCOME) - || Park::RidePricesUnlocked(); - if (!objectiveAllowedByMoneyUsage || !objectiveAllowedByPaymentSettings) - { - // Reset objective - SetObjective(OBJECTIVE_GUESTS_AND_RATING); - } - } - - /** - * - * rct2: 0x00671A73 - */ - void OnTextInputMain(WidgetIndex widgetIndex, std::string_view text) - { - if (text.empty()) - return; - - auto& gameState = getGameState(); - switch (widgetIndex) - { - case WIDX_PARK_NAME: - { - auto action = ParkSetNameAction(std::string(text)); - GameActions::Execute(&action); - - if (gameState.scenarioName.empty()) - { - gameState.scenarioName = gameState.park.Name; - } - break; - } - case WIDX_SCENARIO_NAME: - gameState.scenarioName = text; - Invalidate(); - break; - case WIDX_DETAILS: - gameState.scenarioDetails = text; - Invalidate(); - break; - } - } - - /** - * - * rct2: 0x0067161C - */ - void OnPrepareDrawMain() - { - auto& gameState = getGameState(); - - SetPressedTab(); - - switch (gameState.scenarioObjective.Type) - { - case OBJECTIVE_GUESTS_BY: - case OBJECTIVE_PARK_VALUE_BY: - widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Spinner; - widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Button; - widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Button; - widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Spinner; - widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Button; - widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Button; - break; - case OBJECTIVE_GUESTS_AND_RATING: - case OBJECTIVE_MONTHLY_RIDE_INCOME: - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - case OBJECTIVE_MONTHLY_FOOD_INCOME: - widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Spinner; - widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Button; - widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Button; - widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Empty; - break; - default: - widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Empty; - widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Empty; - break; - } - - widgets[WIDX_CLOSE].type = gLegacyScene == LegacyScene::scenarioEditor ? WindowWidgetType::Empty - : WindowWidgetType::CloseBox; - - AnchorBorderWidgets(); - } - - /** - * - * rct2: 0x0067161C - */ - void OnDrawMain(DrawPixelInfo& dpi) - { - const auto& gameState = getGameState(); - int32_t widthToSet; - StringId stringId; - - DrawWidgets(dpi); - DrawTabImages(dpi); - - // Objective label - auto screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_OBJECTIVE].top }; - DrawTextBasic(dpi, screenCoords, STR_OBJECTIVE_WINDOW); - - // Objective value - screenCoords = windowPos + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE].left + 1, widgets[WIDX_OBJECTIVE].top }; - auto ft = Formatter(); - ft.Add(ObjectiveDropdownOptionNames[gameState.scenarioObjective.Type]); - DrawTextBasic(dpi, screenCoords, STR_WINDOW_COLOUR_2_STRINGID, ft); - - if (widgets[WIDX_OBJECTIVE_ARG_1].type != WindowWidgetType::Empty) - { - // Objective argument 1 label - screenCoords = windowPos + ScreenCoordsXY{ 28, widgets[WIDX_OBJECTIVE_ARG_1].top }; - switch (gameState.scenarioObjective.Type) - { - case OBJECTIVE_GUESTS_BY: - case OBJECTIVE_GUESTS_AND_RATING: - stringId = STR_WINDOW_OBJECTIVE_GUEST_COUNT; - break; - case OBJECTIVE_PARK_VALUE_BY: - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - stringId = STR_WINDOW_OBJECTIVE_PARK_VALUE; - break; - case OBJECTIVE_MONTHLY_RIDE_INCOME: - stringId = STR_WINDOW_OBJECTIVE_MONTHLY_INCOME; - break; - case OBJECTIVE_MONTHLY_FOOD_INCOME: - stringId = STR_WINDOW_OBJECTIVE_MONTHLY_PROFIT; - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - stringId = STR_WINDOW_OBJECTIVE_MINIMUM_LENGTH; - break; - default: - stringId = STR_WINDOW_OBJECTIVE_EXCITEMENT_RATING; - break; - } - DrawTextBasic(dpi, screenCoords, stringId); - - // Objective argument 1 value - screenCoords = windowPos - + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE_ARG_1].left + 1, widgets[WIDX_OBJECTIVE_ARG_1].top }; - ft = Formatter(); - switch (gameState.scenarioObjective.Type) - { - case OBJECTIVE_GUESTS_BY: - case OBJECTIVE_GUESTS_AND_RATING: - stringId = STR_WINDOW_COLOUR_2_COMMA32; - ft.Add(gameState.scenarioObjective.NumGuests); - break; - case OBJECTIVE_PARK_VALUE_BY: - case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: - case OBJECTIVE_MONTHLY_RIDE_INCOME: - case OBJECTIVE_MONTHLY_FOOD_INCOME: - stringId = STR_CURRENCY_FORMAT_LABEL; - ft.Add(gameState.scenarioObjective.Currency); - break; - case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: - stringId = STR_WINDOW_COLOUR_2_LENGTH; - ft.Add(gameState.scenarioObjective.MinimumLength); - break; - case OBJECTIVE_FINISH_5_ROLLERCOASTERS: - stringId = STR_WINDOW_COLOUR_2_COMMA2DP32; - ft.Add(gameState.scenarioObjective.MinimumExcitement); - break; - default: - stringId = STR_WINDOW_COLOUR_2_COMMA2DP32; - ft.Add(gameState.scenarioObjective.Currency); - break; - } - DrawTextBasic(dpi, screenCoords, stringId, ft, { COLOUR_BLACK }); - } - - if (widgets[WIDX_OBJECTIVE_ARG_2].type != WindowWidgetType::Empty) - { - // Objective argument 2 label - screenCoords = windowPos + ScreenCoordsXY{ 28, widgets[WIDX_OBJECTIVE_ARG_2].top }; - DrawTextBasic(dpi, screenCoords, STR_WINDOW_OBJECTIVE_DATE); - - // Objective argument 2 value - screenCoords = windowPos - + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE_ARG_2].left + 1, widgets[WIDX_OBJECTIVE_ARG_2].top }; - ft = Formatter(); - ft.Add((gameState.scenarioObjective.Year * MONTH_COUNT) - 1); - DrawTextBasic(dpi, screenCoords, STR_WINDOW_OBJECTIVE_VALUE_DATE, ft); - } - - // Park name - screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_PARK_NAME].top }; - widthToSet = widgets[WIDX_PARK_NAME].left - 16; - - { - auto parkName = getGameState().park.Name.c_str(); - - ft = Formatter(); - ft.Add(STR_STRING); - ft.Add(parkName); - DrawTextEllipsised(dpi, screenCoords, widthToSet, STR_WINDOW_PARK_NAME, ft); - } - - // Scenario name - screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_SCENARIO_NAME].top }; - widthToSet = widgets[WIDX_SCENARIO_NAME].left - 16; - - ft = Formatter(); - ft.Add(STR_STRING); - ft.Add(gameState.scenarioName.c_str()); - DrawTextEllipsised(dpi, screenCoords, widthToSet, STR_WINDOW_SCENARIO_NAME, ft); - - // Scenario details label - screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_DETAILS].top }; - DrawTextBasic(dpi, screenCoords, STR_WINDOW_PARK_DETAILS); - - // Scenario details value - screenCoords = windowPos + ScreenCoordsXY{ 16, widgets[WIDX_DETAILS].top + 10 }; - widthToSet = widgets[WIDX_DETAILS].left - 4; - - ft = Formatter(); - ft.Add(STR_STRING); - ft.Add(gameState.scenarioDetails.c_str()); - DrawTextWrapped(dpi, screenCoords, widthToSet, STR_BLACK_STRING, ft); - - // Scenario category label - screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_CATEGORY].top }; - DrawTextBasic(dpi, screenCoords, STR_WINDOW_SCENARIO_GROUP); - - // Scenario category value - screenCoords = windowPos + ScreenCoordsXY{ widgets[WIDX_CATEGORY].left + 1, widgets[WIDX_CATEGORY].top }; - ft = Formatter(); - ft.Add(kScenarioCategoryStringIds[EnumValue(gameState.scenarioCategory)]); - DrawTextBasic(dpi, screenCoords, STR_WINDOW_COLOUR_2_STRINGID, ft); - } - -#pragma endregion - -#pragma region Rides - - /** - * - * rct2: 0x006725A8 - */ - void OnResizeRides() - { - WindowSetResize(*this, { 380, 224 }, { 380, 224 }); - } - - /** - * - * rct2: 0x00672544 - */ - void OnUpdateRides() - { - frame_no++; - OnPrepareDraw(); - OnResize(); - InvalidateWidget(WIDX_TAB_2); - - const auto oldSize = _rideableRides.size(); - _rideableRides.clear(); - for (auto& currentRide : GetRideManager()) - { - if (currentRide.isRide()) - { - _rideableRides.push_back(currentRide.id); - } - } - - if (oldSize != _rideableRides.size()) - { - Invalidate(); - } - } - - /** - * - * rct2: 0x006724BF - */ - ScreenSize OnScrollGetSizeRides(int32_t scrollIndex) - { - ScreenSize newSize; - newSize.height = static_cast(_rideableRides.size()) * 10; - - return newSize; - } - - /** - * - * rct2: 0x006724FC - */ - void OnScrollMouseDownRides(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) - { - auto i = screenCoords.y / 12; - if (i < 0 || i >= static_cast(_rideableRides.size())) - return; - - auto* currentRide = GetRide(_rideableRides[i]); - if (currentRide != nullptr) - { - currentRide->lifecycleFlags ^= RIDE_LIFECYCLE_INDESTRUCTIBLE; - } - Invalidate(); - } - - /** - * - * rct2: 0x006724CC - */ - void OnScrollMouseOverRides(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) - { - int32_t i; - - i = screenCoords.y / 12; - if (i < 0 || i >= static_cast(_rideableRides.size())) - return; - - if (selected_list_item != i) - { - selected_list_item = i; - Invalidate(); - } - } - - /** - * - * rct2: 0x006722B5 - */ - void OnPrepareDrawRides() - { - SetPressedTab(); - - widgets[WIDX_CLOSE].type = gLegacyScene == LegacyScene::scenarioEditor ? WindowWidgetType::Empty - : WindowWidgetType::CloseBox; - - AnchorBorderWidgets(); - } - - /** - * - * rct2: 0x00672340 - */ - void OnDrawRides(DrawPixelInfo& dpi) - { - DrawWidgets(dpi); - DrawTabImages(dpi); - - DrawTextBasic( - dpi, windowPos + ScreenCoordsXY{ 6, widgets[WIDX_PAGE_BACKGROUND].top + 3 }, STR_WINDOW_PRESERVATION_ORDER); - } - - /** - * - * rct2: 0x0067236F - */ - void OnScrollDrawRides(DrawPixelInfo& dpi, int32_t scrollIndex) - { - int32_t colour = ColourMapA[colours[1].colour].mid_light; - GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, colour); - - for (int32_t i = 0; i < static_cast(_rideableRides.size()); i++) - { - int32_t y = i * 12; - - if (y + 12 < dpi.y || y >= dpi.y + dpi.height) - continue; - - // Checkbox - GfxFillRectInset(dpi, { { 2, y }, { 11, y + 10 } }, colours[1], INSET_RECT_F_E0); - - // Highlighted - auto stringId = STR_BLACK_STRING; - if (i == selected_list_item) - { - stringId = STR_WINDOW_COLOUR_2_STRINGID; - GfxFilterRect(dpi, { 0, y, width, y + 11 }, FilterPaletteID::PaletteDarken1); - } - - // Checkbox mark - auto* currentRide = GetRide(_rideableRides[i]); - if (currentRide != nullptr) - { - if (currentRide->lifecycleFlags & RIDE_LIFECYCLE_INDESTRUCTIBLE) - { - auto darkness = stringId == STR_WINDOW_COLOUR_2_STRINGID ? TextDarkness::ExtraDark : TextDarkness::Dark; - DrawText( - dpi, { 2, y }, { colours[1].withFlag(ColourFlag::translucent, false), FontStyle::Medium, darkness }, - kCheckMarkString); - } - - // Ride name - - Formatter ft; - currentRide->formatNameTo(ft); - DrawTextBasic(dpi, { 15, y }, stringId, ft); - } - } - } - -#pragma endregion - }; - - /** - * - * rct2: 0x0067137D - */ - WindowBase* EditorObjectiveOptionsOpen() - { - auto* windowMgr = GetWindowManager(); - auto* window = windowMgr->BringToFrontByClass(WindowClass::EditorObjectiveOptions); - if (window != nullptr) - return window; - - window = windowMgr->Create( - WindowClass::EditorObjectiveOptions, 450, 225, WF_10 | WF_CENTRE_SCREEN); - - return window; - } -} // namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/EditorScenarioOptions.cpp b/src/openrct2-ui/windows/EditorScenarioOptions.cpp index 18dfaf22be..27928c82a0 100644 --- a/src/openrct2-ui/windows/EditorScenarioOptions.cpp +++ b/src/openrct2-ui/windows/EditorScenarioOptions.cpp @@ -12,24 +12,34 @@ #include "../interface/Widget.h" #include "Windows.h" +#include #include #include #include #include #include #include +#include #include #include +#include +#include #include #include #include +#include +#include #include +#include +#include #include -#include #include namespace OpenRCT2::Ui::Windows { + static constexpr int32_t WH_OBJECTIVE = 229; + static constexpr int32_t WW_OBJECTIVE = 450; + static constexpr int32_t WW_FINANCIAL = 280; static constexpr int32_t WH_FINANCIAL = 149; @@ -39,16 +49,58 @@ namespace OpenRCT2::Ui::Windows static constexpr int32_t WW_PARK = 400; static constexpr int32_t WH_PARK = 200; + static constexpr money64 kObjectiveCurrencyLoanAndValueMax = 2000000.00_GBP; + static constexpr money64 kObjectiveCurrencyLoanAndValueMin = 1000.00_GBP; + static constexpr money64 kObjectiveCurrencyLoanAndValueAdjustment = 1000.00_GBP; + + static constexpr money64 kObjectiveCurrencyFoodMax = 2000000.00_GBP; + static constexpr money64 kObjectiveCurrencyFoodMin = 1000.00_GBP; + static constexpr money64 kObjectiveCurrencyFoodAdjustment = 100.00_GBP; + + static constexpr uint16_t kObjectiveLengthMax = 5000; + static constexpr uint16_t kObjectiveLengthMin = 1000; + static constexpr uint16_t kObjectiveLengthAdjustment = 100; + + static constexpr ride_rating kObjectiveExcitementMax = MakeRideRating(9, 90); + static constexpr ride_rating kObjectiveExcitementMin = MakeRideRating(4, 00); + static constexpr ride_rating kObjectiveExcitementAdjustment = MakeRideRating(0, 10); + + // The number has to leave a bit of room for other entities like vehicles, litter and balloons. + static constexpr uint16_t kObjectiveGuestsMax = 50000; + static constexpr uint16_t kObjectiveGuestsMin = 250; + static constexpr uint16_t kObjectiveGuestsAdjustment = 50; + + static constexpr uint8_t kObjectiveYearMax = 25; + static constexpr uint8_t kObjectiveYearMin = 1; + static constexpr uint8_t kObjectiveYearAdjustment = 1; + #pragma region Widgets enum { + WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE, WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL, WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS, WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK, + WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES, WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_COUNT }; + static constexpr StringId ObjectiveDropdownOptionNames[] = { + STR_OBJECTIVE_DROPDOWN_NONE, + STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_AT_A_GIVEN_DATE, + STR_OBJECTIVE_DROPDOWN_PARK_VALUE_AT_A_GIVEN_DATE, + STR_OBJECTIVE_DROPDOWN_HAVE_FUN, + STR_OBJECTIVE_DROPDOWN_BUILD_THE_BEST_RIDE_YOU_CAN, + STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS, + STR_OBJECTIVE_DROPDOWN_NUMBER_OF_GUESTS_IN_PARK, + STR_OBJECTIVE_DROPDOWN_MONTHLY_INCOME_FROM_RIDE_TICKETS, + STR_OBJECTIVE_DROPDOWN_BUILD_10_ROLLER_COASTERS_OF_A_GIVEN_LENGTH, + STR_OBJECTIVE_DROPDOWN_FINISH_BUILDING_5_ROLLER_COASTERS, + STR_OBJECTIVE_DROPDOWN_REPAY_LOAN_AND_ACHIEVE_A_GIVEN_PARK_VALUE, + STR_OBJECTIVE_DROPDOWN_MONTHLY_PROFIT_FROM_FOOD_MERCHANDISE, + }; + enum { WIDX_BACKGROUND, @@ -58,8 +110,25 @@ namespace OpenRCT2::Ui::Windows WIDX_TAB_1, WIDX_TAB_2, WIDX_TAB_3, + WIDX_TAB_4, + WIDX_TAB_5, WIDX_PAGE_START, + // Objective tab + WIDX_OBJECTIVE = WIDX_PAGE_START, + WIDX_OBJECTIVE_DROPDOWN, + WIDX_OBJECTIVE_ARG_1, + WIDX_OBJECTIVE_ARG_1_INCREASE, + WIDX_OBJECTIVE_ARG_1_DECREASE, + WIDX_OBJECTIVE_ARG_2, + WIDX_OBJECTIVE_ARG_2_INCREASE, + WIDX_OBJECTIVE_ARG_2_DECREASE, + WIDX_PARK_NAME, + WIDX_SCENARIO_NAME, + WIDX_CATEGORY, + WIDX_CATEGORY_DROPDOWN, + WIDX_DETAILS, + // Financial tab WIDX_NO_MONEY = WIDX_PAGE_START, WIDX_INITIAL_CASH, @@ -114,12 +183,30 @@ namespace OpenRCT2::Ui::Windows }; // clang-format off + #define MAIN_OPTIONS_WIDGETS(TITLE, WIDTH, HEIGHT) \ + WINDOW_SHIM(TITLE, WIDTH, HEIGHT), \ + MakeWidget({ 0, 43}, { WIDTH, 106 }, WindowWidgetType::Resize, WindowColour::Secondary), \ + MakeTab ({ 3, 17}, STR_SELECT_OBJECTIVE_AND_PARK_NAME_TIP ), \ + MakeTab ({ 34, 17}, STR_SCENARIO_OPTIONS_FINANCIAL_TIP ), \ + MakeTab ({ 65, 17}, STR_SCENARIO_OPTIONS_GUESTS_TIP ), \ + MakeTab ({ 96, 17}, STR_SCENARIO_OPTIONS_PARK_TIP ), \ + MakeTab ({127, 17}, STR_SELECT_RIDES_TO_BE_PRESERVED_TIP ) + + static constexpr Widget window_editor_scenario_options_objective_widgets[] = { + MAIN_OPTIONS_WIDGETS(STR_OBJECTIVE_SELECTION, WW_OBJECTIVE, WH_OBJECTIVE), + MakeWidget ({ 98, 48}, {344, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, kStringIdNone, STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP ), + MakeWidget ({430, 49}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_OBJECTIVE_FOR_THIS_SCENARIO_TIP ), + MakeSpinnerWidgets({158, 65}, {120, 12}, WindowWidgetType::Button, WindowColour::Secondary ), // NB: 3 widgets + MakeSpinnerWidgets({158, 82}, {120, 12}, WindowWidgetType::Button, WindowColour::Secondary ), // NB: 3 widgets + MakeWidget ({370, 99}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_NAME_OF_PARK_TIP ), + MakeWidget ({370, 116}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_NAME_OF_SCENARIO_TIP ), + MakeWidget ({ 98, 133}, {180, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, kStringIdNone, STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN), + MakeWidget ({266, 134}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH, STR_SELECT_WHICH_GROUP_THIS_SCENARIO_APPEARS_IN), + MakeWidget ({370, 150}, { 75, 12}, WindowWidgetType::Button, WindowColour::Secondary, STR_CHANGE, STR_CHANGE_DETAIL_NOTES_ABOUT_PARK_SCENARIO_TIP), + }; + static constexpr Widget window_editor_scenario_options_financial_widgets[] = { - WINDOW_SHIM(STR_SCENARIO_OPTIONS_FINANCIAL, WW_FINANCIAL, WH_FINANCIAL), - MakeWidget ({ 0, 43}, { WW_FINANCIAL, 106}, WindowWidgetType::Resize, WindowColour::Secondary ), - MakeTab ({ 3, 17}, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), - MakeTab ({ 34, 17}, STR_SCENARIO_OPTIONS_GUESTS_TIP ), - MakeTab ({ 65, 17}, STR_SCENARIO_OPTIONS_PARK_TIP ), + MAIN_OPTIONS_WIDGETS(STR_SCENARIO_OPTIONS_FINANCIAL, WW_FINANCIAL, WH_FINANCIAL), MakeWidget ({ 8, 48}, {WW_FINANCIAL - 16, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_MAKE_PARK_NO_MONEY, STR_MAKE_PARK_NO_MONEY_TIP ), MakeSpinnerWidgets({168, 65}, { 100, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets MakeSpinnerWidgets({168, 82}, { 100, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets @@ -130,11 +217,7 @@ namespace OpenRCT2::Ui::Windows }; static constexpr Widget window_editor_scenario_options_guests_widgets[] = { - WINDOW_SHIM(STR_SCENARIO_OPTIONS_GUESTS, WW_GUESTS, WH_GUESTS), - MakeWidget ({ 0, 43}, {WW_GUESTS, 106}, WindowWidgetType::Resize, WindowColour::Secondary), - MakeRemapWidget ({ 3, 17}, { 31, 27}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), - MakeRemapWidget ({ 34, 17}, { 31, 30}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_GUESTS_TIP ), - MakeRemapWidget ({ 65, 17}, { 31, 27}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_PARK_TIP ), + MAIN_OPTIONS_WIDGETS(STR_SCENARIO_OPTIONS_GUESTS, WW_GUESTS, WH_GUESTS), MakeSpinnerWidgets({298, 48}, { 70, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets MakeSpinnerWidgets({298, 65}, { 70, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets MakeSpinnerWidgets({298, 82}, { 70, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets @@ -145,11 +228,7 @@ namespace OpenRCT2::Ui::Windows }; static constexpr Widget window_editor_scenario_options_park_widgets[] = { - WINDOW_SHIM(STR_SCENARIO_OPTIONS_PARK, WW_PARK, WH_PARK), - MakeWidget ({ 0, 43}, { WW_PARK, 106}, WindowWidgetType::Resize, WindowColour::Secondary ), - MakeRemapWidget ({ 3, 17}, { 31, 27}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_FINANCIAL_TIP), - MakeRemapWidget ({ 34, 17}, { 31, 30}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_GUESTS_TIP ), - MakeRemapWidget ({ 65, 17}, { 31, 27}, WindowWidgetType::Tab, WindowColour::Secondary, SPR_TAB, STR_SCENARIO_OPTIONS_PARK_TIP ), + MAIN_OPTIONS_WIDGETS(STR_SCENARIO_OPTIONS_PARK, WW_PARK, WH_PARK), MakeSpinnerWidgets({188, 48}, { 70, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets MakeSpinnerWidgets({188, 65}, { 70, 12}, WindowWidgetType::Spinner, WindowColour::Secondary ), // NB: 3 widgets MakeWidget ({ 8, 82}, { 210, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary, kStringIdNone, STR_PAY_FOR_PARK_PAY_FOR_RIDES_TIP), @@ -162,10 +241,17 @@ namespace OpenRCT2::Ui::Windows MakeWidget ({ 8, 184}, {WW_PARK - 16, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_HARD_GUEST_GENERATION, STR_HARD_GUEST_GENERATION_TIP ), }; + static constexpr Widget window_editor_scenario_options_rides_widgets[] = { + MAIN_OPTIONS_WIDGETS(STR_OBJECTIVE_SELECTION, WW_OBJECTIVE, WH_OBJECTIVE), + MakeWidget({ 3, 60}, {374, 161}, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL), + }; + static constexpr std::span window_editor_scenario_options_widgets[] = { + window_editor_scenario_options_objective_widgets, window_editor_scenario_options_financial_widgets, window_editor_scenario_options_guests_widgets, window_editor_scenario_options_park_widgets, + window_editor_scenario_options_rides_widgets, }; #pragma endregion @@ -173,6 +259,10 @@ namespace OpenRCT2::Ui::Windows #pragma region Enabled widgets static uint32_t window_editor_scenario_options_page_hold_down_widgets[] = { + (1uLL << WIDX_OBJECTIVE_ARG_1_INCREASE) | + (1uLL << WIDX_OBJECTIVE_ARG_1_DECREASE) | + (1uLL << WIDX_OBJECTIVE_ARG_2_INCREASE) | + (1uLL << WIDX_OBJECTIVE_ARG_2_DECREASE), (1uLL << WIDX_INITIAL_CASH_INCREASE) | (1uLL << WIDX_INITIAL_CASH_DECREASE) | (1uLL << WIDX_INITIAL_LOAN_INCREASE) | @@ -195,6 +285,7 @@ namespace OpenRCT2::Ui::Windows (1uLL << WIDX_CONSTRUCTION_RIGHTS_COST_DECREASE) | (1uLL << WIDX_ENTRY_PRICE_INCREASE) | (1uLL << WIDX_ENTRY_PRICE_DECREASE), + 0 }; // clang-format on @@ -202,16 +293,36 @@ namespace OpenRCT2::Ui::Windows class EditorScenarioOptionsWindow final : public Window { + private: + // Not shops or facilities + std::vector _rideableRides; + public: void OnOpen() override { - SetPage(WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL); + SetPage(WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE); } void OnMouseUp(WidgetIndex widgetIndex) override { + switch (widgetIndex) + { + case WIDX_CLOSE: + Close(); + return; + case WIDX_TAB_1: + case WIDX_TAB_2: + case WIDX_TAB_3: + case WIDX_TAB_4: + case WIDX_TAB_5: + SetPage(widgetIndex - WIDX_TAB_1); + return; + } + switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnMouseUp(widgetIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialMouseUp(widgetIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: @@ -225,12 +336,16 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnResize(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialResize(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: return GuestsResize(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK: return ParkResize(); + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES: + return RidesOnResize(); } } @@ -238,6 +353,8 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnMouseDown(widgetIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialMouseDown(widgetIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: @@ -251,12 +368,16 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnUpdate(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialUpdate(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: return GuestsUpdate(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK: return ParkUpdate(); + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES: + return RidesOnUpdate(); } } @@ -264,12 +385,16 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnPrepareDraw(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialPrepareDraw(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: return GuestsPrepareDraw(); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK: return ParkPrepareDraw(); + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES: + return RidesOnPrepareDraw(); } } @@ -277,12 +402,16 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnDraw(dpi); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL: return FinancialDraw(dpi); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: return GuestsDraw(dpi); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK: return ParkDraw(dpi); + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES: + return RidesOnDraw(dpi); } } @@ -290,6 +419,8 @@ namespace OpenRCT2::Ui::Windows { switch (page) { + case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE: + return ObjectiveOnDropdown(widgetIndex, selectedIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS: return GuestsDropdown(widgetIndex, selectedIndex); case WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_PARK: @@ -297,6 +428,48 @@ namespace OpenRCT2::Ui::Windows } } + void OnTextInput(WidgetIndex widgetIndex, std::string_view text) override + { + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE) + { + ObjectiveOnTextInput(widgetIndex, text); + } + } + + void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES) + { + RidesOnScrollMouseDown(scrollIndex, screenCoords); + } + } + + void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES) + { + RidesOnScrollMouseOver(scrollIndex, screenCoords); + } + } + + void OnScrollDraw(int32_t scrollIndex, DrawPixelInfo& dpi) override + { + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES) + { + RidesOnScrollDraw(dpi, scrollIndex); + } + } + + ScreenSize OnScrollGetSize(int32_t scrollIndex) override + { + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES) + { + return RidesOnScrollGetSize(scrollIndex); + } + + return {}; + } + private: void SetPressedTab() { @@ -318,24 +491,43 @@ namespace OpenRCT2::Ui::Windows // Tab 1 widget = &widgets[WIDX_TAB_1]; + spriteIndex = SPR_TAB_OBJECTIVE_0; + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_OBJECTIVE) + spriteIndex += (frame_no / 4) % 16; + + GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); + + // Tab 2 + widget = &widgets[WIDX_TAB_2]; spriteIndex = SPR_TAB_FINANCES_SUMMARY_0; if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_FINANCIAL) spriteIndex += (frame_no / 2) % 8; GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); - // Tab 2 - widget = &widgets[WIDX_TAB_2]; + // Tab 3 + widget = &widgets[WIDX_TAB_3]; spriteIndex = SPR_TAB_GUESTS_0; if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_GUESTS) spriteIndex += (frame_no / 4) % 8; GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); - // Tab 3 - widget = &widgets[WIDX_TAB_3]; + // Tab 4 + widget = &widgets[WIDX_TAB_4]; spriteIndex = SPR_TAB_PARK; GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); + + // Tab 5 + if (!IsWidgetDisabled(WIDX_TAB_5)) + { + widget = &widgets[WIDX_TAB_5]; + spriteIndex = SPR_TAB_RIDE_0; + if (page == WINDOW_EDITOR_SCENARIO_OPTIONS_PAGE_RIDES) + spriteIndex += (frame_no / 4) % 16; + + GfxDrawSprite(dpi, ImageId(spriteIndex), windowPos + ScreenCoordsXY{ widget->left, widget->top }); + } } void SetPage(int32_t newPage) @@ -347,14 +539,658 @@ namespace OpenRCT2::Ui::Windows page = newPage; frame_no = 0; hold_down_widgets = window_editor_scenario_options_page_hold_down_widgets[page]; + pressed_widgets = 0; + SetWidgets(window_editor_scenario_options_widgets[page]); Invalidate(); + UpdateDisabledWidgets(); OnResize(); OnPrepareDraw(); InitScrollWidgets(); Invalidate(); } + /** + * + * rct2: 0x00672609 + */ + void UpdateDisabledWidgets() + { + // Check if there are any rides (not shops or facilities) + const auto& rideManager = GetRideManager(); + if (std::any_of( + rideManager.begin(), rideManager.end(), [](const Ride& rideToCheck) { return rideToCheck.isRide(); })) + { + disabled_widgets &= ~(1uLL << WIDX_TAB_5); + } + else + { + disabled_widgets |= (1uLL << WIDX_TAB_5); + } + } + +#pragma region Objective + + /** + * + * rct2: 0x0067201D + */ + void SetObjective(int32_t objective) + { + auto& gameState = getGameState(); + gameState.scenarioObjective.Type = objective; + Invalidate(); + + // Set default objective arguments + switch (objective) + { + case OBJECTIVE_NONE: + case OBJECTIVE_HAVE_FUN: + case OBJECTIVE_BUILD_THE_BEST: + case OBJECTIVE_10_ROLLERCOASTERS: + break; + case OBJECTIVE_GUESTS_BY: + gameState.scenarioObjective.Year = 3; + gameState.scenarioObjective.NumGuests = 1500; + break; + case OBJECTIVE_PARK_VALUE_BY: + gameState.scenarioObjective.Year = 3; + gameState.scenarioObjective.Currency = 50000.00_GBP; + break; + case OBJECTIVE_GUESTS_AND_RATING: + gameState.scenarioObjective.NumGuests = 2000; + break; + case OBJECTIVE_MONTHLY_RIDE_INCOME: + gameState.scenarioObjective.Currency = 10000.00_GBP; + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + gameState.scenarioObjective.MinimumLength = 1200; + break; + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + gameState.scenarioObjective.MinimumExcitement = MakeRideRating(6, 70); + break; + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + gameState.scenarioObjective.Currency = 50000.00_GBP; + break; + case OBJECTIVE_MONTHLY_FOOD_INCOME: + gameState.scenarioObjective.Currency = 1000.00_GBP; + break; + } + } + + void ShowObjectiveDropdown() + { + const auto& gameState = getGameState(); + int32_t numItems = 0, objectiveType; + Widget* dropdownWidget; + + dropdownWidget = &widgets[WIDX_OBJECTIVE]; + + for (auto i = 0; i < OBJECTIVE_COUNT; i++) + { + if (i == OBJECTIVE_NONE || i == OBJECTIVE_BUILD_THE_BEST) + continue; + + const bool objectiveAllowedByMoneyUsage = !(gameState.park.Flags & PARK_FLAGS_NO_MONEY) + || !ObjectiveNeedsMoney(i); + // This objective can only work if the player can ask money for rides. + const bool objectiveAllowedByPaymentSettings = (i != OBJECTIVE_MONTHLY_RIDE_INCOME) + || Park::RidePricesUnlocked(); + if (objectiveAllowedByMoneyUsage && objectiveAllowedByPaymentSettings) + { + gDropdownItems[numItems].Format = STR_DROPDOWN_MENU_LABEL; + gDropdownItems[numItems].Args = ObjectiveDropdownOptionNames[i]; + numItems++; + } + } + + WindowDropdownShowTextCustomWidth( + { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, + colours[1], 0, Dropdown::Flag::StayOpen, numItems, dropdownWidget->width() - 3); + + objectiveType = gameState.scenarioObjective.Type; + for (int32_t j = 0; j < numItems; j++) + { + if (gDropdownItems[j].Args - STR_OBJECTIVE_DROPDOWN_NONE == objectiveType) + { + Dropdown::SetChecked(j, true); + break; + } + } + } + + void ShowCategoryDropdown() + { + int32_t i; + Widget* dropdownWidget; + + dropdownWidget = &widgets[WIDX_CATEGORY]; + + for (i = EnumValue(ScenarioCategory::beginner); i <= EnumValue(ScenarioCategory::other); i++) + { + gDropdownItems[i].Format = STR_DROPDOWN_MENU_LABEL; + gDropdownItems[i].Args = kScenarioCategoryStringIds[i]; + } + WindowDropdownShowTextCustomWidth( + { windowPos.x + dropdownWidget->left, windowPos.y + dropdownWidget->top }, dropdownWidget->height() + 1, + colours[1], 0, Dropdown::Flag::StayOpen, 5, dropdownWidget->width() - 3); + Dropdown::SetChecked(EnumValue(getGameState().scenarioCategory), true); + } + + void Arg1Increase() + { + auto& gameState = getGameState(); + switch (gameState.scenarioObjective.Type) + { + case OBJECTIVE_PARK_VALUE_BY: + case OBJECTIVE_MONTHLY_RIDE_INCOME: + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + if (gameState.scenarioObjective.Currency >= kObjectiveCurrencyLoanAndValueMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Currency += kObjectiveCurrencyLoanAndValueAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_MONTHLY_FOOD_INCOME: + if (gameState.scenarioObjective.Currency >= kObjectiveCurrencyFoodMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Currency += kObjectiveCurrencyFoodAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + if (gameState.scenarioObjective.MinimumLength >= kObjectiveLengthMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.MinimumLength += kObjectiveLengthAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + if (gameState.scenarioObjective.MinimumExcitement >= kObjectiveExcitementMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.MinimumExcitement += kObjectiveExcitementAdjustment; + Invalidate(); + } + break; + default: + if (gameState.scenarioObjective.NumGuests >= kObjectiveGuestsMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.NumGuests += kObjectiveGuestsAdjustment; + Invalidate(); + } + break; + } + } + + void Arg1Decrease() + { + auto& gameState = getGameState(); + switch (gameState.scenarioObjective.Type) + { + case OBJECTIVE_PARK_VALUE_BY: + case OBJECTIVE_MONTHLY_RIDE_INCOME: + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + if (gameState.scenarioObjective.Currency <= kObjectiveCurrencyLoanAndValueMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Currency -= kObjectiveCurrencyLoanAndValueAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_MONTHLY_FOOD_INCOME: + if (gameState.scenarioObjective.Currency <= kObjectiveCurrencyFoodMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Currency -= kObjectiveCurrencyFoodAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + if (gameState.scenarioObjective.MinimumLength <= kObjectiveLengthMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.MinimumLength -= kObjectiveLengthAdjustment; + Invalidate(); + } + break; + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + if (gameState.scenarioObjective.MinimumExcitement <= kObjectiveExcitementMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.MinimumExcitement -= kObjectiveExcitementAdjustment; + Invalidate(); + } + break; + default: + if (gameState.scenarioObjective.NumGuests <= kObjectiveGuestsMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.NumGuests -= kObjectiveGuestsAdjustment; + Invalidate(); + } + break; + } + } + + void Arg2Increase() + { + auto& gameState = getGameState(); + if (gameState.scenarioObjective.Year >= kObjectiveYearMax) + { + ContextShowError(STR_CANT_INCREASE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Year += kObjectiveYearAdjustment; + Invalidate(); + } + } + + void Arg2Decrease() + { + auto& gameState = getGameState(); + if (gameState.scenarioObjective.Year <= kObjectiveYearMin) + { + ContextShowError(STR_CANT_REDUCE_FURTHER, kStringIdNone, {}); + } + else + { + gameState.scenarioObjective.Year -= kObjectiveYearAdjustment; + Invalidate(); + } + } + + /** + * + * rct2: 0x006719CA + */ + void ObjectiveOnMouseUp(WidgetIndex widgetIndex) + { + const auto& gameState = getGameState(); + switch (widgetIndex) + { + case WIDX_PARK_NAME: + { + WindowTextInputRawOpen( + this, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, {}, gameState.park.Name.c_str(), + kParkNameMaxLength); + break; + } + case WIDX_SCENARIO_NAME: + WindowTextInputRawOpen( + this, WIDX_SCENARIO_NAME, STR_SCENARIO_NAME, STR_ENTER_SCENARIO_NAME, {}, + gameState.scenarioName.c_str(), kScenarioNameMaxLength); + break; + case WIDX_DETAILS: + WindowTextInputRawOpen( + this, WIDX_DETAILS, STR_PARK_SCENARIO_DETAILS, STR_ENTER_SCENARIO_DESCRIPTION, {}, + gameState.scenarioDetails.c_str(), kScenarioDetailsNameMaxLength); + break; + } + } + + /** + * + * rct2: 0x00672254 + */ + void ObjectiveOnResize() + { + WindowSetResize(*this, { 450, 229 }, { 450, 229 }); + } + + /** + * + * rct2: 0x00671A0D + */ + void ObjectiveOnMouseDown(WidgetIndex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_OBJECTIVE_DROPDOWN: + ShowObjectiveDropdown(); + break; + case WIDX_OBJECTIVE_ARG_1_INCREASE: + Arg1Increase(); + break; + case WIDX_OBJECTIVE_ARG_1_DECREASE: + Arg1Decrease(); + break; + case WIDX_OBJECTIVE_ARG_2_INCREASE: + Arg2Increase(); + break; + case WIDX_OBJECTIVE_ARG_2_DECREASE: + Arg2Decrease(); + break; + case WIDX_CATEGORY_DROPDOWN: + ShowCategoryDropdown(); + break; + } + } + + /** + * + * rct2: 0x00671A54 + */ + void ObjectiveOnDropdown(WidgetIndex widgetIndex, int32_t dropdownIndex) + { + auto& gameState = getGameState(); + uint8_t newObjectiveType; + + if (dropdownIndex == -1) + return; + + switch (widgetIndex) + { + case WIDX_OBJECTIVE_DROPDOWN: + // TODO: Don't rely on string ID order + newObjectiveType = static_cast(gDropdownItems[dropdownIndex].Args - STR_OBJECTIVE_DROPDOWN_NONE); + if (gameState.scenarioObjective.Type != newObjectiveType) + SetObjective(newObjectiveType); + break; + case WIDX_CATEGORY_DROPDOWN: + if (gameState.scenarioCategory != static_cast(dropdownIndex)) + { + gameState.scenarioCategory = static_cast(dropdownIndex); + Invalidate(); + } + break; + } + } + + /** + * + * rct2: 0x006721E7 + */ + void ObjectiveOnUpdate() + { + uint8_t objectiveType; + + frame_no++; + OnPrepareDraw(); + InvalidateWidget(WIDX_TAB_1); + + objectiveType = getGameState().scenarioObjective.Type; + + // Check if objective is allowed by money and pay-per-ride settings. + const bool objectiveAllowedByMoneyUsage = !(getGameState().park.Flags & PARK_FLAGS_NO_MONEY) + || !ObjectiveNeedsMoney(objectiveType); + // This objective can only work if the player can ask money for rides. + const bool objectiveAllowedByPaymentSettings = (objectiveType != OBJECTIVE_MONTHLY_RIDE_INCOME) + || Park::RidePricesUnlocked(); + if (!objectiveAllowedByMoneyUsage || !objectiveAllowedByPaymentSettings) + { + // Reset objective + SetObjective(OBJECTIVE_GUESTS_AND_RATING); + } + } + + /** + * + * rct2: 0x00671A73 + */ + void ObjectiveOnTextInput(WidgetIndex widgetIndex, std::string_view text) + { + if (text.empty()) + return; + + auto& gameState = getGameState(); + switch (widgetIndex) + { + case WIDX_PARK_NAME: + { + auto action = ParkSetNameAction(std::string(text)); + GameActions::Execute(&action); + + if (gameState.scenarioName.empty()) + { + gameState.scenarioName = gameState.park.Name; + } + break; + } + case WIDX_SCENARIO_NAME: + gameState.scenarioName = text; + Invalidate(); + break; + case WIDX_DETAILS: + gameState.scenarioDetails = text; + Invalidate(); + break; + } + } + + /** + * + * rct2: 0x0067161C + */ + void ObjectiveOnPrepareDraw() + { + auto& gameState = getGameState(); + + SetPressedTab(); + + switch (gameState.scenarioObjective.Type) + { + case OBJECTIVE_GUESTS_BY: + case OBJECTIVE_PARK_VALUE_BY: + widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Spinner; + widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Button; + widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Button; + widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Spinner; + widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Button; + widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Button; + break; + case OBJECTIVE_GUESTS_AND_RATING: + case OBJECTIVE_MONTHLY_RIDE_INCOME: + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + case OBJECTIVE_MONTHLY_FOOD_INCOME: + widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Spinner; + widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Button; + widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Button; + widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Empty; + break; + default: + widgets[WIDX_OBJECTIVE_ARG_1].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_1_INCREASE].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_1_DECREASE].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_2].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_2_INCREASE].type = WindowWidgetType::Empty; + widgets[WIDX_OBJECTIVE_ARG_2_DECREASE].type = WindowWidgetType::Empty; + break; + } + + widgets[WIDX_CLOSE].type = gLegacyScene == LegacyScene::scenarioEditor ? WindowWidgetType::Empty + : WindowWidgetType::CloseBox; + + AnchorBorderWidgets(); + } + + /** + * + * rct2: 0x0067161C + */ + void ObjectiveOnDraw(DrawPixelInfo& dpi) + { + const auto& gameState = getGameState(); + int32_t widthToSet; + StringId stringId; + + DrawWidgets(dpi); + DrawTabImages(dpi); + + // Objective label + auto screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_OBJECTIVE].top }; + DrawTextBasic(dpi, screenCoords, STR_OBJECTIVE_WINDOW); + + // Objective value + screenCoords = windowPos + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE].left + 1, widgets[WIDX_OBJECTIVE].top }; + auto ft = Formatter(); + ft.Add(ObjectiveDropdownOptionNames[gameState.scenarioObjective.Type]); + DrawTextBasic(dpi, screenCoords, STR_WINDOW_COLOUR_2_STRINGID, ft); + + if (widgets[WIDX_OBJECTIVE_ARG_1].type != WindowWidgetType::Empty) + { + // Objective argument 1 label + screenCoords = windowPos + ScreenCoordsXY{ 28, widgets[WIDX_OBJECTIVE_ARG_1].top }; + switch (gameState.scenarioObjective.Type) + { + case OBJECTIVE_GUESTS_BY: + case OBJECTIVE_GUESTS_AND_RATING: + stringId = STR_WINDOW_OBJECTIVE_GUEST_COUNT; + break; + case OBJECTIVE_PARK_VALUE_BY: + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + stringId = STR_WINDOW_OBJECTIVE_PARK_VALUE; + break; + case OBJECTIVE_MONTHLY_RIDE_INCOME: + stringId = STR_WINDOW_OBJECTIVE_MONTHLY_INCOME; + break; + case OBJECTIVE_MONTHLY_FOOD_INCOME: + stringId = STR_WINDOW_OBJECTIVE_MONTHLY_PROFIT; + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + stringId = STR_WINDOW_OBJECTIVE_MINIMUM_LENGTH; + break; + default: + stringId = STR_WINDOW_OBJECTIVE_EXCITEMENT_RATING; + break; + } + DrawTextBasic(dpi, screenCoords, stringId); + + // Objective argument 1 value + screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE_ARG_1].left + 1, widgets[WIDX_OBJECTIVE_ARG_1].top }; + ft = Formatter(); + switch (gameState.scenarioObjective.Type) + { + case OBJECTIVE_GUESTS_BY: + case OBJECTIVE_GUESTS_AND_RATING: + stringId = STR_WINDOW_COLOUR_2_COMMA32; + ft.Add(gameState.scenarioObjective.NumGuests); + break; + case OBJECTIVE_PARK_VALUE_BY: + case OBJECTIVE_REPAY_LOAN_AND_PARK_VALUE: + case OBJECTIVE_MONTHLY_RIDE_INCOME: + case OBJECTIVE_MONTHLY_FOOD_INCOME: + stringId = STR_CURRENCY_FORMAT_LABEL; + ft.Add(gameState.scenarioObjective.Currency); + break; + case OBJECTIVE_10_ROLLERCOASTERS_LENGTH: + stringId = STR_WINDOW_COLOUR_2_LENGTH; + ft.Add(gameState.scenarioObjective.MinimumLength); + break; + case OBJECTIVE_FINISH_5_ROLLERCOASTERS: + stringId = STR_WINDOW_COLOUR_2_COMMA2DP32; + ft.Add(gameState.scenarioObjective.MinimumExcitement); + break; + default: + stringId = STR_WINDOW_COLOUR_2_COMMA2DP32; + ft.Add(gameState.scenarioObjective.Currency); + break; + } + DrawTextBasic(dpi, screenCoords, stringId, ft, { COLOUR_BLACK }); + } + + if (widgets[WIDX_OBJECTIVE_ARG_2].type != WindowWidgetType::Empty) + { + // Objective argument 2 label + screenCoords = windowPos + ScreenCoordsXY{ 28, widgets[WIDX_OBJECTIVE_ARG_2].top }; + DrawTextBasic(dpi, screenCoords, STR_WINDOW_OBJECTIVE_DATE); + + // Objective argument 2 value + screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_OBJECTIVE_ARG_2].left + 1, widgets[WIDX_OBJECTIVE_ARG_2].top }; + ft = Formatter(); + ft.Add((gameState.scenarioObjective.Year * MONTH_COUNT) - 1); + DrawTextBasic(dpi, screenCoords, STR_WINDOW_OBJECTIVE_VALUE_DATE, ft); + } + + // Park name + screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_PARK_NAME].top }; + widthToSet = widgets[WIDX_PARK_NAME].left - 16; + + { + auto parkName = getGameState().park.Name.c_str(); + + ft = Formatter(); + ft.Add(STR_STRING); + ft.Add(parkName); + DrawTextEllipsised(dpi, screenCoords, widthToSet, STR_WINDOW_PARK_NAME, ft); + } + + // Scenario name + screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_SCENARIO_NAME].top }; + widthToSet = widgets[WIDX_SCENARIO_NAME].left - 16; + + ft = Formatter(); + ft.Add(STR_STRING); + ft.Add(gameState.scenarioName.c_str()); + DrawTextEllipsised(dpi, screenCoords, widthToSet, STR_WINDOW_SCENARIO_NAME, ft); + + // Scenario details label + screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_DETAILS].top }; + DrawTextBasic(dpi, screenCoords, STR_WINDOW_PARK_DETAILS); + + // Scenario details value + screenCoords = windowPos + ScreenCoordsXY{ 16, widgets[WIDX_DETAILS].top + 10 }; + widthToSet = widgets[WIDX_DETAILS].left - 4; + + ft = Formatter(); + ft.Add(STR_STRING); + ft.Add(gameState.scenarioDetails.c_str()); + DrawTextWrapped(dpi, screenCoords, widthToSet, STR_BLACK_STRING, ft); + + // Scenario category label + screenCoords = windowPos + ScreenCoordsXY{ 8, widgets[WIDX_CATEGORY].top }; + DrawTextBasic(dpi, screenCoords, STR_WINDOW_SCENARIO_GROUP); + + // Scenario category value + screenCoords = windowPos + ScreenCoordsXY{ widgets[WIDX_CATEGORY].left + 1, widgets[WIDX_CATEGORY].top }; + ft = Formatter(); + ft.Add(kScenarioCategoryStringIds[EnumValue(gameState.scenarioCategory)]); + DrawTextBasic(dpi, screenCoords, STR_WINDOW_COLOUR_2_STRINGID, ft); + } + +#pragma endregion + #pragma region Financial void FinancialMouseUp(WidgetIndex widgetIndex) @@ -362,14 +1198,6 @@ namespace OpenRCT2::Ui::Windows auto& gameState = getGameState(); switch (widgetIndex) { - case WIDX_CLOSE: - Close(); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - SetPage(widgetIndex - WIDX_TAB_1); - break; case WIDX_NO_MONEY: { auto newMoneySetting = (gameState.park.Flags & PARK_FLAGS_NO_MONEY) ? 0 : 1; @@ -525,7 +1353,6 @@ namespace OpenRCT2::Ui::Windows void FinancialUpdate() { frame_no++; - FinancialPrepareDraw(); InvalidateWidget(WIDX_TAB_1); } @@ -643,21 +1470,6 @@ namespace OpenRCT2::Ui::Windows #pragma region Guests - void GuestsMouseUp(WidgetIndex widgetIndex) - { - switch (widgetIndex) - { - case WIDX_CLOSE: - Close(); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - SetPage(widgetIndex - WIDX_TAB_1); - break; - } - } - void GuestsResize() { WindowSetResize(*this, { WW_GUESTS, WH_GUESTS }, { WW_GUESTS, WH_GUESTS }); @@ -829,7 +1641,6 @@ namespace OpenRCT2::Ui::Windows void GuestsUpdate() { frame_no++; - GuestsPrepareDraw(); InvalidateWidget(WIDX_TAB_2); } @@ -943,14 +1754,6 @@ namespace OpenRCT2::Ui::Windows auto& gameState = getGameState(); switch (widgetIndex) { - case WIDX_CLOSE: - Close(); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - SetPage(widgetIndex - WIDX_TAB_1); - break; case WIDX_FORBID_TREE_REMOVAL: { auto scenarioSetSetting = ScenarioSetSettingAction( @@ -1136,7 +1939,6 @@ namespace OpenRCT2::Ui::Windows void ParkUpdate() { frame_no++; - ParkPrepareDraw(); InvalidateWidget(WIDX_TAB_3); } @@ -1257,6 +2059,170 @@ namespace OpenRCT2::Ui::Windows } } +#pragma endregion + +#pragma region Rides + + /** + * + * rct2: 0x006725A8 + */ + void RidesOnResize() + { + WindowSetResize(*this, { 380, 224 }, { 380, 224 }); + } + + /** + * + * rct2: 0x00672544 + */ + void RidesOnUpdate() + { + frame_no++; + OnPrepareDraw(); + OnResize(); + InvalidateWidget(WIDX_TAB_2); + + const auto oldSize = _rideableRides.size(); + _rideableRides.clear(); + for (auto& currentRide : GetRideManager()) + { + if (currentRide.isRide()) + { + _rideableRides.push_back(currentRide.id); + } + } + + if (oldSize != _rideableRides.size()) + { + Invalidate(); + } + } + + /** + * + * rct2: 0x006724BF + */ + ScreenSize RidesOnScrollGetSize(int32_t scrollIndex) + { + ScreenSize newSize; + newSize.height = static_cast(_rideableRides.size()) * 10; + + return newSize; + } + + /** + * + * rct2: 0x006724FC + */ + void RidesOnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) + { + auto i = screenCoords.y / 12; + if (i < 0 || i >= static_cast(_rideableRides.size())) + return; + + auto* currentRide = GetRide(_rideableRides[i]); + if (currentRide != nullptr) + { + currentRide->lifecycleFlags ^= RIDE_LIFECYCLE_INDESTRUCTIBLE; + } + Invalidate(); + } + + /** + * + * rct2: 0x006724CC + */ + void RidesOnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) + { + int32_t i; + + i = screenCoords.y / 12; + if (i < 0 || i >= static_cast(_rideableRides.size())) + return; + + if (selected_list_item != i) + { + selected_list_item = i; + Invalidate(); + } + } + + /** + * + * rct2: 0x006722B5 + */ + void RidesOnPrepareDraw() + { + SetPressedTab(); + + widgets[WIDX_CLOSE].type = gLegacyScene == LegacyScene::scenarioEditor ? WindowWidgetType::Empty + : WindowWidgetType::CloseBox; + + AnchorBorderWidgets(); + } + + /** + * + * rct2: 0x00672340 + */ + void RidesOnDraw(DrawPixelInfo& dpi) + { + DrawWidgets(dpi); + DrawTabImages(dpi); + + DrawTextBasic( + dpi, windowPos + ScreenCoordsXY{ 6, widgets[WIDX_PAGE_BACKGROUND].top + 3 }, STR_WINDOW_PRESERVATION_ORDER); + } + + /** + * + * rct2: 0x0067236F + */ + void RidesOnScrollDraw(DrawPixelInfo& dpi, int32_t scrollIndex) + { + int32_t colour = ColourMapA[colours[1].colour].mid_light; + GfxFillRect(dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, colour); + + for (int32_t i = 0; i < static_cast(_rideableRides.size()); i++) + { + int32_t y = i * 12; + + if (y + 12 < dpi.y || y >= dpi.y + dpi.height) + continue; + + // Checkbox + GfxFillRectInset(dpi, { { 2, y }, { 11, y + 10 } }, colours[1], INSET_RECT_F_E0); + + // Highlighted + auto stringId = STR_BLACK_STRING; + if (i == selected_list_item) + { + stringId = STR_WINDOW_COLOUR_2_STRINGID; + GfxFilterRect(dpi, { 0, y, width, y + 11 }, FilterPaletteID::PaletteDarken1); + } + + // Checkbox mark + auto* currentRide = GetRide(_rideableRides[i]); + if (currentRide != nullptr) + { + if (currentRide->lifecycleFlags & RIDE_LIFECYCLE_INDESTRUCTIBLE) + { + auto darkness = stringId == STR_WINDOW_COLOUR_2_STRINGID ? TextDarkness::ExtraDark : TextDarkness::Dark; + DrawText( + dpi, { 2, y }, { colours[1].withFlag(ColourFlag::translucent, false), FontStyle::Medium, darkness }, + kCheckMarkString); + } + + // Ride name + + Formatter ft; + currentRide->formatNameTo(ft); + DrawTextBasic(dpi, { 15, y }, stringId, ft); + } + } + } + #pragma endregion }; @@ -1264,6 +2230,6 @@ namespace OpenRCT2::Ui::Windows { auto* windowMgr = GetWindowManager(); return windowMgr->FocusOrCreate( - WindowClass::EditorScenarioOptions, 280, 148, WF_NO_SCROLLING); + WindowClass::EditorScenarioOptions, 280, 148, WF_NO_SCROLLING | WF_CENTRE_SCREEN); } } // namespace OpenRCT2::Ui::Windows diff --git a/src/openrct2-ui/windows/Themes.cpp b/src/openrct2-ui/windows/Themes.cpp index a21143b55a..a9fadfeaf8 100644 --- a/src/openrct2-ui/windows/Themes.cpp +++ b/src/openrct2-ui/windows/Themes.cpp @@ -194,7 +194,6 @@ namespace OpenRCT2::Ui::Windows WindowClass::EditorObjectSelection, WindowClass::EditorInventionList, WindowClass::EditorScenarioOptions, - WindowClass::EditorObjectiveOptions, WindowClass::Mapgen, WindowClass::ManageTrackDesign, WindowClass::InstallTrack, diff --git a/src/openrct2-ui/windows/TopToolbar.cpp b/src/openrct2-ui/windows/TopToolbar.cpp index 5b945ba302..9c25eb66d3 100644 --- a/src/openrct2-ui/windows/TopToolbar.cpp +++ b/src/openrct2-ui/windows/TopToolbar.cpp @@ -158,11 +158,10 @@ namespace OpenRCT2::Ui::Windows DDIDX_OBJECT_SELECTION = 2, DDIDX_INVENTIONS_LIST = 3, DDIDX_SCENARIO_OPTIONS = 4, - DDIDX_OBJECTIVE_OPTIONS = 5, - // 6 is a separator - DDIDX_ENABLE_SANDBOX_MODE = 7, - DDIDX_DISABLE_CLEARANCE_CHECKS = 8, - DDIDX_DISABLE_SUPPORT_LIMITS = 9, + // 5 is a separator + DDIDX_ENABLE_SANDBOX_MODE = 6, + DDIDX_DISABLE_CLEARANCE_CHECKS = 7, + DDIDX_DISABLE_SUPPORT_LIMITS = 8, TOP_TOOLBAR_CHEATS_COUNT, }; @@ -1388,7 +1387,6 @@ namespace OpenRCT2::Ui::Windows ToggleOption(DDIDX_OBJECT_SELECTION, STR_DEBUG_DROPDOWN_OBJECT_SELECTION), ToggleOption(DDIDX_INVENTIONS_LIST, STR_DEBUG_DROPDOWN_INVENTIONS_LIST), ToggleOption(DDIDX_SCENARIO_OPTIONS, STR_DEBUG_DROPDOWN_SCENARIO_OPTIONS), - ToggleOption(DDIDX_OBJECTIVE_OPTIONS, STR_CHEATS_MENU_OBJECTIVE_OPTIONS), Separator(), ToggleOption(DDIDX_ENABLE_SANDBOX_MODE, STR_ENABLE_SANDBOX_MODE), ToggleOption(DDIDX_DISABLE_CLEARANCE_CHECKS, STR_DISABLE_CLEARANCE_CHECKS), @@ -1407,7 +1405,6 @@ namespace OpenRCT2::Ui::Windows { Dropdown::SetDisabled(DDIDX_OBJECT_SELECTION, true); Dropdown::SetDisabled(DDIDX_INVENTIONS_LIST, true); - Dropdown::SetDisabled(DDIDX_OBJECTIVE_OPTIONS, true); } if (isInEditorMode()) @@ -1415,7 +1412,6 @@ namespace OpenRCT2::Ui::Windows Dropdown::SetDisabled(DDIDX_OBJECT_SELECTION, true); Dropdown::SetDisabled(DDIDX_INVENTIONS_LIST, true); Dropdown::SetDisabled(DDIDX_SCENARIO_OPTIONS, true); - Dropdown::SetDisabled(DDIDX_OBJECTIVE_OPTIONS, true); Dropdown::SetDisabled(DDIDX_ENABLE_SANDBOX_MODE, true); } @@ -1459,9 +1455,6 @@ namespace OpenRCT2::Ui::Windows case DDIDX_SCENARIO_OPTIONS: ContextOpenWindow(WindowClass::EditorScenarioOptions); break; - case DDIDX_OBJECTIVE_OPTIONS: - ContextOpenWindow(WindowClass::EditorObjectiveOptions); - break; case DDIDX_ENABLE_SANDBOX_MODE: CheatsSet(CheatType::SandboxMode, !getGameState().cheats.sandboxMode); break; diff --git a/src/openrct2-ui/windows/Windows.h b/src/openrct2-ui/windows/Windows.h index b757e11522..e5183c398d 100644 --- a/src/openrct2-ui/windows/Windows.h +++ b/src/openrct2-ui/windows/Windows.h @@ -75,9 +75,6 @@ namespace OpenRCT2::Ui::Windows // EditorBottomToolbar WindowBase* EditorBottomToolbarOpen(); - // EditorObjectiveOptions - WindowBase* EditorObjectiveOptionsOpen(); - // EditorObjectSelection WindowBase* EditorObjectSelectionOpen(); bool EditorObjectSelectionWindowCheck(); diff --git a/src/openrct2/Editor.cpp b/src/openrct2/Editor.cpp index 3be27302a8..12855c2d2f 100644 --- a/src/openrct2/Editor.cpp +++ b/src/openrct2/Editor.cpp @@ -371,6 +371,7 @@ namespace OpenRCT2::Editor ContextOpenWindow(WindowClass::EditorInventionList); break; case EditorStep::OptionsSelection: + case EditorStep::ObjectiveSelection: if (windowMgr->FindByClass(WindowClass::EditorScenarioOptions) != nullptr) { return; @@ -378,14 +379,6 @@ namespace OpenRCT2::Editor ContextOpenWindow(WindowClass::EditorScenarioOptions); break; - case EditorStep::ObjectiveSelection: - if (windowMgr->FindByClass(WindowClass::EditorObjectiveOptions) != nullptr) - { - return; - } - - ContextOpenWindow(WindowClass::EditorObjectiveOptions); - break; case EditorStep::LandscapeEditor: case EditorStep::SaveScenario: case EditorStep::RollercoasterDesigner: diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index ae88b01a8a..fe449143bc 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1185,17 +1185,6 @@ static void ConsoleCommandOpen(InteractiveConsole& console, const arguments_t& a { ContextOpenWindow(WindowClass::EditorScenarioOptions); } - else if (argv[0] == "objective_options" && InvalidArguments(&invalidTitle, !title)) - { - if (NetworkGetMode() != NETWORK_MODE_NONE) - { - console.WriteLineError("Cannot open this window in multiplayer mode."); - } - else - { - ContextOpenWindow(WindowClass::EditorObjectiveOptions); - } - } else if (argv[0] == "options") { ContextOpenWindow(WindowClass::Options); diff --git a/src/openrct2/interface/WindowClasses.h b/src/openrct2/interface/WindowClasses.h index 2ef2f55ad0..6f06f42a8d 100644 --- a/src/openrct2/interface/WindowClasses.h +++ b/src/openrct2/interface/WindowClasses.h @@ -56,7 +56,6 @@ enum class WindowClass : uint8_t EditorInventionList = 43, EditorInventionListDrag = 44, EditorScenarioOptions = 45, - EditorObjectiveOptions = 46, ManageTrackDesign = 47, TrackDeletePrompt = 48, InstallTrack = 49,