713 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			713 lines
		
	
	
	
		
			21 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local QBCore = exports['qb-core']:GetCoreObject()
 | 
						|
local PlayerData = {}
 | 
						|
local currentBooth = nil
 | 
						|
local isPlaying = false
 | 
						|
local currentVolume = Config.DefaultVolume
 | 
						|
local currentSong = nil
 | 
						|
local activeBooths = {}
 | 
						|
local isUIOpen = false
 | 
						|
local isDJBooth = false
 | 
						|
local nearestBooth = nil
 | 
						|
 | 
						|
-- Events
 | 
						|
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
 | 
						|
    PlayerData = QBCore.Functions.GetPlayerData()
 | 
						|
    
 | 
						|
    -- Frage Server nach aktiven DJ-Booths
 | 
						|
    TriggerServerEvent('dj:server:requestActiveDJs')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(JobInfo)
 | 
						|
    PlayerData.job = JobInfo
 | 
						|
end)
 | 
						|
 | 
						|
-- Key Mapping
 | 
						|
RegisterKeyMapping('opendj', 'Open DJ Menu', 'keyboard', Config.OpenMenuKey)
 | 
						|
 | 
						|
RegisterCommand('opendj', function()
 | 
						|
    if not CanUseDJScript() then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du hast keine Berechtigung das DJ System zu nutzen!',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    if not isDJBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ Pult stehen!',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    OpenDJInterface()
 | 
						|
end)
 | 
						|
 | 
						|
-- Musik abspielen (von Server empfangen)
 | 
						|
RegisterNetEvent('dj:client:playMusic', function(data)
 | 
						|
    -- Speichere Booth-Informationen
 | 
						|
    activeBooths[data.booth.name] = {
 | 
						|
        url = data.url,
 | 
						|
        title = data.title,
 | 
						|
        volume = data.volume,
 | 
						|
        coords = data.booth.coords,
 | 
						|
        range = data.range
 | 
						|
    }
 | 
						|
    
 | 
						|
    -- Prüfe ob Spieler in Reichweite ist
 | 
						|
    local playerCoords = GetEntityCoords(PlayerPedId())
 | 
						|
    local distance = #(playerCoords - data.booth.coords)
 | 
						|
    
 | 
						|
    if distance <= data.range then
 | 
						|
        -- Berechne Lautstärke basierend auf Distanz
 | 
						|
        local volumeMultiplier = 1.0 - (distance / data.range)
 | 
						|
        local adjustedVolume = math.floor(data.volume * volumeMultiplier)
 | 
						|
        
 | 
						|
        -- Spiele Musik ab
 | 
						|
        SendNUIMessage({
 | 
						|
            type = 'playMusic',
 | 
						|
            url = data.url,
 | 
						|
            volume = adjustedVolume,
 | 
						|
            title = data.title
 | 
						|
        })
 | 
						|
        
 | 
						|
        -- Setze lokale Variablen
 | 
						|
        currentBooth = {
 | 
						|
            name = data.booth.name,
 | 
						|
            coords = data.booth.coords
 | 
						|
        }
 | 
						|
        isPlaying = true
 | 
						|
        currentSong = {
 | 
						|
            title = data.title,
 | 
						|
            url = data.url
 | 
						|
        }
 | 
						|
        
 | 
						|
        -- Zeige Benachrichtigung
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Spielt: ' .. data.title,
 | 
						|
            type = 'info'
 | 
						|
        })
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Musik stoppen (von Server empfangen)
 | 
						|
RegisterNetEvent('dj:client:stopMusic', function(boothName)
 | 
						|
    -- Entferne Booth-Informationen
 | 
						|
    if activeBooths[boothName] then
 | 
						|
        activeBooths[boothName] = nil
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Wenn der Spieler diese Musik hört, stoppe sie
 | 
						|
    if currentBooth and currentBooth.name == boothName then
 | 
						|
        SendNUIMessage({
 | 
						|
            type = 'stopMusic'
 | 
						|
        })
 | 
						|
        
 | 
						|
        currentBooth = nil
 | 
						|
        isPlaying = false
 | 
						|
        currentSong = nil
 | 
						|
        
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Musik gestoppt',
 | 
						|
            type = 'info'
 | 
						|
        })
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Lautstärke ändern (von Server empfangen)
 | 
						|
