-- error when both menus are enabled if (Config.useContextMenu and Config.useNativeUI) then print("^1[ERROR] You can use only one menu or no menu at all. You cannot use both menus." .. "\nMake sure to set at least one to false in the config and to edit the fxmanifest accordingly!") end local keymakers = {} local lockNotif = nil local createNewKeyNotif = nil local LockStatus = { Unlocked = 1, Locked = 2 } local CB = exports["kimi_callbacks"] local menuPoolNativeUI local keymakerMenuNativeUI local keyInvMenuNativeUI if (Config.useNativeUI) then if (NativeUI == nil) then print("^1[ERROR] NativeUI was not properly initialized! Make sure to install NativeUI and start it before this resource!") end menuPoolNativeUI = NativeUI.CreatePool() keymakerMenuNativeUI = NativeUI.CreateMenu(Config.Strings.keymakerTitle, Config.Strings.keymakerSub) keyInvMenuNativeUI = NativeUI.CreateMenu(Config.Strings.keyInvTitle, Config.Strings.keyInvSub) end local isAtKeymaker = false local menuOpen = false -- create client side peds Citizen.CreateThread(function() for i, keymaker in ipairs(Config.Keymakers) do RequestModel(keymaker.model) while not HasModelLoaded(keymaker.model) do Citizen.Wait(0) end local ped = CreatePed(0, keymaker.model, keymaker.pos.x, keymaker.pos.y, keymaker.pos.z, keymaker.pos.w, false, true) SetBlockingOfNonTemporaryEvents(ped, true) FreezeEntityPosition(ped, true) SetEntityInvincible(ped, true) table.insert(keymakers, ped) -- add blip local blip = AddBlipForCoord(keymaker.pos.x, keymaker.pos.y, keymaker.pos.z) SetBlipSprite(blip, 134) SetBlipColour(blip, 0) SetBlipScale(blip, 1.0) SetBlipDisplay(blip, 2) SetBlipAsShortRange(blip, true) BeginTextCommandSetBlipName('STRING') AddTextComponentSubstringPlayerName(Config.Strings.keymaker) EndTextCommandSetBlipName(blip) end end) -- main loop Citizen.CreateThread(function() while (true) do Citizen.Wait(0) if (Config.useNativeUI) then if (menuOpen) then menuPoolNativeUI:ProcessMenus() end if (isAtKeymaker) then if (not menuOpen) then ShowHelpText(Config.Strings.helpText) end if (IsControlJustPressed(0, 51)) then if (menuPoolNativeUI:IsAnyMenuOpen()) then menuPoolNativeUI:CloseAllMenus() menuOpen = false else GenerateKeymakerMenuNativeUI() keymakerMenuNativeUI:Visible(true) menuOpen = true end end end if (IsControlJustPressed(0, Config.keyMenuKey)) then if (menuPoolNativeUI:IsAnyMenuOpen()) then menuPoolNativeUI:CloseAllMenus() menuOpen = false else GenerateKeyInventoryNativeUI() keyInvMenuNativeUI:Visible(true) menuOpen = true end end end -- lock vehicle with key --[[ if (Config.lockKey and IsControlJustPressed(0, Config.lockKey)) then local vehicle = GetClosestVehicle(GetEntityCoords(PlayerPedId()), 10.0) if (DoesEntityExist(vehicle) and IsVehicleOrKeyOwner(vehicle)) then ToggleLock(vehicle, GetVehicleDoorLockStatus(vehicle) ~= LockStatus.Locked) end end ]] end end) -- ContextMenu if (Config.useContextMenu) then local menuPool = MenuPool() menuPool.OnOpenMenu = function(screenPosition, hitSomething, worldPosition, hitEntity, normalDirection) local playerPos = GetEntityCoords(PlayerPedId()) if (Vdist(worldPosition.x, worldPosition.y, worldPosition.z, playerPos.x, playerPos.y, playerPos.z) < Config.maxDistance) then CreateMenu(screenPosition, hitEntity) end end function CreateMenu(screenPosition, hitEntity) menuPool:Reset() if (hitEntity) then if (hitEntity == PlayerPedId()) then local vehicleData = CB:Trigger("VKC:getPlayerVehicleData") local ownedKeys = GetPlayerKeys() menuPool:Reset() local playerMenu = menuPool:AddMenu() local ownVehMenu, ownVehMenuItem = menuPool:AddSubmenu(playerMenu, Config.Strings.CM.masterKeysTitle) for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local item = ownVehMenu:AddItem(model .. " " .. plate) end local ownKeyMenu, ownKeyMenuItem = menuPool:AddSubmenu(playerMenu, Config.Strings.CM.keysTitle) for i, key in ipairs(ownedKeys) do local model = GetLabelText(GetDisplayNameFromVehicleModel(key.model)) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(key.model) end local item = ownKeyMenu:AddItem(model .. " " .. key.plate) item.rightText = Text("x" .. key.count) end -- Fahrzeugübergabe-Menü hinzufügen local transferVehMenu, transferVehMenuItem = menuPool:AddSubmenu(playerMenu, "Fahrzeug übergeben") for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local item = transferVehMenu:AddItem(model .. " " .. plate) item.closeMenuOnClick = true item.OnClick = function() local nearbyPlayers = GetNearbyPlayersWithNames(5.0) if #nearbyPlayers == 0 then Notification("Keine Spieler in der Nähe gefunden") return end -- Spielerauswahl-Menü erstellen local playerOptions = {} for _, player in ipairs(nearbyPlayers) do table.insert(playerOptions, { title = player.name, description = "Entfernung: " .. math.floor(player.distance * 10) / 10 .. "m", metadata = { ["Spieler ID"] = player.serverId }, args = { serverId = player.serverId, name = player.name } }) end -- Stelle sicher, dass wir mindestens eine Option haben if #playerOptions == 0 then Notification("Keine Spieler in der Nähe gefunden") return end lib.registerMenu({ id = 'transfer_vehicle_menu', title = 'Fahrzeug übergeben', position = 'top-right', options = playerOptions, onSelect = function(selected, scrollIndex, args) if args and args.serverId then local targetPlayer = args.serverId local success = CB:Trigger("VKC:transferVehicleOwnership", plate, targetPlayer) if success then Notification("Du hast dein " .. model .. " an " .. args.name .. " übergeben") else Notification("Übergabe fehlgeschlagen") end else Notification("Fehler bei der Spielerauswahl") end end }) lib.showMenu('transfer_vehicle_menu') end end playerMenu:SetPosition(screenPosition) playerMenu:Visible(true) elseif (IsEntityAKeymaker(hitEntity)) then local vehicleData = GetPlayerVehicleData() local ownedKeys = GetPlayerKeys() menuPool:Reset() local keymakerMenu = menuPool:AddMenu() local createKeyMenu, createKeyMenuItem = menuPool:AddSubmenu(keymakerMenu, Config.Strings.CM.createKeyTitle) for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local keyCount = GetKeyCount(plate, ownedKeys) local keyItem = createKeyMenu:AddItem(model .. " " .. plate) keyItem.rightText = Text("x" .. tostring(keyCount)) keyItem.OnClick = function() local result = CB:Trigger("VKC:createNewKey", plate, 1) if (type(result) == "boolean" and result == true) then Notification(string.format(Config.Strings.createSuccess, model)) local oldCount = keyItem.rightText.title:gsub("x", "") keyItem.rightText.title = "x" .. tostring(tonumber(oldCount) + 1) elseif (type(result) == "string" and result == "noMoney") then Notification(string.format(Config.Strings.createNoMoney, model)) else Notification(string.format(Config.Strings.createFailed, model)) end end end local invalidateKeyMenu, invalidateKeyMenuItem = menuPool:AddSubmenu(keymakerMenu, Config.Strings.CM.invalKeyTitle) for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local item = invalidateKeyMenu:AddItem(model .. " " .. plate) item.closeMenuOnClick = true item.OnClick = function() local result = CB:Trigger("VKC:removeAllKeys", plate) if (type(result) == "boolean" and result == true) then Notification(string.format(Config.Strings.deleteKeys, model)) elseif (type(result) == "string" and result == "noMoney") then Notification(string.format(Config.Strings.removeNoMoney, vehName)) else Notification(string.format(Config.Strings.removeFailed, vehName)) end end end keymakerMenu:SetPosition(screenPosition) keymakerMenu:Visible(true) elseif (IsEntityAPed(hitEntity) and IsPedAPlayer(hitEntity)) then local ownedKeys = GetPlayerKeys() menuPool:Reset() local interactMenu = menuPool:AddMenu() local giveKeyMenu, giveKeyMenuItem = menuPool:AddSubmenu(interactMenu, Config.Strings.CM.giveKey) for i, key in ipairs(ownedKeys) do local model = GetLabelText(GetDisplayNameFromVehicleModel(key.model)) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(key.model) end local keyItem = giveKeyMenu:AddItem(model .. " " .. key.plate) keyItem.rightText = Text("x" .. key.count) keyItem.closeMenuOnClick = true keyItem.OnClick = function() local players = GetActivePlayers() for i, player in ipairs(players) do if (GetPlayerPed(player) == hitEntity) then local success = CB:Trigger("VKC:giveKeyToPlayer", key.plate, GetPlayerServerId(player)) if (success) then Notification(string.format(Config.Strings.giveSuccess, model)) else Notification(string.format(Config.Strings.giveFailed, model)) end break end end end end interactMenu:SetPosition(screenPosition) interactMenu:Visible(true) end end end function IsEntityAKeymaker(entity) for i, keymaker in ipairs(keymakers) do if (entity == keymaker) then return true end end return false end end -- NativeUI function GenerateKeymakerMenuNativeUI() keymakerMenuNativeUI:Clear() local vehicleData = GetPlayerVehicleData() local ownedKeys = GetPlayerKeys() keymakerMenuNativeUI = NativeUI.CreateMenu(Config.Strings.NUI.keymakerMenuTitle, Config.Strings.NUI.keymakerMenuSub) menuPoolNativeUI:Add(keymakerMenuNativeUI) local submenuCreateKey = menuPoolNativeUI:AddSubMenu(keymakerMenuNativeUI, Config.Strings.NUI.createKeyTitle, Config.Strings.NUI.createKeyDesc) submenuCreateKey.ParentItem:RightLabel(">") submenuCreateKey.Subtitle.Text._Text = "~b~" .. Config.Strings.NUI.createKeyTitle for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local keyCount = GetKeyCount(plate, ownedKeys) local vehItem = NativeUI.CreateItem(model .. " " .. plate, string.format(Config.Strings.NUI.createVehicleKey, model, plate)) vehItem:RightLabel("x" .. tostring(keyCount)) submenuCreateKey:AddItem(vehItem) end submenuCreateKey.OnItemSelect = function(menu, item, index) Citizen.CreateThread(function() local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicleData[index][2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicleData[index][2]) end local result = CB:Trigger("VKC:createNewKey", vehicleData[index][1], 1) if (type(result) == "boolean" and result == true) then Notification(string.format(Config.Strings.createSuccess, model)) if (submenuCreateKey:Visible()) then local oldCount = item.Label.Text._Text:gsub("x", "") item:RightLabel("x" .. tostring(tonumber(oldCount) + 1)) end elseif (type(result) == "string" and result == "noMoney") then Notification(string.format(Config.Strings.createNoMoney, model)) else Notification(string.format(Config.Strings.createFailed, model)) end end) end local submenuInvalidateKey = menuPoolNativeUI:AddSubMenu(keymakerMenuNativeUI, Config.Strings.NUI.invalKeyTitle, Config.Strings.NUI.invalKeyDesc) submenuInvalidateKey.ParentItem:RightLabel(">") submenuInvalidateKey.Subtitle.Text._Text = "~b~" .. Config.Strings.NUI.invalKeyTitle for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local keyItem = NativeUI.CreateItem(model .. " " .. plate, string.format(Config.Strings.NUI.invalVehicleKey, model, plate)) submenuInvalidateKey:AddItem(keyItem) end submenuInvalidateKey.OnItemSelect = function(menu, item, index) Citizen.CreateThread(function() local result = CB:Trigger("VKC:removeAllKeys", vehicleData[index][1]) if (type(result) == "boolean" and result == true) then local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicleData[index][2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicleData[index][2]) end Notification(string.format(Config.Strings.deleteKeys, model)) elseif (type(result) == "string" and result == "noMoney") then Notification(string.format(Config.Strings.removeNoMoney, vehName)) else Notification(string.format(Config.Strings.removeFailed, vehName)) end end) end keymakerMenuNativeUI.OnMenuClosed = function(menu) menuOpen = false end menuPoolNativeUI:ControlDisablingEnabled(false) menuPoolNativeUI:MouseControlsEnabled(false) menuPoolNativeUI:RefreshIndex() end -- Funktion zum Abrufen von Spielern in der Nähe mit Namen function GetNearbyPlayersWithNames(maxDistance) local players = {} local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) for _, id in ipairs(GetActivePlayers()) do if id ~= PlayerId() then local targetPed = GetPlayerPed(id) local targetCoords = GetEntityCoords(targetPed) local distance = #(playerCoords - targetCoords) if distance <= maxDistance then local playerName = GetPlayerName(id) table.insert(players, { id = id, serverId = GetPlayerServerId(id), name = playerName, distance = distance }) end end end -- Nach Entfernung sortieren table.sort(players, function(a, b) return a.distance < b.distance end) return players end function GenerateKeyInventoryNativeUI() keyInvMenuNativeUI:Clear() local vehicleData = GetPlayerVehicleData() local ownedKeys = GetPlayerKeys() keyInvMenuNativeUI = NativeUI.CreateMenu(Config.Strings.NUI.keyInventoryTitle, Config.Strings.NUI.keyInventorySub) menuPoolNativeUI:Add(keyInvMenuNativeUI) local submenuShowMasterKeys = menuPoolNativeUI:AddSubMenu(keyInvMenuNativeUI, Config.Strings.NUI.masterKeysTitle, Config.Strings.NUI.masterKeysDesc) submenuShowMasterKeys.ParentItem:RightLabel(">") submenuShowMasterKeys.Subtitle.Text._Text = "~b~" .. Config.Strings.NUI.masterKeysTitle for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end --local keyCount = GetKeyCount(plate, ownedKeys) local vehItem = NativeUI.CreateItem(model .. " " .. plate, "") --vehItem:RightLabel("x" .. tostring(keyCount)) submenuShowMasterKeys:AddItem(vehItem) end -- Fahrzeugübergabe-Untermenü hinzufügen local submenuTransferVehicle = menuPoolNativeUI:AddSubMenu(keyInvMenuNativeUI, "Fahrzeug übergeben", "Übertrage ein Fahrzeug an einen Spieler in der Nähe") submenuTransferVehicle.ParentItem:RightLabel(">") submenuTransferVehicle.Subtitle.Text._Text = "~b~Fahrzeug übergeben" for i, vehicle in ipairs(vehicleData) do local plate = vehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(vehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(vehicle[2]) end local vehItem = NativeUI.CreateItem(model .. " " .. plate, "Wähle dieses Fahrzeug zum Übergeben") submenuTransferVehicle:AddItem(vehItem) end submenuTransferVehicle.OnItemSelect = function(menu, item, index) local selectedVehicle = vehicleData[index] local plate = selectedVehicle[1] local model = GetLabelText(GetDisplayNameFromVehicleModel(selectedVehicle[2])) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(selectedVehicle[2]) end -- Menü schließen und Spielerauswahl anzeigen menuPoolNativeUI:CloseAllMenus() menuOpen = false -- Spieler in der Nähe abrufen local nearbyPlayers = GetNearbyPlayersWithNames(5.0) if #nearbyPlayers == 0 then lib.notify({ title = "Fahrzeug übergeben", description = "Keine Spieler in der Nähe gefunden", position = "top", type = "error", icon = "car" }) return end -- Spielerauswahl-Menü erstellen local playerOptions = {} for _, player in ipairs(nearbyPlayers) do table.insert(playerOptions, { title = player.name, description = "Entfernung: " .. math.floor(player.distance * 10) / 10 .. "m", metadata = { ["Spieler ID"] = player.serverId }, args = { serverId = player.serverId, name = player.name } }) end -- Stelle sicher, dass wir mindestens eine Option haben if #playerOptions == 0 then lib.notify({ title = "Fahrzeug übergeben", description = "Keine Spieler in der Nähe gefunden", position = "top", type = "error", icon = "car" }) return end lib.registerMenu({ id = 'transfer_vehicle_menu', title = 'Fahrzeug übergeben', position = 'top-right', options = playerOptions, onClose = function() -- Optional: Öffne das Hauptmenü wieder GenerateKeyInventoryNativeUI() keyInvMenuNativeUI:Visible(true) menuOpen = true end, onSelect = function(selected, scrollIndex, args) if args and args.serverId then local targetPlayer = args.serverId local success = CB:Trigger("VKC:transferVehicleOwnership", plate, targetPlayer) if success then lib.notify({ title = "Fahrzeug übergeben", description = "Du hast dein " .. model .. " an " .. args.name .. " übergeben", position = "top", type = "success", icon = "car" }) else lib.notify({ title = "Fahrzeug übergeben", description = "Übergabe fehlgeschlagen", position = "top", type = "error", icon = "car" }) end else lib.notify({ title = "Fahrzeug übergeben", description = "Fehler bei der Spielerauswahl", position = "top", type = "error", icon = "car" }) end end }) lib.showMenu('transfer_vehicle_menu') end local submenuShowKeys = menuPoolNativeUI:AddSubMenu(keyInvMenuNativeUI, Config.Strings.NUI.keysTitle, Config.Strings.NUI.keysDesc) submenuShowKeys.ParentItem:RightLabel(">") submenuShowKeys.Subtitle.Text._Text = "~b~" .. Config.Strings.NUI.keysTitle for i, key in ipairs(ownedKeys) do local model = GetLabelText(GetDisplayNameFromVehicleModel(key.model)) if (model == "NULL") then model = GetDisplayNameFromVehicleModel(key.model) end local submenuKey = menuPoolNativeUI:AddSubMenu(submenuShowKeys, model .. " " .. key.plate, "") submenuKey.ParentItem:RightLabel("x" .. tostring(key.count) .. " >") submenuKey.Subtitle.Text._Text = "~b~" .. model .. " " .. key.plate local giveItem = NativeUI.CreateItem(Config.Strings.NUI.giveKeyTitle, Config.Strings.NUI.giveKeyDesc) submenuKey:AddItem(giveItem) local removeItem = NativeUI.CreateItem(Config.Strings.NUI.removeKeyTitle, Config.Strings.NUI.removeKeyDesc) submenuKey:AddItem(removeItem) submenuKey.OnItemSelect = function(menu, item, index) if (item == giveItem) then Citizen.CreateThread(function() local player = GetClosestPlayer(2.0) if (player) then local success = CB:Trigger("VKC:giveKeyToPlayer", key.plate, GetPlayerServerId(player)) if (success) then Notification(string.format(Config.Strings.giveSuccess, key.plate)) else Notification(string.format(Config.Strings.giveFailed, key.plate)) end else Notification(string.format(Config.Strings.giveFailed, key.plate)) end end) elseif (item == removeItem) then Citizen.CreateThread(function() local success = CB:Trigger("VKC:removeKey", key.plate, 1) if (success) then Notification(string.format(Config.Strings.removeSuccess, key.plate)) if (submenuShowKeys:Visible() or submenuKey:Visible()) then local oldCount = submenuKey.ParentItem.Label.Text._Text:gsub("x", "") oldCount = oldCount:gsub(" >", "") submenuKey.ParentItem:RightLabel("x" .. tostring(tonumber(oldCount) - 1) .. " >") end else Notification(string.format(Config.Strings.removeFailed, key.plate)) end end) end end end keyInvMenuNativeUI.OnMenuClosed = function(menu) menuOpen = false end menuPoolNativeUI:ControlDisablingEnabled(false) menuPoolNativeUI:MouseControlsEnabled(false) menuPoolNativeUI:RefreshIndex() end if (Config.useNativeUI) then Citizen.CreateThread(function() while (true) do Citizen.Wait(250) isAtKeymaker = false local pos = GetEntityCoords(PlayerPedId()) for i, keymaker in ipairs(Config.Keymakers) do if (Vdist(pos.x, pos.y, pos.z, keymaker.pos.x, keymaker.pos.y, keymaker.pos.z) < 2.0) then isAtKeymaker = true break end end end end) if (Config.keyMenuCommand) then RegisterCommand(Config.keyMenuCommand, function(source, args, raw) if (menuPoolNativeUI:IsAnyMenuOpen()) then menuPoolNativeUI:CloseAllMenus() end GenerateKeyInventoryNativeUI() keyInvMenuNativeUI:Visible(true) menuOpen = true end, false) end end -- lock vehicle if (Config.lockCommand) then RegisterCommand(Config.lockCommand, function(source, args, raw) local vehicle = GetClosestVehicle(GetEntityCoords(PlayerPedId()), 10.0) if (DoesEntityExist(vehicle) and IsVehicleOrKeyOwner(vehicle)) then ToggleLock(vehicle, GetVehicleDoorLockStatus(vehicle) ~= LockStatus.Locked) end end, false) end function ToggleLock(vehicle, lock) local lockStatus = GetVehicleDoorLockStatus(vehicle) if (NetworkHasControlOfEntity(vehicle)) then ToggleLockOnVehicle(vehicle, lock) else TriggerServerEvent("VKC:toggleLockNet", NetworkGetNetworkIdFromEntity(vehicle), lock) end -- play sound TriggerServerEvent("VKC:playDoorLockSoundNet", NetworkGetNetworkIdFromEntity(vehicle), lock) -- play remote animation if (not IsPedInAnyVehicle(PlayerPedId(), false)) then PlayRemoteAnimation() end -- show notification --[[ if (lockNotif) then RemoveNotification(lockNotif) end lockNotif = Notification(lockStatus == LockStatus.Locked and Config.Strings.unlockNotif or Config.Strings.lockNotif) ]] end function ToggleLockOnVehicle(vehicle, lock) if (lock) then SetVehicleDoorsShut(vehicle, false) SetVehicleDoorsLocked(vehicle, LockStatus.Locked) --exports['okokNotify']:Alert("Fahrzeug", "Du hast dein Fahrzeug Abgeschlossen", 3000, 'error') lib.notify({ title = "Fahrzeug", description = "Du hast dein Fahrzeug Abgeschlossen", position = "top", type = "error", icon = "car" }) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) else SetVehicleDoorsLocked(vehicle, LockStatus.Unlocked) --exports['okokNotify']:Alert("Fahrzeug", "Du hast dein Fahrzeug Aufgeschlossen", 3000, 'success') lib.notify({ title = "Fahrzeug", description = "Du hast dein Fahrzeug Aufgeschlossen", position = "top", type = "success", icon = "car" }) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) Citizen.Wait(150) SetVehicleLights(vehicle, 2) Citizen.Wait(150) SetVehicleLights(vehicle, 0) end end function PlayDoorLockSound(vehicle, lock) if (lock) then PlayVehicleDoorCloseSound(vehicle, 0) else PlayVehicleDoorOpenSound(vehicle, 0) end end if (Config.lockCommand or Config.lockKey) then RegisterNetEvent("VKC:toggleLockOnPlayer") AddEventHandler("VKC:toggleLockOnPlayer", function(vehicleNetId, unlocked) local vehicle = NetworkGetEntityFromNetworkId(vehicleNetId) if (DoesEntityExist(vehicle) and NetworkHasControlOfEntity(vehicle)) then local lockStatus = GetVehicleDoorLockStatus(vehicle) ToggleLockOnVehicle(vehicle, unlocked) end end) RegisterNetEvent("VKC:playDoorLockSound") AddEventHandler("VKC:playDoorLockSound", function(vehicleNetId, lock) local vehicle = NetworkGetEntityFromNetworkId(vehicleNetId) if (DoesEntityExist(vehicle)) then PlayDoorLockSound(vehicle, lock) end end) end RegisterNetEvent("VKC:giveKeyNotif") AddEventHandler("VKC:giveKeyNotif", function(plate) Notification(string.format(Config.Strings.giveSuccessPly, plate)) end) -- Ereignis für Fahrzeugübergabe-Benachrichtigung RegisterNetEvent("VKC:vehicleTransferNotif") AddEventHandler("VKC:vehicleTransferNotif", function(plate, model) lib.notify({ title = "Fahrzeug erhalten", description = "Du hast ein " .. model .. " mit dem Kennzeichen " .. plate .. " erhalten", position = "top", type = "success", icon = "car" }) end) function IsVehicleOwner(vehicle) if (not DoesEntityExist(vehicle)) then print("^1[ERROR] Parameter \"vehicle\" was nil or vehicle did not exist while triggering export \"IsVehicleOwner\"!") return end return CB:Trigger("VKC:isVehicleOwner", GetVehicleNumberPlateText(vehicle)) end function IsKeyOwner(vehicle) if (not DoesEntityExist(vehicle)) then print("^1[ERROR] Parameter \"vehicle\" was nil or vehicle did not exist while triggering export \"IsKeyOwner\"!") return end return CB:Trigger("VKC:isKeyOwner", GetVehicleNumberPlateText(vehicle), GetEntityModel(vehicle)) end function IsVehicleOrKeyOwner(vehicle) if (not DoesEntityExist(vehicle)) then print("^1[ERROR] Parameter \"vehicle\" was nil or vehicle did not exist while triggering export \"IsVehicleOrKeyOwner\"!") return end return CB:Trigger("VKC:isVehicleOrKeyOwner", GetVehicleNumberPlateText(vehicle), GetEntityModel(vehicle)) end function GetPlayerKeys() return CB:Trigger("VKC:getPlayerKeys") end function GetPlayerVehicleData() return CB:Trigger("VKC:getPlayerVehicleData") end -- play lock animation function PlayRemoteAnimation() Citizen.CreateThread(function() RequestModel(keyPropHash) RequestAnimDict("anim@mp_player_intmenu@key_fob@") while (not HasModelLoaded(keyPropHash) and not HasAnimDictLoaded("anim@mp_player_intmenu@key_fob@")) do Citizen.Wait(0) end local playerPed = PlayerPedId() local playerPos = GetEntityCoords(playerPed) local keyObj = CreateObjectNoOffset(keyPropHash, playerPos.x, playerPos.y, playerPos.z, true, true, false) SetModelAsNoLongerNeeded(keyPropHash) local boneIndex = GetEntityBoneIndexByName(playerPed, "IK_R_Hand") local offset = vector3(0.08, 0.025, -0.01) local rotOffset = vector3(0, 70, 140) AttachEntityToEntity(keyObj, playerPed, boneIndex, offset.x, offset.y, offset.z, rotOffset.x, rotOffset.y, rotOffset.z, false, false, true, false, 2, true) TaskPlayAnim(playerPed, "anim@mp_player_intmenu@key_fob@", "fob_click_fp", 8.0, 8.0, -1, 48, 1, false, false, false) RemoveAnimDict("anim@mp_player_intmenu@key_fob@") Citizen.Wait(1500) DeleteEntity(keyObj) end) end -- show text in upper left corner function ShowHelpText(text) BeginTextCommandDisplayHelp('STRING') AddTextComponentSubstringPlayerName(text) EndTextCommandDisplayHelp(0, false, true, -1) end -- displays a notification and returns its handle function Notification(text) SetNotificationTextEntry('STRING') AddTextComponentSubstringPlayerName(text) return DrawNotification(false, true) end -- get key count function GetKeyCount(plate, keyArray) for i, key in ipairs(keyArray) do if (plate == key.plate) then return key.count end end return 0 end -- get all players function GetAllPlayers() local players = {} for k, v in ipairs(GetActivePlayers()) do table.insert(players, v) end return players end -- get the closest player function GetClosestPlayer(maxRange) local playerPed = PlayerPedId() local players = GetAllPlayers() local playerCoords = GetEntityCoords(playerPed) local closestDistance = maxRange local closestPlayer = nil for i=1, #players, 1 do local coords = GetEntityCoords(GetPlayerPed(players[i])) local dist = Vdist(playerCoords.x, playerCoords.y, playerCoords.z, coords.x, coords.y, coords.z) if (dist < closestDistance and players[i] ~= PlayerId()) then closestDistance = dist closestPlayer = players[i] end end if (closestPlayer ~= nil and DoesEntityExist(GetPlayerPed(closestPlayer))) then return closestPlayer else return nil end end -- Return closest loaded vehicle entity or nil if no vehicle is found function GetClosestVehicle(position, maxRadius) local vehicles = GetAllVehicles() local dist = maxRadius local closestVehicle = nil for i=1, #vehicles, 1 do local vehicleCoords = GetEntityCoords(vehicles[i]) local tempDist = Vdist(vehicleCoords.x, vehicleCoords.y, vehicleCoords.z, position.x, position.y, position.z) if (tempDist < dist) then dist = tempDist closestVehicle = vehicles[i] end end if (closestVehicle ~= nil and DoesEntityExist(closestVehicle)) then return closestVehicle else return nil end end -- Returns all loaded vehicles on client side function GetAllVehicles() local vehicles = {} for vehicle in EnumerateVehicles() do table.insert(vehicles, vehicle) end return vehicles end -- getting all vehicles function EnumerateVehicles() return EnumerateEntities(FindFirstVehicle, FindNextVehicle, EndFindVehicle) end function EnumerateEntities(initFunc, moveFunc, disposeFunc) return coroutine.wrap(function() local iter, id = initFunc() if not id or id == 0 then disposeFunc(iter) return end local enum = {handle = iter, destructor = disposeFunc} setmetatable(enum, entityEnumerator) local next = true repeat coroutine.yield(id) next, id = moveFunc(iter) until not next enum.destructor, enum.handle = nil, nil disposeFunc(iter) end) end local entityEnumerator = { __gc = function(enum) if enum.destructor and enum.handle then enum.destructor(enum.handle) end enum.destructor = nil enum.handle = nil end } --[[ RegisterCommand("plate", function(source, args, raw) local vehicle = GetClosestVehicle(GetEntityCoords(PlayerPedId()), 10.0) if (DoesEntityExist(vehicle)) then SetVehicleNumberPlateText(vehicle, args[1]) end end, false) ]] RegisterKeyMapping("vehicleLock", "Vehicle Lock", "keyboard", "PAGEUP") RegisterCommand("vehicleLock", function() local vehicle = GetClosestVehicle(GetEntityCoords(PlayerPedId()), 10.0) if (DoesEntityExist(vehicle) and IsVehicleOrKeyOwner(vehicle)) then ToggleLock(vehicle, GetVehicleDoorLockStatus(vehicle) ~= LockStatus.Locked) end end, false) -- Integration mit dem Mietfahrzeug-System RegisterNetEvent('vehiclerental:client:checkRentalKeys') AddEventHandler('vehiclerental:client:checkRentalKeys', function() TriggerServerEvent('vehiclerental:server:checkRentalKeys') end) -- Überprüfe Mietfahrzeug-Schlüssel beim Öffnen des Schlüssel-Menüs if Config.useNativeUI then -- Speichere die ursprüngliche Funktion local originalGenerateKeyInventoryNativeUI = GenerateKeyInventoryNativeUI -- Überschreibe die Funktion GenerateKeyInventoryNativeUI = function() -- Überprüfe Mietfahrzeug-Schlüssel TriggerServerEvent('vehiclerental:server:checkRentalKeys') -- Warte kurz, damit die Schlüssel aktualisiert werden können Citizen.Wait(100) -- Rufe die ursprüngliche Funktion auf originalGenerateKeyInventoryNativeUI() end end