local QBCore = exports['qb-core']:GetCoreObject() local currentVehicle = nil -- Boot-Klassen für spezielle Behandlung local boatClasses = { [14] = true, -- Boats [15] = true, -- Helicopters (falls gewünscht) [16] = true -- Planes (falls gewünscht) } -- Sitz-Namen für bessere Anzeige local seatNames = { [-1] = "Kapitän", [0] = "Beifahrer", [1] = "Hinten Links", [2] = "Hinten Rechts", [3] = "Hinten Mitte", [4] = "Deck 1", [5] = "Deck 2", [6] = "Deck 3", [7] = "Deck 4", [8] = "Deck 5", [9] = "Deck 6" } -- Prüfe ob Fahrzeug ein Boot ist local function isBoat(vehicle) local vehicleClass = GetVehicleClass(vehicle) return boatClasses[vehicleClass] or false end -- Funktion um verfügbare Sitze zu bekommen local function getAvailableSeats(vehicle) local seats = {} local maxSeats = GetVehicleMaxNumberOfPassengers(vehicle) -- Fahrersitz (-1) if IsVehicleSeatFree(vehicle, -1) then local seatName = isBoat(vehicle) and seatNames[-1] or "Fahrer" table.insert(seats, { index = -1, name = seatName, icon = isBoat(vehicle) and "fas fa-anchor" or "fas fa-steering-wheel" }) end -- Passagiersitze (0 bis maxSeats-1) for i = 0, maxSeats - 1 do if IsVehicleSeatFree(vehicle, i) then table.insert(seats, { index = i, name = seatNames[i] or "Sitz " .. (i + 1), icon = "fas fa-user" }) end end return seats end -- Funktion um belegte Sitze zu bekommen local function getOccupiedSeats(vehicle) local occupiedSeats = {} local maxSeats = GetVehicleMaxNumberOfPassengers(vehicle) -- Fahrersitz prüfen if not IsVehicleSeatFree(vehicle, -1) then local ped = GetPedInVehicleSeat(vehicle, -1) local playerName = "Unbekannt" if IsPedAPlayer(ped) then local playerId = NetworkGetPlayerIndexFromPed(ped) if playerId ~= -1 then playerName = GetPlayerName(playerId) end else playerName = "NPC" end local seatName = isBoat(vehicle) and seatNames[-1] or "Fahrer" table.insert(occupiedSeats, { index = -1, name = seatName, occupant = playerName, icon = isBoat(vehicle) and "fas fa-anchor" or "fas fa-steering-wheel" }) end -- Passagiersitze prüfen for i = 0, maxSeats - 1 do if not IsVehicleSeatFree(vehicle, i) then local ped = GetPedInVehicleSeat(vehicle, i) local playerName = "Unbekannt" if IsPedAPlayer(ped) then local playerId = NetworkGetPlayerIndexFromPed(ped) if playerId ~= -1 then playerName = GetPlayerName(playerId) end else playerName = "NPC" end table.insert(occupiedSeats, { index = i, name = seatNames[i] or "Sitz " .. (i + 1), occupant = playerName, icon = "fas fa-user" }) end end return occupiedSeats end -- Funktion zum direkten Einsteigen (für Boote) local function teleportToSeat(vehicle, seatIndex) local playerPed = PlayerPedId() if IsPedInAnyVehicle(playerPed, false) then QBCore.Functions.Notify('Du bist bereits in einem Fahrzeug!', 'error') return end if not IsVehicleSeatFree(vehicle, seatIndex) then QBCore.Functions.Notify('Dieser Sitz ist bereits belegt!', 'error') return end -- Prüfe ob Fahrzeug abgeschlossen ist if GetVehicleDoorLockStatus(vehicle) == 2 then QBCore.Functions.Notify('Das Fahrzeug ist abgeschlossen!', 'error') return end -- Direkte Teleportation ohne Animation SetPedIntoVehicle(playerPed, vehicle, seatIndex) currentVehicle = vehicle local seatName = seatNames[seatIndex] or "Sitz " .. (seatIndex + 1) if isBoat(vehicle) then QBCore.Functions.Notify('Willkommen an Bord! (' .. seatName .. ')', 'success') else QBCore.Functions.Notify('Du bist eingestiegen (' .. seatName .. ')', 'success') end end -- Funktion zum normalen Einsteigen (für Autos) local function enterVehicleSeat(vehicle, seatIndex) local playerPed = PlayerPedId() if IsPedInAnyVehicle(playerPed, false) then QBCore.Functions.Notify('Du bist bereits in einem Fahrzeug!', 'error') return end if not IsVehicleSeatFree(vehicle, seatIndex) then QBCore.Functions.Notify('Dieser Sitz ist bereits belegt!', 'error') return end -- Prüfe ob Fahrzeug abgeschlossen ist if GetVehicleDoorLockStatus(vehicle) == 2 then QBCore.Functions.Notify('Das Fahrzeug ist abgeschlossen!', 'error') return end TaskEnterVehicle(playerPed, vehicle, 10000, seatIndex, 1.0, 1, 0) currentVehicle = vehicle local seatName = seatNames[seatIndex] or "Sitz " .. (seatIndex + 1) QBCore.Functions.Notify('Steige in das Fahrzeug ein (' .. seatName .. ')...', 'primary') end -- Funktion zum Sitzwechsel local function switchSeat(vehicle, newSeatIndex) local playerPed = PlayerPedId() if not IsPedInVehicle(playerPed, vehicle, false) then QBCore.Functions.Notify('Du bist nicht in diesem Fahrzeug!', 'error') return end if not IsVehicleSeatFree(vehicle, newSeatIndex) then QBCore.Functions.Notify('Dieser Sitz ist bereits belegt!', 'error') return end -- Für Boote: Direkte Teleportation if isBoat(vehicle) then SetPedIntoVehicle(playerPed, vehicle, newSeatIndex) else -- Für Autos: Normale Animation TaskShuffleToNextVehicleSeat(playerPed, vehicle) Wait(100) SetPedIntoVehicle(playerPed, vehicle, newSeatIndex) end local seatName = seatNames[newSeatIndex] or "Sitz " .. (newSeatIndex + 1) QBCore.Functions.Notify('Gewechselt zu: ' .. seatName, 'success') end -- Hauptmenü für Sitzauswahl local function showSeatMenu(vehicle) local playerPed = PlayerPedId() local isInVehicle = IsPedInVehicle(playerPed, vehicle, false) local availableSeats = getAvailableSeats(vehicle) local occupiedSeats = getOccupiedSeats(vehicle) local isVehicleBoat = isBoat(vehicle) local options = {} -- Header local vehicleName = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)) local vehicleLabel = GetLabelText(vehicleName) if vehicleLabel == "NULL" then vehicleLabel = vehicleName end -- Boot-spezifische Anzeige if isVehicleBoat then vehicleLabel = "⛵ " .. vehicleLabel else vehicleLabel = "🚗 " .. vehicleLabel end -- Verfügbare Sitze if #availableSeats > 0 then local headerText = isVehicleBoat and '🟢 Verfügbare Plätze' or '🟢 Verfügbare Sitze' table.insert(options, { title = headerText, description = isVehicleBoat and 'Freie Plätze an Bord' or 'Freie Sitzplätze', disabled = true }) for _, seat in pairs(availableSeats) do local actionText = isInVehicle and 'Zu diesem Platz wechseln' or (isVehicleBoat and 'An Bord gehen' or 'In das Fahrzeug einsteigen') table.insert(options, { title = seat.name, description = actionText, icon = seat.icon, onSelect = function() if isInVehicle then switchSeat(vehicle, seat.index) else if isVehicleBoat then teleportToSeat(vehicle, seat.index) else enterVehicleSeat(vehicle, seat.index) end end end }) end end -- Belegte Sitze anzeigen if #occupiedSeats > 0 then local headerText = isVehicleBoat and '🔴 Belegte Plätze' or '🔴 Belegte Sitze' table.insert(options, { title = headerText, description = isVehicleBoat and 'Bereits besetzte Plätze' or 'Bereits besetzte Sitzplätze', disabled = true }) for _, seat in pairs(occupiedSeats) do table.insert(options, { title = seat.name, description = 'Besetzt von: ' .. seat.occupant, icon = seat.icon, disabled = true }) end end -- Aussteigen Option (nur wenn im Fahrzeug) if isInVehicle then local exitText = isVehicleBoat and '🚪 Von Bord gehen' or '🚪 Aussteigen' local exitDesc = isVehicleBoat and 'Das Boot verlassen' or 'Das Fahrzeug verlassen' table.insert(options, { title = exitText, description = exitDesc, icon = 'fas fa-door-open', onSelect = function() TaskLeaveVehicle(playerPed, vehicle, 0) local exitMsg = isVehicleBoat and 'Du gehst von Bord...' or 'Du steigst aus dem Fahrzeug aus...' QBCore.Functions.Notify(exitMsg, 'primary') end }) end -- Fahrzeuginfo table.insert(options, { title = '📋 Fahrzeuginfo', description = 'Informationen über das Fahrzeug', icon = 'fas fa-info-circle', onSelect = function() showVehicleInfo(vehicle) end }) if #options == 0 then QBCore.Functions.Notify('Keine verfügbaren Aktionen!', 'error') return end lib.registerContext({ id = 'vehicle_seat_menu', title = vehicleLabel, options = options }) lib.showContext('vehicle_seat_menu') end -- Fahrzeuginfo anzeigen function showVehicleInfo(vehicle) local vehicleProps = QBCore.Functions.GetVehicleProperties(vehicle) local vehicleName = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)) local vehicleLabel = GetLabelText(vehicleName) if vehicleLabel == "NULL" then vehicleLabel = vehicleName end local maxSeats = GetVehicleMaxNumberOfPassengers(vehicle) + 1 -- +1 für Fahrer local engineHealth = math.floor(GetVehicleEngineHealth(vehicle) / 10) local bodyHealth = math.floor(GetVehicleBodyHealth(vehicle) / 10) local isVehicleBoat = isBoat(vehicle) local options = { { title = (isVehicleBoat and 'Boot: ' or 'Fahrzeug: ') .. vehicleLabel, description = 'Kennzeichen: ' .. (vehicleProps.plate or 'Unbekannt'), icon = isVehicleBoat and 'fas fa-ship' or 'fas fa-car', disabled = true }, { title = (isVehicleBoat and 'Plätze: ' or 'Sitzplätze: ') .. maxSeats, description = 'Maximale Anzahl Personen', icon = 'fas fa-users', disabled = true }, { title = (isVehicleBoat and 'Motor: ' or 'Motor: ') .. engineHealth .. '%', description = 'Zustand des Motors', icon = 'fas fa-cog', disabled = true }, { title = (isVehicleBoat and 'Rumpf: ' or 'Karosserie: ') .. bodyHealth .. '%', description = isVehicleBoat and 'Zustand des Rumpfes' or 'Zustand der Karosserie', icon = isVehicleBoat and 'fas fa-ship' or 'fas fa-car-crash', disabled = true } } -- Kraftstoff nur für Nicht-Boote (Boote haben oft keinen Kraftstoff-Wert) if not isVehicleBoat then local fuelLevel = math.floor(GetVehicleFuelLevel(vehicle)) table.insert(options, { title = 'Kraftstoff: ' .. fuelLevel .. '%', description = 'Aktueller Tankstand', icon = 'fas fa-gas-pump', disabled = true }) end table.insert(options, { title = '← Zurück', description = 'Zurück zum Sitzmenü', icon = 'fas fa-arrow-left', onSelect = function() showSeatMenu(vehicle) end }) lib.registerContext({ id = 'vehicle_info_menu', title = '📋 Fahrzeuginfo', options = options }) lib.showContext('vehicle_info_menu') end -- QB-Target Setup CreateThread(function() exports['qb-target']:AddGlobalVehicle({ options = { { type = "client", event = "vehicle:openSeatMenu", icon = "fas fa-car", label = "Sitzplatz wählen", } }, distance = 3.0 }) end) -- Event Handler RegisterNetEvent('vehicle:openSeatMenu', function(data) local vehicle = data.entity if DoesEntityExist(vehicle) and IsEntityAVehicle(vehicle) then showSeatMenu(vehicle) else QBCore.Functions.Notify('Kein gültiges Fahrzeug gefunden!', 'error') end end) -- Cleanup AddEventHandler('onResourceStop', function(resourceName) if GetCurrentResourceName() == resourceName then currentVehicle = nil end end) -- Keybind für schnellen Zugriff (Optional) RegisterCommand('seats', function() local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) if vehicle ~= 0 then showSeatMenu(vehicle) else -- Suche nach nahegelegenem Fahrzeug local coords = GetEntityCoords(playerPed) local closestVehicle = GetClosestVehicle(coords.x, coords.y, coords.z, 5.0, 0, 71) if DoesEntityExist(closestVehicle) then showSeatMenu(closestVehicle) else QBCore.Functions.Notify('Kein Fahrzeug in der Nähe!', 'error') end end end, false) -- Keybind registrieren RegisterKeyMapping('seats', 'Sitzplatz Menü öffnen', 'keyboard', 'F6')