Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,28 @@ Radial Menu Used With qbx_Core :arrows_counterclockwise:

**Supports FontAwesome Icons!**
Get the name from [FontAwesome](https://fontawesome.com/v5.0/icons?d=gallery&p=2&s=brands,light,regular,solid&m=free) (v5) and use the icon's name in the config.lua for the icon (no `fa-` or `#` just the name like `arrow-right`)


## Blip Usage

## toggleBlip
```lua
exports.qbx_radialmenu:toggleBlip(category)
```
### Parameters
- `category` (string): The unique category of the blip to toggle


## registerToggleableBlip
```lua
exports.qbx_radialmenu:registerToggleableBlip(blipId, category)
```
### Parameters
- `blipId` (number): The blip handle to register
- `category` (string): The unique category of the blip

### Example
```lua
local blipHandle<const> = AddBlipForCoord(0.0, 0.0, 0.0)
exports.qbx_radialmenu:registerToggleableBlip(blipHandle, "shops")
```
220 changes: 207 additions & 13 deletions client/main.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
local config = require 'config.client'

local lastOutSideVehicle = false
local lastNearVehicle = false
local onVehicle = false
local lastNearPlayer = false
local vehicleFlipped = false

local toggleableBlips = {}
local categoryVisible = {}
local metadataLoaded = false

-----------------------
------- Events --------
-----------------------

lib.onCache('vehicle', function(vehicle)
if vehicle then
onVehicle = true
setupVehicleMenu(true)
else
onVehicle = false
setupVehicleMenu(false)
end
end)

if config.vehicleSeats then
lib.onCache('vehicle', function(vehicle)
if vehicle then
Expand Down Expand Up @@ -52,11 +72,27 @@ end
-----------------------

local function convert(tbl)
if tbl.onVehicleOnly and not onVehicle then
return
end
if tbl.outSideVehicleOnly and not lastOutSideVehicle then
return
end
if tbl.nearByVehicleOnly and not lastNearVehicle then
return
end
if tbl.nearByPlayerOnly and not lastNearPlayer then
return
end
if tbl.items then
local items = {}
for _, v in pairs(tbl.items) do
items[#items + 1] = convert(v)
local converted<const> = convert(v)
if converted then
items[#items + 1] = converted
end
end
if #items == 0 then return end

lib.registerRadial({
id = tbl.id .. 'Menu',
Expand Down Expand Up @@ -97,7 +133,11 @@ local function convert(tbl)
action()
end
end,
keepOpen = tbl.keepOpen
keepOpen = tbl.keepOpen,
onVehicleOnly = tbl.onVehicleOnly,
outSideVehicleOnly = tbl.outSideVehicleOnly,
nearByVehicleOnly = tbl.nearByVehicleOnly,
nearByPlayerOnly = tbl.nearByPlayerOnly
}
end

Expand All @@ -109,19 +149,32 @@ function setupVehicleMenu(seat)
menu = 'vehicleMenu'
}

local vehicleItems = {{
id = 'vehicle-flip',
label = locale('options.flip'),
icon = 'car-burst',
onSelect = function()
TriggerEvent('radialmenu:flipVehicle')
lib.hideRadial()
local vehicleItems = {}
if vehicleFlipped then
vehicleItems[#vehicleItems + 1] = {
id = 'vehicle-flip',
label = locale('options.flip'),
icon = 'car-burst',
onSelect = function()
TriggerEvent('radialmenu:flipVehicle')
lib.hideRadial()
end
}
end

if config.vehicleItems then
for i = 1, #config.vehicleItems do
vehicleItems[#vehicleItems + 1] = convert(config.vehicleItems[i])
end
}}
end

vehicleItems[#vehicleItems + 1] = convert(config.vehicleDoors)
if config.vehicleWindows then
vehicleItems[#vehicleItems + 1] = convert(config.vehicleWindows)
end

vehicleItems[#vehicleItems + 1] = convert(config.vehicleWindows)
if config.vehicleDoors then
vehicleItems[#vehicleItems + 1] = convert(config.vehicleDoors)
end

if config.enableExtraMenu then
vehicleItems[#vehicleItems + 1] = convert(config.vehicleExtras)
Expand All @@ -143,7 +196,10 @@ local function setupRadialMenu()
setupVehicleMenu()

for _, v in pairs(config.menuItems) do
lib.addRadialItem(convert(v))
local converted<const> = convert(v)
if converted then
lib.addRadialItem(converted)
end
end

if config.gangItems[QBX.PlayerData.gang.name] then
Expand Down Expand Up @@ -175,6 +231,29 @@ local function isEMS()
return QBX.PlayerData.job.type == 'ems' and QBX.PlayerData.job.onduty
end

local loadBlipPreferences<const> = function()
if metadataLoaded then return end

local playerData<const> = QBX.PlayerData
if playerData and playerData.metadata then
local blipPreferences = playerData.metadata.blipPreferences or {}

for category, isVisible in pairs(blipPreferences) do
categoryVisible[category] = isVisible

if toggleableBlips[category] then
for blipId, _ in pairs(toggleableBlips[category]) do
if DoesBlipExist(blipId) then
SetBlipAlpha(blipId, isVisible and 255 or 0)
end
end
end
end

metadataLoaded = true
end
end

-- Events
RegisterNetEvent('radialmenu:client:deadradial', function(isDead)
if isDead then
Expand Down Expand Up @@ -366,6 +445,7 @@ end)
-- Sets the metadata when the player spawns
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
setupRadialMenu()
loadBlipPreferences()
end)

RegisterNetEvent('QBCore:Client:OnJobUpdate', function(job)
Expand Down Expand Up @@ -397,6 +477,117 @@ RegisterNetEvent('QBCore:Client:OnGangUpdate', function(gang)
end
end)

local saveBlipPreferences<const> = function ()
TriggerServerEvent('radialmenu:server:saveBlipPreferences', categoryVisible)
end

---@param category string
local toggleBlipsForCategory<const> = function(category)
if not category then
lib.print.warn("No category provided for toggling blips.")
return
end
local toggledCount = 0
local blipCategoryName = string.gsub(category, "_", " ") -- Replaces underscores with spaces
blipCategoryName = blipCategoryName:sub(1,1):upper() .. blipCategoryName:sub(2) -- Capitalizes the first letter

if categoryVisible[category] == nil then
categoryVisible[category] = true -- Default to visible
else
categoryVisible[category] = not categoryVisible[category]
end
local isVisible<const> = categoryVisible[category]

if toggleableBlips[category] then
for blipId, _ in pairs(toggleableBlips[category]) do
if DoesBlipExist(blipId) then
if isVisible then
SetBlipAlpha(blipId, 255) -- Show blip
else
SetBlipAlpha(blipId, 0) -- Hide blip
end
toggledCount = toggledCount + 1
else
if toggleableBlips[category] then
toggleableBlips[category][blipId] = nil
end
end
end
end

saveBlipPreferences()

local status<const> = isVisible and locale('general.blip_shown') or locale('general.blip_hidden')
exports.qbx_core:Notify(("%s %s"):format(blipCategoryName, status), 'info')
return isVisible
end

---@param blipHandle number
---@param category string
local registerToggleableBlip<const> = function(blipHandle, category)
if not category then
lib.print.error(("No category provided when registering blipId: %s"):format(tostring(blipHandle)))
return
end
if not blipHandle then
lib.print.error(("No blipId provided for registration in category: %s"):format(category))
return
end

if DoesBlipExist(blipHandle) then
if not toggleableBlips[category] then
toggleableBlips[category] = {}
end
toggleableBlips[category][blipHandle] = true

if not metadataLoaded then
loadBlipPreferences()
end

local isCurrentlyVisible = categoryVisible[category]
if isCurrentlyVisible == nil then
isCurrentlyVisible = true -- default new categories/blips to visible
categoryVisible[category] = true
saveBlipPreferences()
end

if isCurrentlyVisible then
SetBlipAlpha(blipHandle, 255)
else
SetBlipAlpha(blipHandle, 0)
end
else
lib.print.warn(("Attempted to register non-existent blip %s for category: %s"):format(tostring(blipHandle), category))
end
end


CreateThread(function()
while true do
local outSideVehicle<const> = lib.getClosestVehicle(GetEntityCoords(cache.ped), 5.0, false) ~= nil
local nearByVehicle<const> = lib.getClosestVehicle(GetEntityCoords(cache.ped), 5.0, true) ~= nil
local closestPlayer<const>, _<const> = lib.getClosestPlayer(GetEntityCoords(cache.ped))
local nearPlayer<const> = closestPlayer ~= nil

local playerCoords<const> = GetEntityCoords(cache.ped)
local closestVehicle<const> = lib.getClosestVehicle(playerCoords, 3.0)
local flipableVehicle<const> = closestVehicle and not IsVehicleOnAllWheels(closestVehicle)

local outsideStatusChanged<const> = outSideVehicle ~= lastOutSideVehicle
local nearByVehicleChanged<const> = nearByVehicle ~= lastNearVehicle
local nearPlayerChanged<const> = nearPlayer ~= lastNearPlayer
local vehicleFlipStateChanged<const> = IsVehicleOnAllWheels(closestVehicle) ~= flipableVehicle
if outsideStatusChanged or nearByVehicleChanged or nearPlayerChanged or closestVehicle and not vehicleFlipStateChanged then
lastOutSideVehicle = outSideVehicle
lastNearVehicle = nearByVehicle
lastNearPlayer = nearPlayer
vehicleFlipped = flipableVehicle
setupRadialMenu()
end
Wait(1500)
end
end)

local function createQBExport(name, cb)
AddEventHandler(('__cfx_export_qb-radialmenu_%s'):format(name), function(setCB)
setCB(cb)
Expand All @@ -418,3 +609,6 @@ end

exports('RemoveOption', removeOption)
createQBExport('RemoveOption', removeOption)

exports('toggleBlip', toggleBlipsForCategory)
exports('registerToggleableBlip', registerToggleableBlip)
19 changes: 17 additions & 2 deletions config/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ return {
enableExtraMenu = true,
flipTime = 15000,

vehicleItems = {
{
id = 'quickgivevehkeys',
icon = 'key',
label = locale('options.quickgivekeys'),
serverEvent = 'qbx_vehiclekeys:server:quickgivekeys',

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outSideVehicleOnly = true,
nearByPlayerOnly = true
},
},

menuItems = {
{
id = 'citizen',
Expand All @@ -14,13 +25,15 @@ return {
id = 'givenum',
icon = 'address-book',
label = 'Give Contact Details',
event = 'qb-phone:client:GiveContactDetails'
event = 'qb-phone:client:GiveContactDetails',
nearByPlayerOnly = true
},
{
id = 'getintrunk',
icon = 'car',
label = 'Get In Trunk',
event = 'qb-trunk:client:GetIn'
event = 'qb-trunk:client:GetIn',
outSideVehicleOnly = true
},
{
id = 'cornerselling',
Expand Down Expand Up @@ -50,6 +63,7 @@ return {
icon = 'car-side',
label = 'Take Out Vehicle',
event = 'police:client:SetPlayerOutVehicle',
nearByVehicleOnly = true
},
{
id = 'stealPlayer',
Expand Down Expand Up @@ -366,6 +380,7 @@ return {
icon = 'eye-slash',
label = 'Show/Hide Meter',
event = 'qb-taxi:client:toggleMeter',
onVehicleOnly = true
},
{
id = 'togglemouse',
Expand Down
2 changes: 1 addition & 1 deletion fxmanifest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ game 'gta5'

description 'qbx_radialmenu'
repository 'https://github.com/Qbox-project/qbx_radialmenu'
version '0.1.0'
version '0.3.0'
ox_lib 'locale'


Expand Down
Loading