From f148a720da2ee0485efaa69479580410defc15fc Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Apr 2026 22:45:02 +0200 Subject: [PATCH] Auto-sync 2026-04-15 22:45 --- mercyv-bike/client/main.lua | 70 ++++++++++++++++++------------ mercyv-bike/nui/index.html | 35 ++++++++++++--- mercyv-bike/server/main.lua | 39 ++++++++++++----- mercyv-deathscreen/client/main.lua | 2 +- 4 files changed, 100 insertions(+), 46 deletions(-) diff --git a/mercyv-bike/client/main.lua b/mercyv-bike/client/main.lua index 536b456..fcbec01 100644 --- a/mercyv-bike/client/main.lua +++ b/mercyv-bike/client/main.lua @@ -136,33 +136,30 @@ end) -- Admin: Aktuelle Position erfassen RegisterNUICallback('capturePos', function(data, cb) + local field = data.field or 'npc' ClosePanel() Citizen.Wait(300) - local ped = PlayerPedId() - local coords = GetEntityCoords(ped) - local heading = GetEntityHeading(ped) - Notify("Geh zur NPC-Position und drücke E.", "info") + Notify("Geh zur Position und drücke E.", "info") exports['hex_4_hud']:ShowHelpNotify("Position erfassen", "E") Citizen.CreateThread(function() while true do Citizen.Wait(0) - if IsControlJustPressed(0, 38) then -- E + if IsControlJustPressed(0, 38) then exports['hex_4_hud']:HideHelpNotify() - local c = GetEntityCoords(PlayerPedId()) - local h = GetEntityHeading(PlayerPedId()) - -- Panel wieder öffnen mit erfassten Koordinaten + local coords = GetEntityCoords(PlayerPedId()) + local heading = GetEntityHeading(PlayerPedId()) SetNuiFocus(true, true) exports['hex_4_hud']:HideHud(true) PanelOpen = true SendNUIMessage({ action = "OPEN_ADMIN", isAdmin = IsAdmin, - captured = { x = c.x, y = c.y, z = c.z, heading = h }, + captured = { x = coords.x, y = coords.y, z = coords.z, heading = heading, field = field }, }) break - elseif IsControlJustPressed(0, 322) then -- ESC + elseif IsControlJustPressed(0, 322) then exports['hex_4_hud']:HideHelpNotify() OpenPanel() break @@ -218,27 +215,47 @@ end) -- ── Fahrrad spawnen ──────────────────────────────────────────── -RegisterNetEvent('mercyv-bike:doSpawn', function(bikeModel) +RegisterNetEvent('mercyv-bike:doSpawn', function(bikeModel, spawnData) + print('[mercyv-bike] Spawne Fahrrad: ' .. tostring(bikeModel)) + local model = GetHashKey(bikeModel) + if model == 0 then + Notify("Unbekanntes Fahrrad-Modell: " .. tostring(bikeModel), "error") + return + end + RequestModel(model) - local t = GetGameTimer() + 5000 + local t = GetGameTimer() + 8000 while not HasModelLoaded(model) do if GetGameTimer() > t then - Notify("Fahrrad konnte nicht gespawnt werden.", "error") + Notify("Fahrrad-Modell konnte nicht geladen werden.", "error") return end Citizen.Wait(100) end - local ped = PlayerPedId() - local coords = GetEntityCoords(ped) - local heading = GetEntityHeading(ped) - local rad = math.rad(heading) - local spawnX = coords.x + math.sin(-rad) * Config.SpawnOffset - local spawnY = coords.y + math.cos(-rad) * Config.SpawnOffset + -- Spawn-Position: vom Server gesetzte Koordinaten oder vor Spieler + local sx, sy, sz, sh + if spawnData and spawnData.x and spawnData.x ~= 0 then + sx = spawnData.x + sy = spawnData.y + sz = spawnData.z + sh = spawnData.heading or 0 + else + local ped = PlayerPedId() + local coords = GetEntityCoords(ped) + local heading = GetEntityHeading(ped) + local rad = math.rad(heading) + sx = coords.x + math.sin(-rad) * Config.SpawnOffset + sy = coords.y + math.cos(-rad) * Config.SpawnOffset + sz = coords.z + sh = heading + end - local bike = CreateVehicle(model, spawnX, spawnY, coords.z, heading, true, false) - local tw = GetGameTimer() + 3000 + print(string.format('[mercyv-bike] Spawn bei %.1f, %.1f, %.1f', sx, sy, sz)) + + local bike = CreateVehicle(model, sx, sy, sz, sh, true, false) + local tw = GetGameTimer() + 4000 while not DoesEntityExist(bike) do if GetGameTimer() > tw then break end Citizen.Wait(100) @@ -248,12 +265,11 @@ RegisterNetEvent('mercyv-bike:doSpawn', function(bikeModel) SetEntityAsMissionEntity(bike, true, true) SetVehicleEngineOn(bike, true, true, false) SetModelAsNoLongerNeeded(model) - -- Schlüssel geben - local ks = Config.VehicleKeySystem - if ks == 'jaksam' then - TriggerServerEvent('vehicles_keys:selfGiveVehicleKeys', - GetVehicleNumberPlateText(bike)) - end + TriggerServerEvent('vehicles_keys:selfGiveVehicleKeys', GetVehicleNumberPlateText(bike)) + Notify("Fahrrad erhalten! Viel Spaß!", "success") + print('[mercyv-bike] Fahrrad erfolgreich gespawnt.') + else + Notify("Fahrrad konnte nicht gespawnt werden.", "error") end end) diff --git a/mercyv-bike/nui/index.html b/mercyv-bike/nui/index.html index 8ef3ea0..e5d5868 100644 --- a/mercyv-bike/nui/index.html +++ b/mercyv-bike/nui/index.html @@ -285,8 +285,21 @@ body { +
+
Fahrrad Spawn-Position
+
+ + + + +
+ +
+
@@ -358,7 +371,10 @@ var app = new Vue({ postNUI('close'); }, capturePos: function() { - postNUI('capturePos', {}); + postNUI('capturePos', { field: 'npc' }); + }, + captureSpawn: function() { + postNUI('capturePos', { field: 'spawn' }); }, saveNPC: function() { postNUI('saveNPC', { @@ -387,10 +403,17 @@ window.addEventListener('message', function(event) { app.showAdmin = true; app.isAdmin = true; if (msg.captured) { - app.npc.x = Math.round(msg.captured.x * 100) / 100; - app.npc.y = Math.round(msg.captured.y * 100) / 100; - app.npc.z = Math.round(msg.captured.z * 100) / 100; - app.npc.heading = Math.round(msg.captured.heading * 100) / 100; + var rx = Math.round(msg.captured.x * 100) / 100; + var ry = Math.round(msg.captured.y * 100) / 100; + var rz = Math.round(msg.captured.z * 100) / 100; + var rh = Math.round(msg.captured.heading * 100) / 100; + if (msg.captured.field === 'spawn') { + app.npc.spawn_x = rx; app.npc.spawn_y = ry; + app.npc.spawn_z = rz; app.npc.spawn_heading = rh; + } else { + app.npc.x = rx; app.npc.y = ry; + app.npc.z = rz; app.npc.heading = rh; + } } break; case 'CLOSE': diff --git a/mercyv-bike/server/main.lua b/mercyv-bike/server/main.lua index f14adb4..223f88a 100644 --- a/mercyv-bike/server/main.lua +++ b/mercyv-bike/server/main.lua @@ -45,7 +45,8 @@ end) -- ── NPC-Position synchronisieren ────────────────────────────── -local NPCData = nil -- wird aus DB oder Config geladen +local NPCData = nil +local SpawnData = nil -- separate Spawn-Position für Fahrräder AddEventHandler('onResourceStart', function(res) if res ~= GetCurrentResourceName() then return end @@ -53,18 +54,25 @@ AddEventHandler('onResourceStart', function(res) -- Tabelle ZUERST anlegen MySQL.query.await([[ CREATE TABLE IF NOT EXISTS `mercyv_bike_npc` ( - `id` INT AUTO_INCREMENT PRIMARY KEY, - `model` VARCHAR(100) DEFAULT 'a_m_m_beach_01', - `x` FLOAT DEFAULT 0, - `y` FLOAT DEFAULT 0, - `z` FLOAT DEFAULT 0, - `heading` FLOAT DEFAULT 0 + `id` INT AUTO_INCREMENT PRIMARY KEY, + `model` VARCHAR(100) DEFAULT 'a_m_m_beach_01', + `x` FLOAT DEFAULT 0, + `y` FLOAT DEFAULT 0, + `z` FLOAT DEFAULT 0, + `heading` FLOAT DEFAULT 0, + `spawn_x` FLOAT DEFAULT 0, + `spawn_y` FLOAT DEFAULT 0, + `spawn_z` FLOAT DEFAULT 0, + `spawn_heading` FLOAT DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ]]) -- Dann lesen local r = MySQL.query.await("SELECT * FROM mercyv_bike_npc LIMIT 1") if r and r[1] then NPCData = r[1] + if r[1].spawn_x and r[1].spawn_x ~= 0 then + SpawnData = { x = r[1].spawn_x, y = r[1].spawn_y, z = r[1].spawn_z, heading = r[1].spawn_heading or 0 } + end else NPCData = { model = Config.NPC.model, @@ -117,7 +125,7 @@ RegisterNetEvent('mercyv-bike:claim', function(bikeModel) ) -- Spawn-Signal - TriggerClientEvent('mercyv-bike:doSpawn', src, bikeModel) + TriggerClientEvent('mercyv-bike:doSpawn', src, bikeModel, SpawnData) Config.ServerNotification(src, Config.Notify.CLAIMED, "success") print(string.format('[mercyv-bike] %s hat %s erhalten.', identifier, bikeModel)) end) @@ -148,15 +156,22 @@ RegisterNetEvent('mercyv-bike:saveNPC', function(data) end NPCData = data + if data.spawn_x and data.spawn_x ~= 0 then + SpawnData = { x = data.spawn_x, y = data.spawn_y, z = data.spawn_z, heading = data.spawn_heading or 0 } + end -- In DB speichern local existing = MySQL.query.await('SELECT id FROM mercyv_bike_npc LIMIT 1') + local sx = data.spawn_x or 0 + local sy = data.spawn_y or 0 + local sz = data.spawn_z or 0 + local sh = data.spawn_heading or 0 if existing and existing[1] then - MySQL.update('UPDATE mercyv_bike_npc SET model=?, x=?, y=?, z=?, heading=? WHERE id=?', - { data.model, data.x, data.y, data.z, data.heading, existing[1].id }) + MySQL.update('UPDATE mercyv_bike_npc SET model=?, x=?, y=?, z=?, heading=?, spawn_x=?, spawn_y=?, spawn_z=?, spawn_heading=? WHERE id=?', + { data.model, data.x, data.y, data.z, data.heading, sx, sy, sz, sh, existing[1].id }) else - MySQL.insert('INSERT INTO mercyv_bike_npc (model, x, y, z, heading) VALUES (?, ?, ?, ?, ?)', - { data.model, data.x, data.y, data.z, data.heading }) + MySQL.insert('INSERT INTO mercyv_bike_npc (model, x, y, z, heading, spawn_x, spawn_y, spawn_z, spawn_heading) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)', + { data.model, data.x, data.y, data.z, data.heading, sx, sy, sz, sh }) end TriggerClientEvent('mercyv-bike:syncNPC', -1, NPCData) diff --git a/mercyv-deathscreen/client/main.lua b/mercyv-deathscreen/client/main.lua index 8a950f9..01d5f19 100644 --- a/mercyv-deathscreen/client/main.lua +++ b/mercyv-deathscreen/client/main.lua @@ -703,7 +703,7 @@ AddEventHandler('mercyv-deathscreen:client:npcReviveTeleport', function() local ped = PlayerPedId() -- Kurz warten, damit der Spieler nach dem Revive sicher am Leben ist - Wait(500) + Wait(200) -- Bildschirm langsam schwarz ausblenden (Dauer: 1000 Millisekunden = 1 Sekunde) DoScreenFadeOut(1000)