local ESX = exports['es_extended']:getSharedObject() local isPlacing = false local ghostProp = nil local currentPropItem = nil local PlayerData = {} RegisterNetEvent('esx:playerLoaded', function(xPlayer) PlayerData = xPlayer end) RegisterNetEvent('esx:setJob', function(job) PlayerData.job = job end) CreateThread(function() while ESX.GetPlayerData().job == nil do Wait(100) end PlayerData = ESX.GetPlayerData() setupTargets() end) local function RotationToDirection(rotation) local adjustedRotation = { x = (math.pi / 180) * rotation.x, y = (math.pi / 180) * rotation.y, z = (math.pi / 180) * rotation.z } local direction = { x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)), z = math.sin(adjustedRotation.x) } return direction end local function RayCastGamePlayCamera(distance) local cameraRotation = GetGameplayCamRot() local cameraCoord = GetGameplayCamCoord() local direction = RotationToDirection(cameraRotation) local destination = { x = cameraCoord.x + direction.x * distance, y = cameraCoord.y + direction.y * distance, z = cameraCoord.z + direction.z * distance } local a, b, coords, d, entity = GetShapeTestResult(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, -1, PlayerPedId(), 0)) return b, coords, entity end local function startPlacementGizmo(itemName, propData) if isPlacing then return end isPlacing = true currentPropItem = itemName lib.requestModel(propData.model) ghostProp = CreateObject(GetHashKey(propData.model), 0.0, 0.0, 0.0, false, false, false) SetEntityAlpha(ghostProp, 150, false) SetEntityCollision(ghostProp, false, false) local heading = GetEntityHeading(PlayerPedId()) CreateThread(function() while isPlacing do Wait(0) DisableControlAction(0, 24, true) DisableControlAction(0, 25, true) DisableControlAction(0, 14, true) DisableControlAction(0, 15, true) local hit, coords, _ = RayCastGamePlayCamera(10.0) if hit == 1 then SetEntityCoords(ghostProp, coords.x, coords.y, coords.z) SetEntityHeading(ghostProp, heading) if IsDisabledControlPressed(0, 14) then heading = heading + 3.0 end if IsDisabledControlPressed(0, 15) then heading = heading - 3.0 end if IsDisabledControlJustPressed(0, 24) then local placeCoords = GetEntityCoords(ghostProp) local placeHeading = GetEntityHeading(ghostProp) isPlacing = false DeleteEntity(ghostProp) lib.requestAnimDict(propData.dict) TaskPlayAnim(PlayerPedId(), propData.dict, propData.anim, 8.0, -8.0, -1, 49, 0, false, false, false) if lib.progressBar({ duration = propData.duration, label = propData.placing_text, useWhileDead = false, canCancel = false, disable = { car = true, move = true, combat = true } }) then ClearPedTasks(PlayerPedId()) TriggerServerEvent('sloline_props:confirmPlacement', itemName, placeCoords, placeHeading) else ClearPedTasks(PlayerPedId()) end end if IsDisabledControlJustPressed(0, 25) then isPlacing = false DeleteEntity(ghostProp) lib.notify({ title = 'Sistem', description = Config.Strings.canceled, type = 'inform' }) end end end end) end RegisterNetEvent('sloline_props:useItemClient', function(itemName) local propData = Config.Props[itemName] if propData then -- Check if there is no job requirement OR if the player has the required job if not propData.job or (PlayerData.job and PlayerData.job.name == propData.job) then startPlacementGizmo(itemName, propData) else lib.notify({ title = 'Napaka', description = Config.Strings.no_permission, type = 'error' }) end end end) local propHashToItem = {} for itemName, propData in pairs(Config.Props) do propHashToItem[GetHashKey(propData.model)] = itemName end function setupTargets() for itemName, propData in pairs(Config.Props) do -- If a job is defined, add the target group, otherwise allow everyone local targetGroups = propData.job and { [propData.job] = 0 } or nil exports.ox_target:addModel(propData.model, { { name = 'pickup_prop_' .. itemName, icon = propData.target_icon, label = propData.target_label, groups = targetGroups, distance = 2.5, canInteract = function(entity, distance, coords, name, bone) return not isPlacing end, onSelect = function(data) local entity = data.entity local model = GetEntityModel(entity) local foundItem = propHashToItem[model] if foundItem and DoesEntityExist(entity) then local ped = PlayerPedId() local pData = Config.Props[foundItem] lib.requestAnimDict(pData.dict) TaskPlayAnim(ped, pData.dict, pData.anim, 8.0, -8.0, -1, 49, 0, false, false, false) Wait(1000) ClearPedTasks(ped) NetworkRequestControlOfEntity(entity) local timeout = 0 while not NetworkHasControlOfEntity(entity) and timeout < 50 do Wait(10) timeout = timeout + 1 end if DoesEntityExist(entity) then DeleteEntity(entity) TriggerServerEvent('sloline_props:pickupProp', foundItem) end end end } }) end end