--- Desencrypted By PrejuicioX -- Framework validation if Config.esxSettings.enabled then if Config.qbSettings.enabled then print("^1BOTH FRAMEWORKS ENABLED!! MAKE SURE TO ONLY ENABLE ONE FRAMEWORK IN THE CONFIG FILE!") end end -- Global tables (preserve for cross-file usage) DB_TAG = "kq_outfitbag:outfit" OUTFITS = {} PLAYER_BAGS = {} DELETE_QUEUE = {} -- Bag despawning system if Config.bagDespawning and Config.bagDespawning.enabled then Citizen.CreateThread(function() while true do Citizen.Wait(60000) local queueCopy = json.decode(json.encode(DELETE_QUEUE)) for index, bagData in pairs(DELETE_QUEUE) do if not DoesEntityExist(bagData.entity) then queueCopy[index] = nil else local currentTime = GetGameTimer() local despawnTime = bagData.time + (Config.bagDespawning.time * 1000 * 60) if currentTime > despawnTime then DeleteEntity(bagData.entity) queueCopy[index] = nil end end end DELETE_QUEUE = queueCopy end end) end function GetOrFetchOutfits(playerId, bagTag) local identifier = _GetPlayerIdentifier(playerId) if OUTFITS[identifier] and OUTFITS[identifier][bagTag] then return OUTFITS[identifier][bagTag] end return FetchPlayerOutfits(playerId, bagTag) end function FetchPlayerOutfits(playerId, bagTag) local identifier = _GetPlayerIdentifier(playerId) OUTFITS[identifier] = {} OUTFITS[identifier][bagTag] = nil if not OUTFITS[identifier][bagTag] then local savedOutfits = GetSavedPlayerOutfits(playerId) if savedOutfits then OUTFITS[identifier][bagTag] = {} for _, outfitRecord in ipairs(savedOutfits) do local outfitData = json.decode(outfitRecord.data) -- Filter outfits by bag tag if outfitData.bagItem == bagTag or (Config.bagTag == bagTag and not outfitData.bagItem) then outfitData.id = outfitRecord.id table.insert(OUTFITS[identifier][bagTag], outfitData) end end end end return OUTFITS[identifier][bagTag] end function RefreshBagOutfits(playerId, bagTag, bagEntity) local outfits = GetOrFetchOutfits(playerId, bagTag) local entityState = Entity(bagEntity).state entityState:set("kq_ob_outfits", outfits, true) -- Fallback for non-networked entities if not bagEntity or bagEntity <= 0 then TriggerClientEvent("kq_outfitbag2:client:set_bags", playerId, nil, { kq_ob_outfits = outfits }) end end function GetBagTagFromNetId(networkId) local entity = NetworkGetEntityFromNetworkId(networkId) return Entity(entity).state.kq_ob_bag end -- Command registration if Config.command.enabled then RegisterCommand(Config.command.command, function(source) TriggerClientEvent("kq_outfitbag2:client:place", source, "kq_outfitbag", false) end) RegisterCommand(Config.command.shortCommand, function(source) TriggerClientEvent("kq_outfitbag2:client:place", source, "kq_outfitbag", false) end) end -- Event: Place bag RegisterServerEvent("kq_outfitbag2:server:place") AddEventHandler("kq_outfitbag2:server:place", function(bagTag, networkId, propEntity, itemName) local playerId = source PlaceBag(playerId, bagTag, networkId, propEntity, itemName) end) function PlaceBag(playerId, bagTag, networkId, propEntity, itemName) local identifier = _GetPlayerIdentifier(playerId) -- Handle existing bag on ground if PLAYER_BAGS[identifier] and DoesEntityExist(PLAYER_BAGS[identifier]) then if Config.onlyAllowOneBagOnGround then DeleteEntity(PLAYER_BAGS[identifier]) PLAYER_BAGS[identifier] = nil end end local bagEntity = NetworkGetEntityFromNetworkId(networkId) -- Fallback for non-networked entities if not bagEntity or bagEntity <= 0 then Debug("Could not detect the bag as networked") TriggerClientEvent("kq_outfitbag2:client:set_bags", playerId, propEntity, { kq_ob = true, kq_ob_item = itemName or false, kq_ob_bag = bagTag, kq_ob_public = false, kq_ob_owner = playerId, kq_ob_outfits = GetOrFetchOutfits(playerId, bagTag) }) return end Debug("Created bag entity", bagEntity) Citizen.Wait(500) PLAYER_BAGS[identifier] = bagEntity FreezeEntityPosition(bagEntity, true) Debug("500ms since created bag entity", bagEntity, DoesEntityExist(bagEntity), GetEntityCoords(bagEntity)) if bagEntity and bagEntity > 0 then Debug("object detected, setting state") EnsureEntityStateBag(bagEntity) local entityState = Entity(bagEntity).state entityState:set("kq_ob", true, true) entityState:set("kq_ob_item", itemName or false, true) entityState:set("kq_ob_bag", bagTag, true) entityState:set("kq_ob_public", false, true) entityState:set("kq_ob_owner", playerId, true) RefreshBagOutfits(playerId, bagTag, bagEntity) table.insert(DELETE_QUEUE, { time = GetGameTimer(), entity = bagEntity }) end if itemName then RemoveBagItem(playerId, itemName) end end -- Event: Delete outfit RegisterServerEvent("kq_outfitbag2:server:deleteOutfit") AddEventHandler("kq_outfitbag2:server:deleteOutfit", function(outfitId, bagNetworkId, fallbackBagTag) local bagTag = GetBagTagFromNetId(bagNetworkId) or fallbackBagTag local playerId = source DeleteOutfit(playerId, outfitId) FetchPlayerOutfits(playerId, bagTag) RefreshBagOutfits(playerId, bagTag, NetworkGetEntityFromNetworkId(bagNetworkId)) end) -- Event: Pickup bag RegisterServerEvent("kq_outfitbag2:server:pickup") AddEventHandler("kq_outfitbag2:server:pickup", function(bagNetworkId, itemName) PickupBag(source, bagNetworkId, itemName) end) function PickupBag(playerId, bagNetworkId, itemName) local bagEntity = NetworkGetEntityFromNetworkId(bagNetworkId) local bagItemName = Entity(bagEntity).state.kq_ob_item if bagItemName or itemName then AddPlayerItem(playerId, bagItemName or itemName, 1) end DeleteEntity(bagEntity) local identifier = _GetPlayerIdentifier(playerId) PLAYER_BAGS[identifier] = nil end -- Event: Save outfit RegisterServerEvent("kq_outfitbag2:server:saveOutfit") AddEventHandler("kq_outfitbag2:server:saveOutfit", function(outfitData, bagNetworkId, fallbackBagTag) local bagTag = GetBagTagFromNetId(bagNetworkId) or fallbackBagTag local playerId = tonumber(source) local identifier = _GetPlayerIdentifier(playerId) -- Check outfit limit if OUTFITS[identifier] and OUTFITS[identifier][bagTag] then if #OUTFITS[identifier][bagTag] >= Config.maxOutfits then return end end outfitData.bagItem = bagTag SaveOutfit(playerId, outfitData) FetchPlayerOutfits(playerId, bagTag) RefreshBagOutfits(playerId, bagTag, NetworkGetEntityFromNetworkId(bagNetworkId)) end) function Debug(...) if Config.debug then print(...) end end --- Desencrypted By PrejuicioX