From ffaf33c966880c3de127c6de1acccf6d8735efdd Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Wed, 9 Jul 2025 18:52:29 +0200 Subject: [PATCH] ed --- .../[Nordi]/nordi_kayaktrailer/client.lua | 245 ++++++++++++++++++ .../[Nordi]/nordi_kayaktrailer/config.lua | 29 +++ .../[Nordi]/nordi_kayaktrailer/fxmanifest.lua | 20 ++ .../[Nordi]/nordi_kayaktrailer/server.lua | 22 ++ .../configs/configCarryItems.lua | 12 +- .../tgiann-inventory/configs/configCraft.lua | 10 +- resources/[qb]/qb-core/shared/items.lua | 12 +- 7 files changed, 338 insertions(+), 12 deletions(-) create mode 100644 resources/[Developer]/[Nordi]/nordi_kayaktrailer/client.lua create mode 100644 resources/[Developer]/[Nordi]/nordi_kayaktrailer/config.lua create mode 100644 resources/[Developer]/[Nordi]/nordi_kayaktrailer/fxmanifest.lua create mode 100644 resources/[Developer]/[Nordi]/nordi_kayaktrailer/server.lua diff --git a/resources/[Developer]/[Nordi]/nordi_kayaktrailer/client.lua b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/client.lua new file mode 100644 index 000000000..53ca4d839 --- /dev/null +++ b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/client.lua @@ -0,0 +1,245 @@ +local QBCore = exports['qb-core']:GetCoreObject() +local loadedKayaks = {} +local currentTrailer = nil + +-- Function to check if a model is a kayak +local function IsKayakModel(model) + for _, kayakModel in ipairs(Config.KayakModels) do + if GetHashKey(kayakModel) == model then + return true + end + end + return false +end + +-- Function to get nearby kayak +local function GetNearbyKayak() + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + + local kayak = nil + local minDistance = Config.InteractionRange + + for _, entity in ipairs(GetGamePool('CVehicle')) do + if IsKayakModel(GetEntityModel(entity)) then + local distance = #(playerCoords - GetEntityCoords(entity)) + if distance < minDistance then + minDistance = distance + kayak = entity + end + end + end + + return kayak +end + +-- Function to get nearby trailer +local function GetNearbyTrailer() + local playerPed = PlayerPedId() + local playerCoords = GetEntityCoords(playerPed) + + local trailer = nil + local minDistance = Config.InteractionRange + + for _, entity in ipairs(GetGamePool('CVehicle')) do + if GetEntityModel(entity) == GetHashKey(Config.TrailerModel) then + local distance = #(playerCoords - GetEntityCoords(entity)) + if distance < minDistance then + minDistance = distance + trailer = entity + end + end + end + + return trailer +end + +-- Function to load kayak onto trailer +local function LoadKayakOntoTrailer(trailer, kayak) + if not trailer or not kayak then return end + + local trailerNetId = NetworkGetNetworkIdFromEntity(trailer) + local kayakNetId = NetworkGetNetworkIdFromEntity(kayak) + + -- Check if trailer already has max kayaks + if #loadedKayaks >= Config.MaxKayaks then + QBCore.Functions.Notify("Trailer rack is already fully loaded with kayaks", "error") + return + end + + -- Add kayak to loaded kayaks + table.insert(loadedKayaks, kayakNetId) + + -- Update kayak position on trailer + local position = Config.KayakPositions[#loadedKayaks] + local trailerCoords = GetEntityCoords(trailer) + local trailerHeading = GetEntityHeading(trailer) + + -- Calculate world position based on trailer position and offset + local kayakX = trailerCoords.x + (math.cos(math.rad(trailerHeading)) * position.x) - (math.sin(math.rad(trailerHeading)) * position.y) + local kayakY = trailerCoords.y + (math.sin(math.rad(trailerHeading)) * position.x) + (math.cos(math.rad(trailerHeading)) * position.y) + local kayakZ = trailerCoords.z + position.z + local kayakHeading = trailerHeading + position.heading + + -- Set kayak position and attach to trailer + SetEntityCoords(kayak, kayakX, kayakY, kayakZ, false, false, false, false) + SetEntityHeading(kayak, kayakHeading) + + -- Attach kayak to trailer + AttachEntityToEntity(kayak, trailer, 0, position.x, position.y, position.z, 0.0, 0.0, position.heading, true, false, true, false, 0, true) + + -- Display which rack position was loaded + local side = #loadedKayaks <= 3 and "left" or "right" + local level = (#loadedKayaks - 1) % 3 + 1 + local levelNames = {"bottom", "middle", "top"} + + QBCore.Functions.Notify("Kayak loaded onto " .. levelNames[level] .. " rack, " .. side .. " side", "success") + + -- Save current trailer + currentTrailer = trailerNetId + + -- Sync with server + TriggerServerEvent('kayak_trailer:syncLoadedKayaks', trailerNetId, loadedKayaks) +end + +-- Function to unload kayak from trailer +local function UnloadKayakFromTrailer(trailer) + if not trailer or #loadedKayaks == 0 then return end + + local trailerNetId = NetworkGetNetworkIdFromEntity(trailer) + + -- Get last kayak + local kayakNetId = loadedKayaks[#loadedKayaks] + local kayak = NetworkGetEntityFromNetworkId(kayakNetId) + + -- Get position info for notification + local side = #loadedKayaks <= 3 and "left" or "right" + local level = (#loadedKayaks - 1) % 3 + 1 + local levelNames = {"bottom", "middle", "top"} + + -- Remove from loaded kayaks + table.remove(loadedKayaks, #loadedKayaks) + + -- Detach kayak from trailer + DetachEntity(kayak, true, true) + + -- Place kayak behind trailer + local trailerCoords = GetEntityCoords(trailer) + local trailerHeading = GetEntityHeading(trailer) + local offsetX = -3.0 -- 3 meters behind trailer + + local kayakX = trailerCoords.x - (math.cos(math.rad(trailerHeading)) * offsetX) + local kayakY = trailerCoords.y - (math.sin(math.rad(trailerHeading)) * offsetX) + local kayakZ = trailerCoords.z + + SetEntityCoords(kayak, kayakX, kayakY, kayakZ, false, false, false, false) + SetEntityHeading(kayak, trailerHeading) + + QBCore.Functions.Notify("Kayak unloaded from " .. levelNames[level] .. " rack, " .. side .. " side", "success") + + -- Sync with server + TriggerServerEvent('kayak_trailer:syncLoadedKayaks', trailerNetId, loadedKayaks) +end + +-- Initialize qb-target +Citizen.CreateThread(function() + -- Target for loading kayaks onto trailer + exports['qb-target']:AddTargetModel(Config.TrailerModel, { + options = { + { + type = "client", + event = "kayak_trailer:loadKayak", + icon = "fas fa-truck-loading", + label = "Load Kayak to Rack", + canInteract = function() + local kayak = GetNearbyKayak() + return kayak ~= nil and #loadedKayaks < Config.MaxKayaks + end + }, + { + type = "client", + event = "kayak_trailer:unloadKayak", + icon = "fas fa-dolly", + label = "Unload Kayak from Rack", + canInteract = function() + return #loadedKayaks > 0 + end + } + }, + distance = Config.InteractionRange + }) + + -- Target for kayaks + for _, model in ipairs(Config.KayakModels) do + exports['qb-target']:AddTargetModel(model, { + options = { + { + type = "client", + event = "kayak_trailer:loadKayak", + icon = "fas fa-truck-loading", + label = "Load onto Trailer Rack", + canInteract = function() + local trailer = GetNearbyTrailer() + return trailer ~= nil and #loadedKayaks < Config.MaxKayaks + end + } + }, + distance = Config.InteractionRange + }) + end +end) + +-- Event handlers +RegisterNetEvent('kayak_trailer:loadKayak', function() + local trailer = GetNearbyTrailer() + local kayak = GetNearbyKayak() + + if trailer and kayak then + LoadKayakOntoTrailer(trailer, kayak) + else + QBCore.Functions.Notify("No trailer or kayak nearby", "error") + end +end) + +RegisterNetEvent('kayak_trailer:unloadKayak', function() + local trailer = GetNearbyTrailer() + + if trailer then + UnloadKayakFromTrailer(trailer) + else + QBCore.Functions.Notify("No trailer nearby", "error") + end +end) + +-- Sync loaded kayaks from server +RegisterNetEvent('kayak_trailer:syncLoadedKayaksClient', function(trailerNetId, kayakList) + if NetworkDoesNetworkIdExist(trailerNetId) then + local trailer = NetworkGetEntityFromNetworkId(trailerNetId) + + -- Clear existing kayaks + for _, kayakNetId in ipairs(loadedKayaks) do + if NetworkDoesNetworkIdExist(kayakNetId) then + local kayak = NetworkGetEntityFromNetworkId(kayakNetId) + if DoesEntityExist(kayak) then + DetachEntity(kayak, true, true) + end + end + end + + -- Update loaded kayaks + loadedKayaks = kayakList + + -- Reattach kayaks + for i, kayakNetId in ipairs(loadedKayaks) do + if NetworkDoesNetworkIdExist(kayakNetId) then + local kayak = NetworkGetEntityFromNetworkId(kayakNetId) + if DoesEntityExist(kayak) then + local position = Config.KayakPositions[i] + AttachEntityToEntity(kayak, trailer, 0, position.x, position.y, position.z, 0.0, 0.0, position.heading, true, false, true, false, 0, true) + end + end + end + + currentTrailer = trailerNetId + end +end) diff --git a/resources/[Developer]/[Nordi]/nordi_kayaktrailer/config.lua b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/config.lua new file mode 100644 index 000000000..a87b7977d --- /dev/null +++ b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/config.lua @@ -0,0 +1,29 @@ +Config = {} + +-- Trailer configuration +Config.TrailerModel = 'boattrailer' -- Default trailer model, can be changed to your custom model +Config.MaxKayaks = 6 -- Maximum number of kayaks (3 per side) + +-- Kayak models that can be loaded onto the trailer +Config.KayakModels = { + 'kayak01', -- Replace with your actual kayak model names + 'kayak02', + 'kayak03' +} + +-- Positions for kayaks on the trailer rack (relative to trailer) +-- Arranged as 3 levels on each side of the trailer +Config.KayakPositions = { + -- Left side (3 kayaks stacked vertically) + {x = -0.5, y = 0.0, z = 0.6, heading = 90.0}, -- Bottom level + {x = -0.5, y = 0.0, z = 1.2, heading = 90.0}, -- Middle level + {x = -0.5, y = 0.0, z = 1.8, heading = 90.0}, -- Top level + + -- Right side (3 kayaks stacked vertically) + {x = 0.5, y = 0.0, z = 0.6, heading = 270.0}, -- Bottom level + {x = 0.5, y = 0.0, z = 1.2, heading = 270.0}, -- Middle level + {x = 0.5, y = 0.0, z = 1.8, heading = 270.0} -- Top level +} + +-- Range for qb-target interaction +Config.InteractionRange = 3.0 diff --git a/resources/[Developer]/[Nordi]/nordi_kayaktrailer/fxmanifest.lua b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/fxmanifest.lua new file mode 100644 index 000000000..9b35ea6b3 --- /dev/null +++ b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/fxmanifest.lua @@ -0,0 +1,20 @@ +fx_version 'cerulean' +game 'gta5' + +description 'QBCore Kayak Trailer Script' +author 'Your Name' +version '1.0.0' + +shared_scripts { + 'config.lua' +} + +client_scripts { + 'client.lua' +} + +server_scripts { + 'server.lua' +} + +lua54 'yes' diff --git a/resources/[Developer]/[Nordi]/nordi_kayaktrailer/server.lua b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/server.lua new file mode 100644 index 000000000..1bc7b5d40 --- /dev/null +++ b/resources/[Developer]/[Nordi]/nordi_kayaktrailer/server.lua @@ -0,0 +1,22 @@ +local QBCore = exports['qb-core']:GetCoreObject() +local trailerKayaks = {} + +-- Event to sync loaded kayaks +RegisterNetEvent('kayak_trailer:syncLoadedKayaks', function(trailerNetId, kayakList) + local src = source + + -- Store kayaks for this trailer + trailerKayaks[trailerNetId] = kayakList + + -- Broadcast to all clients + TriggerClientEvent('kayak_trailer:syncLoadedKayaksClient', -1, trailerNetId, kayakList) +end) + +-- When a player connects, send them the current state of all trailers +RegisterNetEvent('QBCore:Server:PlayerLoaded', function() + local src = source + + for trailerNetId, kayakList in pairs(trailerKayaks) do + TriggerClientEvent('kayak_trailer:syncLoadedKayaksClient', src, trailerNetId, kayakList) + end +end) diff --git a/resources/[inventory]/tgiann-inventory/configs/configCarryItems.lua b/resources/[inventory]/tgiann-inventory/configs/configCarryItems.lua index 92f6434df..7025fc313 100644 --- a/resources/[inventory]/tgiann-inventory/configs/configCarryItems.lua +++ b/resources/[inventory]/tgiann-inventory/configs/configCarryItems.lua @@ -17,14 +17,14 @@ config.carryItmes = { moveRate = 0.5, -- https://docs.fivem.net/natives/?_0x085BF80FA50A39D1 (1.0 Default) }, present = { - model = `xm3_prop_xm3_present_01a`, + model = `xm_prop_x17_bag_01d`, bone = 28422, - offset = vector3(0.0, -0.18, -0.16), - rot = vector3(0.0, 0.0, 0.0), + offset = vector3(0.15, -0.05, -0.10), + rot = vector3(100.0, -50.0, 220.0), anim = { - dict = "anim@heists@box_carry@", - name = "idle" - }, + dict = "missfbi4prepp1", + n ame = "idle" -- Neutrale Stehanimation +} disableKeys = { 21, -- INPUT_SPRINT }, diff --git a/resources/[inventory]/tgiann-inventory/configs/configCraft.lua b/resources/[inventory]/tgiann-inventory/configs/configCraft.lua index cfb8f70c2..fe994fdc4 100644 --- a/resources/[inventory]/tgiann-inventory/configs/configCraft.lua +++ b/resources/[inventory]/tgiann-inventory/configs/configCraft.lua @@ -30,15 +30,15 @@ exports("RegisterJobCraft", registerJobCraft) -- Default crafting registerCraft("defaultCraft", "Main Craft", { { - giveAmount = 1, - name = 'testburger', + giveAmount = 24, + name = 'ecola_dose', costs = { - ['testitem'] = 5, - ['testitemuniq'] = 3, + ['pack_ecola'] = 1, + }, duration = 5000, -- 5 seconds crafting times (optional) info = { - label = "My Test Label for Burger" + label = "Auspacken" } }, --[[ diff --git a/resources/[qb]/qb-core/shared/items.lua b/resources/[qb]/qb-core/shared/items.lua index 50bc533f6..c33de9c2b 100644 --- a/resources/[qb]/qb-core/shared/items.lua +++ b/resources/[qb]/qb-core/shared/items.lua @@ -10193,7 +10193,17 @@ QBShared.Items = { image = 'pdbag.png', name = 'pdbag', }, - + pack_ecola = { + shouldClose = true, + type = 'item', + description = '', + weight = 1000, + label = 'Packung E-Cola', + unique = true, + useable = true, + image = 'pack_ecola.png', + name = 'pack_ecola', + },