diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 50902fe8c5..361ed96c34 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -49,6 +49,7 @@ - Fix: [#17369] [Plugin] ‘Car.travelBy()’ moves other cars as well. - Fix: [#17377] When building the park entrance before opening the Footpaths window, the path will be invisible. - Fix: [#17381] Air Powered Vertical Coaster stat penalty is wrong. +- Fix: [#17399] Guests never generate the being watched thought. - Fix: [#17433] Wrong T-shirt colours for guests on a Twist ride. - Fix: [#17450] Ducks can swim on three-corners-up land tile. - Fix: [#17461] Footpath Railing tooltip showing incorrect tooltip. diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index b5cb03e113..67024c76af 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -7,6 +7,7 @@ * OpenRCT2 is licensed under the GNU General Public License version 3. *****************************************************************************/ +#include #include #include #include @@ -45,7 +46,8 @@ enum WindowGuestPage WINDOW_GUEST_FINANCE, WINDOW_GUEST_THOUGHTS, WINDOW_GUEST_INVENTORY, - WINDOW_GUEST_DEBUG + WINDOW_GUEST_DEBUG, + WINDOW_GUEST_PAGE_COUNT, }; enum WindowGuestWidgetIdx @@ -89,7 +91,7 @@ static constexpr int32_t TabWidth = 30; MakeTab({ 189, 17 }, STR_DEBUG_TIP) /* Tab 7 */ // clang-format off -static rct_widget window_guest_overview_widgets[] = { +static rct_widget _guestWindowWidgetsOverview[] = { MAIN_GUEST_WIDGETS, MakeWidget({ 3, 45}, {164, 12}, WindowWidgetType::LabelCentred, WindowColour::Secondary ), // Label Thought marquee MakeWidget({ 3, 57}, {164, 87}, WindowWidgetType::Viewport, WindowColour::Secondary ), // Viewport @@ -102,201 +104,1807 @@ static rct_widget window_guest_overview_widgets[] = { }; // clang-format on -static rct_widget window_guest_stats_widgets[] = { +static rct_widget _guestWindowWidgetsStats[] = { MAIN_GUEST_WIDGETS, WIDGETS_END, }; -static rct_widget window_guest_rides_widgets[] = { +static rct_widget _guestWindowWidgetsRides[] = { MAIN_GUEST_WIDGETS, MakeWidget({ 3, 57 }, { 186, 87 }, WindowWidgetType::Scroll, WindowColour::Secondary, SCROLL_VERTICAL), WIDGETS_END, }; -static rct_widget window_guest_finance_widgets[] = { +static rct_widget _guestWindowWidgetsFinance[] = { MAIN_GUEST_WIDGETS, WIDGETS_END, }; -static rct_widget window_guest_thoughts_widgets[] = { +static rct_widget _guestWindowWidgetsThoughts[] = { MAIN_GUEST_WIDGETS, WIDGETS_END, }; -static rct_widget window_guest_inventory_widgets[] = { +static rct_widget _guestWindowWidgetsInventory[] = { MAIN_GUEST_WIDGETS, WIDGETS_END, }; -static rct_widget window_guest_debug_widgets[] = { +static rct_widget _guestWindowWidgetsDebug[] = { MAIN_GUEST_WIDGETS, WIDGETS_END, }; -// 0x981D0C // clang-format off -static rct_widget* window_guest_page_widgets[] = { - window_guest_overview_widgets, - window_guest_stats_widgets, - window_guest_rides_widgets, - window_guest_finance_widgets, - window_guest_thoughts_widgets, - window_guest_inventory_widgets, - window_guest_debug_widgets, +static constexpr std::array _guestWindowPageWidgets = { + _guestWindowWidgetsOverview, + _guestWindowWidgetsStats, + _guestWindowWidgetsRides, + _guestWindowWidgetsFinance, + _guestWindowWidgetsThoughts, + _guestWindowWidgetsInventory, + _guestWindowWidgetsDebug, }; +static_assert(_guestWindowPageWidgets.size() == WINDOW_GUEST_PAGE_COUNT); // clang-format on -static void WindowGuestSetPage(rct_window* w, int32_t page); -static void WindowGuestDisableWidgets(rct_window* w); -static void WindowGuestViewportInit(rct_window* w); -static void WindowGuestCommonResize(rct_window* w); -static void WindowGuestCommonInvalidate(rct_window* w); - -static void WindowGuestOverviewClose(rct_window* w); -static void WindowGuestOverviewResize(rct_window* w); -static void WindowGuestOverviewMouseUp(rct_window* w, rct_widgetindex widgetIndex); -static void WindowGuestOverviewMouseDown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget); -static void WindowGuestOverviewDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex); -static void WindowGuestOverviewPaint(rct_window* w, rct_drawpixelinfo* dpi); -static void WindowGuestOverviewInvalidate(rct_window* w); -static void WindowGuestOverviewViewportRotate(rct_window* w); -static void WindowGuestOverviewUpdate(rct_window* w); -static void WindowGuestOverviewTextInput(rct_window* w, rct_widgetindex widgetIndex, char* text); -static void WindowGuestOverviewToolUpdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void WindowGuestOverviewToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void WindowGuestOverviewToolAbort(rct_window* w, rct_widgetindex widgetIndex); -static void WindowGuestFollow(rct_window* w); -static void WindowGuestShowLocateDropdown(rct_window* w, rct_widget* widget); - -static void WindowGuestMouseUp(rct_window* w, rct_widgetindex widgetIndex); - -static void WindowGuestStatsUpdate(rct_window* w); -static void WindowGuestStatsPaint(rct_window* w, rct_drawpixelinfo* dpi); - -static void WindowGuestRidesUpdate(rct_window* w); -static void WindowGuestRidesScrollGetSize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height); -static void WindowGuestRidesScrollMouseDown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void WindowGuestRidesScrollMouseOver(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void WindowGuestRidesInvalidate(rct_window* w); -static void WindowGuestRidesPaint(rct_window* w, rct_drawpixelinfo* dpi); -static void WindowGuestRidesScrollPaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex); - -static void WindowGuestFinanceUpdate(rct_window* w); -static void WindowGuestFinancePaint(rct_window* w, rct_drawpixelinfo* dpi); - -static void WindowGuestThoughtsUpdate(rct_window* w); -static void WindowGuestThoughtsPaint(rct_window* w, rct_drawpixelinfo* dpi); - -static void WindowGuestInventoryUpdate(rct_window* w); -static void WindowGuestInventoryPaint(rct_window* w, rct_drawpixelinfo* dpi); - -static void WindowGuestDebugUpdate(rct_window* w); -static void WindowGuestDebugPaint(rct_window* w, rct_drawpixelinfo* dpi); - -static rct_window_event_list window_guest_overview_events([](auto& events) { - events.close = &WindowGuestOverviewClose; - events.mouse_up = &WindowGuestOverviewMouseUp; - events.mouse_down = &WindowGuestOverviewMouseDown; - events.dropdown = &WindowGuestOverviewDropdown; - events.resize = &WindowGuestOverviewResize; - events.update = &WindowGuestOverviewUpdate; - events.tool_update = &WindowGuestOverviewToolUpdate; - events.tool_down = &WindowGuestOverviewToolDown; - events.tool_abort = &WindowGuestOverviewToolAbort; - events.text_input = &WindowGuestOverviewTextInput; - events.viewport_rotate = &WindowGuestOverviewViewportRotate; - events.invalidate = &WindowGuestOverviewInvalidate; - events.paint = &WindowGuestOverviewPaint; -}); - -static rct_window_event_list window_guest_stats_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestStatsUpdate; - events.invalidate = &WindowGuestCommonInvalidate; - events.paint = &WindowGuestStatsPaint; -}); - -static rct_window_event_list window_guest_rides_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestRidesUpdate; - events.get_scroll_size = &WindowGuestRidesScrollGetSize; - events.scroll_mousedown = &WindowGuestRidesScrollMouseDown; - events.scroll_mouseover = &WindowGuestRidesScrollMouseOver; - events.invalidate = &WindowGuestRidesInvalidate; - events.paint = &WindowGuestRidesPaint; - events.scroll_paint = &WindowGuestRidesScrollPaint; -}); - -static rct_window_event_list window_guest_finance_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestFinanceUpdate; - events.invalidate = &WindowGuestCommonInvalidate; - events.paint = &WindowGuestFinancePaint; -}); - -static rct_window_event_list window_guest_thoughts_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestThoughtsUpdate; - events.invalidate = &WindowGuestCommonInvalidate; - events.paint = &WindowGuestThoughtsPaint; -}); - -static rct_window_event_list window_guest_inventory_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestInventoryUpdate; - events.invalidate = &WindowGuestCommonInvalidate; - events.paint = &WindowGuestInventoryPaint; -}); - -static rct_window_event_list window_guest_debug_events([](auto& events) { - events.mouse_up = &WindowGuestMouseUp; - events.resize = &WindowGuestCommonResize; - events.update = &WindowGuestDebugUpdate; - events.invalidate = &WindowGuestCommonInvalidate; - events.paint = &WindowGuestDebugPaint; -}); - -// 0x981D24 -// clang-format off -static rct_window_event_list* window_guest_page_events[] = { - &window_guest_overview_events, - &window_guest_stats_events, - &window_guest_rides_events, - &window_guest_finance_events, - &window_guest_thoughts_events, - &window_guest_inventory_events, - &window_guest_debug_events, +static constexpr const std::array _guestWindowPageSizes = { + std::array{ ScreenSize{ 192, 159 }, ScreenSize{ 500, 450 } }, // WINDOW_GUEST_OVERVIEW + std::array{ ScreenSize{ 192, 180 }, ScreenSize{ 192, 180 } }, // WINDOW_GUEST_STATS + std::array{ ScreenSize{ 192, 180 }, ScreenSize{ 500, 400 } }, // WINDOW_GUEST_RIDES + std::array{ ScreenSize{ 210, 148 }, ScreenSize{ 210, 148 } }, // WINDOW_GUEST_FINANCE + std::array{ ScreenSize{ 192, 159 }, ScreenSize{ 500, 450 } }, // WINDOW_GUEST_THOUGHTS + std::array{ ScreenSize{ 192, 159 }, ScreenSize{ 500, 450 } }, // WINDOW_GUEST_INVENTORY + std::array{ ScreenSize{ 192, 171 }, ScreenSize{ 192, 171 } }, // WINDOW_GUEST_DEBUG }; +static_assert(_guestWindowPageSizes.size() == WINDOW_GUEST_PAGE_COUNT); -// clang-format on - -static constexpr const rct_size16 window_guest_page_sizes[][2] = { - { 192, 159, 500, 450 }, // WINDOW_GUEST_OVERVIEW - { 192, 180, 192, 180 }, // WINDOW_GUEST_STATS - { 192, 180, 500, 400 }, // WINDOW_GUEST_RIDES - { 210, 148, 210, 148 }, // WINDOW_GUEST_FINANCE - { 192, 159, 500, 450 }, // WINDOW_GUEST_THOUGHTS - { 192, 159, 500, 450 }, // WINDOW_GUEST_INVENTORY - { 192, 171, 192, 171 }, // WINDOW_GUEST_DEBUG -}; - -void WindowGuestSetColours(); - -static Guest* GetGuest(rct_window* w) +class GuestWindow final : public Window { - auto guest = GetEntity(EntityId::FromUnderlying(w->number)); - if (guest == nullptr) +private: + uint16_t _marqueePosition = 0; + uint16_t _beingWatchedTimer = 0; + uint16_t _guestAnimationFrame = 0; + int16_t _pickedPeepX = LOCATION_NULL; // entity->x gets set to 0x8000 on pickup, this is the old value + +public: + void OnOpen() override { - window_close(w); - return nullptr; + widgets = _guestWindowWidgetsOverview; + page = WINDOW_GUEST_OVERVIEW; + frame_no = 0; + _marqueePosition = 0; + picked_peep_frame = 0; + min_width = width; + min_height = 157; + max_width = 500; + max_height = 450; + no_list_items = 0; + selected_list_item = -1; } - return guest; -} + + void Init(EntityId id) + { + number = id.ToUnderlying(); + page = -1; // Set Page to something invalid so that SetPage doesn't set audio on viewport + SetPage(WINDOW_GUEST_OVERVIEW); + } + + void OnClose() override + { + if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) + { + if (classification == gCurrentToolWidget.window_classification && number == gCurrentToolWidget.window_number) + tool_cancel(); + } + } + + void OnMouseUp(rct_widgetindex widx) override + { + switch (widx) + { + case WIDX_CLOSE: + Close(); + break; + case WIDX_TAB_1: + case WIDX_TAB_2: + case WIDX_TAB_3: + case WIDX_TAB_4: + case WIDX_TAB_5: + case WIDX_TAB_6: + case WIDX_TAB_7: + SetPage(widx - WIDX_TAB_1); + break; + } + + switch (page) + { + case WINDOW_GUEST_OVERVIEW: + OnMouseUpOverview(widx); + break; + } + } + void OnMouseDown(rct_widgetindex widx) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnMouseDownOverview(widx); + } + } + void OnDropdown(rct_widgetindex widgetIndex, int32_t selectedIndex) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnDropdownOverview(widgetIndex, selectedIndex); + } + } + void OnResize() override + { + switch (page) + { + case WINDOW_GUEST_OVERVIEW: + OnResizeOverview(); + break; + case WINDOW_GUEST_STATS: + case WINDOW_GUEST_RIDES: + case WINDOW_GUEST_FINANCE: + case WINDOW_GUEST_THOUGHTS: + case WINDOW_GUEST_INVENTORY: + case WINDOW_GUEST_DEBUG: + OnResizeCommon(); + break; + } + } + void OnUpdate() override + { + switch (page) + { + case WINDOW_GUEST_OVERVIEW: + OnUpdateOverview(); + break; + case WINDOW_GUEST_STATS: + OnUpdateStats(); + break; + case WINDOW_GUEST_RIDES: + OnUpdateRides(); + break; + case WINDOW_GUEST_FINANCE: + OnUpdateFinance(); + break; + case WINDOW_GUEST_THOUGHTS: + OnUpdateThoughts(); + break; + case WINDOW_GUEST_INVENTORY: + OnUpdateInventory(); + break; + case WINDOW_GUEST_DEBUG: + OnUpdateDebug(); + break; + } + } + void OnToolUpdate(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnToolUpdateOverview(widgetIndex, screenCoords); + } + } + void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnToolDownOverview(widgetIndex, screenCoords); + } + } + void OnToolAbort(rct_widgetindex widgetIndex) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnToolAbortOverview(widgetIndex); + } + } + void OnTextInput(rct_widgetindex widgetIndex, std::string_view text) override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnTextInputOverview(widgetIndex, text); + } + } + void OnViewportRotate() override + { + if (page == WINDOW_GUEST_OVERVIEW) + { + OnViewportRotateOverview(); + } + } + void OnDraw(rct_drawpixelinfo& dpi) override + { + switch (page) + { + case WINDOW_GUEST_OVERVIEW: + OnDrawOverview(dpi); + break; + case WINDOW_GUEST_STATS: + OnDrawStats(dpi); + break; + case WINDOW_GUEST_RIDES: + OnDrawRides(dpi); + break; + case WINDOW_GUEST_FINANCE: + OnDrawFinance(dpi); + break; + case WINDOW_GUEST_THOUGHTS: + OnDrawThoughts(dpi); + break; + case WINDOW_GUEST_INVENTORY: + OnDrawInventory(dpi); + break; + case WINDOW_GUEST_DEBUG: + OnDrawDebug(dpi); + break; + } + } + void OnPrepareDraw() override + { + OnPrepareDrawCommon(); + switch (page) + { + case WINDOW_GUEST_OVERVIEW: + OnPrepareDrawOverview(); + break; + case WINDOW_GUEST_RIDES: + OnPrepareDrawRides(); + break; + } + } + ScreenSize OnScrollGetSize(int32_t scrollIndex) override + { + if (page == WINDOW_GUEST_RIDES) + { + return OnScrollGetSizeRides(scrollIndex); + } + return {}; + } + + void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_GUEST_RIDES) + { + OnScrollMouseOverRides(scrollIndex, screenCoords); + } + } + void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + if (page == WINDOW_GUEST_RIDES) + { + OnScrollMouseDownRides(scrollIndex, screenCoords); + } + } + void OnScrollDraw(int32_t scrollIndex, rct_drawpixelinfo& dpi) override + { + if (page == WINDOW_GUEST_RIDES) + { + OnScrollDrawRides(scrollIndex, dpi); + } + } + +private: + Guest* GetGuest() + { + auto guest = GetEntity(EntityId::FromUnderlying(number)); + if (guest == nullptr) + { + Close(); + return nullptr; + } + return guest; + } + + void OnResizeCommon() + { + // Get page specific min and max size + int32_t minWidth = _guestWindowPageSizes[page][0].width; + int32_t minHeight = _guestWindowPageSizes[page][0].height; + int32_t maxWidth = _guestWindowPageSizes[page][1].width; + int32_t maxHeight = _guestWindowPageSizes[page][1].height; + + // Ensure min size is large enough for all tabs to fit + for (int32_t i = WIDX_TAB_1; i <= WIDX_TAB_7; i++) + { + if (!WidgetIsDisabled(this, i)) + { + minWidth = std::max(minWidth, widgets[i].right + 3); + } + } + maxWidth = std::max(minWidth, maxWidth); + + window_set_resize(this, minWidth, minHeight, maxWidth, maxHeight); + } + + void OnPrepareDrawCommon() + { + if (_guestWindowPageWidgets[page] != widgets) + { + widgets = _guestWindowPageWidgets[page]; + InitScrollWidgets(); + } + + pressed_widgets |= 1ULL << (page + WIDX_TAB_1); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + auto ft = Formatter::Common(); + peep->FormatNameTo(ft); + + widgets[WIDX_BACKGROUND].right = width - 1; + widgets[WIDX_BACKGROUND].bottom = height - 1; + widgets[WIDX_PAGE_BACKGROUND].right = width - 1; + widgets[WIDX_PAGE_BACKGROUND].bottom = height - 1; + widgets[WIDX_TITLE].right = width - 2; + widgets[WIDX_CLOSE].left = width - 13; + widgets[WIDX_CLOSE].right = width - 3; + + window_align_tabs(this, WIDX_TAB_1, WIDX_TAB_7); + } + + void DisableWidgets() + { + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + uint64_t newDisabledWidgets = 0; + + if (peep->CanBePickedUp()) + { + if (WidgetIsDisabled(this, WIDX_PICKUP)) + Invalidate(); + } + else + { + newDisabledWidgets = (1ULL << WIDX_PICKUP); + if (!WidgetIsDisabled(this, WIDX_PICKUP)) + Invalidate(); + } + if (gParkFlags & PARK_FLAGS_NO_MONEY) + { + newDisabledWidgets |= (1ULL << WIDX_TAB_4); // Disable finance tab if no money + } + if (!gConfigGeneral.debugging_tools) + { + newDisabledWidgets |= (1ULL << WIDX_TAB_7); // Disable debug tab when debug tools not turned on + } + disabled_widgets = newDisabledWidgets; + } + + void SetPage(int32_t newPage) + { + if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) + { + if (number == gCurrentToolWidget.window_number && classification == gCurrentToolWidget.window_classification) + tool_cancel(); + } + int32_t listen = 0; + if (newPage == WINDOW_GUEST_OVERVIEW && page == WINDOW_GUEST_OVERVIEW && viewport != nullptr) + { + if (!(viewport->flags & VIEWPORT_FLAG_SOUND_ON)) + listen = 1; + } + + page = newPage; + frame_no = 0; + no_list_items = 0; + selected_list_item = -1; + + RemoveViewport(); + + hold_down_widgets = 0; + pressed_widgets = 0; + widgets = _guestWindowPageWidgets[page]; + DisableWidgets(); + Invalidate(); + OnResize(); + OnPrepareDraw(); + InitScrollWidgets(); + Invalidate(); + + if (listen && viewport != nullptr) + viewport->flags |= VIEWPORT_FLAG_SOUND_ON; + } + +#pragma region Overview + + void OverviewTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_1)) + return; + + const auto& widget = widgets[WIDX_TAB_1]; + int32_t widgWidth = widget.width() - 1; + int32_t widgHeight = widget.height() - 1; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left + 1, widget.top + 1 }; + if (page == WINDOW_GUEST_OVERVIEW) + widgHeight++; + + rct_drawpixelinfo clipDpi; + if (!clip_drawpixelinfo(&clipDpi, &dpi, screenCoords, widgWidth, widgHeight)) + { + return; + } + + screenCoords = ScreenCoordsXY{ 14, 20 }; + + const auto* peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + int32_t animationFrame = GetPeepAnimation(peep->SpriteType).base_image + 1; + + int32_t animationFrameOffset = 0; + + if (page == WINDOW_GUEST_OVERVIEW) + { + animationFrameOffset = _guestAnimationFrame; + animationFrameOffset &= 0xFFFC; + } + animationFrame += animationFrameOffset; + + auto spriteId = ImageId(animationFrame, peep->TshirtColour, peep->TrousersColour); + gfx_draw_sprite(&clipDpi, spriteId, screenCoords); + + auto* guest = peep->As(); + if (guest != nullptr) + { + // If holding a balloon + if (animationFrame >= 0x2A1D && animationFrame < 0x2A3D) + { + gfx_draw_sprite(&clipDpi, ImageId(animationFrame + 32, guest->BalloonColour), screenCoords); + } + + // If holding umbrella + if (animationFrame >= 0x2BBD && animationFrame < 0x2BDD) + { + gfx_draw_sprite(&clipDpi, ImageId(animationFrame + 32, guest->UmbrellaColour), screenCoords); + } + + // If wearing hat + if (animationFrame >= 0x29DD && animationFrame < 0x29FD) + { + gfx_draw_sprite(&clipDpi, ImageId(animationFrame + 32, guest->HatColour), screenCoords); + } + } + } + + void OnResizeOverview() + { + DisableWidgets(); + OnPrepareDraw(); + + widget_invalidate(this, WIDX_MARQUEE); + + OnResizeCommon(); + + if (viewport != nullptr) + { + auto reqViewportWidth = width - 30; + auto reqViewportHeight = height - 72; + if (viewport->width != reqViewportWidth || viewport->height != reqViewportHeight) + { + viewport->width = reqViewportWidth; + viewport->height = reqViewportHeight; + viewport->view_width = viewport->zoom.ApplyInversedTo(viewport->width); + viewport->view_height = viewport->zoom.ApplyInversedTo(viewport->height); + } + } + OnViewportRotate(); + } + + void OnMouseUpOverview(rct_widgetindex widgetIndex) + { + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + switch (widgetIndex) + { + case WIDX_PICKUP: + { + if (!peep->CanBePickedUp()) + { + return; + } + _pickedPeepX = peep->x; + CoordsXYZ nullLoc{}; + nullLoc.SetNull(); + PeepPickupAction pickupAction{ PeepPickupType::Pickup, EntityId::FromUnderlying(number), nullLoc, + network_get_current_player_id() }; + pickupAction.SetCallback([peepnum = number](const GameAction* ga, const GameActions::Result* result) { + if (result->Error != GameActions::Status::Ok) + return; + rct_window* wind = window_find_by_number(WC_PEEP, peepnum); + if (wind != nullptr) + { + tool_set(wind, WC_PEEP__WIDX_PICKUP, Tool::Picker); + } + }); + GameActions::Execute(&pickupAction); + } + break; + case WIDX_RENAME: + { + auto peepName = peep->GetName(); + WindowTextInputRawOpen( + this, widgetIndex, STR_GUEST_RENAME_TITLE, STR_GUEST_RENAME_PROMPT, {}, peepName.c_str(), 32); + break; + } + case WIDX_TRACK: + { + uint32_t guestFlags = peep->PeepFlags ^ PEEP_FLAGS_TRACKING; + + auto guestSetFlagsAction = GuestSetFlagsAction(EntityId::FromUnderlying(number), guestFlags); + GameActions::Execute(&guestSetFlagsAction); + } + break; + } + } + + void OnMouseDownOverview(rct_widgetindex widgetIndex) + { + switch (widgetIndex) + { + case WIDX_LOCATE: + ShowLocateDropdown(widgets[widgetIndex]); + break; + } + } + + void OnDropdownOverview(rct_widgetindex widgetIndex, int32_t dropdownIndex) + { + switch (widgetIndex) + { + case WIDX_LOCATE: + { + if (dropdownIndex == 0) + { + ScrollToViewport(); + } + else if (dropdownIndex == 1) + { + GuestFollow(); + } + break; + } + } + } + + void ShowLocateDropdown(rct_widget& widget) + { + gDropdownItems[0].Format = STR_LOCATE_SUBJECT_TIP; + gDropdownItems[1].Format = STR_FOLLOW_SUBJECT_TIP; + + WindowDropdownShowText({ windowPos.x + widget.left, windowPos.y + widget.top }, widget.height() + 1, colours[1], 0, 2); + gDropdownDefaultIndex = 0; + } + + void GuestFollow() + { + rct_window* main = window_get_main(); + window_follow_sprite(main, EntityId::FromUnderlying(number)); + } + + void OnViewportRotateOverview() + { + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + viewport_update_smart_guest_follow(this, peep); + bool reCreateViewport = false; + uint16_t origViewportFlags{}; + if (viewport != nullptr) + { + if (focus.has_value()) + return; + + origViewportFlags = viewport->flags; + + reCreateViewport = true; + RemoveViewport(); + } + + OnPrepareDraw(); + + if (peep->State != PeepState::Picked && viewport == nullptr) + { + const auto& viewWidget = widgets[WIDX_VIEWPORT]; + auto screenPos = ScreenCoordsXY{ viewWidget.left + 1 + windowPos.x, viewWidget.top + 1 + windowPos.y }; + int32_t widgWidth = viewWidget.width() - 1; + int32_t widgHeight = viewWidget.height() - 1; + + viewport_create(this, screenPos, widgWidth, widgHeight, focus.value()); + if (viewport != nullptr && reCreateViewport) + { + viewport->flags = origViewportFlags; + } + flags |= WF_NO_SCROLLING; + Invalidate(); + } + Invalidate(); + } + + void OnDrawOverview(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + // Draw the viewport no sound sprite + if (viewport != nullptr) + { + window_draw_viewport(&dpi, this); + if (viewport->flags & VIEWPORT_FLAG_SOUND_ON) + { + gfx_draw_sprite(&dpi, ImageId(SPR_HEARING_VIEWPORT), windowPos + ScreenCoordsXY{ 2, 2 }); + } + } + + // Draw the centred label + const auto* peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + const auto& actionLabelWidget = widgets[WIDX_ACTION_LBL]; + auto screenPos = windowPos + ScreenCoordsXY{ actionLabelWidget.midX(), actionLabelWidget.top - 1 }; + + { + auto ft = Formatter(); + peep->FormatActionTo(ft); + int32_t textWidth = actionLabelWidget.width(); + DrawTextEllipsised(&dpi, screenPos, textWidth, STR_BLACK_STRING, ft, { TextAlignment::CENTRE }); + } + + // Draw the marquee thought + const auto& marqueeWidget = widgets[WIDX_MARQUEE]; + auto marqWidth = marqueeWidget.width() - 3; + int32_t left = marqueeWidget.left + 2 + windowPos.x; + int32_t top = marqueeWidget.top + windowPos.y; + int32_t marqHeight = marqueeWidget.height(); + rct_drawpixelinfo dpiMarquee; + if (!clip_drawpixelinfo(&dpiMarquee, &dpi, { left, top }, marqWidth, marqHeight)) + { + return; + } + + int32_t i = 0; + for (; i < PEEP_MAX_THOUGHTS; ++i) + { + if (peep->Thoughts[i].type == PeepThoughtType::None) + { + _marqueePosition = 0; + return; + } + if (peep->Thoughts[i].freshness == 1) + { // If a fresh thought + break; + } + } + if (i == PEEP_MAX_THOUGHTS) + { + _marqueePosition = 0; + return; + } + + screenPos.x = marqueeWidget.width() - _marqueePosition; + { + auto ft = Formatter(); + peep_thought_set_format_args(&peep->Thoughts[i], ft); + DrawTextBasic(&dpiMarquee, { screenPos.x, 0 }, STR_WINDOW_COLOUR_2_STRINGID, ft, { FontSpriteBase::SMALL }); + } + } + + void OnPrepareDrawOverview() + { + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + pressed_widgets &= ~(1ULL << WIDX_TRACK); + if (peep->PeepFlags & PEEP_FLAGS_TRACKING) + { + pressed_widgets |= (1ULL << WIDX_TRACK); + } + + widgets[WIDX_VIEWPORT].right = width - 26; + widgets[WIDX_VIEWPORT].bottom = height - 14; + + widgets[WIDX_ACTION_LBL].top = height - 12; + widgets[WIDX_ACTION_LBL].bottom = height - 3; + widgets[WIDX_ACTION_LBL].right = width - 24; + + widgets[WIDX_MARQUEE].right = width - 24; + + widgets[WIDX_PICKUP].right = width - 2; + widgets[WIDX_RENAME].right = width - 2; + widgets[WIDX_LOCATE].right = width - 2; + widgets[WIDX_TRACK].right = width - 2; + + widgets[WIDX_PICKUP].left = width - 25; + widgets[WIDX_RENAME].left = width - 25; + widgets[WIDX_LOCATE].left = width - 25; + widgets[WIDX_TRACK].left = width - 25; + } + + void OnUpdateOverview() + { + int32_t newAnimationFrame = _guestAnimationFrame; + newAnimationFrame++; + newAnimationFrame %= 24; + _guestAnimationFrame = newAnimationFrame; + + widget_invalidate(this, WIDX_TAB_1); + widget_invalidate(this, WIDX_TAB_2); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_ACTION) + { + peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_ACTION; + widget_invalidate(this, WIDX_ACTION_LBL); + } + + _marqueePosition += 2; + + _beingWatchedTimer++; + + // Disable peep watching thought for multiplayer as it's client specific + if (network_get_mode() == NETWORK_MODE_NONE) + { + // Create the "I have the strangest feeling I am being watched thought" + if (_beingWatchedTimer >= 3840) + { + if (!(_beingWatchedTimer & 0x3FF)) + { + int32_t random = util_rand() & 0xFFFF; + if (random <= 0x2AAA) + { + peep->InsertNewThought(PeepThoughtType::Watched); + } + } + } + } + } + + void OnTextInputOverview(rct_widgetindex widgetIndex, std::string_view text) + { + if (widgetIndex != WIDX_RENAME) + return; + + if (text.empty()) + return; + std::string sText(text); + guest_set_name(EntityId::FromUnderlying(number), sText.c_str()); + } + + void OnToolUpdateOverview(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) + { + if (widgetIndex != WIDX_PICKUP) + return; + + map_invalidate_selection_rect(); + + gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE; + + auto mapCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, nullptr); + if (!mapCoords.IsNull()) + { + gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; + gMapSelectType = MAP_SELECT_TYPE_FULL; + gMapSelectPositionA = mapCoords; + gMapSelectPositionB = mapCoords; + map_invalidate_selection_rect(); + } + + gPickupPeepImage = ImageId(); + + auto info = get_map_coordinates_from_pos(screenCoords, ViewportInteractionItemAll); + if (info.SpriteType == ViewportInteractionItem::None) + return; + + gPickupPeepX = screenCoords.x - 1; + gPickupPeepY = screenCoords.y + 16; + picked_peep_frame++; + if (picked_peep_frame >= 48) + { + picked_peep_frame = 0; + } + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + auto baseImageId = GetPeepAnimation(peep->SpriteType, PeepActionSpriteType::Ui).base_image; + baseImageId += picked_peep_frame >> 2; + gPickupPeepImage = ImageId(baseImageId, peep->TshirtColour, peep->TrousersColour); + } + + void OnToolDownOverview(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) + { + if (widgetIndex != WIDX_PICKUP) + return; + + TileElement* tileElement; + auto destCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, &tileElement); + + if (destCoords.IsNull()) + return; + + PeepPickupAction pickupAction{ PeepPickupType::Place, + EntityId::FromUnderlying(number), + { destCoords, tileElement->GetBaseZ() }, + network_get_current_player_id() }; + pickupAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) { + if (result->Error != GameActions::Status::Ok) + return; + tool_cancel(); + gPickupPeepImage = ImageId(); + }); + GameActions::Execute(&pickupAction); + } + + void OnToolAbortOverview(rct_widgetindex widgetIndex) + { + if (widgetIndex != WIDX_PICKUP) + return; + + PeepPickupAction pickupAction{ + PeepPickupType::Cancel, EntityId::FromUnderlying(number), { _pickedPeepX, 0, 0 }, network_get_current_player_id() + }; + GameActions::Execute(&pickupAction); + } + +#pragma endregion + +#pragma region Stats + void StatsTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_2)) + return; + + const auto& widget = widgets[WIDX_TAB_2]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + int32_t imageId = get_peep_face_sprite_large(peep); + if (page == WINDOW_GUEST_STATS) + { + // If currently viewing this tab animate tab + // if it is very sick or angry. + switch (imageId) + { + case SPR_PEEP_LARGE_FACE_VERY_VERY_SICK_0: + imageId += (frame_no / 4) & 0xF; + break; + case SPR_PEEP_LARGE_FACE_VERY_SICK_0: + imageId += (frame_no / 8) & 0x3; + break; + case SPR_PEEP_LARGE_FACE_ANGRY_0: + imageId += (frame_no / 8) & 0x3; + break; + } + } + gfx_draw_sprite(&dpi, ImageId(imageId), screenCoords); + } + + void OnUpdateStats() + { + frame_no++; + auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_STATS; + + Invalidate(); + } + + void StatsBarsDraw(int32_t value, const ScreenCoordsXY& origCoords, rct_drawpixelinfo& dpi, int32_t colour, bool blinkFlag) + { + auto coords = origCoords; + if (font_get_line_height(FontSpriteBase::MEDIUM) > 10) + { + coords.y += 1; + } + + gfx_fill_rect_inset( + &dpi, { coords + ScreenCoordsXY{ 61, 1 }, coords + ScreenCoordsXY{ 61 + 121, 9 } }, colours[1], INSET_RECT_F_30); + + if (!blinkFlag || game_is_paused() || (gCurrentRealTimeTicks & 8) == 0) + { + value *= 118; + value >>= 8; + + if (value <= 2) + return; + + gfx_fill_rect_inset( + &dpi, { coords + ScreenCoordsXY{ 63, 2 }, coords + ScreenCoordsXY{ 63 + value - 1, 8 } }, colour, 0); + } + } + + /** + * Takes a guest stat value (scaled to currMax) and adjusts it to be scaled out of 255. + * Then clamp the value to between newMin and 255. + */ + int32_t NormalizeGuestStatValue(int32_t value, int32_t currMax, int32_t newMin) const + { + int32_t newValue = (value * 255) / currMax; + return std::clamp(newValue, newMin, 255); + } + + void OnDrawStats(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + // ebx + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + // Not sure why this is not stats widgets + // cx dx + auto screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 4, widgets[WIDX_PAGE_BACKGROUND].top + 4 }; + + // Happiness + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_HAPPINESS_LABEL); + + int32_t happiness = NormalizeGuestStatValue(peep->Happiness, PEEP_MAX_HAPPINESS, 10); + int32_t barColour = COLOUR_BRIGHT_GREEN; + bool barBlink = happiness < 50; + StatsBarsDraw(happiness, screenCoords, dpi, barColour, barBlink); + + // Energy + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_ENERGY_LABEL); + + int32_t energy = NormalizeGuestStatValue(peep->Energy - PEEP_MIN_ENERGY, PEEP_MAX_ENERGY - PEEP_MIN_ENERGY, 10); + barColour = COLOUR_BRIGHT_GREEN; + barBlink = energy < 50; + StatsBarsDraw(energy, screenCoords, dpi, barColour, barBlink); + + // Hunger + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_HUNGER_LABEL); + + int32_t hunger = NormalizeGuestStatValue(peep->Hunger - 32, 158, 0); + hunger = 255 - hunger; // the bar should be longer when peep->Hunger is low + barColour = COLOUR_BRIGHT_RED; + barBlink = hunger > 170; + StatsBarsDraw(hunger, screenCoords, dpi, barColour, barBlink); + + // Thirst + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_THIRST_LABEL); + + int32_t thirst = NormalizeGuestStatValue(peep->Thirst - 32, 158, 0); + thirst = 255 - thirst; // the bar should be longer when peep->Thirst is low + barColour = COLOUR_BRIGHT_RED; + barBlink = thirst > 170; + StatsBarsDraw(thirst, screenCoords, dpi, barColour, barBlink); + + // Nausea + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_NAUSEA_LABEL); + + int32_t nausea = NormalizeGuestStatValue(peep->Nausea - 32, 223, 0); + barColour = COLOUR_BRIGHT_RED; + barBlink = nausea > 120; + StatsBarsDraw(nausea, screenCoords, dpi, barColour, barBlink); + + // Toilet + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_TOILET_LABEL); + + int32_t toilet = NormalizeGuestStatValue(peep->Toilet - 64, 178, 0); + barColour = COLOUR_BRIGHT_RED; + barBlink = toilet > 160; + StatsBarsDraw(toilet, screenCoords, dpi, barColour, barBlink); + + // Time in park + screenCoords.y += LIST_ROW_HEIGHT + 1; + int32_t guestEntryTime = peep->GetParkEntryTime(); + if (guestEntryTime != -1) + { + int32_t timeInPark = (gCurrentTicks - guestEntryTime) >> 11; + auto ft = Formatter(); + ft.Add(timeInPark & 0xFFFF); + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_TIME_IN_PARK, ft); + } + + screenCoords.y += LIST_ROW_HEIGHT + 9; + gfx_fill_rect_inset( + &dpi, { screenCoords - ScreenCoordsXY{ 0, 6 }, screenCoords + ScreenCoordsXY{ 179, -5 } }, colours[1], + INSET_RECT_FLAG_BORDER_INSET); + + // Preferred Ride + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_PREFERRED_RIDE); + screenCoords.y += LIST_ROW_HEIGHT; + + // Intensity + { + auto ft = Formatter(); + auto maxIntensity = peep->Intensity.GetMaximum(); + int32_t string_id = STR_GUEST_STAT_PREFERRED_INTESITY_BELOW; + if (peep->Intensity.GetMinimum() != 0) + { + ft.Add(peep->Intensity.GetMinimum()); + ft.Add(maxIntensity); + string_id = STR_GUEST_STAT_PREFERRED_INTESITY_BETWEEN; + if (maxIntensity == 15) + string_id = STR_GUEST_STAT_PREFERRED_INTESITY_ABOVE; + } + else + { + ft.Add(maxIntensity); + } + + DrawTextBasic(&dpi, screenCoords + ScreenCoordsXY{ 4, 0 }, string_id, ft); + } + + // Nausea tolerance + { + static constexpr const rct_string_id _nauseaTolerances[] = { + STR_PEEP_STAT_NAUSEA_TOLERANCE_NONE, + STR_PEEP_STAT_NAUSEA_TOLERANCE_LOW, + STR_PEEP_STAT_NAUSEA_TOLERANCE_AVERAGE, + STR_PEEP_STAT_NAUSEA_TOLERANCE_HIGH, + }; + screenCoords.y += LIST_ROW_HEIGHT; + auto nausea_tolerance = EnumValue(peep->NauseaTolerance) & 0x3; + auto ft = Formatter(); + ft.Add(_nauseaTolerances[nausea_tolerance]); + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_NAUSEA_TOLERANCE, ft); + } + } + +#pragma endregion + +#pragma region Rides + void RidesTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_3)) + return; + + const auto& widget = widgets[WIDX_TAB_3]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + int32_t imageId = SPR_TAB_RIDE_0; + + if (page == WINDOW_GUEST_RIDES) + { + imageId += (frame_no / 4) & 0xF; + } + + gfx_draw_sprite(&dpi, ImageId(imageId), screenCoords); + } + + void OnUpdateRides() + { + frame_no++; + + widget_invalidate(this, WIDX_TAB_2); + widget_invalidate(this, WIDX_TAB_3); + + const auto guest = GetGuest(); + if (guest == nullptr) + { + return; + } + + // Every 2048 ticks do a full window_invalidate + int32_t numTicks = gCurrentTicks - guest->GetParkEntryTime(); + if (!(numTicks & 0x7FF)) + Invalidate(); + + uint8_t currListPosition = 0; + for (const auto& r : GetRideManager()) + { + if (r.IsRide() && guest->HasRidden(&r)) + { + list_item_positions[currListPosition] = r.id.ToUnderlying(); + currListPosition++; + } + } + + // If there are new items + if (no_list_items != currListPosition) + { + no_list_items = currListPosition; + Invalidate(); + } + } + + ScreenSize OnScrollGetSizeRides(int32_t scrollIndex) + { + ScreenSize newSize; + newSize.height = no_list_items * 10; + + if (selected_list_item != -1) + { + selected_list_item = -1; + Invalidate(); + } + + int32_t visableHeight = newSize.height - widgets[WIDX_RIDE_SCROLL].bottom + widgets[WIDX_RIDE_SCROLL].top + 21; + + if (visableHeight < 0) + visableHeight = 0; + + if (visableHeight < scrolls[0].v_top) + { + scrolls[0].v_top = visableHeight; + Invalidate(); + } + return newSize; + } + + void OnScrollMouseDownRides(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) + { + auto index = screenCoords.y / 10; + if (index >= no_list_items) + return; + + auto intent = Intent(WC_RIDE); + intent.putExtra(INTENT_EXTRA_RIDE_ID, list_item_positions[index]); + context_open_intent(&intent); + } + + void OnScrollMouseOverRides(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) + { + auto index = screenCoords.y / 10; + if (index >= no_list_items) + return; + + if (index == selected_list_item) + return; + selected_list_item = index; + + Invalidate(); + } + + void OnPrepareDrawRides() + { + widgets[WIDX_RIDE_SCROLL].right = width - 4; + widgets[WIDX_RIDE_SCROLL].bottom = height - 15; + } + + void OnDrawRides(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + // cx dx + auto screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 2, widgets[WIDX_PAGE_BACKGROUND].top + 2 }; + + DrawTextBasic(&dpi, screenCoords, STR_GUEST_LABEL_RIDES_BEEN_ON); + + screenCoords.y = windowPos.y + widgets[WIDX_PAGE_BACKGROUND].bottom - 12; + + auto ft = Formatter(); + auto* r = get_ride(peep->FavouriteRide); + if (r != nullptr) + { + r->FormatNameTo(ft); + } + else + { + ft.Add(STR_PEEP_FAVOURITE_RIDE_NOT_AVAILABLE); + } + + DrawTextEllipsised(&dpi, screenCoords, width - 14, STR_FAVOURITE_RIDE, ft); + } + + void OnScrollDrawRides(int32_t scrollIndex, rct_drawpixelinfo& dpi) + { + auto colour = ColourMapA[colours[1]].mid_light; + gfx_fill_rect(&dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, colour); + + for (int32_t listIndex = 0; listIndex < no_list_items; listIndex++) + { + auto y = listIndex * 10; + rct_string_id stringId = STR_BLACK_STRING; + if (listIndex == selected_list_item) + { + gfx_filter_rect(&dpi, { 0, y, 800, y + 9 }, FilterPaletteID::PaletteDarken1); + stringId = STR_WINDOW_COLOUR_2_STRINGID; + } + + const auto rId = RideId::FromUnderlying(list_item_positions[listIndex]); + auto* r = get_ride(rId); + if (r != nullptr) + { + auto ft = Formatter(); + r->FormatNameTo(ft); + DrawTextBasic(&dpi, { 0, y - 1 }, stringId, ft); + } + } + } +#pragma endregion + +#pragma region Finance + void FinanceTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_4)) + return; + + const auto& widget = widgets[WIDX_TAB_4]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + int32_t imageId = SPR_TAB_FINANCES_SUMMARY_0; + + if (page == WINDOW_GUEST_FINANCE) + { + imageId += (frame_no / 2) & 0x7; + } + + gfx_draw_sprite(&dpi, ImageId(imageId), screenCoords); + } + + void OnUpdateFinance() + { + frame_no++; + + widget_invalidate(this, WIDX_TAB_2); + widget_invalidate(this, WIDX_TAB_4); + } + + void OnDrawFinance(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + // cx dx + auto screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 4, widgets[WIDX_PAGE_BACKGROUND].top + 4 }; + + // Cash in pocket + { + auto ft = Formatter(); + ft.Add(peep->CashInPocket); + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_CASH_IN_POCKET, ft); + screenCoords.y += LIST_ROW_HEIGHT; + } + + // Cash spent + { + auto ft = Formatter(); + ft.Add(peep->CashSpent); + DrawTextBasic(&dpi, screenCoords, STR_GUEST_STAT_CASH_SPENT, ft); + screenCoords.y += LIST_ROW_HEIGHT * 2; + } + + gfx_fill_rect_inset( + &dpi, { screenCoords - ScreenCoordsXY{ 0, 6 }, screenCoords + ScreenCoordsXY{ 179, -5 } }, colours[1], + INSET_RECT_FLAG_BORDER_INSET); + + // Paid to enter + { + auto ft = Formatter(); + ft.Add(peep->PaidToEnter); + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_ENTRANCE_FEE, ft); + screenCoords.y += LIST_ROW_HEIGHT; + } + // Paid on rides + { + auto ft = Formatter(); + ft.Add(peep->PaidOnRides); + ft.Add(peep->GuestNumRides); + if (peep->GuestNumRides != 1) + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_RIDE_PLURAL, ft); + } + else + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_RIDE, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + } + // Paid on food + { + auto ft = Formatter(); + ft.Add(peep->PaidOnFood); + ft.Add(peep->AmountOfFood); + if (peep->AmountOfFood != 1) + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_FOOD_PLURAL, ft); + } + else + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_FOOD, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + } + + // Paid on drinks + { + auto ft = Formatter(); + ft.Add(peep->PaidOnDrink); + ft.Add(peep->AmountOfDrinks); + if (peep->AmountOfDrinks != 1) + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_DRINK_PLURAL, ft); + } + else + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_DRINK, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + } + // Paid on souvenirs + { + auto ft = Formatter(); + ft.Add(peep->PaidOnSouvenirs); + ft.Add(peep->AmountOfSouvenirs); + if (peep->AmountOfSouvenirs != 1) + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_SOUVENIR_PLURAL, ft); + } + else + { + DrawTextBasic(&dpi, screenCoords, STR_GUEST_EXPENSES_SOUVENIR, ft); + } + } + } +#pragma endregion + +#pragma region Thoughts + void ThoughtsTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_5)) + return; + + const auto& widget = widgets[WIDX_TAB_5]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + int32_t imageId = SPR_TAB_THOUGHTS_0; + + if (page == WINDOW_GUEST_THOUGHTS) + { + imageId += (frame_no / 2) & 0x7; + } + + gfx_draw_sprite(&dpi, ImageId(imageId), screenCoords); + } + + void OnUpdateThoughts() + { + frame_no++; + + widget_invalidate(this, WIDX_TAB_2); + widget_invalidate(this, WIDX_TAB_5); + + auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_THOUGHTS) + { + peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_THOUGHTS; + Invalidate(); + } + } + + void OnDrawThoughts(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + + // cx dx + auto screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 4, widgets[WIDX_PAGE_BACKGROUND].top + 4 }; + + DrawTextBasic(&dpi, screenCoords, STR_GUEST_RECENT_THOUGHTS_LABEL); + + screenCoords.y += 10; + for (const auto& thought : peep->Thoughts) + { + if (thought.type == PeepThoughtType::None) + return; + if (thought.freshness == 0) + continue; + + int32_t widgWidth = widgets[WIDX_PAGE_BACKGROUND].right - widgets[WIDX_PAGE_BACKGROUND].left - 8; + + auto ft = Formatter(); + peep_thought_set_format_args(&thought, ft); + screenCoords.y += DrawTextWrapped(&dpi, screenCoords, widgWidth, STR_BLACK_STRING, ft, { FontSpriteBase::SMALL }); + + // If this is the last visible line end drawing. + if (screenCoords.y > windowPos.y + widgets[WIDX_PAGE_BACKGROUND].bottom - 32) + return; + } + } +#pragma endregion + +#pragma region Inventory + void InventoryTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_6)) + return; + + const auto& widget = widgets[WIDX_TAB_6]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + gfx_draw_sprite(&dpi, ImageId(SPR_TAB_GUEST_INVENTORY), screenCoords); + } + + void OnUpdateInventory() + { + frame_no++; + + widget_invalidate(this, WIDX_TAB_2); + widget_invalidate(this, WIDX_TAB_6); + + auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_INVENTORY) + { + peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_INVENTORY; + Invalidate(); + } + } + + std::pair InventoryFormatItem(Guest& guest, ShopItem item) const + { + auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark(); + auto parkName = park.Name.c_str(); + + // Default arguments + auto ft = Formatter(); + ft.Add(GetShopItemDescriptor(item).Image); + ft.Add(GetShopItemDescriptor(item).Naming.Display); + ft.Add(STR_STRING); + ft.Add(parkName); + + // Special overrides + Ride* invRide{}; + switch (item) + { + case ShopItem::Balloon: + ft.Rewind(); + ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest.BalloonColour) | GetShopItemDescriptor(item).Image); + break; + case ShopItem::Photo: + invRide = get_ride(guest.Photo1RideRef); + if (invRide != nullptr) + { + ft.Rewind(); + ft.Increment(6); + invRide->FormatNameTo(ft); + } + + break; + case ShopItem::Umbrella: + ft.Rewind(); + ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest.UmbrellaColour) | GetShopItemDescriptor(item).Image); + break; + case ShopItem::Voucher: + switch (guest.VoucherType) + { + case VOUCHER_TYPE_PARK_ENTRY_FREE: + ft.Rewind(); + ft.Increment(6); + ft.Add(STR_PEEP_INVENTORY_VOUCHER_PARK_ENTRY_FREE); + ft.Add(STR_STRING); + ft.Add(parkName); + break; + case VOUCHER_TYPE_RIDE_FREE: + invRide = get_ride(guest.VoucherRideId); + if (invRide != nullptr) + { + ft.Rewind(); + ft.Increment(6); + ft.Add(STR_PEEP_INVENTORY_VOUCHER_RIDE_FREE); + invRide->FormatNameTo(ft); + } + break; + case VOUCHER_TYPE_PARK_ENTRY_HALF_PRICE: + ft.Rewind(); + ft.Increment(6); + ft.Add(STR_PEEP_INVENTORY_VOUCHER_PARK_ENTRY_HALF_PRICE); + ft.Add(STR_STRING); + ft.Add(parkName); + break; + case VOUCHER_TYPE_FOOD_OR_DRINK_FREE: + ft.Rewind(); + ft.Increment(6); + ft.Add(STR_PEEP_INVENTORY_VOUCHER_FOOD_OR_DRINK_FREE); + ft.Add(GetShopItemDescriptor(guest.VoucherShopItem).Naming.Singular); + break; + } + break; + case ShopItem::Hat: + ft.Rewind(); + ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest.HatColour) | GetShopItemDescriptor(item).Image); + break; + case ShopItem::TShirt: + ft.Rewind(); + ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest.TshirtColour) | GetShopItemDescriptor(item).Image); + break; + case ShopItem::Photo2: + invRide = get_ride(guest.Photo2RideRef); + if (invRide != nullptr) + { + ft.Rewind(); + ft.Increment(6); + invRide->FormatNameTo(ft); + } + break; + case ShopItem::Photo3: + invRide = get_ride(guest.Photo3RideRef); + if (invRide != nullptr) + { + ft.Rewind(); + ft.Increment(6); + invRide->FormatNameTo(ft); + } + break; + case ShopItem::Photo4: + invRide = get_ride(guest.Photo4RideRef); + if (invRide != nullptr) + { + ft.Rewind(); + ft.Increment(6); + invRide->FormatNameTo(ft); + } + break; + default: + // This switch handles only items visible in peep window + break; + } + + return std::make_pair(STR_GUEST_ITEM_FORMAT, ft); + } + + void OnDrawInventory(rct_drawpixelinfo& dpi) + { + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + const auto guest = GetGuest(); + if (guest == nullptr) + { + return; + } + + rct_widget* pageBackgroundWidget = &widgets[WIDX_PAGE_BACKGROUND]; + auto screenCoords = windowPos + ScreenCoordsXY{ pageBackgroundWidget->left + 4, pageBackgroundWidget->top + 2 }; + int32_t itemNameWidth = pageBackgroundWidget->width() - 8; + + int32_t maxY = windowPos.y + height - 22; + int32_t numItems = 0; + + DrawTextBasic(&dpi, screenCoords, STR_CARRYING); + screenCoords.y += 10; + + for (ShopItem item = ShopItem::Balloon; item < ShopItem::Count; item++) + { + if (screenCoords.y >= maxY) + break; + if (!guest->HasItem(item)) + continue; + + auto [stringId, ft] = InventoryFormatItem(*guest, item); + screenCoords.y += DrawTextWrapped(&dpi, screenCoords, itemNameWidth, stringId, ft); + numItems++; + } + + if (numItems == 0) + { + DrawTextBasic(&dpi, screenCoords, STR_NOTHING); + } + } +#pragma endregion + +#pragma region Debug + void DebugTabDraw(rct_drawpixelinfo& dpi) + { + if (WidgetIsDisabled(this, WIDX_TAB_7)) + return; + + const auto& widget = widgets[WIDX_TAB_7]; + auto screenCoords = windowPos + ScreenCoordsXY{ widget.left, widget.top }; + + int32_t imageId = SPR_TAB_GEARS_0; + if (page == WINDOW_GUEST_DEBUG) + { + imageId += (frame_no / 2) & 0x3; + } + + gfx_draw_sprite(&dpi, ImageId(imageId), screenCoords); + } + + void OnUpdateDebug() + { + frame_no++; + Invalidate(); + } + + void OnDrawDebug(rct_drawpixelinfo& dpi) + { + char buffer[512]{}; + char buffer2[512]{}; + + DrawWidgets(dpi); + OverviewTabDraw(dpi); + StatsTabDraw(dpi); + RidesTabDraw(dpi); + FinanceTabDraw(dpi); + ThoughtsTabDraw(dpi); + InventoryTabDraw(dpi); + DebugTabDraw(dpi); + + const auto peep = GetGuest(); + if (peep == nullptr) + { + return; + } + auto screenCoords = windowPos + + ScreenCoordsXY{ widgets[WIDX_PAGE_BACKGROUND].left + 4, widgets[WIDX_PAGE_BACKGROUND].top + 4 }; + { + auto ft = Formatter(); + ft.Add(peep->sprite_index); + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_SPRITE_INDEX, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + { + auto ft = Formatter(); + ft.Add(peep->x); + ft.Add(peep->y); + ft.Add(peep->z); + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_POSITION, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + { + auto ft = Formatter(); + ft.Add(peep->NextLoc.x); + ft.Add(peep->NextLoc.y); + ft.Add(peep->NextLoc.z); + format_string(buffer, sizeof(buffer), STR_PEEP_DEBUG_NEXT, ft.Data()); + if (peep->GetNextIsSurface()) + { + format_string(buffer2, sizeof(buffer2), STR_PEEP_DEBUG_NEXT_SURFACE, nullptr); + safe_strcat(buffer, buffer2, sizeof(buffer)); + } + if (peep->GetNextIsSloped()) + { + auto ft2 = Formatter(); + ft2.Add(peep->GetNextDirection()); + format_string(buffer2, sizeof(buffer2), STR_PEEP_DEBUG_NEXT_SLOPE, ft2.Data()); + safe_strcat(buffer, buffer2, sizeof(buffer)); + } + gfx_draw_string(&dpi, screenCoords, buffer, {}); + } + screenCoords.y += LIST_ROW_HEIGHT; + { + auto ft = Formatter(); + ft.Add(peep->DestinationX); + ft.Add(peep->DestinationY); + ft.Add(peep->DestinationTolerance); + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_DEST, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + { + auto ft = Formatter(); + ft.Add(peep->PathfindGoal.x); + ft.Add(peep->PathfindGoal.y); + ft.Add(peep->PathfindGoal.z); + ft.Add(peep->PathfindGoal.direction); + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_GOAL, ft); + } + screenCoords.y += LIST_ROW_HEIGHT; + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_HISTORY); + screenCoords.y += LIST_ROW_HEIGHT; + + screenCoords.x += 10; + for (auto& point : peep->PathfindHistory) + { + auto ft = Formatter(); + ft.Add(point.x); + ft.Add(point.y); + ft.Add(point.z); + ft.Add(point.direction); + DrawTextBasic(&dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_HISTORY_ITEM, ft); + screenCoords.y += LIST_ROW_HEIGHT; + } + screenCoords.x -= 10; + } +#pragma endregion +}; /** * @@ -314,1751 +1922,21 @@ rct_window* WindowGuestOpen(Peep* peep) return WindowStaffOpen(peep); } - rct_window* window; - - window = window_bring_to_front_by_number(WC_PEEP, peep->sprite_index.ToUnderlying()); + auto* window = static_cast(window_bring_to_front_by_number(WC_PEEP, peep->sprite_index.ToUnderlying())); if (window == nullptr) { int32_t windowWidth = 192; if (gConfigGeneral.debugging_tools) windowWidth += TabWidth; - window = WindowCreateAutoPos(windowWidth, 157, &window_guest_overview_events, WC_PEEP, WF_RESIZABLE); - window->widgets = window_guest_overview_widgets; - window->number = peep->sprite_index.ToUnderlying(); - window->page = 0; - window->frame_no = 0; - window->list_information_type = 0; - window->picked_peep_frame = 0; - window->highlighted_item = 0; - WindowGuestDisableWidgets(window); - window->min_width = windowWidth; - window->min_height = 157; - window->max_width = 500; - window->max_height = 450; - window->no_list_items = 0; - window->selected_list_item = -1; + window = WindowCreate(WC_PEEP, windowWidth, 157, WF_RESIZABLE); + if (window == nullptr) + { + return nullptr; + } } - window->page = 0; - window->Invalidate(); - - window->widgets = window_guest_page_widgets[WINDOW_GUEST_OVERVIEW]; - window->hold_down_widgets = 0; - window->event_handlers = window_guest_page_events[WINDOW_GUEST_OVERVIEW]; - window->pressed_widgets = 0; - - WindowGuestDisableWidgets(window); - WindowInitScrollWidgets(window); - WindowGuestViewportInit(window); + window->Init(peep->sprite_index); return window; } - -static void WindowGuestCommonResize(rct_window* w) -{ - // Get page specific min and max size - int32_t minWidth = window_guest_page_sizes[w->page][0].width; - int32_t minHeight = window_guest_page_sizes[w->page][0].height; - int32_t maxWidth = window_guest_page_sizes[w->page][1].width; - int32_t maxHeight = window_guest_page_sizes[w->page][1].height; - - // Ensure min size is large enough for all tabs to fit - for (int32_t i = WIDX_TAB_1; i <= WIDX_TAB_7; i++) - { - if (!WidgetIsDisabled(w, i)) - { - minWidth = std::max(minWidth, w->widgets[i].right + 3); - } - } - maxWidth = std::max(minWidth, maxWidth); - - window_set_resize(w, minWidth, minHeight, maxWidth, maxHeight); -} - -static void WindowGuestCommonInvalidate(rct_window* w) -{ - if (window_guest_page_widgets[w->page] != w->widgets) - { - w->widgets = window_guest_page_widgets[w->page]; - WindowInitScrollWidgets(w); - } - - w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - auto ft = Formatter::Common(); - peep->FormatNameTo(ft); - - w->widgets[WIDX_BACKGROUND].right = w->width - 1; - w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; - w->widgets[WIDX_PAGE_BACKGROUND].right = w->width - 1; - w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; - w->widgets[WIDX_TITLE].right = w->width - 2; - w->widgets[WIDX_CLOSE].left = w->width - 13; - w->widgets[WIDX_CLOSE].right = w->width - 3; - - window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7); -} - -/** - * Disables the finance tab when no money. - * Disables peep pickup when in certain no pickup states. - * rct2: 0x006987A6 - */ -void WindowGuestDisableWidgets(rct_window* w) -{ - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - uint64_t disabled_widgets = 0; - - if (peep->CanBePickedUp()) - { - if (WidgetIsDisabled(w, WIDX_PICKUP)) - w->Invalidate(); - } - else - { - disabled_widgets = (1ULL << WIDX_PICKUP); - if (!WidgetIsDisabled(w, WIDX_PICKUP)) - w->Invalidate(); - } - if (gParkFlags & PARK_FLAGS_NO_MONEY) - { - disabled_widgets |= (1ULL << WIDX_TAB_4); // Disable finance tab if no money - } - if (!gConfigGeneral.debugging_tools) - { - disabled_widgets |= (1ULL << WIDX_TAB_7); // Disable debug tab when debug tools not turned on - } - w->disabled_widgets = disabled_widgets; -} - -/** - * - * rct2: 0x00696A75 - */ -void WindowGuestOverviewClose(rct_window* w) -{ - if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) - { - if (w->classification == gCurrentToolWidget.window_classification && w->number == gCurrentToolWidget.window_number) - tool_cancel(); - } -} - -/** - * - * rct2: 0x00696FBE - */ -void WindowGuestOverviewResize(rct_window* w) -{ - WindowGuestDisableWidgets(w); - window_event_invalidate_call(w); - - widget_invalidate(w, WIDX_MARQUEE); - - WindowGuestCommonResize(w); - - auto viewport = w->viewport; - if (viewport != nullptr) - { - auto reqViewportWidth = w->width - 30; - auto reqViewportHeight = w->height - 72; - if (viewport->width != reqViewportWidth || viewport->height != reqViewportHeight) - { - viewport->width = reqViewportWidth; - viewport->height = reqViewportHeight; - viewport->view_width = viewport->zoom.ApplyInversedTo(viewport->width); - viewport->view_height = viewport->zoom.ApplyInversedTo(viewport->height); - } - } - WindowGuestViewportInit(w); -} - -/** - * - * rct2: 0x00696A06 - */ -void WindowGuestOverviewMouseUp(rct_window* w, rct_widgetindex widgetIndex) -{ - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - case WIDX_TAB_5: - case WIDX_TAB_6: - case WIDX_TAB_7: - WindowGuestSetPage(w, widgetIndex - WIDX_TAB_1); - break; - case WIDX_PICKUP: - { - if (!peep->CanBePickedUp()) - { - return; - } - w->picked_peep_old_x = peep->x; - CoordsXYZ nullLoc{}; - nullLoc.SetNull(); - PeepPickupAction pickupAction{ PeepPickupType::Pickup, EntityId::FromUnderlying(w->number), nullLoc, - network_get_current_player_id() }; - pickupAction.SetCallback([peepnum = w->number](const GameAction* ga, const GameActions::Result* result) { - if (result->Error != GameActions::Status::Ok) - return; - rct_window* wind = window_find_by_number(WC_PEEP, peepnum); - if (wind != nullptr) - { - tool_set(wind, WC_PEEP__WIDX_PICKUP, Tool::Picker); - } - }); - GameActions::Execute(&pickupAction); - } - break; - case WIDX_RENAME: - { - auto peepName = peep->GetName(); - WindowTextInputRawOpen(w, widgetIndex, STR_GUEST_RENAME_TITLE, STR_GUEST_RENAME_PROMPT, {}, peepName.c_str(), 32); - break; - } - case WIDX_TRACK: - { - uint32_t flags = peep->PeepFlags ^ PEEP_FLAGS_TRACKING; - - auto guestSetFlagsAction = GuestSetFlagsAction(EntityId::FromUnderlying(w->number), flags); - GameActions::Execute(&guestSetFlagsAction); - } - break; - } -} - -static void WindowGuestOverviewMouseDown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) -{ - switch (widgetIndex) - { - case WIDX_LOCATE: - WindowGuestShowLocateDropdown(w, widget); - break; - } -} - -static void WindowGuestOverviewDropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex) -{ - switch (widgetIndex) - { - case WIDX_LOCATE: - { - if (dropdownIndex == 0) - { - w->ScrollToViewport(); - } - else if (dropdownIndex == 1) - { - WindowGuestFollow(w); - } - break; - } - } -} - -static void WindowGuestShowLocateDropdown(rct_window* w, rct_widget* widget) -{ - gDropdownItems[0].Format = STR_LOCATE_SUBJECT_TIP; - gDropdownItems[1].Format = STR_FOLLOW_SUBJECT_TIP; - - WindowDropdownShowText( - { w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->height() + 1, w->colours[1], 0, 2); - gDropdownDefaultIndex = 0; -} - -static void WindowGuestFollow(rct_window* w) -{ - rct_window* w_main = window_get_main(); - window_follow_sprite(w_main, EntityId::FromUnderlying(w->number)); -} - -/** - * - * rct2: 0x696AA0 - */ -void WindowGuestSetPage(rct_window* w, int32_t page) -{ - if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) - { - if (w->number == gCurrentToolWidget.window_number && w->classification == gCurrentToolWidget.window_classification) - tool_cancel(); - } - int32_t listen = 0; - if (page == WINDOW_GUEST_OVERVIEW && w->page == WINDOW_GUEST_OVERVIEW && w->viewport != nullptr) - { - if (!(w->viewport->flags & VIEWPORT_FLAG_SOUND_ON)) - listen = 1; - } - - w->page = page; - w->frame_no = 0; - w->no_list_items = 0; - w->selected_list_item = -1; - - w->RemoveViewport(); - - w->hold_down_widgets = 0; - w->event_handlers = window_guest_page_events[page]; - w->pressed_widgets = 0; - w->widgets = window_guest_page_widgets[page]; - WindowGuestDisableWidgets(w); - w->Invalidate(); - window_event_resize_call(w); - window_event_invalidate_call(w); - WindowInitScrollWidgets(w); - w->Invalidate(); - - if (listen && w->viewport != nullptr) - w->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; -} - -void WindowGuestOverviewViewportRotate(rct_window* w) -{ - WindowGuestViewportInit(w); -} - -/** - * - * rct2: 0x0069883C - */ -void WindowGuestViewportInit(rct_window* w) -{ - if (w->page != WINDOW_GUEST_OVERVIEW) - return; - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - viewport_update_smart_guest_follow(w, peep); - bool reCreateViewport = false; - uint16_t origViewportFlags{}; - if (w->viewport != nullptr) - { - if (w->focus.has_value()) - return; - - origViewportFlags = w->viewport->flags; - - reCreateViewport = true; - w->RemoveViewport(); - } - - window_event_invalidate_call(w); - - if (peep->State != PeepState::Picked && w->viewport == nullptr) - { - const auto& view_widget = w->widgets[WIDX_VIEWPORT]; - auto screenPos = ScreenCoordsXY{ view_widget.left + 1 + w->windowPos.x, view_widget.top + 1 + w->windowPos.y }; - int32_t width = view_widget.width() - 1; - int32_t height = view_widget.height() - 1; - - viewport_create(w, screenPos, width, height, w->focus.value()); - if (w->viewport != nullptr && reCreateViewport) - { - w->viewport->flags = origViewportFlags; - } - w->flags |= WF_NO_SCROLLING; - w->Invalidate(); - } - w->Invalidate(); -} - -/** - * - * rct2: 0x6983dd - * used by window_staff as well - */ -static void WindowGuestOverviewTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_1)) - return; - - const auto& widget = w->widgets[WIDX_TAB_1]; - int32_t width = widget.width() - 1; - int32_t height = widget.height() - 1; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left + 1, widget.top + 1 }; - if (w->page == WINDOW_GUEST_OVERVIEW) - height++; - - rct_drawpixelinfo clip_dpi; - if (!clip_drawpixelinfo(&clip_dpi, dpi, screenCoords, width, height)) - { - return; - } - - screenCoords = ScreenCoordsXY{ 14, 20 }; - - const Peep* peep = GetEntity(EntityId::FromUnderlying(w->number)); - if (peep == nullptr) - { - window_close(w); - return; - } - - auto* staff = peep->As(); - if (staff != nullptr && staff->AssignedStaffType == StaffType::Entertainer) - screenCoords.y++; - - int32_t animationFrame = GetPeepAnimation(peep->SpriteType).base_image + 1; - - int32_t animationFrameOffset = 0; - - if (w->page == WINDOW_GUEST_OVERVIEW) - { - animationFrameOffset = w->var_496; - animationFrameOffset &= 0xFFFC; - } - animationFrame += animationFrameOffset; - - auto sprite_id = ImageId(animationFrame, peep->TshirtColour, peep->TrousersColour); - gfx_draw_sprite(&clip_dpi, sprite_id, screenCoords); - - auto* guest = peep->As(); - if (guest != nullptr) - { - // If holding a balloon - if (animationFrame >= 0x2A1D && animationFrame < 0x2A3D) - { - gfx_draw_sprite(&clip_dpi, ImageId(animationFrame + 32, guest->BalloonColour), screenCoords); - } - - // If holding umbrella - if (animationFrame >= 0x2BBD && animationFrame < 0x2BDD) - { - gfx_draw_sprite(&clip_dpi, ImageId(animationFrame + 32, guest->UmbrellaColour), screenCoords); - } - - // If wearing hat - if (animationFrame >= 0x29DD && animationFrame < 0x29FD) - { - gfx_draw_sprite(&clip_dpi, ImageId(animationFrame + 32, guest->HatColour), screenCoords); - } - } -} - -/** - * - * rct2: 0x69869b - */ -static void WindowGuestStatsTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_2)) - return; - - const auto& widget = w->widgets[WIDX_TAB_2]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - int32_t image_id = get_peep_face_sprite_large(peep); - if (w->page == WINDOW_GUEST_STATS) - { - // If currently viewing this tab animate tab - // if it is very sick or angry. - switch (image_id) - { - case SPR_PEEP_LARGE_FACE_VERY_VERY_SICK_0: - image_id += (w->frame_no / 4) & 0xF; - break; - case SPR_PEEP_LARGE_FACE_VERY_SICK_0: - image_id += (w->frame_no / 8) & 0x3; - break; - case SPR_PEEP_LARGE_FACE_ANGRY_0: - image_id += (w->frame_no / 8) & 0x3; - break; - } - } - gfx_draw_sprite(dpi, ImageId(image_id), screenCoords); -} - -/** - * - * rct2: 0x69861F - */ -static void WindowGuestRidesTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_3)) - return; - - const auto& widget = w->widgets[WIDX_TAB_3]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - int32_t image_id = SPR_TAB_RIDE_0; - - if (w->page == WINDOW_GUEST_RIDES) - { - image_id += (w->frame_no / 4) & 0xF; - } - - gfx_draw_sprite(dpi, ImageId(image_id), screenCoords); -} - -/** - * - * rct2: 0x698597 - */ -static void WindowGuestFinanceTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_4)) - return; - - const auto& widget = w->widgets[WIDX_TAB_4]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - int32_t image_id = SPR_TAB_FINANCES_SUMMARY_0; - - if (w->page == WINDOW_GUEST_FINANCE) - { - image_id += (w->frame_no / 2) & 0x7; - } - - gfx_draw_sprite(dpi, ImageId(image_id), screenCoords); -} - -/** - * - * rct2: 0x6985D8 - */ -static void WindowGuestThoughtsTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_5)) - return; - - const auto& widget = w->widgets[WIDX_TAB_5]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - int32_t image_id = SPR_TAB_THOUGHTS_0; - - if (w->page == WINDOW_GUEST_THOUGHTS) - { - image_id += (w->frame_no / 2) & 0x7; - } - - gfx_draw_sprite(dpi, ImageId(image_id), screenCoords); -} - -/** - * - * rct2: 0x698661 - */ -static void WindowGuestInventoryTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_6)) - return; - - const auto& widget = w->widgets[WIDX_TAB_6]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - gfx_draw_sprite(dpi, ImageId(SPR_TAB_GUEST_INVENTORY), screenCoords); -} - -static void WindowGuestDebugTabPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - if (WidgetIsDisabled(w, WIDX_TAB_7)) - return; - - const auto& widget = w->widgets[WIDX_TAB_7]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ widget.left, widget.top }; - - int32_t image_id = SPR_TAB_GEARS_0; - if (w->page == WINDOW_GUEST_DEBUG) - { - image_id += (w->frame_no / 2) & 0x3; - } - - gfx_draw_sprite(dpi, ImageId(image_id), screenCoords); -} - -/** - * - * rct2: 0x696887 - */ -void WindowGuestOverviewPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - // Draw the viewport no sound sprite - if (w->viewport != nullptr) - { - window_draw_viewport(dpi, w); - rct_viewport* viewport = w->viewport; - if (viewport->flags & VIEWPORT_FLAG_SOUND_ON) - { - gfx_draw_sprite(dpi, ImageId(SPR_HEARING_VIEWPORT), w->windowPos + ScreenCoordsXY{ 2, 2 }); - } - } - - // Draw the centred label - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - const auto& actionLabelWidget = w->widgets[WIDX_ACTION_LBL]; - auto screenPos = w->windowPos + ScreenCoordsXY{ actionLabelWidget.midX(), actionLabelWidget.top - 1 }; - - { - auto ft = Formatter(); - peep->FormatActionTo(ft); - int32_t width = actionLabelWidget.width(); - DrawTextEllipsised(dpi, screenPos, width, STR_BLACK_STRING, ft, { TextAlignment::CENTRE }); - } - - // Draw the marquee thought - const auto& marqueeWidget = w->widgets[WIDX_MARQUEE]; - auto width = marqueeWidget.width() - 3; - int32_t left = marqueeWidget.left + 2 + w->windowPos.x; - int32_t top = marqueeWidget.top + w->windowPos.y; - int32_t height = marqueeWidget.height(); - rct_drawpixelinfo dpi_marquee; - if (!clip_drawpixelinfo(&dpi_marquee, dpi, { left, top }, width, height)) - { - return; - } - - int32_t i = 0; - for (; i < PEEP_MAX_THOUGHTS; ++i) - { - if (peep->Thoughts[i].type == PeepThoughtType::None) - { - w->list_information_type = 0; - return; - } - if (peep->Thoughts[i].freshness == 1) - { // If a fresh thought - break; - } - } - if (i == PEEP_MAX_THOUGHTS) - { - w->list_information_type = 0; - return; - } - - screenPos.x = marqueeWidget.width() - w->list_information_type; - { - auto ft = Formatter(); - peep_thought_set_format_args(&peep->Thoughts[i], ft); - DrawTextBasic(&dpi_marquee, { screenPos.x, 0 }, STR_WINDOW_COLOUR_2_STRINGID, ft, { FontSpriteBase::SMALL }); - } -} - -/** - * - * rct2: 0x696749 - */ -void WindowGuestOverviewInvalidate(rct_window* w) -{ - WindowGuestCommonInvalidate(w); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - w->pressed_widgets &= ~(1ULL << WIDX_TRACK); - if (peep->PeepFlags & PEEP_FLAGS_TRACKING) - { - w->pressed_widgets |= (1ULL << WIDX_TRACK); - } - - window_guest_overview_widgets[WIDX_VIEWPORT].right = w->width - 26; - window_guest_overview_widgets[WIDX_VIEWPORT].bottom = w->height - 14; - - window_guest_overview_widgets[WIDX_ACTION_LBL].top = w->height - 12; - window_guest_overview_widgets[WIDX_ACTION_LBL].bottom = w->height - 3; - window_guest_overview_widgets[WIDX_ACTION_LBL].right = w->width - 24; - - window_guest_overview_widgets[WIDX_MARQUEE].right = w->width - 24; - - window_guest_overview_widgets[WIDX_PICKUP].right = w->width - 2; - window_guest_overview_widgets[WIDX_RENAME].right = w->width - 2; - window_guest_overview_widgets[WIDX_LOCATE].right = w->width - 2; - window_guest_overview_widgets[WIDX_TRACK].right = w->width - 2; - - window_guest_overview_widgets[WIDX_PICKUP].left = w->width - 25; - window_guest_overview_widgets[WIDX_RENAME].left = w->width - 25; - window_guest_overview_widgets[WIDX_LOCATE].left = w->width - 25; - window_guest_overview_widgets[WIDX_TRACK].left = w->width - 25; -} - -/** - * - * rct2: 0x696F45 - */ -void WindowGuestOverviewUpdate(rct_window* w) -{ - int32_t newAnimationFrame = w->var_496; - newAnimationFrame++; - newAnimationFrame %= 24; - w->var_496 = newAnimationFrame; - - widget_invalidate(w, WIDX_TAB_1); - widget_invalidate(w, WIDX_TAB_2); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_ACTION) - { - peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_ACTION; - widget_invalidate(w, WIDX_ACTION_LBL); - } - - w->list_information_type += 2; - - if ((w->highlighted_item & 0xFFFF) == 0xFFFF) - w->highlighted_item &= 0xFFFF0000; - else - w->highlighted_item++; - - // Disable peep watching thought for multiplayer as it's client specific - if (network_get_mode() == NETWORK_MODE_NONE) - { - // Create the "I have the strangest feeling I am being watched thought" - if ((w->highlighted_item & 0xFFFF) >= 3840) - { - if (!(w->highlighted_item & 0x3FF)) - { - int32_t random = util_rand() & 0xFFFF; - if (random <= 0x2AAA) - { - peep->InsertNewThought(PeepThoughtType::Watched); - } - } - } - } -} - -/* rct2: 0x696A6A */ -void WindowGuestOverviewTextInput(rct_window* w, rct_widgetindex widgetIndex, char* text) -{ - if (widgetIndex != WIDX_RENAME) - return; - - if (text == nullptr) - return; - guest_set_name(EntityId::FromUnderlying(w->number), text); -} - -/** - * - * rct2: 0x696A5F - */ -void WindowGuestOverviewToolUpdate(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - if (widgetIndex != WIDX_PICKUP) - return; - - map_invalidate_selection_rect(); - - gMapSelectFlags &= ~MAP_SELECT_FLAG_ENABLE; - - auto mapCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, nullptr); - if (!mapCoords.IsNull()) - { - gMapSelectFlags |= MAP_SELECT_FLAG_ENABLE; - gMapSelectType = MAP_SELECT_TYPE_FULL; - gMapSelectPositionA = mapCoords; - gMapSelectPositionB = mapCoords; - map_invalidate_selection_rect(); - } - - gPickupPeepImage = ImageId(); - - auto info = get_map_coordinates_from_pos(screenCoords, ViewportInteractionItemAll); - if (info.SpriteType == ViewportInteractionItem::None) - return; - - gPickupPeepX = screenCoords.x - 1; - gPickupPeepY = screenCoords.y + 16; - w->picked_peep_frame++; - if (w->picked_peep_frame >= 48) - { - w->picked_peep_frame = 0; - } - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - auto baseImageId = GetPeepAnimation(peep->SpriteType, PeepActionSpriteType::Ui).base_image; - baseImageId += w->picked_peep_frame >> 2; - gPickupPeepImage = ImageId(baseImageId, peep->TshirtColour, peep->TrousersColour); -} - -/** - * - * rct2: 0x696A54 - */ -void WindowGuestOverviewToolDown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - if (widgetIndex != WIDX_PICKUP) - return; - - TileElement* tileElement; - auto destCoords = footpath_get_coordinates_from_pos({ screenCoords.x, screenCoords.y + 16 }, nullptr, &tileElement); - - if (destCoords.IsNull()) - return; - - PeepPickupAction pickupAction{ PeepPickupType::Place, - EntityId::FromUnderlying(w->number), - { destCoords, tileElement->GetBaseZ() }, - network_get_current_player_id() }; - pickupAction.SetCallback([](const GameAction* ga, const GameActions::Result* result) { - if (result->Error != GameActions::Status::Ok) - return; - tool_cancel(); - gPickupPeepImage = ImageId(); - }); - GameActions::Execute(&pickupAction); -} - -/** - * - * rct2: 0x696A49 - */ -void WindowGuestOverviewToolAbort(rct_window* w, rct_widgetindex widgetIndex) -{ - if (widgetIndex != WIDX_PICKUP) - return; - - PeepPickupAction pickupAction{ PeepPickupType::Cancel, - EntityId::FromUnderlying(w->number), - { w->picked_peep_old_x, 0, 0 }, - network_get_current_player_id() }; - GameActions::Execute(&pickupAction); -} - -/** - * This is a combination of 5 functions that were identical - * rct2: 0x69744F, 0x697795, 0x697BDD, 0x697E18, 0x698279 - */ -void WindowGuestMouseUp(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) - { - case WIDX_CLOSE: - window_close(w); - break; - case WIDX_TAB_1: - case WIDX_TAB_2: - case WIDX_TAB_3: - case WIDX_TAB_4: - case WIDX_TAB_5: - case WIDX_TAB_6: - case WIDX_TAB_7: - WindowGuestSetPage(w, widgetIndex - WIDX_TAB_1); - break; - } -} - -/** - * - * rct2: 0x69746A - */ -void WindowGuestStatsUpdate(rct_window* w) -{ - w->frame_no++; - auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_STATS; - - w->Invalidate(); -} - -/** - * - * rct2: 0x0066ECC1 - * - */ -static void WindowGuestStatsBarsPaint( - int32_t value, const ScreenCoordsXY& origCoords, rct_window* w, rct_drawpixelinfo* dpi, int32_t colour, bool blinkFlag) -{ - auto coords = origCoords; - if (font_get_line_height(FontSpriteBase::MEDIUM) > 10) - { - coords.y += 1; - } - - gfx_fill_rect_inset( - dpi, { coords + ScreenCoordsXY{ 61, 1 }, coords + ScreenCoordsXY{ 61 + 121, 9 } }, w->colours[1], INSET_RECT_F_30); - - if (!blinkFlag || game_is_paused() || (gCurrentRealTimeTicks & 8) == 0) - { - value *= 118; - value >>= 8; - - if (value <= 2) - return; - - gfx_fill_rect_inset(dpi, { coords + ScreenCoordsXY{ 63, 2 }, coords + ScreenCoordsXY{ 63 + value - 1, 8 } }, colour, 0); - } -} - -/** - * Takes a guest stat value (scaled to currMax) and adjusts it to be scaled out of 255. - * Then clamp the value to between newMin and 255. - */ -static int32_t NormalizeGuestStatValue(int32_t value, int32_t currMax, int32_t newMin) -{ - int32_t newValue = (value * 255) / currMax; - return std::clamp(newValue, newMin, 255); -} - -/** - * - * rct2: 0x0069711D - */ -void WindowGuestStatsPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - // ebx - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - // Not sure why this is not stats widgets - // cx dx - auto screenCoords = w->windowPos - + ScreenCoordsXY{ window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].left + 4, - window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].top + 4 }; - - // Happiness - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_HAPPINESS_LABEL); - - int32_t happiness = NormalizeGuestStatValue(peep->Happiness, PEEP_MAX_HAPPINESS, 10); - int32_t barColour = COLOUR_BRIGHT_GREEN; - bool barBlink = happiness < 50; - WindowGuestStatsBarsPaint(happiness, screenCoords, w, dpi, barColour, barBlink); - - // Energy - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_ENERGY_LABEL); - - int32_t energy = NormalizeGuestStatValue(peep->Energy - PEEP_MIN_ENERGY, PEEP_MAX_ENERGY - PEEP_MIN_ENERGY, 10); - barColour = COLOUR_BRIGHT_GREEN; - barBlink = energy < 50; - WindowGuestStatsBarsPaint(energy, screenCoords, w, dpi, barColour, barBlink); - - // Hunger - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_HUNGER_LABEL); - - int32_t hunger = NormalizeGuestStatValue(peep->Hunger - 32, 158, 0); - hunger = 255 - hunger; // the bar should be longer when peep->Hunger is low - barColour = COLOUR_BRIGHT_RED; - barBlink = hunger > 170; - WindowGuestStatsBarsPaint(hunger, screenCoords, w, dpi, barColour, barBlink); - - // Thirst - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_THIRST_LABEL); - - int32_t thirst = NormalizeGuestStatValue(peep->Thirst - 32, 158, 0); - thirst = 255 - thirst; // the bar should be longer when peep->Thirst is low - barColour = COLOUR_BRIGHT_RED; - barBlink = thirst > 170; - WindowGuestStatsBarsPaint(thirst, screenCoords, w, dpi, barColour, barBlink); - - // Nausea - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_NAUSEA_LABEL); - - int32_t nausea = NormalizeGuestStatValue(peep->Nausea - 32, 223, 0); - barColour = COLOUR_BRIGHT_RED; - barBlink = nausea > 120; - WindowGuestStatsBarsPaint(nausea, screenCoords, w, dpi, barColour, barBlink); - - // Toilet - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_TOILET_LABEL); - - int32_t toilet = NormalizeGuestStatValue(peep->Toilet - 64, 178, 0); - barColour = COLOUR_BRIGHT_RED; - barBlink = toilet > 160; - WindowGuestStatsBarsPaint(toilet, screenCoords, w, dpi, barColour, barBlink); - - // Time in park - screenCoords.y += LIST_ROW_HEIGHT + 1; - int32_t guestEntryTime = peep->GetParkEntryTime(); - if (guestEntryTime != -1) - { - int32_t timeInPark = (gCurrentTicks - guestEntryTime) >> 11; - auto ft = Formatter(); - ft.Add(timeInPark & 0xFFFF); - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_TIME_IN_PARK, ft); - } - - screenCoords.y += LIST_ROW_HEIGHT + 9; - gfx_fill_rect_inset( - dpi, { screenCoords - ScreenCoordsXY{ 0, 6 }, screenCoords + ScreenCoordsXY{ 179, -5 } }, w->colours[1], - INSET_RECT_FLAG_BORDER_INSET); - - // Preferred Ride - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_PREFERRED_RIDE); - screenCoords.y += LIST_ROW_HEIGHT; - - // Intensity - { - auto ft = Formatter(); - auto maxIntensity = peep->Intensity.GetMaximum(); - int32_t string_id = STR_GUEST_STAT_PREFERRED_INTESITY_BELOW; - if (peep->Intensity.GetMinimum() != 0) - { - ft.Add(peep->Intensity.GetMinimum()); - ft.Add(maxIntensity); - string_id = STR_GUEST_STAT_PREFERRED_INTESITY_BETWEEN; - if (maxIntensity == 15) - string_id = STR_GUEST_STAT_PREFERRED_INTESITY_ABOVE; - } - else - { - ft.Add(maxIntensity); - } - - DrawTextBasic(dpi, screenCoords + ScreenCoordsXY{ 4, 0 }, string_id, ft); - } - - // Nausea tolerance - { - static constexpr const rct_string_id _nauseaTolerances[] = { - STR_PEEP_STAT_NAUSEA_TOLERANCE_NONE, - STR_PEEP_STAT_NAUSEA_TOLERANCE_LOW, - STR_PEEP_STAT_NAUSEA_TOLERANCE_AVERAGE, - STR_PEEP_STAT_NAUSEA_TOLERANCE_HIGH, - }; - screenCoords.y += LIST_ROW_HEIGHT; - auto nausea_tolerance = EnumValue(peep->NauseaTolerance) & 0x3; - auto ft = Formatter(); - ft.Add(_nauseaTolerances[nausea_tolerance]); - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_NAUSEA_TOLERANCE, ft); - } -} - -/** - * - * rct2: 0x6977B0 - */ -void WindowGuestRidesUpdate(rct_window* w) -{ - w->frame_no++; - - widget_invalidate(w, WIDX_TAB_2); - widget_invalidate(w, WIDX_TAB_3); - - const auto guest = GetGuest(w); - if (guest == nullptr) - { - return; - } - - // Every 2048 ticks do a full window_invalidate - int32_t number_of_ticks = gCurrentTicks - guest->GetParkEntryTime(); - if (!(number_of_ticks & 0x7FF)) - w->Invalidate(); - - uint8_t curr_list_position = 0; - for (const auto& ride : GetRideManager()) - { - if (ride.IsRide() && guest->HasRidden(&ride)) - { - w->list_item_positions[curr_list_position] = ride.id.ToUnderlying(); - curr_list_position++; - } - } - - // If there are new items - if (w->no_list_items != curr_list_position) - { - w->no_list_items = curr_list_position; - w->Invalidate(); - } -} - -/** - * - * rct2: 0x69784E - */ -void WindowGuestRidesScrollGetSize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height) -{ - *height = w->no_list_items * 10; - - if (w->selected_list_item != -1) - { - w->selected_list_item = -1; - w->Invalidate(); - } - - int32_t visable_height = *height - window_guest_rides_widgets[WIDX_RIDE_SCROLL].bottom - + window_guest_rides_widgets[WIDX_RIDE_SCROLL].top + 21; - - if (visable_height < 0) - visable_height = 0; - - if (visable_height < w->scrolls[0].v_top) - { - w->scrolls[0].v_top = visable_height; - w->Invalidate(); - } -} - -/** - * - * rct2: 0x006978CC - */ -void WindowGuestRidesScrollMouseDown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - int32_t index; - - index = screenCoords.y / 10; - if (index >= w->no_list_items) - return; - - auto intent = Intent(WC_RIDE); - intent.putExtra(INTENT_EXTRA_RIDE_ID, w->list_item_positions[index]); - context_open_intent(&intent); -} - -/** - * - * rct2: 0x0069789C - */ -void WindowGuestRidesScrollMouseOver(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - int32_t index; - - index = screenCoords.y / 10; - if (index >= w->no_list_items) - return; - - if (index == w->selected_list_item) - return; - w->selected_list_item = index; - - w->Invalidate(); -} - -/** - * - * rct2: 0x0069757A - */ -void WindowGuestRidesInvalidate(rct_window* w) -{ - WindowGuestCommonInvalidate(w); - - window_guest_rides_widgets[WIDX_RIDE_SCROLL].right = w->width - 4; - window_guest_rides_widgets[WIDX_RIDE_SCROLL].bottom = w->height - 15; -} - -/** - * - * rct2: 0x00697637 - */ -void WindowGuestRidesPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - // cx dx - auto screenCoords = w->windowPos - + ScreenCoordsXY{ window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].left + 2, - window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].top + 2 }; - - DrawTextBasic(dpi, screenCoords, STR_GUEST_LABEL_RIDES_BEEN_ON); - - screenCoords.y = w->windowPos.y + window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].bottom - 12; - - auto ft = Formatter(); - auto ride = get_ride(peep->FavouriteRide); - if (ride != nullptr) - { - ride->FormatNameTo(ft); - } - else - { - ft.Add(STR_PEEP_FAVOURITE_RIDE_NOT_AVAILABLE); - } - - DrawTextEllipsised(dpi, screenCoords, w->width - 14, STR_FAVOURITE_RIDE, ft); -} - -/** - * - * rct2: 0x006976FC - */ -void WindowGuestRidesScrollPaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex) -{ - auto colour = ColourMapA[w->colours[1]].mid_light; - gfx_fill_rect(dpi, { { dpi->x, dpi->y }, { dpi->x + dpi->width - 1, dpi->y + dpi->height - 1 } }, colour); - - for (int32_t list_index = 0; list_index < w->no_list_items; list_index++) - { - auto y = list_index * 10; - rct_string_id stringId = STR_BLACK_STRING; - if (list_index == w->selected_list_item) - { - gfx_filter_rect(dpi, { 0, y, 800, y + 9 }, FilterPaletteID::PaletteDarken1); - stringId = STR_WINDOW_COLOUR_2_STRINGID; - } - - const auto rideId = RideId::FromUnderlying(w->list_item_positions[list_index]); - auto ride = get_ride(rideId); - if (ride != nullptr) - { - auto ft = Formatter(); - ride->FormatNameTo(ft); - DrawTextBasic(dpi, { 0, y - 1 }, stringId, ft); - } - } -} - -/** - * - * rct2: 0x00697BF8 - */ -void WindowGuestFinanceUpdate(rct_window* w) -{ - w->frame_no++; - - widget_invalidate(w, WIDX_TAB_2); - widget_invalidate(w, WIDX_TAB_4); -} - -/** - * - * rct2: 0x00697A08 - */ -void WindowGuestFinancePaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - // cx dx - auto screenCoords = w->windowPos - + ScreenCoordsXY{ window_guest_finance_widgets[WIDX_PAGE_BACKGROUND].left + 4, - window_guest_finance_widgets[WIDX_PAGE_BACKGROUND].top + 4 }; - - // Cash in pocket - { - auto ft = Formatter(); - ft.Add(peep->CashInPocket); - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_CASH_IN_POCKET, ft); - screenCoords.y += LIST_ROW_HEIGHT; - } - - // Cash spent - { - auto ft = Formatter(); - ft.Add(peep->CashSpent); - DrawTextBasic(dpi, screenCoords, STR_GUEST_STAT_CASH_SPENT, ft); - screenCoords.y += LIST_ROW_HEIGHT * 2; - } - - gfx_fill_rect_inset( - dpi, { screenCoords - ScreenCoordsXY{ 0, 6 }, screenCoords + ScreenCoordsXY{ 179, -5 } }, w->colours[1], - INSET_RECT_FLAG_BORDER_INSET); - - // Paid to enter - { - auto ft = Formatter(); - ft.Add(peep->PaidToEnter); - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_ENTRANCE_FEE, ft); - screenCoords.y += LIST_ROW_HEIGHT; - } - // Paid on rides - { - auto ft = Formatter(); - ft.Add(peep->PaidOnRides); - ft.Add(peep->GuestNumRides); - if (peep->GuestNumRides != 1) - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_RIDE_PLURAL, ft); - } - else - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_RIDE, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - } - // Paid on food - { - auto ft = Formatter(); - ft.Add(peep->PaidOnFood); - ft.Add(peep->AmountOfFood); - if (peep->AmountOfFood != 1) - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_FOOD_PLURAL, ft); - } - else - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_FOOD, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - } - - // Paid on drinks - { - auto ft = Formatter(); - ft.Add(peep->PaidOnDrink); - ft.Add(peep->AmountOfDrinks); - if (peep->AmountOfDrinks != 1) - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_DRINK_PLURAL, ft); - } - else - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_DRINK, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - } - // Paid on souvenirs - { - auto ft = Formatter(); - ft.Add(peep->PaidOnSouvenirs); - ft.Add(peep->AmountOfSouvenirs); - if (peep->AmountOfSouvenirs != 1) - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_SOUVENIR_PLURAL, ft); - } - else - { - DrawTextBasic(dpi, screenCoords, STR_GUEST_EXPENSES_SOUVENIR, ft); - } - } -} - -/** - * - * rct2: 0x00697EB4 - */ -void WindowGuestThoughtsUpdate(rct_window* w) -{ - w->frame_no++; - - widget_invalidate(w, WIDX_TAB_2); - widget_invalidate(w, WIDX_TAB_5); - - auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_THOUGHTS) - { - peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_THOUGHTS; - w->Invalidate(); - } -} - -/** - * - * rct2: 0x00697D2A - */ -void WindowGuestThoughtsPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - - // cx dx - auto screenCoords = w->windowPos - + ScreenCoordsXY{ window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].left + 4, - window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].top + 4 }; - - DrawTextBasic(dpi, screenCoords, STR_GUEST_RECENT_THOUGHTS_LABEL); - - screenCoords.y += 10; - for (const auto& thought : peep->Thoughts) - { - if (thought.type == PeepThoughtType::None) - return; - if (thought.freshness == 0) - continue; - - int32_t width = window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].right - - window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].left - 8; - - auto ft = Formatter(); - peep_thought_set_format_args(&thought, ft); - screenCoords.y += DrawTextWrapped(dpi, screenCoords, width, STR_BLACK_STRING, ft, { FontSpriteBase::SMALL }); - - // If this is the last visible line end drawing. - if (screenCoords.y > w->windowPos.y + window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].bottom - 32) - return; - } -} - -/** - * - * rct2: 0x00698315 - */ -void WindowGuestInventoryUpdate(rct_window* w) -{ - w->frame_no++; - - widget_invalidate(w, WIDX_TAB_2); - widget_invalidate(w, WIDX_TAB_6); - - auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - if (peep->WindowInvalidateFlags & PEEP_INVALIDATE_PEEP_INVENTORY) - { - peep->WindowInvalidateFlags &= ~PEEP_INVALIDATE_PEEP_INVENTORY; - w->Invalidate(); - } -} - -static std::pair WindowGuestInventoryFormatItem(Guest* guest, ShopItem item) -{ - auto& park = OpenRCT2::GetContext()->GetGameState()->GetPark(); - auto parkName = park.Name.c_str(); - - // Default arguments - auto ft = Formatter(); - ft.Add(GetShopItemDescriptor(item).Image); - ft.Add(GetShopItemDescriptor(item).Naming.Display); - ft.Add(STR_STRING); - ft.Add(parkName); - - // Special overrides - Ride* ride{}; - switch (item) - { - case ShopItem::Balloon: - ft.Rewind(); - ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest->BalloonColour) | GetShopItemDescriptor(item).Image); - break; - case ShopItem::Photo: - ride = get_ride(guest->Photo1RideRef); - if (ride != nullptr) - { - ft.Rewind(); - ft.Increment(6); - ride->FormatNameTo(ft); - } - - break; - case ShopItem::Umbrella: - ft.Rewind(); - ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest->UmbrellaColour) | GetShopItemDescriptor(item).Image); - break; - case ShopItem::Voucher: - switch (guest->VoucherType) - { - case VOUCHER_TYPE_PARK_ENTRY_FREE: - ft.Rewind(); - ft.Increment(6); - ft.Add(STR_PEEP_INVENTORY_VOUCHER_PARK_ENTRY_FREE); - ft.Add(STR_STRING); - ft.Add(parkName); - break; - case VOUCHER_TYPE_RIDE_FREE: - ride = get_ride(guest->VoucherRideId); - if (ride != nullptr) - { - ft.Rewind(); - ft.Increment(6); - ft.Add(STR_PEEP_INVENTORY_VOUCHER_RIDE_FREE); - ride->FormatNameTo(ft); - } - break; - case VOUCHER_TYPE_PARK_ENTRY_HALF_PRICE: - ft.Rewind(); - ft.Increment(6); - ft.Add(STR_PEEP_INVENTORY_VOUCHER_PARK_ENTRY_HALF_PRICE); - ft.Add(STR_STRING); - ft.Add(parkName); - break; - case VOUCHER_TYPE_FOOD_OR_DRINK_FREE: - ft.Rewind(); - ft.Increment(6); - ft.Add(STR_PEEP_INVENTORY_VOUCHER_FOOD_OR_DRINK_FREE); - ft.Add(GetShopItemDescriptor(guest->VoucherShopItem).Naming.Singular); - break; - } - break; - case ShopItem::Hat: - ft.Rewind(); - ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest->HatColour) | GetShopItemDescriptor(item).Image); - break; - case ShopItem::TShirt: - ft.Rewind(); - ft.Add(SPRITE_ID_PALETTE_COLOUR_1(guest->TshirtColour) | GetShopItemDescriptor(item).Image); - break; - case ShopItem::Photo2: - ride = get_ride(guest->Photo2RideRef); - if (ride != nullptr) - { - ft.Rewind(); - ft.Increment(6); - ride->FormatNameTo(ft); - } - break; - case ShopItem::Photo3: - ride = get_ride(guest->Photo3RideRef); - if (ride != nullptr) - { - ft.Rewind(); - ft.Increment(6); - ride->FormatNameTo(ft); - } - break; - case ShopItem::Photo4: - ride = get_ride(guest->Photo4RideRef); - if (ride != nullptr) - { - ft.Rewind(); - ft.Increment(6); - ride->FormatNameTo(ft); - } - break; - default: - // This switch handles only items visible in peep window - break; - } - - return std::make_pair(STR_GUEST_ITEM_FORMAT, ft); -} - -/** - * - * rct2: 0x00697F81 - */ -void WindowGuestInventoryPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - const auto guest = GetGuest(w); - if (guest == nullptr) - { - return; - } - - rct_widget* pageBackgroundWidget = &window_guest_inventory_widgets[WIDX_PAGE_BACKGROUND]; - auto screenCoords = w->windowPos + ScreenCoordsXY{ pageBackgroundWidget->left + 4, pageBackgroundWidget->top + 2 }; - int32_t itemNameWidth = pageBackgroundWidget->width() - 8; - - int32_t maxY = w->windowPos.y + w->height - 22; - int32_t numItems = 0; - - DrawTextBasic(dpi, screenCoords, STR_CARRYING); - screenCoords.y += 10; - - for (ShopItem item = ShopItem::Balloon; item < ShopItem::Count; item++) - { - if (screenCoords.y >= maxY) - break; - if (!guest->HasItem(item)) - continue; - - auto [stringId, ft] = WindowGuestInventoryFormatItem(guest, item); - screenCoords.y += DrawTextWrapped(dpi, screenCoords, itemNameWidth, stringId, ft); - numItems++; - } - - if (numItems == 0) - { - DrawTextBasic(dpi, screenCoords, STR_NOTHING); - } -} - -/** - * - * rct2: 0x00698315 - */ -void WindowGuestDebugUpdate(rct_window* w) -{ - w->frame_no++; - w->Invalidate(); -} - -void WindowGuestDebugPaint(rct_window* w, rct_drawpixelinfo* dpi) -{ - char buffer[512]{}; - char buffer2[512]{}; - - WindowDrawWidgets(w, dpi); - WindowGuestOverviewTabPaint(w, dpi); - WindowGuestStatsTabPaint(w, dpi); - WindowGuestRidesTabPaint(w, dpi); - WindowGuestFinanceTabPaint(w, dpi); - WindowGuestThoughtsTabPaint(w, dpi); - WindowGuestInventoryTabPaint(w, dpi); - WindowGuestDebugTabPaint(w, dpi); - - const auto peep = GetGuest(w); - if (peep == nullptr) - { - return; - } - auto screenCoords = w->windowPos - + ScreenCoordsXY{ window_guest_debug_widgets[WIDX_PAGE_BACKGROUND].left + 4, - window_guest_debug_widgets[WIDX_PAGE_BACKGROUND].top + 4 }; - { - auto ft = Formatter(); - ft.Add(peep->sprite_index); - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_SPRITE_INDEX, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - { - auto ft = Formatter(); - ft.Add(peep->x); - ft.Add(peep->y); - ft.Add(peep->z); - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_POSITION, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - { - auto ft = Formatter(); - ft.Add(peep->NextLoc.x); - ft.Add(peep->NextLoc.y); - ft.Add(peep->NextLoc.z); - format_string(buffer, sizeof(buffer), STR_PEEP_DEBUG_NEXT, ft.Data()); - if (peep->GetNextIsSurface()) - { - format_string(buffer2, sizeof(buffer2), STR_PEEP_DEBUG_NEXT_SURFACE, nullptr); - safe_strcat(buffer, buffer2, sizeof(buffer)); - } - if (peep->GetNextIsSloped()) - { - auto ft2 = Formatter(); - ft2.Add(peep->GetNextDirection()); - format_string(buffer2, sizeof(buffer2), STR_PEEP_DEBUG_NEXT_SLOPE, ft2.Data()); - safe_strcat(buffer, buffer2, sizeof(buffer)); - } - gfx_draw_string(dpi, screenCoords, buffer, {}); - } - screenCoords.y += LIST_ROW_HEIGHT; - { - auto ft = Formatter(); - ft.Add(peep->DestinationX); - ft.Add(peep->DestinationY); - ft.Add(peep->DestinationTolerance); - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_DEST, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - { - auto ft = Formatter(); - ft.Add(peep->PathfindGoal.x); - ft.Add(peep->PathfindGoal.y); - ft.Add(peep->PathfindGoal.z); - ft.Add(peep->PathfindGoal.direction); - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_GOAL, ft); - } - screenCoords.y += LIST_ROW_HEIGHT; - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_HISTORY); - screenCoords.y += LIST_ROW_HEIGHT; - - screenCoords.x += 10; - for (auto& point : peep->PathfindHistory) - { - auto ft = Formatter(); - ft.Add(point.x); - ft.Add(point.y); - ft.Add(point.z); - ft.Add(point.direction); - DrawTextBasic(dpi, screenCoords, STR_PEEP_DEBUG_PATHFIND_HISTORY_ITEM, ft); - screenCoords.y += LIST_ROW_HEIGHT; - } - screenCoords.x -= 10; -} diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index 226226d292..ab9398374b 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -146,7 +146,6 @@ rct_window* WindowPlayerOpen(uint8_t id) window->frame_no = 0; window->list_information_type = 0; window->picked_peep_frame = 0; - window->highlighted_item = 0; window->min_width = 210; window->min_height = 134; window->max_width = 500; diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index 9de33b9c69..bdf457d867 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -71,12 +71,12 @@ struct rct_window }; union { - int16_t picked_peep_old_x; // staff/guest window: peep x gets set to 0x8000 on pickup, this is the old value + int16_t picked_peep_old_x; // staff window: peep x gets set to 0x8000 on pickup, this is the old value int16_t vehicleIndex; // Ride window: selected car when setting vehicle colours int16_t var_48C; }; uint16_t frame_no{}; // updated every tic for motion in windows sprites - uint16_t list_information_type{}; // 0 for none, Used as current position of marquee in window_peep + uint16_t list_information_type{}; // 0 for none union { int16_t picked_peep_frame; // Animation frame of picked peep in staff window and guest window @@ -84,11 +84,9 @@ struct rct_window }; union { - uint32_t highlighted_item; uint16_t ride_colour; ResearchItem* research_item; const scenario_index_entry* highlighted_scenario; - uint16_t var_496; }; int16_t selected_tab{}; int16_t var_4AE{};