EquippedItem = nil ItemData = nil local AttachedProp local PerformingAction local ProcessingEffect function DisableControls(denied) for i=1, #denied do DisableControlAction(0, denied[i], true) end end function RemoveAttachedProp() if AttachedProp and DoesEntityExist(AttachedProp) then DeleteEntity(AttachedProp) end AttachedProp = nil end function AttachProp(name) RemoveAttachedProp() local ped = PlayerPedId() local coords = GetEntityCoords(ped) local cfg = Config.Items[name] local prop = cfg.prop AttachedProp = CreateProp(prop.model, coords.x, coords.y, coords.z, true, true, false) SetEntityCollision(AttachedProp, false, true) AttachEntityToEntity(AttachedProp, ped, GetPedBoneIndex(ped, prop.boneId), prop.offset.x, prop.offset.y, prop.offset.z, prop.rotation.x, prop.rotation.y, prop.rotation.z, false, false, false, true, 2, true) end function ConsumeItem(name) if PerformingAction then return end PerformingAction = "consume" local cfg = Config.Items[name] -- Check if config exists if not cfg then print("^1ERROR: Configuration missing for item: " .. name .. "^0") PerformingAction = nil return end local anim = cfg.animation -- Check if animation exists if not anim then print("^1ERROR: Animation configuration missing for item: " .. name .. "^0") PerformingAction = nil return end -- Ensure animation time exists if not anim.time then print("^1ERROR: Animation time not defined for item: " .. name .. "^0") anim.time = 2000 -- Default to 2 seconds if missing end local ped = PlayerPedId() CreateThread(function() local timeLeft = anim.time -- Now we know this won't be nil SendNUIMessage({ type = "holdInteract", bool = true }) while PerformingAction == "consume" and timeLeft > 0 do if anim.time - timeLeft > 100 and not IsEntityPlayingAnim(ped, anim.dict, anim.anim, 13) then timeLeft = timeLeft - 100 PlayAnim(ped, anim.dict, anim.anim, anim.params[1] or 1.0, anim.params[2] or -1.0, anim.params[3] or -1, anim.params[4] or 1, anim.params[5] or 1, anim.params[6], anim.params[7], anim.params[8]) Wait(100) else timeLeft = timeLeft - 10 Wait(10) end end SendNUIMessage({ type = "holdInteract", bool = false }) ClearPedTasks(ped) -- Store animation time in a local variable to avoid nil reference local animTime = anim.time -- Check if timeLeft is nil and provide a default if timeLeft == nil then timeLeft = 0 end -- Now use the local variable for comparison if timeLeft > 0 and animTime and (animTime - timeLeft <= 100) then OptionsMenu() PerformingAction = nil elseif timeLeft <= 0 then lib.callback("pickle_consumables:useItem", "", function(result, uses) -- Check if cfg still exists (could have changed during callback) if not cfg then PerformingAction = nil return end -- Safe access to cfg.effect local effectName = "" if cfg.effect and cfg.effect.name then effectName = cfg.effect.name end if result and Config.Effects[effectName] and Config.Effects[effectName].process then CreateThread(function() if ProcessingEffect and not Config.Effects[effectName].canOverlap then return end ProcessingEffect = true Config.Effects[effectName].process(cfg.effect) ProcessingEffect = false end) end -- Check if ItemData exists if not ItemData then PerformingAction = nil return end ItemData.uses = uses if uses < 1 then return RemoveItem() end -- Re-fetch config to ensure it's current local cfg = Config.Items[name] if cfg and cfg.animation and cfg.animation.time then SendNUIMessage({ type = "displayApp", data = { quantity = uses, time = cfg.animation.time } }) else -- Fallback if config is missing SendNUIMessage({ type = "displayApp", data = { quantity = uses, time = 2000 } }) end PerformingAction = nil end) else PerformingAction = nil end end) end function RemoveItem() local ped = PlayerPedId() SendNUIMessage({ type = "hideApp", }) RemoveAttachedProp() ClearPedTasks(ped) EquippedItem = nil ItemData = nil PerformingAction = nil end function ItemThread(name, metadata) if EquippedItem then return end EquippedItem = name ItemData = metadata AttachProp(name) local cfg = Config.Items[name] -- Check if config exists if not cfg then print("^1ERROR: Configuration missing for item: " .. name .. "^0") return RemoveItem() end -- Safe access to animation time local animTime = (cfg.animation and cfg.animation.time) or 2000 SendNUIMessage({ type = "displayApp", data = { quantity = ItemData.uses, time = animTime } }) CreateThread(function() local pressTime = 0 local holding = false while EquippedItem == name do local ped = PlayerPedId() if IsControlJustPressed(1, 45) then TriggerServerEvent("pickle_consumables:returnItem") RemoveItem() elseif IsControlPressed(1, 191) or IsControlPressed(1, 51) then if not PerformingAction then ConsumeItem(name) end elseif PerformingAction then PerformingAction = nil end if cfg.idle and not PerformingAction then local anim = cfg.idle if not IsEntityPlayingAnim(ped, anim.dict, anim.anim, 13) then PlayAnim(ped, anim.dict, anim.anim, anim.params[1] or 1.0, anim.params[2] or -1.0, anim.params[3] or -1, anim.params[4] or 1, anim.params[5] or 1, anim.params[6], anim.params[7], anim.params[8]) Wait(100) end end if GetEntityHealth(ped) < 1 then local coords = GetEntityCoords(AttachedProp) local _, zCoords = GetGroundZFor_3dCoord(coords.x, coords.y, coords.z) RemoveItem() TriggerServerEvent("pickle_consumables:drop:createDrop", vector3(coords.x, coords.y, zCoords + 1.0)) end if insideMenu then DisableControls({1, 2, 24, 69, 70, 92, 114, 140, 141, 142, 257, 263, 264}) else DisableControls({24, 69, 70, 92, 114, 140, 141, 142, 257, 263, 264}) end Wait(0) end local ped = PlayerPedId() ClearPedTasks(ped) end) end RegisterNetEvent("pickle_consumables:equipItem", function(name, metadata) if not Config.Items[name] then return print("^1ERROR: This item is not configured.^0") end if EquippedItem then return ShowNotification(_L("item_active")) end ItemThread(name, metadata) end) RegisterNetEvent("pickle_consumables:removeItem", function() RemoveItem() end) AddEventHandler("onResourceStop", function(name) if name ~= GetCurrentResourceName() then return end TransitionFromBlurred(0) RemoveAttachedProp() end) function ValidateItemConfigs() print("^2Validating item configurations...^0") local issues = 0 for itemName, itemConfig in pairs(Config.Items) do -- Check for required properties if not itemConfig.animation then print("^1WARNING: Item '" .. itemName .. "' is missing animation configuration^0") issues = issues + 1 elseif not itemConfig.animation.time then print("^1WARNING: Item '" .. itemName .. "' is missing animation time configuration^0") issues = issues + 1 end if not itemConfig.prop then print("^1WARNING: Item '" .. itemName .. "' is missing prop configuration^0") issues = issues + 1 end -- Check for effect configuration if referenced if itemConfig.effect and itemConfig.effect.name then if not Config.Effects[itemConfig.effect.name] then print("^1WARNING: Item '" .. itemName .. "' references non-existent effect: " .. itemConfig.effect.name .. "^0") issues = issues + 1 end end end if issues > 0 then print("^1Found " .. issues .. " configuration issues. Please fix them to ensure proper functionality.^0") else print("^2All item configurations validated successfully!^0") end end -- Call this when the resource starts AddEventHandler('onResourceStart', function(resourceName) if (GetCurrentResourceName() ~= resourceName) then return end ValidateItemConfigs() end)