2025-06-12 15:31:23 +02:00
|
|
|
local positions = {}
|
|
|
|
local presets = {}
|
|
|
|
local positionsFile = 'positions.json'
|
|
|
|
local presetsFile = 'presets.json'
|
|
|
|
|
|
|
|
-- 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
|
|
|
|
|
|
|
|
-- Load data when resource starts
|
|
|
|
CreateThread(function()
|
|
|
|
LoadPositions()
|
|
|
|
LoadPresets()
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Weapon sync
|
2025-06-12 00:25:14 +02:00
|
|
|
local attachedWeapons = {}
|
|
|
|
|
|
|
|
RegisterNetEvent('force-sling:server:syncWeapons')
|
|
|
|
AddEventHandler('force-sling:server:syncWeapons', function(weaponData, action)
|
|
|
|
local src = source
|
|
|
|
if action == 'attach' then
|
|
|
|
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)
|
|
|
|
|
2025-06-12 15:31:23 +02:00
|
|
|
-- Callbacks
|
|
|
|
lib.callback.register('force-sling:callback:getCachedPositions', function(source)
|
|
|
|
return positions
|
|
|
|
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
|
|
|
|
-- Add your admin check logic here
|
|
|
|
-- Example for QBCore:
|
|
|
|
-- local Player = QBCore.Functions.GetPlayer(src)
|
|
|
|
-- return Player.PlayerData.admin or false
|
|
|
|
|
|
|
|
-- For testing, returning true
|
|
|
|
return {isAdmin = true}
|
|
|
|
end)
|
|
|
|
|
|
|
|
lib.callback.register('force-sling:callback:resetWeaponPositions', function(source, weapon)
|
|
|
|
local src = source
|
|
|
|
if weapon then
|
|
|
|
positions[weapon] = nil
|
|
|
|
else
|
|
|
|
positions = {}
|
|
|
|
end
|
|
|
|
SavePositions()
|
|
|
|
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
|
|
|
|
presets[weaponName] = data
|
|
|
|
SavePresets()
|
|
|
|
else
|
|
|
|
positions[weaponName] = data
|
|
|
|
SavePositions()
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
-- Cleanup on player drop
|
2025-06-12 00:25:14 +02:00
|
|
|
AddEventHandler('playerDropped', function()
|
|
|
|
local src = source
|
|
|
|
if attachedWeapons[src] then
|
|
|
|
TriggerClientEvent('force-sling:client:cleanupPlayerWeapons', -1, src)
|
|
|
|
attachedWeapons[src] = nil
|
|
|
|
end
|
2025-06-07 08:51:21 +02:00
|
|
|
end)
|