local positions = {} local presets = {} local positionsFile = 'positions.json' local presetsFile = 'presets.json' local attachedWeapons = {} -- Load saved positions from JSON file local function LoadPositions() local file = LoadResourceFile(GetCurrentResourceName(), 'json/' .. positionsFile) if file then positions = json.decode(file) or {} end end -- Load saved presets from JSON file local function LoadPresets() local file = LoadResourceFile(GetCurrentResourceName(), 'json/' .. presetsFile) if file then presets = json.decode(file) or {} end end -- Save positions to JSON file local function SavePositions() SaveResourceFile(GetCurrentResourceName(), 'json/' .. positionsFile, json.encode(positions), -1) end -- Save presets to JSON file local function SavePresets() SaveResourceFile(GetCurrentResourceName(), 'json/' .. presetsFile, json.encode(presets), -1) end -- Überprüfe ob ein Spieler eine Waffe besitzt local function DoesPlayerHaveWeapon(source, weaponName) if Config.Framework.name == "qbcore" then local Player = QBCore.Functions.GetPlayer(source) if Player then for _, item in pairs(Player.PlayerData.items) do if item.name == weaponName then return true end end end elseif Config.Framework.name == "esx" then local xPlayer = ESX.GetPlayerFromId(source) if xPlayer then local hasWeapon = xPlayer.hasWeapon(weaponName) return hasWeapon end end return false end -- Load data when resource starts CreateThread(function() LoadPositions() LoadPresets() end) -- Weapon sync with verification RegisterNetEvent('force-sling:server:syncWeapons') AddEventHandler('force-sling:server:syncWeapons', function(weaponData, action) local src = source if action == 'attach' then -- Überprüfe ob der Spieler die Waffe besitzt if not DoesPlayerHaveWeapon(src, weaponData.weaponName) then return end attachedWeapons[src] = attachedWeapons[src] or {} attachedWeapons[src][weaponData.weaponName] = weaponData elseif action == 'detach' then if attachedWeapons[src] then attachedWeapons[src][weaponData.weaponName] = nil end end TriggerClientEvent('force-sling:client:syncWeapons', -1, src, weaponData, action) end) -- Callbacks lib.callback.register('force-sling:callback:getCachedPositions', function(source) local src = source local playerPositions = {} -- Filtere nur die Positionen für Waffen, die der Spieler besitzt for weaponName, posData in pairs(positions) do if DoesPlayerHaveWeapon(src, weaponName) then playerPositions[weaponName] = posData end end return playerPositions end) lib.callback.register('force-sling:callback:getCachedPresets', function(source) return presets end) lib.callback.register('force-sling:callback:isPlayerAdmin', function(source) local src = source if Config.Framework.name == "qbcore" then local Player = QBCore.Functions.GetPlayer(src) return Player and Player.PlayerData.admin or false elseif Config.Framework.name == "esx" then local xPlayer = ESX.GetPlayerFromId(src) return xPlayer and xPlayer.getGroup() == 'admin' or false end return false end) lib.callback.register('force-sling:callback:resetWeaponPositions', function(source, weapon) local src = source if weapon then if DoesPlayerHaveWeapon(src, weapon) then positions[weapon] = nil SavePositions() end else -- Beim kompletten Reset nur die Positionen der Waffen löschen, die der Spieler besitzt local newPositions = {} for weaponName, posData in pairs(positions) do if not DoesPlayerHaveWeapon(src, weaponName) then newPositions[weaponName] = posData end end positions = newPositions SavePositions() end return positions end) RegisterNetEvent('force-sling:server:saveWeaponPosition') AddEventHandler('force-sling:server:saveWeaponPosition', function(position, rotation, weapon, weaponName, boneId, isPreset) local src = source local data = { coords = position, rot = rotation, boneId = boneId } if isPreset then -- Nur Admins können Presets speichern local isAdmin = lib.callback.await('force-sling:callback:isPlayerAdmin', src) if isAdmin then presets[weaponName] = data SavePresets() end else -- Überprüfe ob der Spieler die Waffe besitzt if DoesPlayerHaveWeapon(src, weaponName) then positions[weaponName] = data SavePositions() end end end) -- Cleanup on player drop AddEventHandler('playerDropped', function() local src = source if attachedWeapons[src] then TriggerClientEvent('force-sling:client:cleanupPlayerWeapons', -1, src) attachedWeapons[src] = nil end end) -- Periodische Überprüfung der angehängten Waffen CreateThread(function() while true do for playerId, weapons in pairs(attachedWeapons) do for weaponName, _ in pairs(weapons) do if not DoesPlayerHaveWeapon(playerId, weaponName) then -- Spieler hat die Waffe nicht mehr, entferne sie TriggerClientEvent('force-sling:client:syncWeapons', -1, playerId, {weaponName = weaponName}, 'detach') attachedWeapons[playerId][weaponName] = nil end end end Wait(5000) -- Alle 5 Sekunden überprüfen end end)