316 lines
10 KiB
Lua
316 lines
10 KiB
Lua
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)
|