RegisterNetEvent('dj:client:setVolume', function(data)
 | 
						|
    -- Aktualisiere Booth-Informationen
 | 
						|
    if activeBooths[data.booth.name] then
 | 
						|
        activeBooths[data.booth.name].volume = data.volume
 | 
						|
        activeBooths[data.booth.name].range = data.range
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Wenn der Spieler diese Musik hört, ändere die Lautstärke
 | 
						|
    if currentBooth and currentBooth.name == data.booth.name then
 | 
						|
        -- Berechne Lautstärke basierend auf Distanz
 | 
						|
        local playerCoords = GetEntityCoords(PlayerPedId())
 | 
						|
        local distance = #(playerCoords - data.booth.coords)
 | 
						|
        local volumeMultiplier = 1.0 - (distance / data.range)
 | 
						|
        local adjustedVolume = math.floor(data.volume * volumeMultiplier)
 | 
						|
        
 | 
						|
        SendNUIMessage({
 | 
						|
            type = 'setVolume',
 | 
						|
            volume = adjustedVolume
 | 
						|
        })
 | 
						|
        
 | 
						|
        currentVolume = data.volume
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Empfange aktive DJs
 | 
						|
RegisterNetEvent('dj:client:receiveActiveDJs', function(booths)
 | 
						|
    activeBooths = booths
 | 
						|
    
 | 
						|
    -- Prüfe ob Spieler in Reichweite eines aktiven DJ-Booths ist
 | 
						|
    local playerCoords = GetEntityCoords(PlayerPedId())
 | 
						|
    
 | 
						|
    for boothName, boothData in pairs(activeBooths) do
 | 
						|
        local distance = #(playerCoords - boothData.coords)
 | 
						|
        
 | 
						|
        if distance <= boothData.range then
 | 
						|
            -- Berechne Lautstärke basierend auf Distanz
 | 
						|
            local volumeMultiplier = 1.0 - (distance / boothData.range)
 | 
						|
            local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | 
						|
            
 | 
						|
            -- Spiele Musik ab
 | 
						|
            SendNUIMessage({
 | 
						|
                type = 'playMusic',
 | 
						|
                url = boothData.url,
 | 
						|
                volume = adjustedVolume,
 | 
						|
                title = boothData.title
 | 
						|
            })
 | 
						|
            
 | 
						|
            currentBooth = {
 | 
						|
                name = boothName,
 | 
						|
                coords = boothData.coords
 | 
						|
            }
 | 
						|
            isPlaying = true
 | 
						|
            currentSong = {
 | 
						|
                title = boothData.title,
 | 
						|
                url = boothData.url
 | 
						|
            }
 | 
						|
            
 | 
						|
            lib.notify({
 | 
						|
                title = 'DJ System',
 | 
						|
                description = 'Spielt: ' .. boothData.title,
 | 
						|
                type = 'info'
 | 
						|
            })
 | 
						|
            
 | 
						|
            break
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('djInterfaceClosed', function(data, cb)
 | 
						|
    SetNuiFocus(false, false)
 | 
						|
    isUIOpen = false
 | 
						|
    
 | 
						|
    -- Kurze Verzögerung, um sicherzustellen, dass alle Animationen abgeschlossen sind
 | 
						|
    Wait(100)
 | 
						|
    
 | 
						|
    -- Aktiviere alle Controls wieder
 | 
						|
    EnableAllControlActions(0)
 | 
						|
    
 | 
						|
    -- Musik NICHT stoppen, wenn stopMusic nicht explizit true ist
 | 
						|
    if data.stopMusic then
 | 
						|
        -- Stoppe Musik nur wenn explizit angefordert
 | 
						|
        if currentBooth then
 | 
						|
            TriggerServerEvent('dj:server:stopMusic', currentBooth.name)
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
 | 
						|
RegisterNUICallback('deckStateChanged', function(data, cb)
 | 
						|
    if Config.Debug then
 | 
						|
        print(string.format('[DJ System] Deck %s %s: %s', 
 | 
						|
            data.deck, 
 | 
						|
            data.isPlaying and 'playing' or 'stopped',
 | 
						|
            data.track and data.track.title or 'No track'
 | 
						|
        ))
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Wenn Deck A oder B abspielt, sende an Server
 | 
						|
    if data.isPlaying and data.track then
 | 
						|
        PlayMusicAsDJ(data.track.title, data.track.url, currentVolume)
 | 
						|
    end
 | 
						|
    
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('volumeChanged', function(data, cb)
 | 
						|
    if data.volume then
 | 
						|
        SetVolumeAsDJ(data.volume)
 | 
						|
    end
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('stopMusic', function(data, cb)
 | 
						|
    StopMusicAsDJ()
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('audioError', function(data, cb)
 | 
						|
    lib.notify({
 | 
						|
        title = 'DJ System',
 | 
						|
        description = 'Audio Fehler: ' .. (data.error or 'Unbekannter Fehler'),
 | 
						|
        type = 'error'
 | 
						|
    })
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('songEnded', function(data, cb)
 | 
						|
    -- Wenn ein Song endet, kann hier Playlist-Logik implementiert werden
 | 
						|
    if Config.Debug then
 | 
						|
        print('[DJ System] Song ended')
 | 
						|
    end
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('loadTrack', function(data, cb)
 | 
						|
    if data.deck and data.track then
 | 
						|
        -- Lade Track in Deck
 | 
						|
        if data.deck == "A" or data.deck == "B" then
 | 
						|
            -- Hier könntest du zusätzliche Logik hinzufügen
 | 
						|
            cb({success = true})
 | 
						|
        else
 | 
						|
            cb({success = false, error = "Ungültiges Deck"})
 | 
						|
        end
 | 
						|
    else
 | 
						|
        cb({success = false, error = "Fehlende Daten"})
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('playTrack', function(data, cb)
 | 
						|
    if data.deck and data.track then
 | 
						|
        -- Spiele Track ab
 | 
						|
        PlayMusicAsDJ(data.track.title, data.track.url, currentVolume)
 | 
						|
        cb({success = true})
 | 
						|
    else
 | 
						|
        cb({success = false, error = "Fehlende Daten"})
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('getPlaylists', function(data, cb)
 | 
						|
    -- Hole Playlists vom Server
 | 
						|
    QBCore.Functions.TriggerCallback('dj:server:getPlaylists', function(playlists)
 | 
						|
        cb({success = true, playlists = playlists})
 | 
						|
    end)
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('createPlaylist', function(data, cb)
 | 
						|
    if data.name then
 | 
						|
        -- Erstelle Playlist
 | 
						|
        TriggerServerEvent('dj:server:createPlaylist', data.name, data.description, data.isPublic)
 | 
						|
        cb({success = true})
 | 
						|
    else
 | 
						|
        cb({success = false, error = "Fehlender Name"})
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('addToPlaylist', function(data, cb)
 | 
						|
    if data.playlistId and data.track then
 | 
						|
        -- Füge Track zu Playlist hinzu
 | 
						|
        TriggerServerEvent('dj:server:addSongToPlaylist', data.playlistId, data.track)
 | 
						|
        cb({success = true})
 | 
						|
    else
 | 
						|
        cb({success = false, error = "Fehlende Daten"})
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNUICallback('getSessionHistory', function(data, cb)
 | 
						|
    -- Hole Session-Historie vom Server
 | 
						|
    QBCore.Functions.TriggerCallback('dj:server:getSessionHistory', function(history)
 | 
						|
        cb({success = true, history = history})
 | 
						|
    end, data.limit)
 | 
						|
end)
 | 
						|
 | 
						|
-- Functions
 | 
						|
function CanUseDJScript()
 | 
						|
    if not Config.UseJobRestriction then
 | 
						|
        return true
 | 
						|
    end
 | 
						|
    
 | 
						|
    if not PlayerData.job then
 | 
						|
        return false
 | 
						|
    end
 | 
						|
    
 | 
						|
    for _, job in pairs(Config.AllowedJobs) do
 | 
						|
        if PlayerData.job.name == job then
 | 
						|
            return true
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
function OpenDJInterface()
 | 
						|
    if not isDJBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ Pult stehen',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    SetNuiFocus(true, true)
 | 
						|
    SendNUIMessage({
 | 
						|
        type = 'showDJInterface'
 | 
						|
    })
 | 
						|
    
 | 
						|
    isUIOpen = true
 | 
						|
    
 | 
						|
    -- Disable controls while UI is open
 | 
						|
    CreateThread(function()
 | 
						|
        while isUIOpen do
 | 
						|
            DisableAllControlActions(0)
 | 
						|
            EnableControlAction(0, 1, true) -- Mouse look
 | 
						|
            EnableControlAction(0, 2, true) -- Mouse look
 | 
						|
            EnableControlAction(0, 3, true) -- Mouse movement
 | 
						|
            EnableControlAction(0, 4, true) -- Mouse movement
 | 
						|
            EnableControlAction(0, 5, true) -- Mouse wheel
 | 
						|
            EnableControlAction(0, 6, true) -- Mouse wheel
 | 
						|
            Wait(0)
 | 
						|
        end
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
function PlayMusicAsDJ(title, url, volume)
 | 
						|
    if not nearestBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ-Pult stehen!',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Bereinige YouTube URL von Playlist-Parametern
 | 
						|
    local cleanUrl = url
 | 
						|
    if string.find(url, "youtube") then
 | 
						|
        cleanUrl = string.gsub(url, "&list=.-$", "")
 | 
						|
        cleanUrl = string.gsub(cleanUrl, "&start_radio=.-$", "")
 | 
						|
        cleanUrl = string.gsub(cleanUrl, "&index=.-$", "")
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Sende an Server zur Synchronisation
 | 
						|
    TriggerServerEvent('dj:server:playMusic', {
 | 
						|
        title = title,
 | 
						|
        url = cleanUrl,
 | 
						|
        volume = volume or Config.DefaultVolume,
 | 
						|
        booth = {
 | 
						|
            name = nearestBooth,
 | 
						|
            coords = Config.DJBooths[nearestBooth].coords
 | 
						|
        },
 | 
						|
        range = CalculateRange(volume or Config.DefaultVolume)
 | 
						|
    })
 | 
						|
    
 | 
						|
    -- Lokale Variablen aktualisieren
 | 
						|
    isPlaying = true
 | 
						|
    currentVolume = volume or Config.DefaultVolume
 | 
						|
    currentSong = {
 | 
						|
        title = title,
 | 
						|
        url = cleanUrl
 | 
						|
    }
 | 
						|
    currentBooth = {
 | 
						|
        name = nearestBooth,
 | 
						|
        coords = Config.DJBooths[nearestBooth].coords
 | 
						|
    }
 | 
						|
end
 | 
						|
 | 
						|
function StopMusicAsDJ()
 | 
						|
    if not nearestBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ-Pult stehen!',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Sende an Server zur Synchronisation
 | 
						|
    TriggerServerEvent('dj:server:stopMusic', nearestBooth)
 | 
						|
    
 | 
						|
    -- Lokale Variablen aktualisieren
 | 
						|
    isPlaying = false
 | 
						|
    currentSong = nil
 | 
						|
    currentBooth = nil
 | 
						|
end
 | 
						|
 | 
						|
function SetVolumeAsDJ(volume)
 | 
						|
    if not nearestBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ-Pult stehen!',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Sende an Server zur Synchronisation
 | 
						|
    TriggerServerEvent('dj:server:setVolume', {
 | 
						|
        volume = volume,
 | 
						|
        booth = {
 | 
						|
            name = nearestBooth,
 | 
						|
            coords = Config.DJBooths[nearestBooth].coords
 | 
						|
        },
 | 
						|
        range = CalculateRange(volume)
 | 
						|
    })
 | 
						|
    
 | 
						|
    -- Lokale Variablen aktualisieren
 | 
						|
    currentVolume = volume
 | 
						|
end
 | 
						|
 | 
						|
function CalculateRange(volume)
 | 
						|
    if not nearestBooth or not Config.DJBooths[nearestBooth] then return 30.0 end
 | 
						|
    
 | 
						|
    local booth = Config.DJBooths[nearestBooth]
 | 
						|
    local baseRange = booth.range or 30.0
 | 
						|
    local maxRange = booth.maxRange or 50.0
 | 
						|
    local volumePercent = volume / 100
 | 
						|
    
 | 
						|
    return baseRange + ((maxRange - baseRange) * volumePercent)
 | 
						|
end
 | 
						|
 | 
						|
-- Regelmäßige Prüfung der Distanz zu DJ-Booths und aktiven Musiken
 | 
						|
CreateThread(function()
 | 
						|
    while true do
 | 
						|
        Wait(Config.DistanceVolume and Config.DistanceVolume.updateInterval or 1000)
 | 
						|
        
 | 
						|
        local playerCoords = GetEntityCoords(PlayerPedId())
 | 
						|
        local foundBooth = false
 | 
						|
        nearestBooth = nil
 | 
						|
        local nearestDistance = 999999.9
 | 
						|
        
 | 
						|
        -- Prüfe Nähe zu DJ-Booths
 | 
						|
        for boothName, booth in pairs(Config.DJBooths) do
 | 
						|
            local distance = #(playerCoords - booth.coords)
 | 
						|
            
 | 
						|
            -- Finde das nächste DJ-Booth
 | 
						|
            if distance < nearestDistance then
 | 
						|
                nearestDistance = distance
 | 
						|
                nearestBooth = boothName
 | 
						|
            end
 | 
						|
            
 | 
						|
            -- Prüfe ob Spieler an einem DJ-Booth steht
 | 
						|
            if distance <= 2.0 then
 | 
						|
                foundBooth = true
 | 
						|
                break
 | 
						|
            end
 | 
						|
        end
 | 
						|
        
 | 
						|
        isDJBooth = foundBooth
 | 
						|
        
 | 
						|
        -- Prüfe Distanz zu aktiven Musiken
 | 
						|
        if not isPlaying and next(activeBooths) then
 | 
						|
            -- Spieler hört keine Musik, prüfe ob er in Reichweite eines aktiven DJ-Booths ist
 | 
						|
            for boothName, boothData in pairs(activeBooths) do
 | 
						|
                local distance = #(playerCoords - boothData.coords)
 | 
						|
                
 | 
						|
                if distance <= boothData.range then
 | 
						|
                    -- Berechne Lautstärke basierend auf Distanz
 | 
						|
                    local volumeMultiplier = 1.0 - (distance / boothData.range)
 | 
						|
                    local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | 
						|
                    
 | 
						|
                    -- Spiele Musik ab
 | 
						|
                    SendNUIMessage({
 | 
						|
                        type = 'playMusic',
 | 
						|
                        url = boothData.url,
 | 
						|
                        volume = adjustedVolume,
 | 
						|
                        title = boothData.title
 | 
						|
                    })
 | 
						|
                    
 | 
						|
                    currentBooth = {
 | 
						|
                        name = boothName,
 | 
						|
                        coords = boothData.coords
 | 
						|
                    }
 | 
						|
                    isPlaying = true
 | 
						|
                    currentSong = {
 | 
						|
                        title = boothData.title,
 | 
						|
                        url = boothData.url
 | 
						|
                    }
 | 
						|
                    
 | 
						|
                    lib.notify({
 | 
						|
                        title = 'DJ System',
 | 
						|
                        description = 'Spielt: ' .. boothData.title,
 | 
						|
                        type = 'info'
 | 
						|
                    })
 | 
						|
                    
 | 
						|
                    break
 | 
						|
                end
 | 
						|
            end
 | 
						|
        elseif isPlaying and currentBooth then
 | 
						|
            -- Spieler hört Musik, prüfe ob er noch in Reichweite ist
 | 
						|
            local boothData = activeBooths[currentBooth.name]
 | 
						|
            
 | 
						|
            if boothData then
 | 
						|
                local distance = #(playerCoords - boothData.coords)
 | 
						|
                
 | 
						|
                if distance > boothData.range then
 | 
						|
                    -- Spieler hat Reichweite verlassen, stoppe Musik
 | 
						|
                    SendNUIMessage({
 | 
						|
                        type = 'stopMusic'
 | 
						|
                    })
 | 
						|
                    
 | 
						|
                    currentBooth = nil
 | 
						|
                    isPlaying = false
 | 
						|
                    currentSong = nil
 | 
						|
                    
 | 
						|
                    lib.notify({
 | 
						|
                        title = 'DJ System',
 | 
						|
                        description = 'Musik außer Reichweite',
 | 
						|
                        type = 'info'
 | 
						|
                    })
 | 
						|
                else
 | 
						|
                    -- Spieler ist noch in Reichweite, passe Lautstärke an
 | 
						|
                    local volumeMultiplier = 1.0 - (distance / boothData.range)
 | 
						|
                    local adjustedVolume = math.floor(boothData.volume * volumeMultiplier)
 | 
						|
                    
 | 
						|
                    SendNUIMessage({
 | 
						|
                        type = 'setVolume',
 | 
						|
                        volume = adjustedVolume
 | 
						|
                    })
 | 
						|
                end
 | 
						|
            else
 | 
						|
                -- Booth existiert nicht mehr, stoppe Musik
 | 
						|
                SendNUIMessage({
 | 
						|
                    type = 'stopMusic'
 | 
						|
                })
 | 
						|
                
 | 
						|
                currentBooth = nil
 | 
						|
                isPlaying = false
 | 
						|
                currentSong = nil
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- DJ Booth Blips und Interaktionen
 | 
						|
CreateThread(function()
 | 
						|
    -- Erstelle Blips für DJ-Booths
 | 
						|
    for boothName, booth in pairs(Config.DJBooths) do
 | 
						|
        local blip = AddBlipForCoord(booth.coords)
 | 
						|
        SetBlipSprite(blip, 614)
 | 
						|
        SetBlipDisplay(blip, 4)
 | 
						|
        SetBlipScale(blip, 0.7)
 | 
						|
        SetBlipColour(blip, 47)
 | 
						|
        SetBlipAsShortRange(blip, true)
 | 
						|
        BeginTextCommandSetBlipName("STRING")
 | 
						|
        AddTextComponentString("DJ Booth - " .. boothName)
 | 
						|
        EndTextCommandSetBlipName(blip)
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Erstelle Interaktionspunkte für DJ-Booths
 | 
						|
    for boothName, booth in pairs(Config.DJBooths) do
 | 
						|
        exports['qb-target']:AddBoxZone("dj_booth_" .. boothName, booth.coords, 1.5, 1.5, {
 | 
						|
            name = "dj_booth_" .. boothName,
 | 
						|
            heading = 0,
 | 
						|
            debugPoly = Config.Debug,
 | 
						|
            minZ = booth.coords.z - 1.0,
 | 
						|
            maxZ = booth.coords.z + 1.0
 | 
						|
        }, {
 | 
						|
            options = {
 | 
						|
                {
 | 
						|
                    type = "client",
 | 
						|
                    event = "dj:client:openDJMenu",
 | 
						|
                    icon = "fas fa-music",
 | 
						|
                    label = "DJ System öffnen",
 | 
						|
                    boothName = boothName,
 | 
						|
                    job = Config.UseJobRestriction and Config.AllowedJobs or nil
 | 
						|
                }
 | 
						|
            },
 | 
						|
            distance = 2.0
 | 
						|
        })
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Event für Target-Integration
 | 
						|
RegisterNetEvent('dj:client:openDJMenu', function(data)
 | 
						|
    nearestBooth = data.boothName
 | 
						|
    isDJBooth = true
 | 
						|
    OpenDJInterface()
 | 
						|
end)
 | 
						|
 | 
						|
-- Debug
 | 
						|
if Config.Debug then
 | 
						|
    RegisterCommand('djdebug', function()
 | 
						|
        print('--- DJ SYSTEM DEBUG ---')
 | 
						|
        print('isPlaying:', isPlaying)
 | 
						|
        print('isDJBooth:', isDJBooth)
 | 
						|
        print('nearestBooth:', nearestBooth)
 | 
						|
        print('currentBooth:', currentBooth and currentBooth.name or 'nil')
 | 
						|
        print('currentVolume:', currentVolume)
 | 
						|
        print('currentSong:', currentSong and currentSong.title or 'nil')
 | 
						|
        print('activeBooths:')
 | 
						|
        for boothName, boothData in pairs(activeBooths) do
 | 
						|
            print('  -', boothName, boothData.title, boothData.volume)
 | 
						|
        end
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
function OpenDJInterface()
 | 
						|
    if not isDJBooth then
 | 
						|
        lib.notify({
 | 
						|
            title = 'DJ System',
 | 
						|
            description = 'Du musst an einem DJ Pult stehen',
 | 
						|
            type = 'error'
 | 
						|
        })
 | 
						|
        return
 | 
						|
    end
 | 
						|
    
 | 
						|
    SetNuiFocus(true, true)
 | 
						|
    SendNUIMessage({
 | 
						|
        type = 'showDJInterface',
 | 
						|
        center = true, -- Hinzugefügt: Zentriere das Interface
 | 
						|
        reset = true   -- Hinzugefügt: Setze Position zurück
 | 
						|
    })
 | 
						|
    
 | 
						|
    isUIOpen = true
 | 
						|
    
 | 
						|
    -- Disable controls while UI is open
 | 
						|
    CreateThread(function()
 | 
						|
        while isUIOpen do
 | 
						|
            DisableAllControlActions(0)
 | 
						|
            EnableControlAction(0, 1, true) -- Mouse look
 | 
						|
            EnableControlAction(0, 2, true) -- Mouse look
 | 
						|
            EnableControlAction(0, 3, true) -- Mouse movement
 | 
						|
            EnableControlAction(0, 4, true) -- Mouse movement
 | 
						|
            EnableControlAction(0, 5, true) -- Mouse wheel
 | 
						|
            EnableControlAction(0, 6, true) -- Mouse wheel
 | 
						|
            Wait(0)
 | 
						|
        end
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
 | 
						|
-- Callback-Handler für NUI
 | 
						|
RegisterNUICallback('callback', function(data, cb)
 | 
						|
    if data.callbackId then
 | 
						|
        SendNUIMessage({
 | 
						|
            type = 'callbackResponse',
 | 
						|
            callbackId = data.callbackId,
 | 
						|
            response = data.response or {}
 | 
						|
        })
 | 
						|
    end
 | 
						|
    cb('ok')
 | 
						|
end)
 | 
						|
 | 
						|
-- Verbesserte Error-Handling
 | 
						|
RegisterNUICallback('error', function(data, cb)
 | 
						|
    print("DJ System Error: " .. (data.error or "Unknown error"))
 | 
						|
    cb('ok')
 | 
						|
    
 | 
						|
    -- Benachrichtige Spieler
 | 
						|
    lib.notify({
 | 
						|
        title = 'DJ System Error',
 | 
						|
        description = data.error or "Ein unbekannter Fehler ist aufgetreten",
 | 
						|
        type = 'error'
 | 
						|
    })
 | 
						|
end)
 | 
						|
 | 
						|
-- Debug-Funktion für NUI-Status
 | 
						|
function DebugNUIStatus()
 | 
						|
    local nuiFocus = {GetNuiFocus()}
 | 
						|
    print("NUI Focus:", json.encode(nuiFocus))
 | 
						|
    print("isUIOpen:", isUIOpen)
 | 
						|
    print("isDJBooth:", isDJBooth)
 | 
						|
    print("nearestBooth:", nearestBooth)
 | 
						|
end
 | 
						|
 | 
						|
-- Debug-Befehl
 | 
						|
RegisterCommand('djdebug', function()
 | 
						|
    DebugNUIStatus()
 | 
						|
end, false)
 |