{"slug":"databindings/uiapps/hud_quick_select/hud_quick_select","category":"databindings","title":"Hud quick select","kind":"code","intro":"","body":"--[[\n--------------------------------------------------------------------------------------------------------------------------------------------\n--                                                                                                                                        --\n--                                                                EVENTS SYSTEM                                                           --\n--                                                Requires using dataview by Gottfriedleibniz                                             --\n--                                                                                                                                        --\n--------------------------------------------------------------------------------------------------------------------------------------------\n]]\n\nlocal open, fireOpen = false, false\nlocal currentWheel = nil\nlocal currentItem, previousItem = 0, 0\n\nlocal PARAMETERS <const> = {\n    -- Wheels\n    [`WEAPON_WHEEL`]              = \"WEAPON_WHEEL\",\n    [`SATCHEL_ITEM_WHEEL`]        = \"SATCHEL_ITEM_WHEEL\",\n    [`SATCHEL_HORSE_ITEM_WHEEL`]  = \"SATCHEL_HORSE_ITEM_WHEEL\",\n    [`FISHING_WHEEL`]             = \"FISHING_WHEEL\",\n\n    -- Actions\n    [`FLOW_LAUNCHED`]             = \"FLOW_LAUNCHED\",\n    [`PUT_AWAY_FISHING_ROD`]      = \"PUT_AWAY_FISHING_ROD\",\n\n    -- Slots\n    [`DUAL_WIELD`]                = \"WEAPONS_DUAL_WIELD\",\n    [`WEAPONS_LONGARMS_AND_BOWS`] = \"WEAPONS_LONGARMS_AND_BOWS\",\n    [`WEAPONS_MELEE_NO_UNARMED`]  = \"WEAPONS_MELEE_NO_UNARMED\",\n    [`OFFHAND`]                   = \"WEAPONS_OFFHAND\",\n    [`WEAPONS_SIDEARMS_LEFT`]     = \"WEAPONS_SIDEARMS_LEFT\",\n    [`WEAPONS_SIDEARMS_RIGHT`]    = \"WEAPONS_SIDEARMS_RIGHT\",\n    [`WEAPONS_SIDEARMS`]          = \"WEAPONS_SIDEARMS\",\n    [`WEAPONS_THROWN`]            = \"WEAPONS_THROWN\",\n    [`WEAPONS_UNARMED`]           = \"WEAPONS_UNARMED\",\n}\n\nlocal function getState(index, parameter)\n    return {\n        open = open,                 -- Whether the UI is currently open\n        index = index,               -- The UI index of the slot or item\n        parameter = parameter,       -- The parameter sent by the UI, such as the item or type\n        wheel = currentWheel,        -- The currently focused wheel\n        item = currentItem,          -- The currently focused item (0 if none, or the item hash)\n        previousItem = previousItem, -- The previously focused item (0 if none, or the item hash)\n    }\nend\n\nCreateThread(function()\n    while true do\n        -- Feel free to tweak if needed, 0 is also a valid option but not needed\n        Wait(10)\n\n        -- Update the currently selected item while (and only while) the wheel is open\n        if open then\n            -- HUD::_HUD_GET_INVENTORY_WHEEL_CURRENTLY_HIGHLIGHTED\n            currentItem = Citizen.InvokeNative(0x9C409BBC492CB5B1) or 0\n            previousItem = currentItem ~= 0 and currentItem or previousItem\n        end\n\n        -- Bulk process all pending event in this thread tick instead of one at a time\n        while EventsUiIsPending(`hud_quick_select`) do\n            local data = DataView.ArrayBuffer(8 * 4)\n\n            if (Citizen.InvokeNative(0x90237103F27F7937, `hud_quick_select`, data:Buffer()) ~= 0) then -- EVENTS_UI_PEEK_MESSAGE\n                local event = data:GetInt32(0)\n                local index = data:GetInt32(8)\n                local parameter = data:GetInt32(16)\n\n                parameter = PARAMETERS[parameter] or parameter\n\n                if event == `ITEM_FOCUSED` then\n                    if parameter == \"WEAPON_WHEEL\" then\n                        currentWheel = parameter\n                        TriggerEvent(\"wheel:focus_weapon\", getState(index, parameter))\n                    elseif parameter == \"SATCHEL_ITEM_WHEEL\" then\n                        currentWheel = parameter\n                        TriggerEvent(\"wheel:focus_item\", getState(index, parameter))\n                    elseif parameter == \"SATCHEL_HORSE_ITEM_WHEEL\" then\n                        currentWheel = parameter\n                        TriggerEvent(\"wheel:focus_horse\", getState(index, parameter))\n                    elseif parameter == \"FISHING_WHEEL\" then\n                        currentWheel = parameter\n                        TriggerEvent(\"wheel:focus_fishing\", getState(index, parameter))\n                    else\n                        TriggerEvent(\"wheel:focus_slot\", getState(index, parameter))\n                    end\n                elseif event == `ITEM_UNFOCUSED` then\n                    if parameter == \"WEAPON_WHEEL\" then\n                        TriggerEvent(\"wheel:unfocus_weapon\", getState(index, parameter))\n                        previousItem = 0\n                    elseif parameter == \"SATCHEL_ITEM_WHEEL\" then\n                        TriggerEvent(\"wheel:unfocus_item\", getState(index, parameter))\n                        previousItem = 0\n                    elseif parameter == \"SATCHEL_HORSE_ITEM_WHEEL\" then\n                        TriggerEvent(\"wheel:unfocus_horse\", getState(index, parameter))\n                        previousItem = 0\n                    elseif parameter == \"FISHING_WHEEL\" then\n                        TriggerEvent(\"wheel:unfocus_fishing\", getState(index, parameter))\n                        previousItem = 0\n                    else\n                        TriggerEvent(\"wheel:unfocus_slot\", getState(index, parameter))\n                    end\n\n                    -- Prevents the item attribute preview (RPG stats) from sticking\n                    StopItemPreview()\n                elseif event == `ITEM_SELECTED` then\n                    if parameter == \"FLOW_LAUNCHED\" then\n                        open, fireOpen = true, true\n                    elseif parameter == \"SATCHEL_HORSE_ITEM_WHEEL\" then\n                        TriggerEvent(\"wheel:action_horse_item\", getState(index, parameter))\n                    elseif parameter == \"PUT_AWAY_FISHING_ROD\" then\n                        TriggerEvent(\"wheel:action_put_away\", getState(index, parameter))\n\n                        -- The UI doesn't automatically close after this action\n                        CloseUiappByHash(`hud_quick_select`)\n                    else\n                        TriggerEvent(\"wheel:action_slot\", getState(index, parameter))\n                    end\n                end\n            end\n\n            EventsUiPopMessage(`hud_quick_select`)\n        end\n\n        -- Only fire the opened event once\n        if fireOpen then\n            TriggerEvent(\"wheel:opened\", getState())\n            fireOpen = false\n        end\n\n        -- Check if we are closed and properly fire the closed event, as well as reset the state\n        if open and IsControlReleased(0, `INPUT_OPEN_WHEEL_MENU`) then\n            TriggerEvent(\"wheel:closed\", getState())\n\n            open, fireOpen = false, false\n            currentWheel = nil\n            currentItem, previousItem = 0, 0\n        end\n    end\nend)\n\n--[[\n--------------------------------------------------------------------------------------------------------------------------------------------\n--                                                                                                                                        --\n--                                                                EXAMPLE USAGE                                                           --\n--                                                                                                                                        --\n--------------------------------------------------------------------------------------------------------------------------------------------\n]]\n\nAddEventHandler(\"wheel:opened\", function(data)\n    -- Note: Due to UI bugs (yes, multiple), the starting wheel isn't always accurate\n    print(\"Wheel Opened\", json.encode(data))\nend)\n\nAddEventHandler(\"wheel:closed\", function(data)\n    print(\"Wheel Closed\", json.encode(data))\nend)\n\nAddEventHandler(\"wheel:action_horse_item\", function(data)\n    print(\"Select Horse Item\", json.encode(data))\nend)\n\nAddEventHandler(\"wheel:action_put_away\", function(data)\n    print(\"Put Away Fishing Rod\", json.encode(data))\nend)\n\nAddEventHandler(\"wheel:action_slot\", function(data)\n    print(\"Select Slot\", json.encode(data))\nend)\n\n-- Omitted unfocus and focus events for brevity, but they work the same as the above\n-- wheel:focus_weapon, wheel:focus_item, wheel:focus_horse, wheel:focus_fishing\n-- wheel:focus_slot, wheel:unfocus_weapon, wheel:unfocus_item, wheel:unfocus_horse\n-- wheel:unfocus_fishing, wheel:unfocus_slot\n","tables":[],"sourceUrl":"https://github.com/femga/rdr3_discoveries/blob/477aaaccadb7f0c042286611d9939009636cff12/databindings/uiapps/hud_quick_select/hud_quick_select.lua","rows":[]}