248 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
local QBCore = exports['qb-core']:GetCoreObject()
 | 
						|
 | 
						|
-- Get character gender (0 = male, 1 = female) using model hash
 | 
						|
function GetCharacterGender()
 | 
						|
    local ped = PlayerPedId()
 | 
						|
    local modelHash = GetEntityModel(ped)
 | 
						|
    
 | 
						|
    -- List of female model hashes
 | 
						|
    local femaleModels = {
 | 
						|
        `mp_f_freemode_01`, -- MP Female
 | 
						|
        `a_f_m_beach_01`, `a_f_m_bevhills_01`, `a_f_m_bevhills_02`,
 | 
						|
        `a_f_m_bodybuild_01`, `a_f_m_business_02`, `a_f_m_downtown_01`,
 | 
						|
        `a_f_m_eastsa_01`, `a_f_m_eastsa_02`, `a_f_m_fatbla_01`,
 | 
						|
        `a_f_m_fatwhite_01`, `a_f_m_ktown_01`, `a_f_m_ktown_02`,
 | 
						|
        `a_f_m_prolhost_01`, `a_f_m_salton_01`, `a_f_m_skidrow_01`,
 | 
						|
        `a_f_m_soucent_01`, `a_f_m_soucent_02`, `a_f_m_soucentmc_01`,
 | 
						|
        `a_f_m_tourist_01`, `a_f_m_trampbeac_01`, `a_f_m_tramp_01`,
 | 
						|
        `a_f_o_genstreet_01`, `a_f_o_indian_01`, `a_f_o_ktown_01`,
 | 
						|
        `a_f_o_salton_01`, `a_f_o_soucent_01`, `a_f_o_soucent_02`,
 | 
						|
        `a_f_y_beach_01`, `a_f_y_bevhills_01`, `a_f_y_bevhills_02`,
 | 
						|
        `a_f_y_bevhills_03`, `a_f_y_bevhills_04`, `a_f_y_business_01`,
 | 
						|
        `a_f_y_business_02`, `a_f_y_business_03`, `a_f_y_business_04`,
 | 
						|
        `a_f_y_eastsa_01`, `a_f_y_eastsa_02`, `a_f_y_eastsa_03`,
 | 
						|
        `a_f_y_epsilon_01`, `a_f_y_fitness_01`, `a_f_y_fitness_02`,
 | 
						|
        `a_f_y_genhot_01`, `a_f_y_golfer_01`, `a_f_y_hiker_01`,
 | 
						|
        `a_f_y_hippie_01`, `a_f_y_hipster_01`, `a_f_y_hipster_02`,
 | 
						|
        `a_f_y_hipster_03`, `a_f_y_hipster_04`, `a_f_y_indian_01`,
 | 
						|
        `a_f_y_juggalo_01`, `a_f_y_runner_01`, `a_f_y_rurmeth_01`,
 | 
						|
        `a_f_y_scdressy_01`, `a_f_y_skater_01`, `a_f_y_soucent_01`,
 | 
						|
        `a_f_y_soucent_02`, `a_f_y_soucent_03`, `a_f_y_tennis_01`,
 | 
						|
        `a_f_y_tourist_01`, `a_f_y_tourist_02`, `a_f_y_vinewood_01`,
 | 
						|
        `a_f_y_vinewood_02`, `a_f_y_vinewood_03`, `a_f_y_vinewood_04`,
 | 
						|
        `a_f_y_yoga_01`, `g_f_importexport_01`, `g_f_y_ballas_01`,
 | 
						|
        `g_f_y_families_01`, `g_f_y_lost_01`, `g_f_y_vagos_01`,
 | 
						|
        `s_f_m_fembarber`, `s_f_m_maid_01`, `s_f_m_shop_high`,
 | 
						|
        `s_f_m_sweatshop_01`, `s_f_y_airhostess_01`, `s_f_y_bartender_01`,
 | 
						|
        `s_f_y_baywatch_01`, `s_f_y_cop_01`, `s_f_y_factory_01`,
 | 
						|
        `s_f_y_hooker_01`, `s_f_y_hooker_02`, `s_f_y_hooker_03`,
 | 
						|
        `s_f_y_migrant_01`, `s_f_y_movprem_01`, `s_f_y_ranger_01`,
 | 
						|
        `s_f_y_scrubs_01`, `s_f_y_sheriff_01`, `s_f_y_shop_low`,
 | 
						|
        `s_f_y_shop_mid`, `s_f_y_stripper_01`, `s_f_y_stripper_02`,
 | 
						|
        `s_f_y_stripperlite`, `s_f_y_sweatshop_01`, `u_f_m_corpse_01`,
 | 
						|
        `u_f_m_miranda`, `u_f_m_promourn_01`, `u_f_o_moviestar`,
 | 
						|
        `u_f_o_prolhost_01`, `u_f_y_bikerchic`, `u_f_y_comjane`,
 | 
						|
        `u_f_y_corpse_01`, `u_f_y_corpse_02`, `u_f_y_hotposh_01`,
 | 
						|
        `u_f_y_jewelass_01`, `u_f_y_mistress`, `u_f_y_poppymich`,
 | 
						|
        `u_f_y_princess`, `u_f_y_spyactress`
 | 
						|
    }
 | 
						|
    
 | 
						|
    -- Check if the model is in the female list
 | 
						|
    for _, hash in ipairs(femaleModels) do
 | 
						|
        if hash == modelHash then
 | 
						|
            return 1 -- Female
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Check specifically for MP Female model (most common)
 | 
						|
    if modelHash == `mp_f_freemode_01` then
 | 
						|
        return 1 -- Female
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Check specifically for MP Male model (most common)
 | 
						|
    if modelHash == `mp_m_freemode_01` then
 | 
						|
        return 0 -- Male
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Alternative method: check player data if available
 | 
						|
    local Player = QBCore.Functions.GetPlayerData()
 | 
						|
    if Player and Player.charinfo and Player.charinfo.gender then
 | 
						|
        return Player.charinfo.gender == 1 and 1 or 0
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Default to male if we can't determine
 | 
						|
    return 0
 | 
						|
