diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index cec14ffa0a..3794d85412 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -1096,7 +1096,7 @@ void window_staff_stats_paint(rct_window* w, rct_drawpixelinfo* dpi) if (!(gParkFlags & PARK_FLAGS_NO_MONEY)) { auto ft = Formatter(); - ft.Add(gStaffWageTable[static_cast(peep->AssignedStaffType)]); + ft.Add(GetStaffWage(peep->AssignedStaffType)); gfx_draw_string_left(dpi, STR_STAFF_STAT_WAGES, ft.Data(), COLOUR_BLACK, screenCoords); screenCoords.y += LIST_ROW_HEIGHT; } diff --git a/src/openrct2-ui/windows/StaffList.cpp b/src/openrct2-ui/windows/StaffList.cpp index ef65aa0ae4..9e0ab3705c 100644 --- a/src/openrct2-ui/windows/StaffList.cpp +++ b/src/openrct2-ui/windows/StaffList.cpp @@ -30,51 +30,16 @@ #include #include -// clang-format off -enum { +enum +{ WINDOW_STAFF_LIST_TAB_HANDYMEN, WINDOW_STAFF_LIST_TAB_MECHANICS, WINDOW_STAFF_LIST_TAB_SECURITY, WINDOW_STAFF_LIST_TAB_ENTERTAINERS }; -static std::vector StaffList; -static bool _quick_fire_mode = false; - -static void window_staff_list_close(rct_window *w); -static void window_staff_list_mouseup(rct_window *w, rct_widgetindex widgetIndex); -static void window_staff_list_resize(rct_window *w); -static void window_staff_list_mousedown(rct_window *w, rct_widgetindex widgetIndex, rct_widget* widget); -static void window_staff_list_dropdown(rct_window *w, rct_widgetindex widgetIndex, int32_t dropdownIndex); -static void window_staff_list_update(rct_window *w); -static void window_staff_list_tooldown(rct_window *w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords); -static void window_staff_list_toolabort(rct_window *w, rct_widgetindex widgetIndex); -static void window_staff_list_scrollgetsize(rct_window *w, int32_t scrollIndex, int32_t *width, int32_t *height); -static void window_staff_list_scrollmousedown(rct_window *w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void window_staff_list_scrollmouseover(rct_window *w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords); -static void window_staff_list_invalidate(rct_window *w); -static void window_staff_list_paint(rct_window *w, rct_drawpixelinfo *dpi); -static void window_staff_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int32_t scrollIndex); - -static rct_window_event_list window_staff_list_events([](auto& events) +enum WINDOW_STAFF_LIST_WIDGET_IDX { - events.close = &window_staff_list_close; - events.mouse_up = &window_staff_list_mouseup; - events.resize = &window_staff_list_resize; - events.mouse_down = &window_staff_list_mousedown; - events.dropdown = &window_staff_list_dropdown; - events.update = &window_staff_list_update; - events.tool_down = &window_staff_list_tooldown; - events.tool_abort = &window_staff_list_toolabort; - events.get_scroll_size = &window_staff_list_scrollgetsize; - events.scroll_mousedown = &window_staff_list_scrollmousedown; - events.scroll_mouseover = &window_staff_list_scrollmouseover; - events.invalidate = &window_staff_list_invalidate; - events.paint = &window_staff_list_paint; - events.scroll_paint = &window_staff_list_scrollpaint; -}); - -enum WINDOW_STAFF_LIST_WIDGET_IDX { WIDX_STAFF_LIST_BACKGROUND, WIDX_STAFF_LIST_TITLE, WIDX_STAFF_LIST_CLOSE, @@ -97,6 +62,7 @@ static constexpr const int32_t WH = 270; constexpr int32_t MAX_WW = 500; constexpr int32_t MAX_WH = 450; +// clang-format off static rct_widget window_staff_list_widgets[] = { WINDOW_SHIM(WINDOW_TITLE, WW, WH), MakeWidget({ 0, 43}, { WW, WH - 43}, WindowWidgetType::Resize, WindowColour::Secondary ), // tab content panel @@ -112,261 +78,491 @@ static rct_widget window_staff_list_widgets[] = { MakeWidget({291, 46}, { 24, 24}, WindowWidgetType::FlatBtn, WindowColour::Secondary, SPR_MAP, STR_SHOW_STAFF_ON_MAP_TIP ), // show staff on map button { WIDGETS_END }, }; - -static int32_t _windowStaffListHighlightedIndex; -static int32_t _windowStaffListSelectedTab = WINDOW_STAFF_LIST_TAB_HANDYMEN; - -static EntertainerCostume window_staff_list_get_random_entertainer_costume(); - -struct staff_naming_convention -{ - rct_string_id plural; - rct_string_id singular; - rct_string_id action_hire; -}; - -static constexpr const staff_naming_convention StaffNamingConvention[] = { - { STR_HANDYMAN_PLURAL, STR_HANDYMAN_SINGULAR, STR_HIRE_HANDYMAN }, - { STR_MECHANIC_PLURAL, STR_MECHANIC_SINGULAR, STR_HIRE_MECHANIC }, - { STR_SECURITY_GUARD_PLURAL, STR_SECURITY_GUARD_SINGULAR, STR_HIRE_SECURITY_GUARD }, - { STR_ENTERTAINER_PLURAL, STR_ENTERTAINER_SINGULAR, STR_HIRE_ENTERTAINER }, -}; // clang-format on -/* - * rct2: 0x006BD3CC - **/ -rct_window* window_staff_list_open() +class StaffListWindow final : public Window { - rct_window* window; - - // Check if window is already open - window = window_bring_to_front_by_class(WC_STAFF_LIST); - if (window != nullptr) - return window; - - window = WindowCreateAutoPos(WW, WH, &window_staff_list_events, WC_STAFF_LIST, WF_10 | WF_RESIZABLE); - window->widgets = window_staff_list_widgets; - window->enabled_widgets = (1 << WIDX_STAFF_LIST_CLOSE) | (1 << WIDX_STAFF_LIST_HANDYMEN_TAB) - | (1 << WIDX_STAFF_LIST_MECHANICS_TAB) | (1 << WIDX_STAFF_LIST_SECURITY_TAB) | (1 << WIDX_STAFF_LIST_ENTERTAINERS_TAB) - | (1 << WIDX_STAFF_LIST_HIRE_BUTTON) | (1 << WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER) - | (1 << WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) | (1 << WIDX_STAFF_LIST_MAP) | (1 << WIDX_STAFF_LIST_QUICK_FIRE); - - WindowInitScrollWidgets(window); - _windowStaffListHighlightedIndex = -1; - window->list_information_type = 0; - - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::Empty; - window->min_width = WW; - window->min_height = WH; - window->max_width = MAX_WW; - window->max_height = MAX_WH; - _quick_fire_mode = false; - - WindowStaffListRefresh(); - return window; -} - -void WindowStaffListRefresh() -{ - auto w = window_find_by_class(WC_STAFF_LIST); - if (w == nullptr) +private: + struct StaffNamingConvention { - return; - } - StaffList.clear(); + rct_string_id Plural; + rct_string_id Singular; + rct_string_id ActionHire; + }; - for (auto peep : EntityList(EntityListId::Peep)) + std::vector _staffList; + bool _quickFireMode{}; + std::optional _highlightedIndex{}; + int32_t _selectedTab{}; + uint32_t _tabAnimationIndex{}; + +public: + void OnOpen() override { - sprite_set_flashing(peep, false); - if (static_cast(peep->AssignedStaffType) != _windowStaffListSelectedTab) - continue; - sprite_set_flashing(peep, true); + widgets = window_staff_list_widgets; + enabled_widgets = (1 << WIDX_STAFF_LIST_CLOSE) | (1 << WIDX_STAFF_LIST_HANDYMEN_TAB) + | (1 << WIDX_STAFF_LIST_MECHANICS_TAB) | (1 << WIDX_STAFF_LIST_SECURITY_TAB) + | (1 << WIDX_STAFF_LIST_ENTERTAINERS_TAB) | (1 << WIDX_STAFF_LIST_HIRE_BUTTON) + | (1 << WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER) | (1 << WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) + | (1 << WIDX_STAFF_LIST_MAP) | (1 << WIDX_STAFF_LIST_QUICK_FIRE); + WindowInitScrollWidgets(this); - StaffList.push_back(peep->sprite_index); + widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::Empty; + min_width = WW; + min_height = WH; + max_width = MAX_WW; + max_height = MAX_WH; + + RefreshList(); } - std::sort(StaffList.begin(), StaffList.end(), [](const uint16_t a, const uint16_t b) { return peep_compare(a, b) < 0; }); -} - -static void window_staff_list_cancel_tools(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: 0x006BD9B1 - **/ -void window_staff_list_close(rct_window* w) -{ - window_staff_list_cancel_tools(w); -} - -/** - * - * rct2: 0x006BD94C - */ -static void window_staff_list_mouseup(rct_window* w, rct_widgetindex widgetIndex) -{ - switch (widgetIndex) + void OnClose() override { - case WIDX_STAFF_LIST_CLOSE: - window_close(w); - break; - case WIDX_STAFF_LIST_HIRE_BUTTON: + CancelTools(); + } + + void OnMouseUp(rct_widgetindex widgetIndex) override + { + switch (widgetIndex) { - StaffType staffType = static_cast(_windowStaffListSelectedTab); - auto costume = EntertainerCostume::Count; - if (staffType == StaffType::Entertainer) - { - costume = window_staff_list_get_random_entertainer_costume(); - } - staff_hire_new_member(staffType, costume); - break; - } - case WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON: - if (!tool_set(w, WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON, Tool::Crosshair)) - { - show_gridlines(); - gStaffDrawPatrolAreas = _windowStaffListSelectedTab | 0x8000; - gfx_invalidate_screen(); - } - break; - case WIDX_STAFF_LIST_MAP: - context_open_window(WC_MAP); - break; - case WIDX_STAFF_LIST_QUICK_FIRE: - _quick_fire_mode ^= 1; - w->Invalidate(); - break; - } -} - -/** - * - * rct2: 0x006BDD5D - */ -static void window_staff_list_resize(rct_window* w) -{ - w->min_width = WW; - w->min_height = WH; - if (w->width < w->min_width) - { - w->width = w->min_width; - w->Invalidate(); - } - if (w->height < w->min_height) - { - w->height = w->min_height; - w->Invalidate(); - } -} - -/** - * - * rct2: 0x006BD971 - */ -static void window_staff_list_mousedown(rct_window* w, rct_widgetindex widgetIndex, rct_widget* widget) -{ - int16_t newSelectedTab; - - switch (widgetIndex) - { - case WIDX_STAFF_LIST_HANDYMEN_TAB: - case WIDX_STAFF_LIST_MECHANICS_TAB: - case WIDX_STAFF_LIST_SECURITY_TAB: - case WIDX_STAFF_LIST_ENTERTAINERS_TAB: - newSelectedTab = widgetIndex - WIDX_STAFF_LIST_HANDYMEN_TAB; - if (_windowStaffListSelectedTab == newSelectedTab) + case WIDX_STAFF_LIST_CLOSE: + Close(); break; - - _windowStaffListSelectedTab = static_cast(newSelectedTab); - w->Invalidate(); - w->scrolls[0].v_top = 0; - window_staff_list_cancel_tools(w); - break; - case WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER: - WindowDropdownShowColour( - w, widget, w->colours[1], staff_get_colour(static_cast(_windowStaffListSelectedTab))); - break; - } -} - -/** - * - * rct2: 0x006BD9A6 - */ -static void window_staff_list_dropdown(rct_window* w, rct_widgetindex widgetIndex, int32_t dropdownIndex) -{ - if (widgetIndex == WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER && dropdownIndex != -1) - { - auto action = StaffSetColourAction(static_cast(_windowStaffListSelectedTab), dropdownIndex); - GameActions::Execute(&action); - } -} - -/** - * - * rct2: 0x006BDCEA - */ -void window_staff_list_update(rct_window* w) -{ - w->list_information_type++; - if (w->list_information_type >= 24) - { - w->list_information_type = 0; - } - else - { - widget_invalidate(w, WIDX_STAFF_LIST_HANDYMEN_TAB + _windowStaffListSelectedTab); - - // Enable highlighting of these staff members in map window - if (window_find_by_class(WC_MAP) != nullptr) - { - gWindowMapFlashingFlags |= MapFlashingFlags::StaffListOpen; - for (auto peep : EntityList(EntityListId::Peep)) + case WIDX_STAFF_LIST_HIRE_BUTTON: { - sprite_set_flashing(peep, false); - - if (static_cast(peep->AssignedStaffType) == _windowStaffListSelectedTab) + auto staffType = GetSelectedStaffType(); + auto costume = EntertainerCostume::Count; + if (staffType == StaffType::Entertainer) { - sprite_set_flashing(peep, true); + costume = GetRandomEntertainerCostume(); + } + staff_hire_new_member(staffType, costume); + break; + } + case WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON: + if (!tool_set(this, WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON, Tool::Crosshair)) + { + show_gridlines(); + gStaffDrawPatrolAreas = _selectedTab | 0x8000; + gfx_invalidate_screen(); + } + break; + case WIDX_STAFF_LIST_MAP: + context_open_window(WC_MAP); + break; + case WIDX_STAFF_LIST_QUICK_FIRE: + _quickFireMode = !_quickFireMode; + Invalidate(); + break; + } + } + + void OnResize() override + { + min_width = WW; + min_height = WH; + if (width < min_width) + { + width = min_width; + Invalidate(); + } + if (height < min_height) + { + height = min_height; + Invalidate(); + } + } + + void OnUpdate() override + { + _tabAnimationIndex++; + if (_tabAnimationIndex >= 24) + { + _tabAnimationIndex = 0; + } + else + { + InvalidateWidget(WIDX_STAFF_LIST_HANDYMEN_TAB + _selectedTab); + + // Enable highlighting of these staff members in map window + if (window_find_by_class(WC_MAP) != nullptr) + { + gWindowMapFlashingFlags |= MapFlashingFlags::StaffListOpen; + for (auto peep : EntityList(EntityListId::Peep)) + { + sprite_set_flashing(peep, false); + if (peep->AssignedStaffType == GetSelectedStaffType()) + { + sprite_set_flashing(peep, true); + } } } } + + // Note this may be slow if number of staff increases a large amount. + // See GuestList for fix (more intents) if required. + RefreshList(); } - // Note this may be slow if number of staff increases a large amount. - // See GuestList for fix (more intents) if required. - WindowStaffListRefresh(); -} - -/** - * - * rct2: 0x006BD990 - */ -static void window_staff_list_tooldown(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) -{ - if (widgetIndex == WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) + void OnMouseDown(rct_widgetindex widgetIndex) override { - int32_t selectedPeepType = _windowStaffListSelectedTab; + switch (widgetIndex) + { + case WIDX_STAFF_LIST_HANDYMEN_TAB: + case WIDX_STAFF_LIST_MECHANICS_TAB: + case WIDX_STAFF_LIST_SECURITY_TAB: + case WIDX_STAFF_LIST_ENTERTAINERS_TAB: + { + auto newSelectedTab = widgetIndex - WIDX_STAFF_LIST_HANDYMEN_TAB; + if (_selectedTab != newSelectedTab) + { + _selectedTab = static_cast(newSelectedTab); + Invalidate(); + scrolls[0].v_top = 0; + CancelTools(); + } + break; + } + case WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER: + WindowDropdownShowColour(this, &widgets[widgetIndex], colours[1], staff_get_colour(GetSelectedStaffType())); + break; + } + } - int32_t direction; - TileElement* tileElement; - auto footpathCoords = footpath_get_coordinates_from_pos(screenCoords, &direction, &tileElement); - if (footpathCoords.isNull()) - return; + void OnDropdown(rct_widgetindex widgetIndex, int32_t dropdownIndex) override + { + if (widgetIndex == WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER) + { + auto action = StaffSetColourAction(GetSelectedStaffType(), dropdownIndex); + GameActions::Execute(&action); + } + } - bool isPatrolAreaSet = staff_is_patrol_area_set_for_type(static_cast(selectedPeepType), footpathCoords); + void OnPrepareDraw() override + { + // Set selected tab + SetWidgetPressed(WIDX_STAFF_LIST_HANDYMEN_TAB, false); + SetWidgetPressed(WIDX_STAFF_LIST_MECHANICS_TAB, false); + SetWidgetPressed(WIDX_STAFF_LIST_SECURITY_TAB, false); + SetWidgetPressed(WIDX_STAFF_LIST_ENTERTAINERS_TAB, false); + SetWidgetPressed(_selectedTab + WIDX_STAFF_LIST_HANDYMEN_TAB, true); - Peep* closestPeep = nullptr; - int32_t closestPeepDistance = std::numeric_limits::max(); + widgets[WIDX_STAFF_LIST_HIRE_BUTTON].text = GetStaffNamingConvention(GetSelectedStaffType()).ActionHire; + widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::Empty; + + if (GetSelectedStaffType() != StaffType::Entertainer) + { + widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::ColourBtn; + auto spriteIdPalette = SPRITE_ID_PALETTE_COLOUR_1(static_cast(staff_get_colour(GetSelectedStaffType()))); + widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].image = spriteIdPalette | IMAGE_TYPE_TRANSPARENT | SPR_PALETTE_BTN; + } + SetWidgetPressed(WIDX_STAFF_LIST_QUICK_FIRE, _quickFireMode); + + widgets[WIDX_STAFF_LIST_BACKGROUND].right = width - 1; + widgets[WIDX_STAFF_LIST_BACKGROUND].bottom = height - 1; + widgets[WIDX_STAFF_LIST_TAB_CONTENT_PANEL].right = width - 1; + widgets[WIDX_STAFF_LIST_TAB_CONTENT_PANEL].bottom = height - 1; + widgets[WIDX_STAFF_LIST_TITLE].right = width - 2; + widgets[WIDX_STAFF_LIST_CLOSE].left = width - 2 - 11; + widgets[WIDX_STAFF_LIST_CLOSE].right = width - 2 - 11 + 10; + widgets[WIDX_STAFF_LIST_LIST].right = width - 4; + widgets[WIDX_STAFF_LIST_LIST].bottom = height - 15; + widgets[WIDX_STAFF_LIST_QUICK_FIRE].left = width - 77; + widgets[WIDX_STAFF_LIST_QUICK_FIRE].right = width - 54; + widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].left = width - 53; + widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].right = width - 30; + widgets[WIDX_STAFF_LIST_MAP].left = width - 29; + widgets[WIDX_STAFF_LIST_MAP].right = width - 6; + widgets[WIDX_STAFF_LIST_HIRE_BUTTON].left = width - 155; + widgets[WIDX_STAFF_LIST_HIRE_BUTTON].right = width - 11; + } + + void OnDraw(rct_drawpixelinfo& dpi) override + { + DrawWidgets(dpi); + DrawTabImages(dpi); + + if (!(gParkFlags & PARK_FLAGS_NO_MONEY)) + { + auto ft = Formatter(); + ft.Add(GetStaffWage(GetSelectedStaffType())); + gfx_draw_string_left( + &dpi, STR_COST_PER_MONTH, ft.Data(), COLOUR_BLACK, windowPos + ScreenCoordsXY{ width - 155, 32 }); + } + + if (GetSelectedStaffType() != StaffType::Entertainer) + { + gfx_draw_string_left( + &dpi, STR_UNIFORM_COLOUR, nullptr, COLOUR_BLACK, + windowPos + ScreenCoordsXY{ 6, widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].top + 1 }); + } + + auto namingConvention = GetStaffNamingConvention(GetSelectedStaffType()); + auto staffTypeStringId = _staffList.size() == 1 ? namingConvention.Singular : namingConvention.Plural; + + auto ft = Formatter(); + ft.Add(_staffList.size()); + ft.Add(staffTypeStringId); + + gfx_draw_string_left( + &dpi, STR_STAFF_LIST_COUNTER, ft.Data(), COLOUR_BLACK, + windowPos + ScreenCoordsXY{ 4, widgets[WIDX_STAFF_LIST_LIST].bottom + 2 }); + } + + ScreenSize OnScrollGetSize(int32_t scrollIndex) override + { + if (_highlightedIndex) + { + _highlightedIndex = {}; + Invalidate(); + } + + auto scrollHeight = static_cast(_staffList.size()) * SCROLLABLE_ROW_HEIGHT; + auto i = scrollHeight - widgets[WIDX_STAFF_LIST_LIST].bottom + widgets[WIDX_STAFF_LIST_LIST].top + 21; + if (i < 0) + i = 0; + if (i < scrolls[0].v_top) + { + scrolls[0].v_top = i; + Invalidate(); + } + + auto scrollWidth = widgets[WIDX_STAFF_LIST_LIST].width() - 15; + return { scrollWidth, scrollHeight }; + } + + void OnScrollMouseOver(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + auto i = static_cast(screenCoords.y / SCROLLABLE_ROW_HEIGHT); + if (i != _highlightedIndex) + { + _highlightedIndex = static_cast(i); + Invalidate(); + } + } + + void OnScrollMouseDown(int32_t scrollIndex, const ScreenCoordsXY& screenCoords) override + { + int32_t i = screenCoords.y / SCROLLABLE_ROW_HEIGHT; + for (auto spriteIndex : _staffList) + { + if (i == 0) + { + if (_quickFireMode) + { + auto staffFireAction = StaffFireAction(spriteIndex); + GameActions::Execute(&staffFireAction); + } + else + { + auto peep = GetEntity(spriteIndex); + if (peep != nullptr) + { + auto intent = Intent(WC_PEEP); + intent.putExtra(INTENT_EXTRA_PEEP, peep); + context_open_intent(&intent); + } + } + break; + } + + i--; + } + } + + void OnScrollDraw(int32_t scrollIndex, rct_drawpixelinfo& dpi) override + { + auto dpiCoords = ScreenCoordsXY{ dpi.x, dpi.y }; + gfx_fill_rect( + &dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi.width - 1, dpi.height - 1 } }, ColourMapA[colours[1]].mid_light); + + // How much space do we have for the name and action columns? (Discount scroll area and icons.) + const int32_t nonIconSpace = widgets[WIDX_STAFF_LIST_LIST].width() - 15 - 68; + const int32_t nameColumnSize = nonIconSpace * 0.42; + const int32_t actionColumnSize = nonIconSpace * 0.58; + const int32_t actionOffset = widgets[WIDX_STAFF_LIST_LIST].right - actionColumnSize - 15; + + auto y = 0; + size_t i = 0; + for (auto spriteIndex : _staffList) + { + if (y > dpi.y + dpi.height) + { + break; + } + + if (y + 11 >= dpi.y) + { + auto peep = GetEntity(spriteIndex); + if (peep == nullptr) + { + continue; + } + int32_t format = (_quickFireMode ? STR_RED_STRINGID : STR_BLACK_STRING); + + if (i == _highlightedIndex) + { + gfx_filter_rect(&dpi, 0, y, 800, y + (SCROLLABLE_ROW_HEIGHT - 1), FilterPaletteID::PaletteDarken1); + format = (_quickFireMode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID); + } + + auto ft = Formatter(); + peep->FormatNameTo(ft); + DrawTextEllipsised(&dpi, { 0, y }, nameColumnSize, format, ft, COLOUR_BLACK); + + ft = Formatter(); + peep->FormatActionTo(ft); + DrawTextEllipsised(&dpi, { actionOffset, y }, actionColumnSize, format, ft, COLOUR_BLACK); + + // True if a patrol path is set for the worker + if (gStaffModes[peep->StaffId] == StaffMode::Patrol) + { + gfx_draw_sprite(&dpi, SPR_STAFF_PATROL_PATH, { nameColumnSize + 5, y }, 0); + } + + auto staffOrderIcon_x = nameColumnSize + 20; + if (peep->AssignedStaffType != StaffType::Entertainer) + { + auto staffOrders = peep->StaffOrders; + auto staffOrderSprite = GetStaffOrderBaseSprite(GetSelectedStaffType()); + + while (staffOrders != 0) + { + if (staffOrders & 1) + { + gfx_draw_sprite(&dpi, staffOrderSprite, { staffOrderIcon_x, y }, 0); + } + staffOrders = staffOrders >> 1; + staffOrderIcon_x += 9; + // TODO: Remove sprite ID addition + staffOrderSprite++; + } + } + else + { + gfx_draw_sprite(&dpi, GetEntertainerCostumeSprite(peep->SpriteType), { staffOrderIcon_x, y }, 0); + } + } + + y += SCROLLABLE_ROW_HEIGHT; + i++; + } + } + + void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) override + { + if (widgetIndex == WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) + { + auto closestStaffMember = GetClosestStaffMemberTo(screenCoords); + if (closestStaffMember != nullptr) + { + tool_cancel(); + auto* staffWindow = window_staff_open(closestStaffMember); + window_event_dropdown_call(staffWindow, WC_PEEP__WIDX_PATROL, 0); + } + else + { + auto ft = Formatter(); + ft.Add(GetStaffNamingConvention(GetSelectedStaffType()).Plural); + context_show_error(STR_NO_THING_IN_PARK_YET, STR_NONE, ft); + } + } + } + + void OnToolAbort(rct_widgetindex widgetIndex) override + { + if (widgetIndex == WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) + { + hide_gridlines(); + tool_cancel(); + gStaffDrawPatrolAreas = 0xFFFF; + gfx_invalidate_screen(); + } + } + + void RefreshList() + { + _staffList.clear(); for (auto peep : EntityList(EntityListId::Peep)) { - if (static_cast(peep->AssignedStaffType) != selectedPeepType) + sprite_set_flashing(peep, false); + if (peep->AssignedStaffType == GetSelectedStaffType()) + { + sprite_set_flashing(peep, true); + _staffList.push_back(peep->sprite_index); + } + } + + std::sort( + _staffList.begin(), _staffList.end(), [](const uint16_t a, const uint16_t b) { return peep_compare(a, b) < 0; }); + } + +private: + StaffType GetSelectedStaffType() const + { + return static_cast(_selectedTab); + } + + void DrawTabImages(rct_drawpixelinfo& dpi) const + { + DrawTabImage(dpi, WINDOW_STAFF_LIST_TAB_HANDYMEN, PeepSpriteType::Handyman, gStaffHandymanColour); + DrawTabImage(dpi, WINDOW_STAFF_LIST_TAB_MECHANICS, PeepSpriteType::Mechanic, gStaffMechanicColour); + DrawTabImage(dpi, WINDOW_STAFF_LIST_TAB_SECURITY, PeepSpriteType::Security, gStaffSecurityColour); + DrawTabImage(dpi, WINDOW_STAFF_LIST_TAB_ENTERTAINERS, PeepSpriteType::EntertainerElephant); + } + + void DrawTabImage(rct_drawpixelinfo& dpi, int32_t tabIndex, PeepSpriteType type, colour_t colour) const + { + auto widgetIndex = WIDX_STAFF_LIST_HANDYMEN_TAB + tabIndex; + const auto& widget = widgets[widgetIndex]; + auto imageId = (_selectedTab == tabIndex ? (_tabAnimationIndex & ~3) : 0); + imageId += GetPeepAnimation(type).base_image + 1; + imageId |= SPRITE_ID_PALETTE_COLOUR_1(colour); + gfx_draw_sprite(&dpi, imageId, windowPos + ScreenCoordsXY{ (widget.left + widget.right) / 2, widget.bottom - 6 }, 0); + } + + void DrawTabImage(rct_drawpixelinfo& dpi, int32_t tabIndex, PeepSpriteType type) const + { + auto widgetIndex = WIDX_STAFF_LIST_HANDYMEN_TAB + tabIndex; + const auto& widget = widgets[widgetIndex]; + rct_drawpixelinfo clippedDpi; + if (clip_drawpixelinfo( + &clippedDpi, &dpi, windowPos + ScreenCoordsXY{ widget.left + 1, widget.top + 1 }, + widget.right - widget.left - 1, widget.bottom - widget.top - 1)) + { + auto imageId = (_selectedTab == 3 ? (_tabAnimationIndex & ~3) : 0); + imageId += GetPeepAnimation(type).base_image + 1; + gfx_draw_sprite(&clippedDpi, imageId, { 15, 23 }, 0); + } + } + + void CancelTools() + { + if (input_test_flag(INPUT_FLAG_TOOL_ACTIVE)) + { + if (classification == gCurrentToolWidget.window_classification && number == gCurrentToolWidget.window_number) + { + tool_cancel(); + } + } + } + + Peep* GetClosestStaffMemberTo(const ScreenCoordsXY& screenCoords) + { + int32_t direction{}; + TileElement* tileElement{}; + auto footpathCoords = footpath_get_coordinates_from_pos(screenCoords, &direction, &tileElement); + if (footpathCoords.isNull()) + return nullptr; + + auto isPatrolAreaSet = staff_is_patrol_area_set_for_type(GetSelectedStaffType(), footpathCoords); + + Peep* closestPeep = nullptr; + auto closestPeepDistance = std::numeric_limits::max(); + for (auto peep : EntityList(EntityListId::Peep)) + { + if (peep->AssignedStaffType != GetSelectedStaffType()) continue; if (isPatrolAreaSet) @@ -386,374 +582,99 @@ static void window_staff_list_tooldown(rct_window* w, rct_widgetindex widgetInde continue; } - int32_t distance = abs(footpathCoords.x - peep->x) + abs(footpathCoords.y - peep->y); + auto distance = std::abs(footpathCoords.x - peep->x) + std::abs(footpathCoords.y - peep->y); if (distance < closestPeepDistance) { closestPeepDistance = distance; closestPeep = peep; } } + return closestPeep; + } - if (closestPeep != nullptr) + static EntertainerCostume GetRandomEntertainerCostume() + { + auto result = EntertainerCostume::Panda; + EntertainerCostume costumeList[static_cast(EntertainerCostume::Count)]; + int32_t numCostumes = staff_get_available_entertainer_costume_list(costumeList); + if (numCostumes > 0) { - tool_cancel(); - rct_window* staffWindow = window_staff_open(closestPeep); - window_event_dropdown_call(staffWindow, WC_PEEP__WIDX_PATROL, 0); + int32_t index = util_rand() % numCostumes; + result = costumeList[index]; } - else + return result; + } + + static constexpr StaffNamingConvention GetStaffNamingConvention(StaffType type) + { + switch (type) { - auto ft = Formatter(); - ft.Add(StaffNamingConvention[selectedPeepType].plural); - context_show_error(STR_NO_THING_IN_PARK_YET, STR_NONE, ft); + default: + case StaffType::Handyman: + return { STR_HANDYMAN_PLURAL, STR_HANDYMAN_SINGULAR, STR_HIRE_HANDYMAN }; + case StaffType::Mechanic: + return { STR_MECHANIC_PLURAL, STR_MECHANIC_SINGULAR, STR_HIRE_MECHANIC }; + case StaffType::Security: + return { STR_SECURITY_GUARD_PLURAL, STR_SECURITY_GUARD_SINGULAR, STR_HIRE_SECURITY_GUARD }; + case StaffType::Entertainer: + return { STR_ENTERTAINER_PLURAL, STR_ENTERTAINER_SINGULAR, STR_HIRE_ENTERTAINER }; } } -} -/** - * - * rct2: 0x006BD99B - */ -void window_staff_list_toolabort(rct_window* w, rct_widgetindex widgetIndex) -{ - if (widgetIndex == WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) + static uint32_t GetStaffOrderBaseSprite(StaffType type) { - hide_gridlines(); - tool_cancel(); - gStaffDrawPatrolAreas = 0xFFFF; - gfx_invalidate_screen(); - } -} - -/** - * - * rct2: 0x006BDBE6 - */ -void window_staff_list_scrollgetsize(rct_window* w, int32_t scrollIndex, int32_t* width, int32_t* height) -{ - if (_windowStaffListHighlightedIndex != -1) - { - _windowStaffListHighlightedIndex = -1; - w->Invalidate(); - } - - *height = static_cast(StaffList.size()) * SCROLLABLE_ROW_HEIGHT; - auto i = *height - window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom - + window_staff_list_widgets[WIDX_STAFF_LIST_LIST].top + 21; - if (i < 0) - i = 0; - if (i < w->scrolls[0].v_top) - { - w->scrolls[0].v_top = i; - w->Invalidate(); - } - - *width = w->widgets[WIDX_STAFF_LIST_LIST].width() - 15; -} - -/** - * - * rct2: 0x006BDC9A - */ -void window_staff_list_scrollmousedown(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - int32_t i = screenCoords.y / SCROLLABLE_ROW_HEIGHT; - for (auto spriteIndex : StaffList) - { - if (i == 0) + switch (type) { - if (_quick_fire_mode) - { - auto staffFireAction = StaffFireAction(spriteIndex); - GameActions::Execute(&staffFireAction); - } - else - { - auto peep = GetEntity(spriteIndex); - if (peep != nullptr) - { - auto intent = Intent(WC_PEEP); - intent.putExtra(INTENT_EXTRA_PEEP, peep); - context_open_intent(&intent); - } - } - break; + case StaffType::Handyman: + return SPR_STAFF_ORDERS_SWEEPING; + case StaffType::Mechanic: + return SPR_STAFF_ORDERS_INSPECT_RIDES; + default: + return 0; } - - i--; } -} -/** - * - * rct2: 0x006BDC6B - */ -void window_staff_list_scrollmouseover(rct_window* w, int32_t scrollIndex, const ScreenCoordsXY& screenCoords) -{ - int32_t i; - - i = screenCoords.y / SCROLLABLE_ROW_HEIGHT; - if (i != _windowStaffListHighlightedIndex) + static uint32_t GetEntertainerCostumeSprite(PeepSpriteType type) { - _windowStaffListHighlightedIndex = i; - w->Invalidate(); + switch (type) + { + default: + case PeepSpriteType::EntertainerPanda: + return SPR_STAFF_COSTUME_PANDA; + case PeepSpriteType::EntertainerTiger: + return SPR_STAFF_COSTUME_TIGER; + case PeepSpriteType::EntertainerElephant: + return SPR_STAFF_COSTUME_ELEPHANT; + case PeepSpriteType::EntertainerRoman: + return SPR_STAFF_COSTUME_ROMAN; + case PeepSpriteType::EntertainerGorilla: + return SPR_STAFF_COSTUME_GORILLA; + case PeepSpriteType::EntertainerSnowman: + return SPR_STAFF_COSTUME_SNOWMAN; + case PeepSpriteType::EntertainerKnight: + return SPR_STAFF_COSTUME_KNIGHT; + case PeepSpriteType::EntertainerAstronaut: + return SPR_STAFF_COSTUME_ASTRONAUT; + case PeepSpriteType::EntertainerBandit: + return SPR_STAFF_COSTUME_BANDIT; + case PeepSpriteType::EntertainerSheriff: + return SPR_STAFF_COSTUME_SHERIFF; + case PeepSpriteType::EntertainerPirate: + return SPR_STAFF_COSTUME_PIRATE; + } } -} - -/** - * - * rct2: 0x006BD477 - */ -void window_staff_list_invalidate(rct_window* w) -{ - int32_t pressed_widgets = w->pressed_widgets - & ~((1LL << WIDX_STAFF_LIST_HANDYMEN_TAB) | (1LL << WIDX_STAFF_LIST_MECHANICS_TAB) - | (1LL << WIDX_STAFF_LIST_SECURITY_TAB) | (1LL << WIDX_STAFF_LIST_ENTERTAINERS_TAB)); - uint8_t tabIndex = _windowStaffListSelectedTab; - uint8_t widgetIndex = tabIndex + WIDX_STAFF_LIST_HANDYMEN_TAB; - - w->pressed_widgets = pressed_widgets | (1ULL << widgetIndex); - window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].text = StaffNamingConvention[tabIndex].action_hire; - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::Empty; - - if (tabIndex < 3) - { - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WindowWidgetType::ColourBtn; - auto spriteIdPalette = SPRITE_ID_PALETTE_COLOUR_1( - static_cast(staff_get_colour(static_cast(tabIndex)))); - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].image = spriteIdPalette | IMAGE_TYPE_TRANSPARENT - | SPR_PALETTE_BTN; - } - if (_quick_fire_mode) - w->pressed_widgets |= (1ULL << WIDX_STAFF_LIST_QUICK_FIRE); - else - w->pressed_widgets &= ~(1ULL << WIDX_STAFF_LIST_QUICK_FIRE); - - window_staff_list_widgets[WIDX_STAFF_LIST_BACKGROUND].right = w->width - 1; - window_staff_list_widgets[WIDX_STAFF_LIST_BACKGROUND].bottom = w->height - 1; - window_staff_list_widgets[WIDX_STAFF_LIST_TAB_CONTENT_PANEL].right = w->width - 1; - window_staff_list_widgets[WIDX_STAFF_LIST_TAB_CONTENT_PANEL].bottom = w->height - 1; - window_staff_list_widgets[WIDX_STAFF_LIST_TITLE].right = w->width - 2; - window_staff_list_widgets[WIDX_STAFF_LIST_CLOSE].left = w->width - 2 - 11; - window_staff_list_widgets[WIDX_STAFF_LIST_CLOSE].right = w->width - 2 - 11 + 10; - window_staff_list_widgets[WIDX_STAFF_LIST_LIST].right = w->width - 4; - window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom = w->height - 15; - window_staff_list_widgets[WIDX_STAFF_LIST_QUICK_FIRE].left = w->width - 77; - window_staff_list_widgets[WIDX_STAFF_LIST_QUICK_FIRE].right = w->width - 54; - window_staff_list_widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].left = w->width - 53; - window_staff_list_widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].right = w->width - 30; - window_staff_list_widgets[WIDX_STAFF_LIST_MAP].left = w->width - 29; - window_staff_list_widgets[WIDX_STAFF_LIST_MAP].right = w->width - 6; - window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].left = w->width - 155; - window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].right = w->width - 11; -} - -/** - * - * rct2: 0x006BD533 - */ -void window_staff_list_paint(rct_window* w, rct_drawpixelinfo* dpi) -{ - int32_t i; - uint8_t selectedTab; - - // Widgets - WindowDrawWidgets(w, dpi); - - selectedTab = _windowStaffListSelectedTab; - - // Handymen tab image - i = (selectedTab == 0 ? (w->list_information_type & ~3) : 0); - i += GetPeepAnimation(PeepSpriteType::Handyman).base_image + 1; - i |= SPRITE_ID_PALETTE_COLOUR_1(gStaffHandymanColour); - gfx_draw_sprite( - dpi, i, - w->windowPos - + ScreenCoordsXY{ (window_staff_list_widgets[WIDX_STAFF_LIST_HANDYMEN_TAB].left - + window_staff_list_widgets[WIDX_STAFF_LIST_HANDYMEN_TAB].right) - / 2, - window_staff_list_widgets[WIDX_STAFF_LIST_HANDYMEN_TAB].bottom - 6 }, - 0); - - // Mechanic tab image - i = (selectedTab == 1 ? (w->list_information_type & ~3) : 0); - i += GetPeepAnimation(PeepSpriteType::Mechanic).base_image + 1; - i |= SPRITE_ID_PALETTE_COLOUR_1(gStaffMechanicColour); - gfx_draw_sprite( - dpi, i, - w->windowPos - + ScreenCoordsXY{ (window_staff_list_widgets[WIDX_STAFF_LIST_MECHANICS_TAB].left - + window_staff_list_widgets[WIDX_STAFF_LIST_MECHANICS_TAB].right) - / 2, - window_staff_list_widgets[WIDX_STAFF_LIST_MECHANICS_TAB].bottom - 6 }, - 0); - - // Security tab image - i = (selectedTab == 2 ? (w->list_information_type & ~3) : 0); - i += GetPeepAnimation(PeepSpriteType::Security).base_image + 1; - i |= SPRITE_ID_PALETTE_COLOUR_1(gStaffSecurityColour); - gfx_draw_sprite( - dpi, i, - w->windowPos - + ScreenCoordsXY{ (window_staff_list_widgets[WIDX_STAFF_LIST_SECURITY_TAB].left - + window_staff_list_widgets[WIDX_STAFF_LIST_SECURITY_TAB].right) - / 2, - window_staff_list_widgets[WIDX_STAFF_LIST_SECURITY_TAB].bottom - 6 }, - 0); - - rct_drawpixelinfo sprite_dpi; - if (clip_drawpixelinfo( - &sprite_dpi, dpi, - w->windowPos - + ScreenCoordsXY{ window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].left + 1, - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].top + 1 }, - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].right - - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].left - 1, - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].bottom - - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].top - 1)) - { - // Entertainers tab image - i = (selectedTab == 3 ? (w->list_information_type & ~3) : 0); - i += GetPeepAnimation(PeepSpriteType::EntertainerElephant).base_image + 1; - gfx_draw_sprite(&sprite_dpi, i, { 0x0F, 0x17 }, 0); - } - - if (!(gParkFlags & PARK_FLAGS_NO_MONEY)) - { - auto ft = Formatter(); - ft.Add(gStaffWageTable[selectedTab]); - gfx_draw_string_left( - dpi, STR_COST_PER_MONTH, ft.Data(), COLOUR_BLACK, w->windowPos + ScreenCoordsXY{ w->width - 155, 0x20 }); - } - - if (selectedTab < 3) - { - gfx_draw_string_left( - dpi, STR_UNIFORM_COLOUR, nullptr, COLOUR_BLACK, - w->windowPos + ScreenCoordsXY{ 6, window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].top + 1 }); - } - - int32_t staffTypeStringId = StaffNamingConvention[selectedTab].plural; - // If the number of staff for a given type is 1, we use the singular forms of the names - if (StaffList.size() == 1) - { - staffTypeStringId = StaffNamingConvention[selectedTab].singular; - } - - auto ft = Formatter(); - ft.Add(StaffList.size()); - ft.Add(staffTypeStringId); - - gfx_draw_string_left( - dpi, STR_STAFF_LIST_COUNTER, ft.Data(), COLOUR_BLACK, - w->windowPos + ScreenCoordsXY{ 4, window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom + 2 }); -} - -/** rct2: 0x00992A08 */ -static constexpr const uint32_t staffOrderBaseSprites[] = { - SPR_STAFF_ORDERS_SWEEPING, - SPR_STAFF_ORDERS_INSPECT_RIDES, - 0, - 0, }; -static constexpr const uint32_t staffCostumeSprites[] = { - SPR_STAFF_COSTUME_PANDA, SPR_STAFF_COSTUME_TIGER, SPR_STAFF_COSTUME_ELEPHANT, SPR_STAFF_COSTUME_ROMAN, - SPR_STAFF_COSTUME_GORILLA, SPR_STAFF_COSTUME_SNOWMAN, SPR_STAFF_COSTUME_KNIGHT, SPR_STAFF_COSTUME_ASTRONAUT, - SPR_STAFF_COSTUME_BANDIT, SPR_STAFF_COSTUME_SHERIFF, SPR_STAFF_COSTUME_PIRATE, -}; - -/** - * - * rct2: 0x006BD785 - */ -void window_staff_list_scrollpaint(rct_window* w, rct_drawpixelinfo* dpi, int32_t scrollIndex) +rct_window* window_staff_list_open() { - auto dpiCoords = ScreenCoordsXY{ dpi->x, dpi->y }; - gfx_fill_rect( - dpi, { dpiCoords, dpiCoords + ScreenCoordsXY{ dpi->width - 1, dpi->height - 1 } }, ColourMapA[w->colours[1]].mid_light); - - // How much space do we have for the name and action columns? (Discount scroll area and icons.) - const int32_t nonIconSpace = w->widgets[WIDX_STAFF_LIST_LIST].width() - 15 - 68; - const int32_t nameColumnSize = nonIconSpace * 0.42; - const int32_t actionColumnSize = nonIconSpace * 0.58; - const int32_t actionOffset = w->widgets[WIDX_STAFF_LIST_LIST].right - actionColumnSize - 15; - - auto y = 0; - auto i = 0; - for (auto spriteIndex : StaffList) - { - if (y > dpi->y + dpi->height) - { - break; - } - - if (y + 11 >= dpi->y) - { - auto peep = GetEntity(spriteIndex); - if (peep == nullptr) - { - continue; - } - int32_t format = (_quick_fire_mode ? STR_RED_STRINGID : STR_BLACK_STRING); - - if (i == _windowStaffListHighlightedIndex) - { - gfx_filter_rect(dpi, 0, y, 800, y + (SCROLLABLE_ROW_HEIGHT - 1), FilterPaletteID::PaletteDarken1); - format = (_quick_fire_mode ? STR_LIGHTPINK_STRINGID : STR_WINDOW_COLOUR_2_STRINGID); - } - - auto ft = Formatter(); - peep->FormatNameTo(ft); - DrawTextEllipsised(dpi, { 0, y }, nameColumnSize, format, ft, COLOUR_BLACK); - - ft = Formatter(); - peep->FormatActionTo(ft); - DrawTextEllipsised(dpi, { actionOffset, y }, actionColumnSize, format, ft, COLOUR_BLACK); - - // True if a patrol path is set for the worker - if (gStaffModes[peep->StaffId] == StaffMode::Patrol) - { - gfx_draw_sprite(dpi, SPR_STAFF_PATROL_PATH, { nameColumnSize + 5, y }, 0); - } - - auto staffOrderIcon_x = nameColumnSize + 20; - if (peep->AssignedStaffType != StaffType::Entertainer) - { - auto staffOrders = peep->StaffOrders; - auto staffOrderSprite = staffOrderBaseSprites[_windowStaffListSelectedTab]; - - while (staffOrders != 0) - { - if (staffOrders & 1) - { - gfx_draw_sprite(dpi, staffOrderSprite, { staffOrderIcon_x, y }, 0); - } - staffOrders = staffOrders >> 1; - staffOrderIcon_x += 9; - // TODO: Remove sprite ID addition - staffOrderSprite++; - } - } - else - { - gfx_draw_sprite(dpi, staffCostumeSprites[EnumValue(peep->SpriteType) - 4], { staffOrderIcon_x, y }, 0); - } - } - - y += SCROLLABLE_ROW_HEIGHT; - i++; - } + return WindowFocusOrCreate(WC_STAFF_LIST, WW, WH, WF_10 | WF_RESIZABLE); } -static EntertainerCostume window_staff_list_get_random_entertainer_costume() +void WindowStaffListRefresh() { - auto result = EntertainerCostume::Panda; - EntertainerCostume costumeList[static_cast(EntertainerCostume::Count)]; - int32_t numCostumes = staff_get_available_entertainer_costume_list(costumeList); - if (numCostumes > 0) + auto* window = window_find_by_class(WC_STAFF_LIST); + if (window == nullptr) { - int32_t index = util_rand() % numCostumes; - result = costumeList[index]; + static_cast(window)->RefreshList(); } - return result; } diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index e5d99854c7..96465e6441 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1469,9 +1469,10 @@ void window_event_tool_update_call(rct_window* w, rct_widgetindex widgetIndex, c void window_event_tool_down_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) { - if (w->event_handlers != nullptr) - if (w->event_handlers->tool_down != nullptr) - w->event_handlers->tool_down(w, widgetIndex, screenCoords); + if (w->event_handlers == nullptr) + w->OnToolDown(widgetIndex, screenCoords); + else if (w->event_handlers->tool_down != nullptr) + w->event_handlers->tool_down(w, widgetIndex, screenCoords); } void window_event_tool_drag_call(rct_window* w, rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) @@ -1490,9 +1491,10 @@ void window_event_tool_up_call(rct_window* w, rct_widgetindex widgetIndex, const void window_event_tool_abort_call(rct_window* w, rct_widgetindex widgetIndex) { - if (w->event_handlers != nullptr) - if (w->event_handlers->tool_abort != nullptr) - w->event_handlers->tool_abort(w, widgetIndex); + if (w->event_handlers == nullptr) + w->OnToolAbort(widgetIndex); + else if (w->event_handlers->tool_abort != nullptr) + w->event_handlers->tool_abort(w, widgetIndex); } void window_event_unknown_0E_call(rct_window* w) diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index 874ca722ab..137b3e111a 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -684,6 +684,11 @@ void window_update_all(); void window_set_window_limit(int32_t value); +rct_window* window_bring_to_front(rct_window* w); +rct_window* window_bring_to_front_by_class(rct_windowclass cls); +rct_window* window_bring_to_front_by_class_with_flags(rct_windowclass cls, uint16_t flags); +rct_window* window_bring_to_front_by_number(rct_windowclass cls, rct_windownumber number); + rct_window* WindowCreate( std::unique_ptr&& w, rct_windowclass cls, ScreenCoordsXY pos, int32_t width, int32_t height, uint32_t flags); template::value>::type* = nullptr> @@ -696,6 +701,16 @@ T* WindowCreate(rct_windowclass cls, int32_t width, int32_t height, uint32_t fla { return static_cast(WindowCreate(std::make_unique(), cls, {}, width, height, flags | WF_AUTO_POSITION)); } +template::value>::type* = nullptr> +T* WindowFocusOrCreate(rct_windowclass cls, int32_t width, int32_t height, uint32_t flags = 0) +{ + auto* w = window_bring_to_front_by_class(cls); + if (w == nullptr) + { + w = WindowCreate(cls, width, height, flags); + } + return static_cast(w); +} rct_window* WindowCreate( const ScreenCoordsXY& pos, int32_t width, int32_t height, rct_window_event_list* event_handlers, rct_windowclass cls, @@ -726,11 +741,6 @@ void WindowInitScrollWidgets(rct_window* w); void window_update_scroll_widgets(rct_window* w); int32_t window_get_scroll_data_index(rct_window* w, rct_widgetindex widget_index); -rct_window* window_bring_to_front(rct_window* w); -rct_window* window_bring_to_front_by_class(rct_windowclass cls); -rct_window* window_bring_to_front_by_class_with_flags(rct_windowclass cls, uint16_t flags); -rct_window* window_bring_to_front_by_number(rct_windowclass cls, rct_windownumber number); - void window_push_others_right(rct_window* w); void window_push_others_below(rct_window* w1); diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index c16ac13584..fcd8dafc2e 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -160,6 +160,12 @@ struct rct_window virtual void OnScrollDraw(int32_t scrollIndex, rct_drawpixelinfo& dpi) { } + virtual void OnToolDown(rct_widgetindex widgetIndex, const ScreenCoordsXY& screenCoords) + { + } + virtual void OnToolAbort(rct_widgetindex widgetIndex) + { + } }; #ifdef __WARN_SUGGEST_FINAL_METHODS__ diff --git a/src/openrct2/management/Finance.cpp b/src/openrct2/management/Finance.cpp index dc6942d818..dd0cb1bddc 100644 --- a/src/openrct2/management/Finance.cpp +++ b/src/openrct2/management/Finance.cpp @@ -113,7 +113,7 @@ void finance_pay_wages() for (auto peep : EntityList(EntityListId::Peep)) { - finance_payment(gStaffWageTable[static_cast(peep->AssignedStaffType)] / 4, ExpenditureType::Wages); + finance_payment(GetStaffWage(peep->AssignedStaffType) / 4, ExpenditureType::Wages); } } @@ -244,7 +244,7 @@ void finance_update_daily_profit() // Staff costs for (auto peep : EntityList(EntityListId::Peep)) { - current_profit -= gStaffWageTable[static_cast(peep->AssignedStaffType)]; + current_profit -= GetStaffWage(peep->AssignedStaffType); } // Research costs diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 59667ba90c..d58df21b5a 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -44,18 +44,6 @@ #include #include -/** - * Monthly staff wages - * - * rct2: 0x00992A00 - */ -const money32 gStaffWageTable[static_cast(StaffType::Count)] = { - MONEY(50, 00), // Handyman - MONEY(80, 00), // Mechanic - MONEY(60, 00), // Security guard - MONEY(55, 00), // Entertainer -}; - // clang-format off const rct_string_id StaffCostumeNames[] = { STR_STAFF_OPTION_COSTUME_PANDA, @@ -2677,3 +2665,19 @@ void Staff::UpdateRideInspected(ride_id_t rideIndex) | RIDE_INVALIDATE_RIDE_LIST; } } + +money32 GetStaffWage(StaffType type) +{ + switch (type) + { + default: + case StaffType::Handyman: + return MONEY(50, 00); + case StaffType::Mechanic: + return MONEY(80, 00); + case StaffType::Security: + return MONEY(60, 00); + case StaffType::Entertainer: + return MONEY(55, 00); + } +} diff --git a/src/openrct2/peep/Staff.h b/src/openrct2/peep/Staff.h index b3edc6d80c..245af03882 100644 --- a/src/openrct2/peep/Staff.h +++ b/src/openrct2/peep/Staff.h @@ -52,8 +52,6 @@ enum class EntertainerCostume : uint8_t Count }; -extern const money32 gStaffWageTable[static_cast(StaffType::Count)]; - extern const rct_string_id StaffCostumeNames[static_cast(EntertainerCostume::Count)]; extern uint32_t gStaffPatrolAreas[(STAFF_MAX_COUNT + static_cast(StaffType::Count)) * STAFF_PATROL_AREA_SIZE]; @@ -75,6 +73,7 @@ bool staff_set_colour(StaffType staffType, colour_t value); uint32_t staff_get_available_entertainer_costumes(); int32_t staff_get_available_entertainer_costume_list(EntertainerCostume* costumeList); +money32 GetStaffWage(StaffType type); PeepSpriteType EntertainerCostumeToSprite(EntertainerCostume entertainerType); #endif