ESX = exports['es_extended']:getSharedObject() local isNuiOpen = false local currentProp = nil local currentCardData = nil local currentCardType = nil -- ===================== -- ANIMATION -- ===================== function PlayIdAnimation() local playerPed = PlayerPedId() local anim = Config.Animation RequestAnimDict(anim.dict) while not HasAnimDictLoaded(anim.dict) do Citizen.Wait(10) end TaskPlayAnim(playerPed, anim.dict, anim.name, 8.0, -8.0, anim.duration, anim.flag, 0, false, false, false) -- Prop attachen if anim.prop and anim.prop.enabled and anim.prop.model then local propHash = GetHashKey(anim.prop.model) RequestModel(propHash) while not HasModelLoaded(propHash) do Citizen.Wait(10) end local prop = CreateObject(propHash, 0.0, 0.0, 0.0, true, true, false) AttachEntityToEntity(prop, playerPed, GetPedBoneIndex(playerPed, anim.prop.bone), anim.prop.offset.x, anim.prop.offset.y, anim.prop.offset.z, anim.prop.rotation.x, anim.prop.rotation.y, anim.prop.rotation.z, true, true, false, true, 1, true) SetModelAsNoLongerNeeded(propHash) currentProp = prop end end function StopIdAnimation() local playerPed = PlayerPedId() ClearPedTasks(playerPed) if currentProp and DoesEntityExist(currentProp) then DeleteEntity(currentProp) currentProp = nil end end -- ===================== -- MUGSHOT (wird einmal beim Spawnen generiert) -- ===================== local cachedMugShot = nil local mugShotReady = false -- Mugshot im Hintergrund generieren (beim Spawn) local function GenerateMugShotAsync() if not Config.MugShot or not Config.MugShot.enabled then return end Citizen.CreateThread(function() -- Kurz warten bis Ped vollstaendig geladen Citizen.Wait(5000) local ok, mugshot = pcall(function() return exports["MugShotBase64"]:GetMugShotBase64(PlayerPedId(), Config.MugShot.transparent) end) if ok and mugshot and mugshot ~= '' then cachedMugShot = mugshot mugShotReady = true print('[mercyv-id] Mugshot erfolgreich generiert und gecacht') else print('[mercyv-id] Mugshot konnte nicht generiert werden') end end) end -- Beim Spieler-Spawn Mugshot generieren RegisterNetEvent('esx:playerLoaded') AddEventHandler('esx:playerLoaded', function() GenerateMugShotAsync() end) -- Falls Spieler schon geladen ist (z.B. Resource-Restart) Citizen.CreateThread(function() while not ESX.IsPlayerLoaded() do Citizen.Wait(500) end if not mugShotReady then GenerateMugShotAsync() end end) -- ===================== -- NUI MANAGEMENT -- ===================== function OpenIdCard(cardType, data, isViewing) if isNuiOpen then return end isNuiOpen = true currentCardData = data currentCardType = cardType SetNuiFocus(true, true) SendNUIMessage({ type = 'open', cardType = cardType, playerData = data, licenseDisplay = Config.LicenseDisplay, theme = Config.Theme, cardTitle = Config.CardTitle, isViewing = isViewing or false, }) end function CloseMenu() if not isNuiOpen then return end isNuiOpen = false currentCardData = nil currentCardType = nil SetNuiFocus(false, false) SendNUIMessage({ type = 'close' }) StopIdAnimation() end -- ===================== -- ITEM USE (vom Server getriggert) -- ===================== RegisterNetEvent('mercyv-id:useItem') AddEventHandler('mercyv-id:useItem', function(itemName, cardType) if isNuiOpen then return end -- Animation starten PlayIdAnimation() -- Daten vom Server holen ESX.TriggerServerCallback('mercyv-id:getPlayerData', function(data) if not data then StopIdAnimation() TriggerEvent(Config.Notification.event, Config.Notification.title, 'Daten konnten nicht geladen werden', 'error', Config.Notification.duration) return end -- Gecachtes Mugshot anwenden if (not data.photo or data.photo == '') and cachedMugShot then data.photo = cachedMugShot end OpenIdCard(cardType, data, false) end) end) -- ===================== -- AUSWEIS VON ANDEREM SPIELER EMPFANGEN -- ===================== RegisterNetEvent('mercyv-id:receiveCard') AddEventHandler('mercyv-id:receiveCard', function(cardData, cardType, senderName) if isNuiOpen then return end TriggerEvent(Config.Notification.event, Config.Notification.title, senderName .. ' zeigt dir einen Ausweis', 'info', Config.Notification.duration) OpenIdCard(cardType, cardData, true) end) -- ===================== -- NUI CALLBACKS -- ===================== RegisterNUICallback('close', function(_, cb) CloseMenu() cb('ok') end) RegisterNUICallback('showToNearby', function(_, cb) if not currentCardData or not currentCardType then cb('ok') return end local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local nearbyIds = {} -- Alle Spieler in der Naehe finden local players = GetActivePlayers() for _, playerId in ipairs(players) do if playerId ~= PlayerId() then local targetPed = GetPlayerPed(playerId) if DoesEntityExist(targetPed) then local targetCoords = GetEntityCoords(targetPed) local dist = #(playerCoords - targetCoords) if dist <= Config.ShowDistance then nearbyIds[#nearbyIds + 1] = GetPlayerServerId(playerId) end end end end if #nearbyIds == 0 then TriggerEvent(Config.Notification.event, Config.Notification.title, 'Keine Spieler in der Naehe', 'info', Config.Notification.duration) else TriggerServerEvent('mercyv-id:showToNearby', currentCardData, currentCardType, nearbyIds) TriggerEvent(Config.Notification.event, Config.Notification.title, 'Ausweis wird ' .. #nearbyIds .. ' Spieler(n) gezeigt', 'success', Config.Notification.duration) end cb('ok') end) -- ===================== -- RADIAL MENU EVENTS (rlo_radialmenu) -- ===================== -- Hilfsfunktion: Nahe Spieler finden und Karte senden local function ShowCardToNearby(playerData, cardType, cardLabel) local playerPed = PlayerPedId() local playerCoords = GetEntityCoords(playerPed) local nearbyIds = {} local players = GetActivePlayers() for _, playerId in ipairs(players) do if playerId ~= PlayerId() then local targetPed = GetPlayerPed(playerId) if DoesEntityExist(targetPed) then local targetCoords = GetEntityCoords(targetPed) local dist = #(playerCoords - targetCoords) if dist <= Config.ShowDistance then nearbyIds[#nearbyIds + 1] = GetPlayerServerId(playerId) end end end end if #nearbyIds > 0 then TriggerServerEvent('mercyv-id:showToNearby', playerData, cardType, nearbyIds) TriggerEvent(Config.Notification.event, Config.Notification.title, cardLabel .. ' wird ' .. #nearbyIds .. ' Spieler(n) gezeigt', 'success', Config.Notification.duration) else TriggerEvent(Config.Notification.event, Config.Notification.title, 'Keine Spieler in der Nähe', 'info', Config.Notification.duration) end end -- Hilfsfunktion: Karte oeffnen mit Lizenz-Check local function OpenCardWithCheck(cardType, showToOthers) if isNuiOpen then return end ESX.TriggerServerCallback('mercyv-id:hasLicense', function(hasLicense) if not hasLicense then local names = { license = 'Führerschein', weapon = 'Waffenschein', } TriggerEvent(Config.Notification.event, Config.Notification.title, 'Du besitzt keinen ' .. (names[cardType] or 'Ausweis'), 'error', Config.Notification.duration) return end PlayIdAnimation() ESX.TriggerServerCallback('mercyv-id:getPlayerData', function(playerData) if not playerData then StopIdAnimation() TriggerEvent(Config.Notification.event, Config.Notification.title, 'Daten konnten nicht geladen werden', 'error', Config.Notification.duration) return end -- Gecachtes Mugshot anwenden if (not playerData.photo or playerData.photo == '') and cachedMugShot then playerData.photo = cachedMugShot end OpenIdCard(cardType, playerData, false) if showToOthers then local labels = { id = 'Ausweis', license = 'Führerschein', weapon = 'Waffenschein' } ShowCardToNearby(playerData, cardType, labels[cardType] or 'Ausweis') end end) end, cardType) end -- Ausweis ansehen RegisterNetEvent('mercyv-id:radial:viewId') AddEventHandler('mercyv-id:radial:viewId', function(data) OpenCardWithCheck('id', false) end) -- Ausweis zeigen RegisterNetEvent('mercyv-id:radial:showId') AddEventHandler('mercyv-id:radial:showId', function(data) OpenCardWithCheck('id', true) end) -- Führerschein ansehen RegisterNetEvent('mercyv-id:radial:viewLicense') AddEventHandler('mercyv-id:radial:viewLicense', function(data) OpenCardWithCheck('license', false) end) -- Führerschein zeigen RegisterNetEvent('mercyv-id:radial:showLicense') AddEventHandler('mercyv-id:radial:showLicense', function(data) OpenCardWithCheck('license', true) end) -- Waffenschein ansehen RegisterNetEvent('mercyv-id:radial:viewWeapon') AddEventHandler('mercyv-id:radial:viewWeapon', function(data) OpenCardWithCheck('weapon', false) end) -- Waffenschein zeigen RegisterNetEvent('mercyv-id:radial:showWeapon') AddEventHandler('mercyv-id:radial:showWeapon', function(data) OpenCardWithCheck('weapon', true) end) -- ===================== -- CLEANUP -- ===================== AddEventHandler('onResourceStop', function(resourceName) if resourceName ~= GetCurrentResourceName() then return end if isNuiOpen then SetNuiFocus(false, false) end if currentProp and DoesEntityExist(currentProp) then DeleteEntity(currentProp) end ClearPedTasks(PlayerPedId()) end)