end
 | 
						|
 | 
						|
-- Debug function to print all clothing components with improved gender detection
 | 
						|
function PrintAllClothingComponents()
 | 
						|
    local ped = PlayerPedId()
 | 
						|
    local components = {}
 | 
						|
    local gender = GetCharacterGender()
 | 
						|
    local modelHash = GetEntityModel(ped)
 | 
						|
    
 | 
						|
    print("Character Model Hash: " .. modelHash)
 | 
						|
    print("Character Gender: " .. (gender == 0 and "Male" or "Female"))
 | 
						|
    
 | 
						|
    -- Component IDs: 0=face, 1=mask, 2=hair, 3=torso, 4=leg, 5=bag, 6=shoes, 7=accessory, 8=undershirt, 9=kevlar, 10=badge, 11=torso2
 | 
						|
    for i = 0, 11 do
 | 
						|
        local drawable = GetPedDrawableVariation(ped, i)
 | 
						|
        local texture = GetPedTextureVariation(ped, i)
 | 
						|
        local palette = GetPedPaletteVariation(ped, i)
 | 
						|
        
 | 
						|
        components[i] = {
 | 
						|
            drawable = drawable,
 | 
						|
            texture = texture,
 | 
						|
            palette = palette
 | 
						|
        }
 | 
						|
        
 | 
						|
        print("Component " .. i .. ": Drawable=" .. drawable .. ", Texture=" .. texture .. ", Palette=" .. palette)
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Props: 0=hat, 1=glasses, 2=ear, 6=watch, 7=bracelet
 | 
						|
    for i = 0, 7 do
 | 
						|
        if i ~= 3 and i ~= 4 and i ~= 5 then -- Skip invalid prop IDs
 | 
						|
            local prop = GetPedPropIndex(ped, i)
 | 
						|
            local texture = GetPedPropTextureIndex(ped, i)
 | 
						|
            
 | 
						|
            print("Prop " .. i .. ": Index=" .. prop .. ", Texture=" .. texture)
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    return components, gender
 | 
						|
end
 | 
						|
 | 
						|
-- Command to print all clothing components (for debugging)
 | 
						|
RegisterCommand('checkclothing', function()
 | 
						|
    local components, gender = PrintAllClothingComponents()
 | 
						|
    lib.notify({
 | 
						|
        title = 'Debug',
 | 
						|
        description = 'Clothing components printed to console. Gender: ' .. (gender == 0 and "Male" or "Female"),
 | 
						|
        type = 'info'
 | 
						|
    })
 | 
						|
end, false)
 | 
						|
 | 
						|
-- Check if player has a backpack equipped with improved gender detection
 | 
						|
function CheckForBackpack()
 | 
						|
    local ped = PlayerPedId()
 | 
						|
    local gender = GetCharacterGender()
 | 
						|
    
 | 
						|
    -- Get the current bag drawable ID (component 5 is the bag slot)
 | 
						|
    local currentBag = GetPedDrawableVariation(ped, 5)
 | 
						|
    local currentTexture = GetPedTextureVariation(ped, 5)
 | 
						|
    
 | 
						|
    if Config.Debug then
 | 
						|
        print("Current bag: Gender=" .. gender .. ", Drawable=" .. currentBag .. ", Texture=" .. currentTexture)
 | 
						|
    end
 | 
						|
    
 | 
						|
    -- Check if this bag ID is in our config for the current gender
 | 
						|
    if Config.Backpacks[gender] and Config.Backpacks[gender][currentBag] then
 | 
						|
        -- If we need to check for specific textures as well
 | 
						|
        if Config.Backpacks[gender][currentBag].textures then
 | 
						|
            if Config.Backpacks[gender][currentBag].textures[currentTexture] then
 | 
						|
                return currentBag, currentTexture, gender
 | 
						|
            end
 | 
						|
        else
 | 
						|
            -- If we don't care about texture, just return the drawable
 | 
						|
            return currentBag, currentTexture, gender
 | 
						|
        end
 | 
						|
    end
 | 
						|
    
 | 
						|
    return nil, nil, gender
 | 
						|
