function Framework.Client.ShowTextUI(text) if (Config.DrawText == "auto" and GetResourceState("jg-textui") == "started") or Config.DrawText == "jg-textui" then exports["jg-textui"]:DrawText(text) elseif (Config.DrawText == "auto" and GetResourceState("okokTextUI") == "started") or Config.DrawText == "okokTextUI" then exports["okokTextUI"]:Open(text, "lightblue", "left") elseif (Config.DrawText == "auto" and GetResourceState("ps-ui") == "started") or Config.DrawText == "ps-ui" then exports["ps-ui"]:DisplayText(text, "primary") elseif (Config.DrawText == "auto" and GetResourceState("lation_ui") == "started") or Config.DrawText == "lation_ui" then exports["lation_ui"]:showText({ description = text, }) elseif (Config.DrawText == "auto" and GetResourceState("ox_lib") == "started") or Config.DrawText == "ox_lib" then exports["ox_lib"]:showTextUI(text, { position = "left-center" }) elseif Config.Framework == "QBCore" then exports["qb-core"]:DrawText(text) else error("You do not have a notifications system set up!") end end function Framework.Client.HideTextUI() if (Config.DrawText == "auto" and GetResourceState("jg-textui") == "started") or Config.DrawText == "jg-textui" then exports["jg-textui"]:HideText() elseif (Config.DrawText == "auto" and GetResourceState("okokTextUI") == "started") or Config.DrawText == "okokTextUI" then exports["okokTextUI"]:Close() elseif (Config.DrawText == "auto" and GetResourceState("ps-ui") == "started") or Config.DrawText == "ps-ui" then exports["ps-ui"]:HideText() elseif (Config.DrawText == "auto" and GetResourceState("lation_ui") == "started") or Config.DrawText == "lation_ui" then exports["lation_ui"]:hideText() elseif (Config.DrawText == "auto" and GetResourceState("ox_lib") == "started") or Config.DrawText == "ox_lib" then exports["ox_lib"]:hideTextUI() elseif Config.Framework == "QBCore" then exports["qb-core"]:HideText() else error("You do not have a notifications system set up!") end end function Framework.Client.Notify(msg, type, time) type = type or "success" time = time or 5000 -- Titel kannst du anpassen local title = "Mechanic" exports['hex_4_hud']:Notify(title, msg, type, time) end RegisterNetEvent("jg-mechanic:client:notify", function(...) Framework.Client.Notify(...) end) function Framework.Client.ToggleHud(toggle) if GetResourceState("jg-hud") == "started" then exports["jg-hud"]:toggleHud(toggle) return end DisplayHud(toggle) DisplayRadar(toggle) end function Framework.Client.ProgressBar(text, duration, anim, prop, cb, cbCancelled) if (Config.ProgressBar == "auto" and GetResourceState("lation_ui") == "started") or Config.ProgressBar == "lation_ui" then if exports["lation_ui"]:progressBar({ title = text or "", duration = duration or 5000, icon = "fas fa-screwdriver-wrench", useWhileDead = false, canCancel = true, anim = not anim and {} or { dict = anim.dict, clip = anim.name }, prop = not prop and {} or { model = GetHashKey(prop.model), bone = prop.bone, pos = prop.coords, rot = prop.rotation }, }) then cb() elseif cbCancelled then cbCancelled() end elseif Config.ProgressBar == "auto" or Config.ProgressBar == "ox-bar" or Config.ProgressBar == "ox-circle" then if (Config.ProgressBar == "ox-bar" and lib.progressBar or lib.progressCircle)({ duration = duration or 5000, label = text or "", useWhileDead = false, canCancel = true, anim = not anim and {} or { dict = anim.dict, clip = anim.name }, prop = not prop and {} or { model = GetHashKey(prop.model), bone = prop.bone, pos = prop.coords, rot = prop.rotation }, }) then cb() elseif cbCancelled then cbCancelled() end elseif Config.ProgressBar == "qb" then QBCore.Functions.Progressbar(text or "", text, duration, false, true, { disableMovement = false, disableCarMovement = false, disableMouse = false, disableCombat = true, }, not anim and {} or { animDict = anim.dict, anim = anim.name }, not prop and {} or { model = GetHashKey(prop.model), bone = prop.bone, coords = prop.coords, rotation = prop.rotation }, {}, cb(), cbCancelled and cbCancelled() or false) end end function Framework.Client.SkillCheck(cb, cbFailed) if not Config.UseSkillbars then return Framework.Client.ProgressBar("", Config.ProgressBarDuration or 10000, false, false, cb, cbFailed) end local attempts, maxFails = 0, Config.MaximumSkillCheckAttempts or 3 if Config.SkillCheck == "lation_ui" or (Config.SkillCheck == "auto" and GetResourceState("lation_ui") == "started") then repeat success = exports["lation_ui"]:skillCheck("Skill Check", Config.SkillCheckDifficulty, Config.SkillCheckInputs) if not success then attempts += 1 if attempts == maxFails then return cbFailed() end Framework.Client.Notify(Locale.skillCheckFailed:format(maxFails - attempts), "error") end Wait(success and 100 or 2000) until success return cb() elseif Config.SkillCheck == "auto" or Config.SkillCheck == "ox" then repeat success = lib.skillCheck(Config.SkillCheckDifficulty, Config.SkillCheckInputs) if not success then attempts += 1 if attempts == maxFails then return cbFailed() end Framework.Client.Notify(Locale.skillCheckFailed:format(maxFails - attempts), "error") end Wait(success and 100 or 2000) until success return cb() elseif Config.SkillCheck == "qb" and GetResourceState("qb-skillbar") == "started" then local Skillbar = exports["qb-skillbar"]:GetSkillbarObject() Skillbar.Start({ duration = math.random(5000, 10000), pos = math.random(10, 30), width = math.random(10, 20), }, function() cb() end, function() cbFailed() end) else error("Config.SkillCheck is invalid or no skill check resource is available!") end end function Framework.Client.GetVehicleLabel(model) if type(model) == "string" then if Config.Framework == "QBCore" and QBCore.Shared.Vehicles then local vehShared = QBCore.Shared.Vehicles[model] if vehShared then return vehShared.brand .. " " .. vehShared.name end end if Config.Framework == "Qbox" and exports.qbx_core:GetVehiclesByName() then local vehShared = exports.qbx_core:GetVehiclesByName()[model] if vehShared then return vehShared.brand .. " " .. vehShared.name end end end local hash = type(model) == "string" and joaat(model) or model local makeName = GetMakeNameFromVehicleModel(hash) local modelName = GetDisplayNameFromVehicleModel(hash) local label = GetLabelText(makeName) .. " " .. GetLabelText(modelName) if makeName == "CARNOTFOUND" or modelName == "CARNOTFOUND" then label = tostring(model) else if GetLabelText(modelName) == "NULL" and GetLabelText(makeName) == "NULL" then label = (makeName or "") .. " " .. (modelName or "") elseif GetLabelText(makeName) == "NULL" then label = GetLabelText(modelName) end end return label end function Framework.Client.GetVehicleValue(model) local hash = type(model) == "string" and joaat(model) or model local vehicleValue = GetVehicleModelValue(hash) if type(model) == "string" then if Config.Framework == "QBCore" and QBCore.Shared.Vehicles then local vehShared = QBCore.Shared.Vehicles[model] if vehShared and vehShared.price then vehicleValue = vehShared.price end end if Config.Framework == "Qbox" and exports.qbx_core:GetVehiclesByName() then local vehShared = exports.qbx_core:GetVehiclesByName()[model] if vehShared and vehShared.price then vehicleValue = vehShared.price end end end if GetResourceState("jg-dealerships") == "started" then local price = lib.callback.await("jg-mechanic:server:dealerships-vehicle-value", false, hash) if price then vehicleValue = price end end return vehicleValue or 50000 -- fallback value of 50000, I guess the average price of a car? end function Framework.Client.GetPlate(vehicle) local plate = GetVehicleNumberPlateText(vehicle) if not plate or plate == "" then return false end if GetResourceState("brazzers-fakeplates") == "started" then local originalPlate = lib.callback.await("jg-mechanic:server:brazzers-get-plate-from-fakeplate", false, plate) if originalPlate then plate = originalPlate end end local trPlate = string.gsub(plate, "^%s*(.-)%s*$", "%1") return trPlate end function Framework.Client.RepairVehicle(vehicle) SetVehicleUndriveable(vehicle, false) WashDecalsFromVehicle(vehicle, 1.0) SetVehicleEngineHealth(vehicle, 1000.0) SetVehicleBodyHealth(vehicle, 1000.0) SetVehiclePetrolTankHealth(vehicle, 1000.0) SetVehicleDirtLevel(vehicle, 0.0) SetVehicleDeformationFixed(vehicle) SetVehicleFixed(vehicle) if GetResourceState("VehicleDeformation") == "started" then exports["VehicleDeformation"]:FixVehicleDeformation(vehicle) end end function Framework.Client.GetPlayerData() if Config.Framework == "QBCore" then return QBCore.Functions.GetPlayerData() elseif Config.Framework == "Qbox" then return exports.qbx_core:GetPlayerData() elseif Config.Framework == "ESX" then return ESX.GetPlayerData() end end function Framework.Client.GetBalance(type) if Config.Framework == "QBCore" then return QBCore.Functions.GetPlayerData().money[type] elseif Config.Framework == "Qbox" then return exports.qbx_core:GetPlayerData().money[type] elseif Config.Framework == "ESX" then if type == "cash" then type = "money" end for _, acc in pairs(ESX.GetPlayerData().accounts) do if acc.name == type then return acc.money end end return 0 end end function Framework.Client.GetPlayerJob() local player = Framework.Client.GetPlayerData() if not player or not player.job then return {} end if Config.Framework == "QBCore" or Config.Framework == "Qbox" then return { name = player.job.name, label = player.job.label, grade = player.job.grade.level } elseif Config.Framework == "ESX" then return { name = player.job.name, label = player.job.label, grade = player.job.grade } end return {} end function Framework.Client.GetPlayerJobDuty(mechanicId) if not Config.MechanicLocations[mechanicId] then return false end local onDuty = lib.callback.await("jg-mechanic:server:is-on-duty", false, mechanicId) if Config.Framework == "QBCore" or Config.Framework == "Qbox" then local player = Framework.Client.GetPlayerData() if not player or not player.job then return false end onDuty = player.job.onduty end return onDuty end function Framework.Client.ToggleJobDuty(toggle) lib.callback.await("jg-mechanic:server:toggle-duty", false, toggle) end function Framework.Client.PlaySound(soundName, coords) if Config.DisableSound then return false end lib.requestAudioBank("audiodirectory/jg_mechanic") local soundId = GetSoundId() PlaySoundFromCoord(soundId, soundName, coords.x, coords.y, coords.z, "special_soundset", true, 7.5, false) CreateThread(function() while not HasSoundFinished(soundId) do Wait(1) end ReleaseSoundId(soundId) ReleaseNamedScriptAudioBank("audiodirectory/jg_mechanic") end) return soundId end function Framework.Client.OpenInventoryStash(stashId, stashName) if (Config.Inventory == "auto" and GetResourceState("ox_inventory") == "started") or Config.Inventory == "ox_inventory" then exports.ox_inventory:openInventory("stash", stashId) elseif (Config.Inventory == "auto" and GetResourceState("qb-inventory") == "started") or Config.Inventory == "qb-inventory" then TriggerServerEvent("jg-mechanic:server:open-inventory-stash", stashId, stashName) elseif (Config.Inventory == "auto" and GetResourceState("qs-inventory") == "started") or Config.Inventory == "qs-inventory" then exports["qs-inventory"]:RegisterStash(stashName, 50, 50000000) elseif (Config.Inventory == "auto" and GetResourceState("codem-inventory") == "started") or Config.Inventory == "codem-inventory" then TriggerServerEvent("codem-inventory:server:openstash", stashId, 15, 15000, stashName) else error("Error: Invalid inventory system set in config.") end end function Framework.Client.StopSound(soundId) if not soundId or Config.DisableSound then return false end StopSound(soundId) end