From b846de7b20dca5b414c184c544c9b111d6920ca6 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Mon, 28 Jul 2025 04:10:56 +0200 Subject: [PATCH] ed --- .../[carscripts]/nordi_seats/client/main.lua | 191 ++++++++++++++++-- 1 file changed, 170 insertions(+), 21 deletions(-) diff --git a/resources/[carscripts]/nordi_seats/client/main.lua b/resources/[carscripts]/nordi_seats/client/main.lua index 27d5b82f8..3bf15ce27 100644 --- a/resources/[carscripts]/nordi_seats/client/main.lua +++ b/resources/[carscripts]/nordi_seats/client/main.lua @@ -1,11 +1,10 @@ local QBCore = exports['qb-core']:GetCoreObject() local currentVehicle = nil +local anchoredBoats = {} -- Speichert verankerte Boote -- 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 @@ -29,6 +28,84 @@ local function isBoat(vehicle) return boatClasses[vehicleClass] or false end +-- Anker setzen/entfernen +local function toggleAnchor(vehicle) + if not isBoat(vehicle) then + QBCore.Functions.Notify('Nur Boote können verankert werden!', 'error') + return + end + + local vehicleNetId = NetworkGetNetworkIdFromEntity(vehicle) + + if anchoredBoats[vehicleNetId] then + -- Anker lichten + FreezeEntityPosition(vehicle, false) + SetEntityInvincible(vehicle, false) + anchoredBoats[vehicleNetId] = nil + + QBCore.Functions.Notify('⚓ Anker gelichtet! Das Boot kann wieder bewegt werden.', 'success') + + -- Effekt: Kurzes Wackeln beim Anker lichten + CreateThread(function() + local originalCoords = GetEntityCoords(vehicle) + for i = 1, 10 do + local offset = math.random(-10, 10) / 100 + SetEntityCoords(vehicle, originalCoords.x + offset, originalCoords.y + offset, originalCoords.z) + Wait(50) + end + SetEntityCoords(vehicle, originalCoords.x, originalCoords.y, originalCoords.z) + end) + else + -- Anker werfen + local coords = GetEntityCoords(vehicle) + local heading = GetEntityHeading(vehicle) + + FreezeEntityPosition(vehicle, true) + SetEntityInvincible(vehicle, true) + + anchoredBoats[vehicleNetId] = { + coords = coords, + heading = heading, + time = GetGameTimer() + } + + QBCore.Functions.Notify('⚓ Anker geworfen! Das Boot ist jetzt verankert.', 'success') + + -- Anker-Wurf Effekt + CreateThread(function() + -- Spiele Anker-Sound (falls vorhanden) + PlaySoundFromEntity(-1, "CHECKPOINT_PERFECT", vehicle, "HUD_MINI_GAME_SOUNDSET", 0, 0) + + -- Kleine Wellen-Animation + for i = 1, 5 do + local waterHeight = GetWaterHeight(coords.x, coords.y, coords.z) + if waterHeight then + -- Erstelle Wasser-Effekt um das Boot + local effect = "ent_sht_water" + RequestNamedPtfxAsset(effect) + while not HasNamedPtfxAssetLoaded(effect) do + Wait(1) + end + + for j = 1, 3 do + local offsetX = math.random(-200, 200) / 100 + local offsetY = math.random(-200, 200) / 100 + UsePartikelFxAssetNextCall(effect) + StartParticleFxNonLoopedAtCoord("ent_sht_water", coords.x + offsetX, coords.y + offsetY, waterHeight, 0.0, 0.0, 0.0, 0.5, false, false, false) + end + end + Wait(200) + end + end) + end +end + +-- Prüfe ob Boot verankert ist +local function isBoatAnchored(vehicle) + local vehicleNetId = NetworkGetNetworkIdFromEntity(vehicle) + return anchoredBoats[vehicleNetId] ~= nil +end + -- Funktion um verfügbare Sitze zu bekommen local function getAvailableSeats(vehicle) local seats = {} @@ -140,6 +217,11 @@ local function teleportToSeat(vehicle, seatIndex) local seatName = seatNames[seatIndex] or "Sitz " .. (seatIndex + 1) if isBoat(vehicle) then QBCore.Functions.Notify('Willkommen an Bord! (' .. seatName .. ')', 'success') + + -- Zeige Anker-Status wenn Kapitän + if seatIndex == -1 and isBoatAnchored(vehicle) then + QBCore.Functions.Notify('⚓ Das Boot ist verankert. Nutze das Menü um den Anker zu lichten.', 'primary') + end else QBCore.Functions.Notify('Du bist eingestiegen (' .. seatName .. ')', 'success') end @@ -198,6 +280,11 @@ local function switchSeat(vehicle, newSeatIndex) local seatName = seatNames[newSeatIndex] or "Sitz " .. (newSeatIndex + 1) QBCore.Functions.Notify('Gewechselt zu: ' .. seatName, 'success') + + -- Zeige Anker-Status wenn zum Kapitän gewechselt + if isBoat(vehicle) and newSeatIndex == -1 and isBoatAnchored(vehicle) then + QBCore.Functions.Notify('⚓ Das Boot ist verankert. Nutze das Menü um den Anker zu lichten.', 'primary') + end end -- Hauptmenü für Sitzauswahl @@ -207,6 +294,7 @@ local function showSeatMenu(vehicle) local availableSeats = getAvailableSeats(vehicle) local occupiedSeats = getOccupiedSeats(vehicle) local isVehicleBoat = isBoat(vehicle) + local isAnchored = isBoatAnchored(vehicle) local options = {} -- Header @@ -216,13 +304,35 @@ local function showSeatMenu(vehicle) vehicleLabel = vehicleName end - -- Boot-spezifische Anzeige + -- Boot-spezifische Anzeige mit Anker-Status if isVehicleBoat then - vehicleLabel = "⛵ " .. vehicleLabel + vehicleLabel = (isAnchored and "⚓ " or "⛵ ") .. vehicleLabel else vehicleLabel = "🚗 " .. vehicleLabel end + -- Anker-Kontrolle (nur für Boote und nur wenn im Boot) + if isVehicleBoat and isInVehicle then + local currentSeat = GetPedVehicleSeat(playerPed) + -- Nur Kapitän kann Anker bedienen + if currentSeat == -1 then + table.insert(options, { + title = isAnchored and '⚓ Anker lichten' or '⚓ Anker werfen', + description = isAnchored and 'Boot wieder beweglich machen' or 'Boot an aktueller Position verankern', + icon = 'fas fa-anchor', + onSelect = function() + toggleAnchor(vehicle) + end + }) + + -- Trennlinie + table.insert(options, { + title = '─────────────────', + disabled = true + }) + end + end + -- Verfügbare Sitze if #availableSeats > 0 then local headerText = isVehicleBoat and '🟢 Verfügbare Plätze' or '🟢 Verfügbare Sitze' @@ -325,6 +435,7 @@ function showVehicleInfo(vehicle) local engineHealth = math.floor(GetVehicleEngineHealth(vehicle) / 10) local bodyHealth = math.floor(GetVehicleBodyHealth(vehicle) / 10) local isVehicleBoat = isBoat(vehicle) + local isAnchored = isBoatAnchored(vehicle) local options = { { @@ -338,22 +449,34 @@ function showVehicleInfo(vehicle) 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) + -- Anker-Status für Boote + if isVehicleBoat then + table.insert(options, { + title = 'Anker-Status: ' .. (isAnchored and 'Verankert ⚓' or 'Gelichtet ⛵'), + description = isAnchored and 'Das Boot ist an der aktuellen Position verankert' or 'Das Boot kann frei bewegt werden', + icon = 'fas fa-anchor', + disabled = true + }) + end + + table.insert(options, { + title = (isVehicleBoat and 'Motor: ' or 'Motor: ') .. engineHealth .. '%', + description = 'Zustand des Motors', + icon = 'fas fa-cog', + disabled = true + }) + + table.insert(options, { + 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 if not isVehicleBoat then local fuelLevel = math.floor(GetVehicleFuelLevel(vehicle)) table.insert(options, { @@ -407,14 +530,23 @@ RegisterNetEvent('vehicle:openSeatMenu', function(data) end end) --- Cleanup +-- Cleanup verankerte Boote bei Resource Stop AddEventHandler('onResourceStop', function(resourceName) if GetCurrentResourceName() == resourceName then + -- Alle verankerten Boote wieder freigeben + for vehicleNetId, _ in pairs(anchoredBoats) do + local vehicle = NetworkGetEntityFromNetworkId(vehicleNetId) + if DoesEntityExist(vehicle) then + FreezeEntityPosition(vehicle, false) + SetEntityInvincible(vehicle, false) + end + end + anchoredBoats = {} currentVehicle = nil end end) --- Keybind für schnellen Zugriff (Optional) +-- Keybind für schnellen Zugriff RegisterCommand('seats', function() local playerPed = PlayerPedId() local vehicle = GetVehiclePedIsIn(playerPed, false) @@ -422,7 +554,6 @@ RegisterCommand('seats', function() 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) @@ -434,5 +565,23 @@ RegisterCommand('seats', function() end end, false) --- Keybind registrieren +-- Schneller Anker-Befehl für Kapitäne +RegisterCommand('anchor', function() + local playerPed = PlayerPedId() + local vehicle = GetVehiclePedIsIn(playerPed, false) + + if vehicle ~= 0 and isBoat(vehicle) then + local seat = GetPedVehicleSeat(playerPed) + if seat == -1 then -- Nur Kapitän + toggleAnchor(vehicle) + else + QBCore.Functions.Notify('Nur der Kapitän kann den Anker bedienen!', 'error') + end + else + QBCore.Functions.Notify('Du musst Kapitän eines Bootes sein!', 'error') + end +end, false) + +-- Keybinds registrieren RegisterKeyMapping('seats', 'Sitzplatz Menü öffnen', 'keyboard', 'F6') +RegisterKeyMapping('anchor', 'Anker werfen/lichten', 'keyboard', 'H')