end
 | 
						|
 | 
						|
-- Open backpack inventory command
 | 
						|
RegisterCommand('openbackpack', function()
 | 
						|
    local backpackId, textureId, gender = CheckForBackpack()
 | 
						|
    
 | 
						|
    if backpackId then
 | 
						|
        local citizenId = QBCore.Functions.GetPlayerData().citizenid
 | 
						|
        local backpackStashId = "backpack_" .. citizenId .. "_" .. gender .. "_" .. backpackId .. "_" .. textureId
 | 
						|
        
 | 
						|
        TriggerServerEvent('backpack:server:openInventory', backpackStashId, backpackId, textureId, gender)
 | 
						|
    else
 | 
						|
        lib.notify(Config.Notifications.noBackpack)
 | 
						|
    end
 | 
						|
end, false)
 | 
						|
 | 
						|
-- Register key binding
 | 
						|
RegisterKeyMapping('openbackpack', 'Open Backpack Inventory', 'keyboard', Config.BackpackKey)
 | 
						|
 | 
						|
-- Listen for inventory open event
 | 
						|
RegisterNetEvent('inventory:client:OpenInventory', function()
 | 
						|
    -- Check if player has a backpack
 | 
						|
    local backpackId, textureId, gender = CheckForBackpack()
 | 
						|
    if backpackId then
 | 
						|
        local citizenId = QBCore.Functions.GetPlayerData().citizenid
 | 
						|
        local backpackStashId = "backpack_" .. citizenId .. "_" .. gender .. "_" .. backpackId .. "_" .. textureId
 | 
						|
        
 | 
						|
        -- Small delay to let the main inventory open first
 | 
						|
        Citizen.Wait(100)
 | 
						|
        TriggerServerEvent('backpack:server:openInventory', backpackStashId, backpackId, textureId, gender)
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Monitor for clothing changes to update backpack status
 | 
						|
Citizen.CreateThread(function()
 | 
						|
    local lastBackpack = nil
 | 
						|
    local lastTexture = nil
 | 
						|
    local lastGender = nil
 | 
						|
    
 | 
						|
    while true do
 | 
						|
        Citizen.Wait(1000) -- Check every second
 | 
						|
        
 | 
						|
        local currentBackpack, currentTexture, currentGender = CheckForBackpack()
 | 
						|
        
 | 
						|
        -- If backpack status changed
 | 
						|
        if currentBackpack ~= lastBackpack or currentTexture ~= lastTexture or currentGender ~= lastGender then
 | 
						|
            lastBackpack = currentBackpack
 | 
						|
            lastTexture = currentTexture
 | 
						|
            lastGender = currentGender
 | 
						|
            
 | 
						|
            -- If player removed a backpack, we could add additional logic here
 | 
						|
            if not currentBackpack then
 | 
						|
                -- Player removed backpack
 | 
						|
                if Config.Debug then
 | 
						|
                    print("Backpack removed")
 | 
						|
                end
 | 
						|
            else
 | 
						|
                -- Player equipped backpack
 | 
						|
                if Config.Debug then
 | 
						|
                    print("Backpack equipped: Gender=" .. currentGender .. ", ID=" .. currentBackpack .. ", Texture=" .. currentTexture)
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 | 
						|
 | 
						|
-- Event for checking backpack info
 | 
						|
RegisterNetEvent('backpack:client:checkBackpack', function()
 | 
						|
    local backpackId, textureId, gender = CheckForBackpack()
 | 
						|
    TriggerServerEvent('backpack:server:showBackpackInfo', backpackId, textureId, gender)
 | 
						|
end)
 | 
						|
 | 
						|
-- Event for listing all clothing (debug)
 | 
						|
RegisterNetEvent('backpack:client:listClothing', function()
 | 
						|
    PrintAllClothingComponents()
 | 
						|
    lib.notify({
 | 
						|
        title = 'Debug',
 | 
						|
        description = 'Clothing components printed to console',
 | 
						|
        type = 'info'
 | 
						|
    })
 | 
						|
end)
 | 
						|
 | 
						|
-- Initialize when player loads
 | 
						|
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
 | 
						|
    -- Nothing needed here, backpack will be checked when inventory is opened
 | 
						|
    Citizen.Wait(1000) -- Wait a bit for player data to be ready
 | 
						|
    local backpackId, textureId, gender = CheckForBackpack()
 | 
						|
    if backpackId then
 | 
						|
        if Config.Debug then
 | 
						|
            print("Player loaded with backpack: Gender=" .. gender .. ", ID=" .. backpackId .. ", Texture=" .. textureId)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        if Config.Debug then
 | 
						|
            print("Player loaded without backpack. Gender=" .. gender)
 | 
						|
        end
 | 
						|
    end
 | 
						|
end)
 |