diff --git a/sonorancad/configuration/tablet_config.lua b/sonorancad/configuration/tablet_config.lua new file mode 100644 index 0000000..daba0cf --- /dev/null +++ b/sonorancad/configuration/tablet_config.lua @@ -0,0 +1,49 @@ +--[[ + +Sonoran Plugins + + tablet_config Plugin Configuration + + Put all needed configuration in this file. + +]] + +local config = { + enabled = true, + configVersion = "1.0", + pluginName = "tablet_config", -- name your plugin here + pluginAuthor = "Bushcowboy", -- author + requiresPlugins = {}, -- required plugins for this plugin to work, separated by commas + + -- Auto-hide and access settings + AutoHideOnVehicleExit = true, -- if true, the cad will automatically hide when the player exits a vehicle + AllowMiniCadOnFoot = false, -- if true, player can access the cad while on foot + + AccessRestrictions = { + RequireTabletItem = true, -- if true, player must have the tablet item to access the cad + TabletItemName = "sonoran_tablet", -- name of the tablet item + RestrictByJob = true, -- if true, player must have a job in the allowed jobs list to access the cad + RestrictByVehicle = false, -- if true, player must be in a vehicle in the allowed vehicles list to access the cad + AllowedJobs = { + "lspd", + "sheriff", + "ambulance", + "fire" + }, + AllowedVehicles = { + "police", + "police2", + "police3", + "police4", + "fbi", + "fbi2", + "ambulance", + "firetruk" + } + } + +} + +if config.enabled then + Config.RegisterPluginConfig(config.pluginName, config) +end \ No newline at end of file diff --git a/sonorancad/configuration/vehreg_config.dist.lua b/sonorancad/configuration/vehreg_config.dist.lua index 7f3e8e0..a96a4bc 100644 --- a/sonorancad/configuration/vehreg_config.dist.lua +++ b/sonorancad/configuration/vehreg_config.dist.lua @@ -6,13 +6,13 @@ local config = { enabled = false, - pluginName = "vehreg", -- name your plugin here + pluginName = "vehreg", -- name your plugin here pluginAuthor = "Jordan.#2139", -- author - configVersion = "1.3", + configVersion = "1.4", - reigsterCommand = "reg", -- Command to register car + reigsterCommand = "reg", -- Command to register car defaultRegExpire = '01/02/2030', -- The default date that all registrations will expire - defaultRegStatus = 'VALID', -- The default status that all registrations will have | MUST BE IN CAPS + defaultRegStatus = 'VALID', -- The default status that all registrations will have | MUST BE IN CAPS language = { notInVeh = "Player Not In Vehicle... Please Ensure You're In A Vehicle And Try Again!", @@ -20,7 +20,8 @@ local config = { plateAlrRegisted = "This plate has already been registered to another person", helpMsg = 'Register your current vehicle in CAD', noCharFound = "No character found. Please ensure you are logged in to a character.", - incompleteCharData = "Character data is incomplete. Please ensure you have all required data filled out in CAD. Unable to register vehicle.", + incompleteCharData = + "Character data is incomplete. Please ensure you have all required data filled out in CAD. Unable to register vehicle.", --[[ Placeholders: {{PLATE}} = The plate of the vehicle @@ -35,15 +36,18 @@ local config = { plateUid = "plate", typeUid = "type", modelUid = "model", + makeUid = "make", + yearUid = "year", statusUid = "status", expiresUid = "_imtoih149", }, customData = { - { - spawncode = "adder", + ["adder"] = { model = "Adder", + make = "Truffade", + year = 2013 }, - { + ["blista"] = { spawncode = "blista", model = "Blista", } diff --git a/sonorancad/submodules/vehreg/cl_vehreg.lua b/sonorancad/submodules/vehreg/cl_vehreg.lua index f30089d..1884ffa 100644 --- a/sonorancad/submodules/vehreg/cl_vehreg.lua +++ b/sonorancad/submodules/vehreg/cl_vehreg.lua @@ -28,10 +28,12 @@ CreateThread(function() Config.LoadPlugin("vehreg", function(pluginConfig) local realName, make, year if override then realName = override.model + make = override.make + year = override.year else realName = GetLabelText(displayCode) -- e.g. “Adder” end - TriggerServerEvent(GetCurrentResourceName() .. "::registerVeh", primary, plate, class, realName) + TriggerServerEvent(GetCurrentResourceName() .. "::registerVeh", primary, plate, class, realName, make, year) end end) TriggerEvent("chat:addSuggestion", "/" .. pluginConfig.reigsterCommand, diff --git a/sonorancad/submodules/vehreg/sv_vehreg.lua b/sonorancad/submodules/vehreg/sv_vehreg.lua index 2bd85ad..69da9fc 100644 --- a/sonorancad/submodules/vehreg/sv_vehreg.lua +++ b/sonorancad/submodules/vehreg/sv_vehreg.lua @@ -9,32 +9,17 @@ CreateThread(function() end return message end - RegisterNetEvent(GetCurrentResourceName() .. '::registerVeh', function(primary, plate, class, realName) - local source = source - exports['sonorancad']:registerApiType('NEW_RECORD', 'general') - exports['sonorancad']:registerApiType('GET_CHARACTERS', 'civilian') - exports['sonorancad']:performApiRequest({ - { - ['apiId'] = GetIdentifiers(source)[Config.primaryIdentifier] - } - }, 'GET_CHARACTERS', function(res, err) - if err == 404 then - TriggerClientEvent('chat:addMessage', source, { - color = { - 255, - 0, - 0 - }, - multiline = true, - args = { - '[CAD - ERROR] ', - pluginConfig.language.noApiId - } - }) - return; - else - res = json.decode(res) - if not res or type(res) ~= 'table' then + RegisterNetEvent(GetCurrentResourceName() .. '::registerVeh', + function(primary, plate, class, realName, make, year) + local source = source + exports['sonorancad']:registerApiType('NEW_RECORD', 'general') + exports['sonorancad']:registerApiType('GET_CHARACTERS', 'civilian') + exports['sonorancad']:performApiRequest({ + { + ['apiId'] = GetIdentifiers(source)[Config.primaryIdentifier] + } + }, 'GET_CHARACTERS', function(res, err) + if err == 404 then TriggerClientEvent('chat:addMessage', source, { color = { 255, @@ -44,12 +29,96 @@ CreateThread(function() multiline = true, args = { '[CAD - ERROR] ', - pluginConfig.language.noCharFound or "No character found. Please ensure you are logged in to a character." + pluginConfig.language.noApiId } }) return; + else + res = json.decode(res) + if not res or type(res) ~= 'table' then + TriggerClientEvent('chat:addMessage', source, { + color = { + 255, + 0, + 0 + }, + multiline = true, + args = { + '[CAD - ERROR] ', + pluginConfig.language.noCharFound or + "No character found. Please ensure you are logged in to a character." + } + }) + return; + end + if #res < 1 then + TriggerClientEvent('chat:addMessage', source, { + color = { + 255, + 0, + 0 + }, + multiline = true, + args = { + '[CAD - ERROR] ', + pluginConfig.language.noCharFound or + "No character found. Please ensure you are logged in to a character." + } + }) + return; + end + for iterator, table in pairs(res[1].sections) do + if table.category == 0 then + for iterator, field in pairs(table.fields) do + civData[field.uid] = field.value + end + end + end end - if #res < 1 then + end) + Citizen.Wait(1000) + if not pluginConfig.recordData then + notSetConfig = true + pluginConfig.recordData = { + colorUid = "color", + plateUid = "plate", + typeUid = "type", + modelUid = "model", + makeUid = "make", + yearUid = "year", + statusUid = "status", + expiresUid = "_imtoih149", + } + warnLog( + 'Record data not found in configuration. Using default values. Please update your configuration using the vehreg_config.dist.lua file located in the configuration folder') + end + if notSetConfig then + warnLog( + 'Record data not found in configuration. Using default values. Please update your configuration using the vehreg_config.dist.lua file located in the configuration folder') + end + local replaceValues = { + [pluginConfig.recordData.colorUid] = primary, + [pluginConfig.recordData.plateUid] = plate, + [pluginConfig.recordData.typeUid] = class, + [pluginConfig.recordData.modelUid] = realName, + [pluginConfig.recordData.makeUid] = make, + [pluginConfig.recordData.yearUid] = year, + [pluginConfig.recordData.statusUid] = pluginConfig.defaultRegStatus, + [pluginConfig.recordData.expiresUid] = pluginConfig.defaultRegExpire + } + for k, v in pairs(civData) do + replaceValues[k] = v + end + exports['sonorancad']:performApiRequest({ + { + ['user'] = GetIdentifiers(source)[Config.primaryIdentifier], + ['useDictionary'] = true, + ['recordTypeId'] = 5, + ['replaceValues'] = replaceValues + } + }, 'NEW_RECORD', function(res) + res = tostring(res) + if string.find(res, 'taken') ~= nil then TriggerClientEvent('chat:addMessage', source, { color = { 255, @@ -59,90 +128,30 @@ CreateThread(function() multiline = true, args = { '[CAD - ERROR] ', - pluginConfig.language.noCharFound or "No character found. Please ensure you are logged in to a character." + pluginConfig.language.plateAlrRegisted } }) - return; - end - for iterator, table in pairs(res[1].sections) do - if table.category == 0 then - for iterator, field in pairs(table.fields) do - civData[field.uid] = field.value - end - end - end - end - end) - Citizen.Wait(1000) - if not pluginConfig.recordData then - notSetConfig = true - pluginConfig.recordData = { - colorUid = "color", - plateUid = "plate", - typeUid = "type", - modelUid = "model", - statusUid = "status", - expiresUid = "_imtoih149", - } - warnLog('Record data not found in configuration. Using default values. Please update your configuration using the vehreg_config.dist.lua file located in the configuration folder') - end - if notSetConfig then - warnLog('Record data not found in configuration. Using default values. Please update your configuration using the vehreg_config.dist.lua file located in the configuration folder') - end - local replaceValues = { - [pluginConfig.recordData.colorUid] = primary, - [pluginConfig.recordData.plateUid] = plate, - [pluginConfig.recordData.typeUid] = class, - [pluginConfig.recordData.modelUid] = realName, - [pluginConfig.recordData.statusUid] = pluginConfig.defaultRegStatus, - [pluginConfig.recordData.expiresUid] = pluginConfig.defaultRegExpire - } - for k, v in pairs(civData) do - replaceValues[k] = v - end - exports['sonorancad']:performApiRequest({ - { - ['user'] = GetIdentifiers(source)[Config.primaryIdentifier], - ['useDictionary'] = true, - ['recordTypeId'] = 5, - ['replaceValues'] = replaceValues - } - }, 'NEW_RECORD', function(res) - res = tostring(res) - if string.find(res, 'taken') ~= nil then - TriggerClientEvent('chat:addMessage', source, { - color = { - 255, - 0, - 0 - }, - multiline = true, - args = { - '[CAD - ERROR] ', - pluginConfig.language.plateAlrRegisted + else + local placeHolders = { + ['{{PLATE}}'] = plate, + ['{{FIRST}}'] = civData.first, + ['{{LAST}}'] = civData.last } - }) - else - local placeHolders = { - ['{{PLATE}}'] = plate, - ['{{FIRST}}'] = civData.first, - ['{{LAST}}'] = civData.last - } - TriggerClientEvent('chat:addMessage', source, { - color = { - 0, - 255, - 0 - }, - multiline = true, - args = { - '[CAD - SUCCESS] ', - placeholderReplace(pluginConfig.language.successReg, placeHolders) - } - }) - end + TriggerClientEvent('chat:addMessage', source, { + color = { + 0, + 255, + 0 + }, + multiline = true, + args = { + '[CAD - SUCCESS] ', + placeholderReplace(pluginConfig.language.successReg, placeHolders) + } + }) + end + end) end) - end) end end) end) diff --git a/sonorancad/version.json b/sonorancad/version.json index 2ec3742..5b67a8c 100644 --- a/sonorancad/version.json +++ b/sonorancad/version.json @@ -104,7 +104,7 @@ "requiresPlugins": [] }, "vehreg": { - "version": "1.3", + "version": "1.4", "requiresPlugins": [] }, "wraithv2": { diff --git a/tablet/cl_main.lua b/tablet/cl_main.lua index 5601c36..3dddb16 100644 --- a/tablet/cl_main.lua +++ b/tablet/cl_main.lua @@ -7,6 +7,10 @@ isMiniVisible = false -- Debugging Information isDebugging = true +TabletConfig = nil +FrameworkConfig = nil +Framework = nil + function DebugMessage(message, module) if not isDebugging then return end if module ~= nil then message = "[" .. module .. "] " .. message end @@ -14,8 +18,10 @@ function DebugMessage(message, module) end -- Initialization Procedure -Citizen.CreateThread(function() +CreateThread(function() Wait(1000) + -- Request framework configuration from server + TriggerServerEvent("SonoranCAD::requestConfig") -- Set Default Module Sizes InitModuleSize("cad") InitModuleSize("hud") @@ -37,6 +43,38 @@ Citizen.CreateThread(function() TriggerServerEvent("SonoranCAD::mini:CallSync_S") + -- Vehicle Exit/Enter Detection for Auto-Hide Mini-CAD + if TabletConfig.AutoHideOnVehicleExit then + local wasInVehicle = false + local miniCadWasVisible = false + + CreateThread(function() + while true do + local playerPed = GetPlayerPed(-1) + local isInVehicle = IsPedInAnyVehicle(playerPed, false) + + -- Check if player just exited a vehicle + if wasInVehicle and not isInVehicle then + if isMiniVisible then + miniCadWasVisible = true + DisplayModule("hud", false) + DebugMessage("Auto-hiding mini-CAD on vehicle exit") + end + -- Check if player just entered a vehicle + elseif not wasInVehicle and isInVehicle then + if miniCadWasVisible then + DisplayModule("hud", true) + miniCadWasVisible = false + DebugMessage("Auto-showing mini-CAD on vehicle enter") + end + end + + wasInVehicle = isInVehicle + Wait(50) + end + end) + end + -- Disable Controls Loop while true do if nuiFocused then -- Disable controls while NUI is focused. @@ -45,17 +83,15 @@ Citizen.CreateThread(function() DisableControlAction(0, 142, nuiFocused) -- MeleeAttackAlternate DisableControlAction(0, 106, nuiFocused) -- VehicleMouseControlOverride end - Citizen.Wait(0) -- Yield until next frame. + Wait(0) -- Yield until next frame. end end) function InitModuleSize(module) - -- Check if the size of the specified module is already configured. local moduleWidth = GetResourceKvpString(module .. "width") local moduleHeight = GetResourceKvpString(module .. "height") if moduleWidth ~= nil and moduleHeight ~= nil then DebugMessage("retrieving saved presets", module) - -- Send message to NUI to resize the specified module. SetModuleSize(module, moduleWidth, moduleHeight) SendNUIMessage({ type = "refresh", @@ -68,7 +104,6 @@ function InitModuleConfig(module) local moduleMaxRows = GetResourceKvpString(module .. "maxrows") if moduleMaxRows ~= nil then DebugMessage("retrieving config presets", module) - -- Send messsage to NUI to update config of specified module. SetModuleConfigValue(module, "maxrows", moduleMaxRows) SendNUIMessage({ type = "refresh", @@ -163,7 +198,11 @@ RegisterNetEvent("SonoranCAD::mini:OpenMini:Return") AddEventHandler('SonoranCAD::mini:OpenMini:Return', function(authorized, ident) myident = ident if authorized then - DisplayModule("hud", true) + if not isMiniVisible then + DisplayModule("hud", true) + else + DisplayModule("hud", false) + end if not GetResourceKvpString("shownTutorial") then ShowHelpMessage() SetResourceKvp("shownTutorial", "yes") @@ -186,9 +225,68 @@ function ShowHelpMessage() PrintChatMessage("Keybinds: Attach/Detach [K], Details [L], Previous/Next [LEFT/RIGHT], changable in settings!") end +function IsInWhitelistedVehicle() + local ped = PlayerPedId() + if not IsPedInAnyVehicle(ped, false) then return false end + local veh = GetVehiclePedIsIn(ped, false) + if veh and veh ~= 0 then + local model = GetEntityModel(veh) + for _, allowed in ipairs(TabletConfig.AccessRestrictions.AllowedVehicles or {}) do + if model == GetHashKey(allowed) then + return true + end + end + end + return false +end + +function CheckJobRestriction() + local jobAllowed = true + if TabletConfig.AccessRestrictions.RestrictByJob then + jobAllowed = false + local playerJob = nil + + -- Check if framework is initialized + if FrameworkConfig.usingQBCore then + local Player = Framework.Functions.GetPlayerData() + playerJob = Player.job.name + else + local xPlayer = Framework.GetPlayerData() + playerJob = xPlayer.job.name + end + + if playerJob then + for _, allowedJob in pairs(TabletConfig.AccessRestrictions.AllowedJobs) do + if playerJob == allowedJob then + jobAllowed = true + break + end + end + end + end + + local vehicleAllowed = true + if TabletConfig.AccessRestrictions.RestrictByVehicle then + vehicleAllowed = IsInWhitelistedVehicle() + end + + return jobAllowed and vehicleAllowed +end + -- Mini Module Commands RegisterCommand("minicad", function(source, args, rawCommand) - TriggerServerEvent("SonoranCAD::mini:OpenMini") + if not CheckJobRestriction() then + PrintChatMessage("You do not have permission to access the Mini-CAD.") + return + end + + local ped = PlayerPedId() + local inVehicle = IsPedInAnyVehicle(ped, false) + if TabletConfig.AllowMiniCadOnFoot or inVehicle then + TriggerServerEvent("SonoranCAD::mini:OpenMini") + else + PrintChatMessage("You must be in a vehicle to access the Mini-CAD.") + end end, false) RegisterKeyMapping('minicad', 'Mini CAD', 'keyboard', '') @@ -201,7 +299,7 @@ end, false) RegisterKeyMapping('minicadp', 'Previous Call', 'keyboard', 'LEFT') RegisterCommand("minicada", function(source, args, rawCommand) - print("ismini "..tostring(isMiniVisible)) + print("attach") if not isMiniVisible then return end SendNUIMessage({ type = "command", key="attach" }) end, false) @@ -243,14 +341,25 @@ TriggerEvent('chat:addSuggestion', '/minicadrows', "Specify max number of call n { name="rows", help="any number (default 10)" } }) + -- CAD Module Commands RegisterCommand("showcad", function(source, args, rawCommand) + if not CheckJobRestriction() then + PrintChatMessage("You do not have permission to access the CAD Tablet.") + return + end DisplayModule("cad", true) toggleTabletDisplay(true) SetFocused(true) end, false) RegisterKeyMapping('showcad', 'CAD Tablet', 'keyboard', '') +RegisterNetEvent("SonoranCAD::showcad", function() + DisplayModule("cad", true) + toggleTabletDisplay(true) + SetFocused(true) +end) + TriggerEvent('chat:addSuggestion', '/cadsize', "Resize CAD to specific width and height in pixels. Default is 1100x510", { { name="Width", help="Width in pixels" }, { name="Height", help="Height in pixels" } }) @@ -367,8 +476,8 @@ AddEventHandler('onClientResourceStart', function(resourceName) --When resource TriggerServerEvent("sonoran:tablet:forceCheckApiId") end) -RegisterNetEvent("SonoranCAD::Tablet::ApiIdNotLinked") -AddEventHandler('SonoranCAD::Tablet::ApiIdNotLinked', function() +RegisterNetEvent("sonoran:tablet:apiIdNotFound") +AddEventHandler('sonoran:tablet:apiIdNotFound', function() SendNUIMessage({ type = "regbar" }) @@ -379,8 +488,8 @@ AddEventHandler("sonoran:tablet:apiIdFound", function() isRegistered = true end) -RegisterNUICallback('SetAPIInformation', function(data,cb) - TriggerServerEvent("SonoranCAD::Tablet::SetApiData", data.session, data.username) +RegisterNUICallback('SetAPIData', function(data,cb) + TriggerServerEvent("sonoran:tablet:setApiId", data.session, data.username) TriggerServerEvent("sonoran:tablet:forceCheckApiId") cb(true) end) @@ -392,4 +501,25 @@ end) RegisterNetEvent("sonoran:tablet:failed") AddEventHandler("sonoran:tablet:failed", function(message) errorLog("Failed to set API ID: "..tostring(message)) -end) \ No newline at end of file +end) + +RegisterNetEvent("SonoranCAD::receiveConfig") +AddEventHandler("SonoranCAD::receiveConfig", function(frameworkConfig, tabletConfig) + FrameworkConfig = frameworkConfig + TabletConfig = tabletConfig + + if isDebugging then + print("Framework Configuration received:") + print("Using QBCore: " .. tostring(FrameworkConfig.usingQBCore)) + for key, value in pairs(FrameworkConfig) do + print(key .. ": " .. tostring(value)) + end + end + if FrameworkConfig.usingQBCore then + Framework = exports['qb-core']:GetCoreObject() + print("Framework initialized: QBCore") + else + Framework = exports.es_extended:getSharedObject() + print("Framework initialized: ESX") + end +end) diff --git a/tablet/fxmanifest.lua b/tablet/fxmanifest.lua index a5aca96..bd0ce65 100644 --- a/tablet/fxmanifest.lua +++ b/tablet/fxmanifest.lua @@ -17,5 +17,6 @@ files { 'html/index.html', 'html/style.css', 'html/reset.css', - "html/script.js" -} \ No newline at end of file + "html/script.js", + "html/tablet.png" +} diff --git a/tablet/sv_main.lua b/tablet/sv_main.lua index 9a1d3b9..af86775 100644 --- a/tablet/sv_main.lua +++ b/tablet/sv_main.lua @@ -1,5 +1,15 @@ CallCache = {} EmergencyCache = {} +FrameworkConfig = exports.sonorancad:GetPluginConfig("frameworksupport") +TabletConfig = exports.sonorancad:GetPluginConfig("tablet_config") + +Framework = nil + +if FrameworkConfig.usingQBCore then + Framework = exports['qb-core']:GetCoreObject() +else + Framework = exports.es_extended:getSharedObject() +end CreateThread(function() while GetResourceState("sonorancad") ~= "started" do @@ -12,7 +22,7 @@ CreateThread(function() return function() i = i + 1 local iCopy = i - Citizen.CreateThread(function() + CreateThread(function() Wait(time) -- invoke if 'i' hasn't been incremented since this thread was created if i == iCopy then fn() end @@ -92,10 +102,10 @@ CreateThread(function() if ident ~= nil then local data = {callId = callId, units = {ident.data.apiIds[1]}, serverId = GetConvar("sonoran_serverId", 1)} exports["sonorancad"]:performApiRequest({data}, "ATTACH_UNIT", function(res) - --print("Attach OK: " .. tostring(res)) + print("Attach OK: " .. tostring(res)) end) else - --print("Unable to attach... if api id is set properly, try relogging into cad.") + print("Unable to attach... if api id is set properly, try relogging into cad.") end end) @@ -105,11 +115,80 @@ CreateThread(function() if ident ~= nil then local data = {callId = callId, units = {ident.data.apiIds[1]}, serverId = GetConvar("sonoran_serverId", 1)} exports["sonorancad"]:performApiRequest({data}, "DETACH_UNIT", function(res) - --print("Detach OK: " .. tostring(res)) + print("Detach OK: " .. tostring(res)) end) else - --print("Unable to detach... if api id is set properly, try relogging into cad.") + print("Unable to detach... if api id is set properly, try relogging into cad.") end end) + + -- Send requestConfig configuration to client + RegisterServerEvent("SonoranCAD::requestConfig") + AddEventHandler("SonoranCAD::requestConfig", function() + TriggerClientEvent("SonoranCAD::receiveConfig", source, FrameworkConfig, TabletConfig) + end) end) +-- Server-side job restriction check function +function CheckJobRestrictionServer(source) + if not TabletConfig.AccessRestrictions.RestrictByJob then + return true + end + + local playerJob = nil + if FrameworkConfig.usingQBCore then + local Player = Framework.Functions.GetPlayer(source) + if Player then + playerJob = Player.PlayerData.job.name + end + elseif not FrameworkConfig.usingQBCore then + local xPlayer = Framework.GetPlayerFromId(source) + if xPlayer then + playerJob = xPlayer.job.name + end + end + + if playerJob then + for _, allowedJob in pairs(TabletConfig.AccessRestrictions.AllowedJobs) do + if playerJob == allowedJob then + return true + end + end + end + + return false +end + +if TabletConfig.AccessRestrictions.RequireTabletItem and FrameworkConfig.usingQBCore then + Framework.Functions.CreateUseableItem(TabletConfig.AccessRestrictions.TabletItemName, function(source, item) + if CheckJobRestrictionServer(source) then + TriggerClientEvent("SonoranCAD::showcad", source) + else + TriggerClientEvent('chatMessage', source, "System", {255, 0, 0}, "You do not have permission to use the CAD Tablet.") + end + end) +elseif TabletConfig.AccessRestrictions.RequireTabletItem and FrameworkConfig.usingQBCore then + exports.qbx_core:CreateUseableItem(TabletConfig.AccessRestrictions.TabletItemName, function(source, item) + if CheckJobRestrictionServer(source) then + TriggerClientEvent("SonoranCAD::showcad", source) + else + TriggerClientEvent('chatMessage', source, "System", {255, 0, 0}, "You do not have permission to use the CAD Tablet.") + end + end) +elseif TabletConfig.AccessRestrictions.RequireTabletItem and not FrameworkConfig.usingQBCore then + Framework.RegisterUsableItem(TabletConfig.AccessRestrictions.TabletItemName, function(source, item) + if CheckJobRestrictionServer(source) then + TriggerClientEvent("SonoranCAD::showcad", source) + else + TriggerClientEvent('chatMessage', source, "System", {255, 0, 0}, "You do not have permission to use the CAD Tablet.") + end + end) +elseif not TabletConfig.AccessRestrictions.RequireTabletItem or FrameworkConfig == nil then + RegisterCommand("showcad", function(source, args, rawCommand) + if CheckJobRestrictionServer(source) then + TriggerClientEvent("SonoranCAD::showcad", source) + else + TriggerClientEvent('chatMessage', source, "System", {255, 0, 0}, "You do not have permission to use the CAD Tablet.") + end + end, false) +end