301 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			301 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
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)
 | 
						|
                                -- Event auslösen
 | 
						|
                        TriggerEvent("pickle_consumables:effectStarted", effectName, cfg.effect, name)
 | 
						|
                        ProcessingEffect = false
 | 
						|
                    end)
 | 
						|
                end
 | 
						|
                
 | 
						|
                -- Check if ItemData exists
 | 
						|
                if not ItemData then
 | 
						|
                    PerformingAction = nil
 | 
						|
                    return
 | 
						|
                end
 | 
						|
                
 | 
						|
                -- Check if uses is nil and provide a default
 | 
						|
                if uses == nil then
 | 
						|
                    print("^1WARNING: Server returned nil for uses. Defaulting to 0.^0")
 | 
						|
                    uses = 0
 | 
						|
                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)
 | 
						|
 | 
						|
-- Event-Listener für Alkoholkonsum
 | 
						|
AddEventHandler("pickle_consumables:effectStarted", function(effectName, effectData, itemName)
 | 
						|
    if effectName == "drunk" then
 | 
						|
        local intensity = effectData.intensity or 1.0
 | 
						|
        TriggerServerEvent('qb-alcoholtest:server:alcoholConsumed', itemName, intensity)
 | 
						|
    end
 | 
						|
end)
 |