From 731706d0fabe64c61924a1d8afa443bc96611e55 Mon Sep 17 00:00:00 2001 From: Fast-Lane RolePlay Date: Sun, 21 Aug 2022 00:33:17 -0400 Subject: [PATCH 1/2] Updated Core Features --- lj-inventory/client/main.lua | 570 +++++-------- lj-inventory/config.lua | 339 +------- lj-inventory/server/decay.lua | 13 +- lj-inventory/server/main.lua | 1493 ++++++++++++++++++++++++--------- 4 files changed, 1286 insertions(+), 1129 deletions(-) diff --git a/lj-inventory/client/main.lua b/lj-inventory/client/main.lua index 9704dc2..defaafb 100644 --- a/lj-inventory/client/main.lua +++ b/lj-inventory/client/main.lua @@ -4,7 +4,9 @@ local QBCore = exports['qb-core']:GetCoreObject() local PlayerData = QBCore.Functions.GetPlayerData() local inInventory = false local currentWeapon = nil + local CurrentWeaponData = {} + local currentOtherInventory = nil local Drops = {} local CurrentDrop = nil @@ -12,87 +14,133 @@ local DropsNear = {} local CurrentVehicle = nil local CurrentGlovebox = nil local CurrentStash = nil -local isCrafting = false local isHotbar = false -local itemInfos = {} local showBlur = true RegisterNUICallback('showBlur', function() Wait(50) TriggerEvent("lj-inventory:client:showBlur") -end) +end) RegisterNetEvent("lj-inventory:client:showBlur", function() Wait(50) showBlur = not showBlur end) --- Functions - -local function GetClosestVending() - local ped = PlayerPedId() - local pos = GetEntityCoords(ped) - local object = nil - for _, machine in pairs(Config.VendingObjects) do - local ClosestObject = GetClosestObjectOfType(pos.x, pos.y, pos.z, 0.75, GetHashKey(machine), 0, 0, 0) - if ClosestObject ~= 0 then - if object == nil then - object = ClosestObject +---Checks if you have an item or not +local function HasItem(items, amount) + local isTable = type(items) == 'table' + local isArray = isTable and table.type(items) == 'array' or false + local totalItems = #items + local count = 0 + local kvIndex = 2 + if isTable and not isArray then + totalItems = 0 + for _ in pairs(items) do totalItems += 1 end + kvIndex = 1 + end + for _, itemData in pairs(PlayerData.items) do + if isTable then + for k, v in pairs(items) do + local itemKV = {k, v} + if itemData and itemData.name == itemKV[kvIndex] and ((amount and itemData.amount >= amount) or (not isArray and itemData.amount >= v) or (not amount and isArray)) then + count += 1 + end + end + if count == totalItems then + return true + end + else -- Single item as string + if itemData and itemData.name == items and (not amount or (itemData and amount and itemData.amount >= amount)) then + return true end end end - return object + return false +end +exports("HasItem", HasItem) + +---Removes drops in the area of the client +local function RemoveNearbyDrop(index) + if not DropsNear[index] then return end + + local dropItem = DropsNear[index].object + if DoesEntityExist(dropItem) then + DeleteEntity(dropItem) + end + + DropsNear[index] = nil + + if not Drops[index] then return end + + Drops[index].object = nil + Drops[index].isDropShowing = nil end -local function DrawText3Ds(x, y, z, text) - SetTextScale(0.35, 0.35) - SetTextFont(4) - SetTextProportional(1) - SetTextColour(255, 255, 255, 215) - SetTextEntry("STRING") - SetTextCentre(true) - AddTextComponentString(text) - SetDrawOrigin(x,y,z, 0) - DrawText(0.0, 0.0) - local factor = (string.len(text)) / 370 - DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75) - ClearDrawOrigin() +---Removes all drops in the area of the client +local function RemoveAllNearbyDrops() + for k in pairs(DropsNear) do + RemoveNearbyDrop(k) + end end +---Creates a new item drop object on the ground +local function CreateItemDrop(index) + local dropItem = CreateObject(Config.ItemDropObject, DropsNear[index].coords.x, DropsNear[index].coords.y, DropsNear[index].coords.z, false, false, false) + DropsNear[index].object = dropItem + DropsNear[index].isDropShowing = true + PlaceObjectOnGroundProperly(dropItem) + FreezeEntityPosition(dropItem, true) + if Config.UseTarget then + exports['qb-target']:AddTargetEntity(dropItem, { + options = { + { + icon = 'fas fa-backpack', + label = 'Open Bag', + action = function() + TriggerServerEvent("inventory:server:OpenInventory", "drop", index) + end, + } + }, + distance = 2.5, + }) + end +end + +AddEventHandler('onResourceStop', function(name) + if name ~= GetCurrentResourceName() then return end + if Config.UseItemDrop then RemoveAllNearbyDrops() end +end) + +-- Functions + local function FormatWeaponAttachments(itemdata) local attachments = {} itemdata.name = itemdata.name:upper() if itemdata.info.attachments ~= nil and next(itemdata.info.attachments) ~= nil then - for k, v in pairs(itemdata.info.attachments) do - if WeaponAttachments[itemdata.name] ~= nil then - for key, value in pairs(WeaponAttachments[itemdata.name]) do - if value.component == v.component then - item = value.item - attachments[#attachments+1] = { - attachment = key, - label = QBCore.Shared.Items[item].label - --label = value.label - } - end - end - end + for _, v in pairs(itemdata.info.attachments) do + attachments[#attachments+1] = { + attachment = v.item, + label = v.label, + image = QBCore.Shared.Items[v.item].image, + component = v.component + } end end return attachments end local function IsBackEngine(vehModel) - if BackEngineVehicles[vehModel] then return true end - return false + return BackEngineVehicles[vehModel] end local function OpenTrunk() local vehicle = QBCore.Functions.GetClosestVehicle() while (not HasAnimDictLoaded("amb@prop_human_bum_bin@idle_b")) do RequestAnimDict("amb@prop_human_bum_bin@idle_b") - Wait(100) + Wait(50) end TaskPlayAnim(PlayerPedId(), "amb@prop_human_bum_bin@idle_b", "idle_d", 4.0, 4.0, -1, 50, 0, false, false, false) - if (IsBackEngine(GetEntityModel(vehicle))) then + if IsBackEngine(GetEntityModel(vehicle)) then SetVehicleDoorOpen(vehicle, 4, false, false) else SetVehicleDoorOpen(vehicle, 5, false, false) @@ -103,10 +151,10 @@ local function CloseTrunk() local vehicle = QBCore.Functions.GetClosestVehicle() while (not HasAnimDictLoaded("amb@prop_human_bum_bin@idle_b")) do RequestAnimDict("amb@prop_human_bum_bin@idle_b") - Wait(100) + Wait(50) end TaskPlayAnim(PlayerPedId(), "amb@prop_human_bum_bin@idle_b", "exit", 4.0, 4.0, -1, 50, 0, false, false, false) - if (IsBackEngine(GetEntityModel(vehicle))) then + if IsBackEngine(GetEntityModel(vehicle)) then SetVehicleDoorShut(vehicle, 4, false) else SetVehicleDoorShut(vehicle, 5, false) @@ -158,101 +206,6 @@ local function openAnim() StopAnimTask(ped, 'pickup_object', 'putdown_low', 1.0) end -local function ItemsToItemInfo() - itemInfos = { - [1] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 22x, " ..QBCore.Shared.Items["plastic"]["label"] .. ": 32x."}, - [2] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 30x, " ..QBCore.Shared.Items["plastic"]["label"] .. ": 42x."}, - [3] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 30x, " ..QBCore.Shared.Items["plastic"]["label"] .. ": 45x, "..QBCore.Shared.Items["aluminum"]["label"] .. ": 28x."}, - [4] = {costs = QBCore.Shared.Items["electronickit"]["label"] .. ": 2x, " ..QBCore.Shared.Items["plastic"]["label"] .. ": 52x, "..QBCore.Shared.Items["steel"]["label"] .. ": 40x."}, - [5] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 10x, " ..QBCore.Shared.Items["plastic"]["label"] .. ": 50x, "..QBCore.Shared.Items["aluminum"]["label"] .. ": 30x, "..QBCore.Shared.Items["iron"]["label"] .. ": 17x, "..QBCore.Shared.Items["electronickit"]["label"] .. ": 1x."}, - [6] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 36x, " ..QBCore.Shared.Items["steel"]["label"] .. ": 24x, "..QBCore.Shared.Items["aluminum"]["label"] .. ": 28x."}, - [7] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 32x, " ..QBCore.Shared.Items["steel"]["label"] .. ": 43x, "..QBCore.Shared.Items["plastic"]["label"] .. ": 61x."}, - [8] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 50x, " ..QBCore.Shared.Items["steel"]["label"] .. ": 37x, "..QBCore.Shared.Items["copper"]["label"] .. ": 26x."}, - [9] = {costs = QBCore.Shared.Items["iron"]["label"] .. ": 60x, " ..QBCore.Shared.Items["glass"]["label"] .. ": 30x."}, - [10] = {costs = QBCore.Shared.Items["aluminum"]["label"] .. ": 60x, " ..QBCore.Shared.Items["glass"]["label"] .. ": 30x."}, - [11] = {costs = QBCore.Shared.Items["iron"]["label"] .. ": 33x, " ..QBCore.Shared.Items["steel"]["label"] .. ": 44x, "..QBCore.Shared.Items["plastic"]["label"] .. ": 55x, "..QBCore.Shared.Items["aluminum"]["label"] .. ": 22x."}, - [12] = {costs = QBCore.Shared.Items["iron"]["label"] .. ": 50x, " ..QBCore.Shared.Items["steel"]["label"] .. ": 50x, "..QBCore.Shared.Items["screwdriverset"]["label"] .. ": 3x, "..QBCore.Shared.Items["advancedlockpick"]["label"] .. ": 2x."}, - } - - local items = {} - for k, item in pairs(Config.CraftingItems) do - local itemInfo = QBCore.Shared.Items[item.name:lower()] - items[item.slot] = { - name = itemInfo["name"], - amount = tonumber(item.amount), - info = itemInfos[item.slot], - label = itemInfo["label"], - description = itemInfo["description"] or "", - weight = itemInfo["weight"], - type = itemInfo["type"], - unique = itemInfo["unique"], - useable = itemInfo["useable"], - image = itemInfo["image"], - slot = item.slot, - costs = item.costs, - threshold = item.threshold, - points = item.points, - } - end - Config.CraftingItems = items -end - -local function SetupAttachmentItemsInfo() - itemInfos = { - [1] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 140x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 250x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 60x"}, - [2] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 165x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 285x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 75x"}, - [3] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 190x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 305x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 85x, " .. QBCore.Shared.Items["smg_extendedclip"]["label"] .. ": 1x"}, - [4] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 205x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 340x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 110x, " .. QBCore.Shared.Items["smg_extendedclip"]["label"] .. ": 2x"}, - [5] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 230x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 365x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 130x"}, - [6] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 255x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 390x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 145x"}, - [7] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 270x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 435x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 155x"}, - [8] = {costs = QBCore.Shared.Items["metalscrap"]["label"] .. ": 300x, " .. QBCore.Shared.Items["steel"]["label"] .. ": 469x, " .. QBCore.Shared.Items["rubber"]["label"] .. ": 170x"}, - } - - local items = {} - for k, item in pairs(Config.AttachmentCrafting["items"]) do - local itemInfo = QBCore.Shared.Items[item.name:lower()] - items[item.slot] = { - name = itemInfo["name"], - amount = tonumber(item.amount), - info = itemInfos[item.slot], - label = itemInfo["label"], - description = itemInfo["description"] or "", - weight = itemInfo["weight"], - unique = itemInfo["unique"], - useable = itemInfo["useable"], - image = itemInfo["image"], - slot = item.slot, - costs = item.costs, - threshold = item.threshold, - points = item.points, - } - end - Config.AttachmentCrafting["items"] = items -end - -local function GetThresholdItems() - ItemsToItemInfo() - local items = {} - for k, item in pairs(Config.CraftingItems) do - if PlayerData.metadata["craftingrep"] >= Config.CraftingItems[k].threshold then - items[k] = Config.CraftingItems[k] - end - end - return items -end - -local function GetAttachmentThresholdItems() - SetupAttachmentItemsInfo() - local items = {} - for k, item in pairs(Config.AttachmentCrafting["items"]) do - if PlayerData.metadata["attachmentcraftingrep"] >= Config.AttachmentCrafting["items"][k].threshold then - items[k] = Config.AttachmentCrafting["items"][k] - end - end - return items -end - -- Events RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() @@ -332,7 +285,6 @@ end) RegisterNetEvent('inventory:client:OpenInventory', function(PlayerAmmo, inventory, other) if not IsEntityDead(PlayerPedId()) then - Wait(500) ToggleHotbar(false) if showBlur == true then TriggerScreenblurFadeIn(1000) @@ -347,14 +299,14 @@ RegisterNetEvent('inventory:client:OpenInventory', function(PlayerAmmo, inventor SendNUIMessage({ action = "open", inventory = inventory, - slots = MaxInventorySlots, + slots = Config.MaxInventorySlots, other = other, - maxweight = QBCore.Config.Player.MaxWeight, + maxweight = Config.MaxInventoryWeight, Ammo = PlayerAmmo, maxammo = Config.MaximumAmmoValues, }) inInventory = true - end,inventory,other) + end, inventory, other) end end) @@ -362,66 +314,12 @@ RegisterNetEvent('inventory:client:UpdatePlayerInventory', function(isError) SendNUIMessage({ action = "update", inventory = PlayerData.items, - maxweight = QBCore.Config.Player.MaxWeight, - slots = MaxInventorySlots, + maxweight = Config.MaxInventoryWeight, + slots = Config.MaxInventorySlots, error = isError, }) end) -RegisterNetEvent('inventory:client:CraftItems', function(itemName, itemCosts, amount, toSlot, points) - local ped = PlayerPedId() - SendNUIMessage({ - action = "close", - }) - isCrafting = true - QBCore.Functions.Progressbar("repair_vehicle", "Crafting..", (math.random(2000, 5000) * amount), false, true, { - disableMovement = true, - disableCarMovement = true, - disableMouse = false, - disableCombat = true, - }, { - animDict = "mini@repair", - anim = "fixing_a_player", - flags = 16, - }, {}, {}, function() -- Done - StopAnimTask(ped, "mini@repair", "fixing_a_player", 1.0) - TriggerServerEvent("inventory:server:CraftItems", itemName, itemCosts, amount, toSlot, points) - TriggerEvent('inventory:client:ItemBox', QBCore.Shared.Items[itemName], 'add') - isCrafting = false - end, function() -- Cancel - StopAnimTask(ped, "mini@repair", "fixing_a_player", 1.0) - QBCore.Functions.Notify("Failed", "error") - isCrafting = false - end) -end) - -RegisterNetEvent('inventory:client:CraftAttachment', function(itemName, itemCosts, amount, toSlot, points) - local ped = PlayerPedId() - SendNUIMessage({ - action = "close", - }) - isCrafting = true - QBCore.Functions.Progressbar("repair_vehicle", "Crafting..", (math.random(2000, 5000) * amount), false, true, { - disableMovement = true, - disableCarMovement = true, - disableMouse = false, - disableCombat = true, - }, { - animDict = "mini@repair", - anim = "fixing_a_player", - flags = 16, - }, {}, {}, function() -- Done - StopAnimTask(ped, "mini@repair", "fixing_a_player", 1.0) - TriggerServerEvent("inventory:server:CraftAttachment", itemName, itemCosts, amount, toSlot, points) - TriggerEvent('inventory:client:ItemBox', QBCore.Shared.Items[itemName], 'add') - isCrafting = false - end, function() -- Cancel - StopAnimTask(ped, "mini@repair", "fixing_a_player", 1.0) - QBCore.Functions.Notify("Failed", "error") - isCrafting = false - end) -end) - RegisterNetEvent('inventory:client:PickupSnowballs', function() local ped = PlayerPedId() LoadAnimDict('anim@mp_snowball') @@ -433,7 +331,7 @@ RegisterNetEvent('inventory:client:PickupSnowballs', function() disableCombat = true, }, {}, {}, {}, function() -- Done ClearPedTasks(ped) - TriggerServerEvent('QBCore:Server:AddItem', "snowball", 1) + TriggerServerEvent('inventory:server:snowball', 'add') TriggerEvent('inventory:client:ItemBox', QBCore.Shared.Items["snowball"], "add") end, function() -- Cancel ClearPedTasks(ped) @@ -441,63 +339,58 @@ RegisterNetEvent('inventory:client:PickupSnowballs', function() end) end) -RegisterNetEvent('inventory:client:UseSnowball', function(amount) - local ped = PlayerPedId() - GiveWeaponToPed(ped, `weapon_snowball`, amount, false, false) - SetPedAmmo(ped, `weapon_snowball`, amount) - SetCurrentPedWeapon(ped, `weapon_snowball`, true) -end) - RegisterNetEvent('inventory:client:UseWeapon', function(weaponData, shootbool) local ped = PlayerPedId() local weaponName = tostring(weaponData.name) + local weaponHash = joaat(weaponData.name) if currentWeapon == weaponName then SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true) Wait(1500) RemoveAllPedWeapons(ped, true) TriggerEvent('weapons:client:SetCurrentWeapon', nil, shootbool) currentWeapon = nil - elseif weaponName == "weapon_stickybomb" or weaponName == "weapon_pipebomb" or weaponName == "weapon_smokegrenade" or weaponName == "weapon_flare" or weaponName == "weapon_proxmine" or weaponName == "weapon_ball" or weaponName == "weapon_molotov" or weaponName == "weapon_grenade" or weaponName == "weapon_bzgas" then - GiveWeaponToPed(ped, GetHashKey(weaponName), 1, false, false) - SetPedAmmo(ped, GetHashKey(weaponName), 1) - SetCurrentPedWeapon(ped, GetHashKey(weaponName), true) + elseif weaponName == "weapon_stickybomb" or weaponName == "weapon_pipebomb" or weaponName == "weapon_smokegrenade" or weaponName == "weapon_flare" or weaponName == "weapon_proxmine" or weaponName == "weapon_ball" or weaponName == "weapon_molotov" or weaponName == "weapon_grenade" or weaponName == "weapon_bzgas" or weaponName == "weapon_shoe" or weaponName == "prop_anim_cash_pile_01" then + GiveWeaponToPed(ped, weaponHash, 1, false, false) + SetPedAmmo(ped, weaponHash, 1) + SetCurrentPedWeapon(ped, weaponHash, true) TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool) currentWeapon = weaponName elseif weaponName == "weapon_snowball" then - GiveWeaponToPed(ped, GetHashKey(weaponName), 10, false, false) - SetPedAmmo(ped, GetHashKey(weaponName), 10) - SetCurrentPedWeapon(ped, GetHashKey(weaponName), true) - TriggerServerEvent('QBCore:Server:RemoveItem', weaponName, 1) + GiveWeaponToPed(ped, weaponHash, 10, false, false) + SetPedAmmo(ped, weaponHash, 10) + SetCurrentPedWeapon(ped, weaponHash, true) + TriggerServerEvent('inventory:server:snowball', 'remove') TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool) currentWeapon = weaponName else TriggerEvent('weapons:client:SetCurrentWeapon', weaponData, shootbool) - QBCore.Functions.TriggerCallback("weapon:server:GetWeaponAmmo", function(result) - local ammo = tonumber(result) - if weaponName == "weapon_petrolcan" or weaponName == "weapon_fireextinguisher" then - ammo = 4000 - end - GiveWeaponToPed(ped, GetHashKey(weaponName), 0, false, false) - SetPedAmmo(ped, GetHashKey(weaponName), ammo) - SetCurrentPedWeapon(ped, GetHashKey(weaponName), true) - if weaponData.info.attachments ~= nil then - for _, attachment in pairs(weaponData.info.attachments) do - GiveWeaponComponentToPed(ped, GetHashKey(weaponName), GetHashKey(attachment.component)) - end + local ammo = tonumber(weaponData.info.ammo) or 0 + + if weaponName == "weapon_petrolcan" then + ammo = 4000 + end + + GiveWeaponToPed(ped, weaponHash, ammo, false, false) + SetPedAmmo(ped, weaponHash, ammo) + SetCurrentPedWeapon(ped, weaponHash, true) + + if weaponData.info.attachments then + for _, attachment in pairs(weaponData.info.attachments) do + GiveWeaponComponentToPed(ped, weaponHash, joaat(attachment.component)) end - currentWeapon = weaponName - end, CurrentWeaponData) + end + + currentWeapon = weaponName end end) RegisterNetEvent('inventory:client:CheckWeapon', function(weaponName) + if currentWeapon ~= weaponName:lower() then return end local ped = PlayerPedId() - if currentWeapon == weaponName then - TriggerEvent('weapons:ResetHolster') - SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true) - RemoveAllPedWeapons(ped, true) - currentWeapon = nil - end + TriggerEvent('weapons:ResetHolster') + SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true) + RemoveAllPedWeapons(ped, true) + currentWeapon = nil end) RegisterNetEvent('inventory:client:AddDropItem', function(dropId, player, coords) @@ -543,13 +436,12 @@ RegisterCommand('closeinv', function() end, false) RegisterCommand('inventory', function() - if not isCrafting and not inInventory then + if not inInventory then if not PlayerData.metadata["isdead"] and not PlayerData.metadata["inlaststand"] and not PlayerData.metadata["ishandcuffed"] and not IsPauseMenuActive() then local ped = PlayerPedId() local curVeh = nil - local VendingMachine = GetClosestVending() - if IsPedInAnyVehicle(ped) then -- Is Player In Vehicle + if IsPedInAnyVehicle(ped, false) then -- Is Player In Vehicle local vehicle = GetVehiclePedIsIn(ped, false) CurrentGlovebox = QBCore.Functions.GetPlate(vehicle) curVeh = vehicle @@ -558,11 +450,14 @@ RegisterCommand('inventory', function() local vehicle = QBCore.Functions.GetClosestVehicle() if vehicle ~= 0 and vehicle ~= nil then local pos = GetEntityCoords(ped) - local trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0, -2.5, 0) - if (IsBackEngine(GetEntityModel(vehicle))) then - trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0, 2.5, 0) + local minimum, maximum = GetModelDimensions(GetEntityModel(vehicle)) + local ratio = math.abs(minimum.y/maximum.y) + local offset = minimum.y - (maximum.y + minimum.y)*ratio + local trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0, offset, 0) + if IsBackEngine(GetEntityModel(vehicle)) then + trunkpos = GetOffsetFromEntityInWorldCoords(vehicle, 0, math.abs(offset), 0) end - if #(pos - trunkpos) < 2.0 and not IsPedInAnyVehicle(ped) then + if #(pos - trunkpos) < 1.5 and not IsPedInAnyVehicle(ped) then if GetVehicleDoorLockStatus(vehicle) < 2 then CurrentVehicle = QBCore.Functions.GetPlate(vehicle) curVeh = vehicle @@ -642,12 +537,6 @@ RegisterCommand('inventory', function() TriggerServerEvent("inventory:server:OpenInventory", "glovebox", CurrentGlovebox) elseif CurrentDrop then TriggerServerEvent("inventory:server:OpenInventory", "drop", CurrentDrop) - elseif VendingMachine then - local ShopItems = {} - ShopItems.label = "Vending Machine" - ShopItems.items = Config.VendingItem - ShopItems.slots = #Config.VendingItem - TriggerServerEvent("inventory:server:OpenInventory", "shop", "Vendingshop_"..math.random(1, 99), ShopItems) else openAnim() TriggerServerEvent("inventory:server:OpenInventory") @@ -663,7 +552,7 @@ RegisterCommand('hotbar', function() if not PlayerData.metadata["isdead"] and not PlayerData.metadata["inlaststand"] and not PlayerData.metadata["ishandcuffed"] and not IsPauseMenuActive() then ToggleHotbar(isHotbar) end -end) +end, false) RegisterKeyMapping('hotbar', 'Toggles keybind slots', 'keyboard', 'z') @@ -671,11 +560,11 @@ for i = 1, 6 do RegisterCommand('slot' .. i,function() if not PlayerData.metadata["isdead"] and not PlayerData.metadata["inlaststand"] and not PlayerData.metadata["ishandcuffed"] and not IsPauseMenuActive() then if i == 6 then - i = MaxInventorySlots + i = Config.MaxInventorySlots end TriggerServerEvent("inventory:server:UseItemSlot", i) end - end) + end, false) RegisterKeyMapping('slot' .. i, 'Uses the item in slot ' .. i, 'keyboard', i) end @@ -705,31 +594,26 @@ end) RegisterNUICallback('RemoveAttachment', function(data, cb) local ped = PlayerPedId() local WeaponData = QBCore.Shared.Items[data.WeaponData.name] - local label = QBCore.Shared.Items - local Attachment = WeaponAttachments[WeaponData.name:upper()][data.AttachmentData.attachment] - + print(data.AttachmentData.attachment:gsub("(.*).*_",'')) + data.AttachmentData.attachment = data.AttachmentData.attachment:gsub("(.*).*_",'') QBCore.Functions.TriggerCallback('weapons:server:RemoveAttachment', function(NewAttachments) if NewAttachments ~= false then - local Attachies = {} - RemoveWeaponComponentFromPed(ped, GetHashKey(data.WeaponData.name), GetHashKey(Attachment.component)) - for k, v in pairs(NewAttachments) do - for wep, pew in pairs(WeaponAttachments[WeaponData.name:upper()]) do - if v.component == pew.component then - item = pew.item - Attachies[#Attachies+1] = { - attachment = pew.item, - label = QBCore.Shared.Items[item].label, - } - end - end + local attachments = {} + RemoveWeaponComponentFromPed(ped, joaat(data.WeaponData.name), joaat(data.AttachmentData.component)) + for _, v in pairs(NewAttachments) do + attachments[#attachments+1] = { + attachment = v.item, + label = v.label, + image = QBCore.Shared.Items[v.item].image + } end local DJATA = { - Attachments = Attachies, + Attachments = attachments, WeaponData = WeaponData, } cb(DJATA) else - RemoveWeaponComponentFromPed(ped, GetHashKey(data.WeaponData.name), GetHashKey(Attachment.component)) + RemoveWeaponComponentFromPed(ped, joaat(data.WeaponData.name), joaat(data.AttachmentData.component)) cb({}) end end, data.AttachmentData, data.WeaponData) @@ -821,7 +705,7 @@ end) RegisterNUICallback("GiveItem", function(data) local player, distance = QBCore.Functions.GetClosestPlayer(GetEntityCoords(PlayerPedId())) if player ~= -1 and distance < 3 then - if (data.inventory == 'player') then + if data.inventory == 'player' then local playerId = GetPlayerServerId(player) SetCurrentPedWeapon(PlayerPedId(),'WEAPON_UNARMED',true) TriggerServerEvent("inventory:server:GiveItem", playerId, data.item.name, data.amount, data.item.slot) @@ -837,14 +721,38 @@ end) CreateThread(function() while true do - local sleep = 1000 - if DropsNear then + local sleep = 100 + if DropsNear ~= nil then + local ped = PlayerPedId() + local closestDrop = nil + local closestDistance = nil for k, v in pairs(DropsNear) do - if DropsNear[k] then - sleep = 0 - DrawMarker(2, v.coords.x, v.coords.y, v.coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.15, 120, 10, 20, 155, false, false, false, 1, false, false, false) + + if DropsNear[k] ~= nil then + if Config.UseItemDrop then + if not v.isDropShowing then + CreateItemDrop(k) + end + else + sleep = 0 + DrawMarker(20, v.coords.x, v.coords.y, v.coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.15, 120, 10, 20, 155, false, false, false, 1, false, false, false) + end + + local coords = (v.object ~= nil and GetEntityCoords(v.object)) or vector3(v.coords.x, v.coords.y, v.coords.z) + local distance = #(GetEntityCoords(ped) - coords) + if distance < 2 and (not closestDistance or distance < closestDistance) then + closestDrop = k + closestDistance = distance + end end end + + + if not closestDrop then + CurrentDrop = 0 + else + CurrentDrop = closestDrop + end end Wait(sleep) end @@ -852,20 +760,19 @@ end) CreateThread(function() while true do - if Drops and next(Drops) then + if Drops ~= nil and next(Drops) ~= nil then local pos = GetEntityCoords(PlayerPedId(), true) for k, v in pairs(Drops) do - if Drops[k] then + if Drops[k] ~= nil then local dist = #(pos - vector3(v.coords.x, v.coords.y, v.coords.z)) - if dist < 7.5 then + if dist < Config.MaxDropViewDistance then DropsNear[k] = v - if dist < 2 then - CurrentDrop = k + else + if Config.UseItemDrop and DropsNear[k] then + RemoveNearbyDrop(k) else - CurrentDrop = nil + DropsNear[k] = nil end - else - DropsNear[k] = nil end end end @@ -875,96 +782,3 @@ CreateThread(function() Wait(500) end end) - -RegisterNUICallback('Notify', function(data) - QBCore.Functions.Notify(data.message, data.type) -end) - ---[[CreateThread(function() - while true do - Wait(0) - local pos, awayFromObject = GetEntityCoords(PlayerPedId()), true - local craftObject = GetClosestObjectOfType(pos, 2.0, -573669520, false, false, false) - if craftObject ~= 0 then - local objectPos = GetEntityCoords(craftObject) - if #(pos - objectPos) < 1.5 then - awayFromObject = false - DrawText3Ds(objectPos.x, objectPos.y, objectPos.z + 1.0, "~g~E~w~ - Craft") - if IsControlJustReleased(0, 38) then - local crafting = {} - crafting.label = "Crafting" - crafting.items = GetThresholdItems() - TriggerServerEvent("inventory:server:OpenInventory", "crafting", math.random(1, 99), crafting) - end - end - end - if awayFromObject then - Wait(1000) - end - end -end) -CreateThread(function() - while true do - local pos = GetEntityCoords(PlayerPedId()) - local inRange = false - local distance = #(pos - Config.AttachmentCrafting.location) - if distance < 10 then - inRange = true - if distance < 1.5 then - DrawText3Ds(Config.AttachmentCrafting["location"].x, Config.AttachmentCrafting["location"].y, Config.AttachmentCrafting["location"].z, "~g~E~w~ - Craft") - if IsControlJustPressed(0, 38) then - local crafting = {} - crafting.label = "Attachment Crafting" - crafting.items = GetAttachmentThresholdItems() - TriggerServerEvent("inventory:server:OpenInventory", "attachment_crafting", math.random(1, 99), crafting) - end - end - end - if not inRange then - Wait(1000) - end - Wait(3) - end -end)]]-- - - --qb-target - RegisterNetEvent("inventory:client:Crafting", function(dropId) - local crafting = {} - crafting.label = "Crafting" - crafting.items = GetThresholdItems() - TriggerServerEvent("inventory:server:OpenInventory", "crafting", math.random(1, 99), crafting) - end) - - - RegisterNetEvent("inventory:client:WeaponAttachmentCrafting", function(dropId) - local crafting = {} - crafting.label = "Attachment Crafting" - crafting.items = GetAttachmentThresholdItems() - TriggerServerEvent("inventory:server:OpenInventory", "attachment_crafting", math.random(1, 99), crafting) - end) - - local toolBoxModels = { - `prop_toolchest_05`, - `prop_tool_bench02_ld`, - `prop_tool_bench02`, - `prop_toolchest_02`, - `prop_toolchest_03`, - `prop_toolchest_03_l2`, - `prop_toolchest_05`, - `prop_toolchest_04`, - } - exports['qb-target']:AddTargetModel(toolBoxModels, { - options = { - { - event = "inventory:client:WeaponAttachmentCrafting", - icon = "fas fa-wrench", - label = "Weapon Attachment Crafting", - }, - { - event = "inventory:client:Crafting", - icon = "fas fa-wrench", - label = "Item Crafting", - }, - }, - distance = 1.0 - }) diff --git a/lj-inventory/config.lua b/lj-inventory/config.lua index 8c98518..9db00e0 100644 --- a/lj-inventory/config.lua +++ b/lj-inventory/config.lua @@ -1,329 +1,11 @@ Config = {} -Config.VendingObjects = { - "prop_vend_soda_01", - "prop_vend_soda_02", - "prop_vend_water_01" -} - -Config.BinObjects = { - "prop_bin_05a", -} - -Config.CraftingObject = `prop_toolchest_05` -- Only needed if not using target | Line 928 to change Target Models - -Config.VendingItem = { - [1] = { - name = "kurkakola", - price = 4, - amount = 50, - info = {}, - type = "item", - slot = 1, - }, - [2] = { - name = "water_bottle", - price = 4, - amount = 50, - info = {}, - type = "item", - slot = 2, - }, -} - -Config.CraftingItems = { - [1] = { - name = "lockpick", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 22, - ["plastic"] = 32, - }, - type = "item", - slot = 1, - threshold = 0, - points = 1, - }, - [2] = { - name = "screwdriverset", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 30, - ["plastic"] = 42, - }, - type = "item", - slot = 2, - threshold = 0, - points = 2, - }, - [3] = { - name = "electronickit", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 30, - ["plastic"] = 45, - ["aluminum"] = 28, - }, - type = "item", - slot = 3, - threshold = 0, - points = 3, - }, - [4] = { - name = "radioscanner", - amount = 50, - info = {}, - costs = { - ["electronickit"] = 2, - ["plastic"] = 52, - ["steel"] = 40, - }, - type = "item", - slot = 4, - threshold = 0, - points = 4, - }, - [5] = { - name = "gatecrack", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 10, - ["plastic"] = 50, - ["aluminum"] = 30, - ["iron"] = 17, - ["electronickit"] = 2, - }, - type = "item", - slot = 5, - threshold = 110, - points = 5, - }, - [6] = { - name = "handcuffs", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 36, - ["steel"] = 24, - ["aluminum"] = 28, - }, - type = "item", - slot = 6, - threshold = 160, - points = 6, - }, - [7] = { - name = "repairkit", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 32, - ["steel"] = 43, - ["plastic"] = 61, - }, - type = "item", - slot = 7, - threshold = 200, - points = 7, - }, - [8] = { - name = "pistol_ammo", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 50, - ["steel"] = 37, - ["copper"] = 26, - }, - type = "item", - slot = 8, - threshold = 250, - points = 8, - }, - [9] = { - name = "ironoxide", - amount = 50, - info = {}, - costs = { - ["iron"] = 60, - ["glass"] = 30, - }, - type = "item", - slot = 9, - threshold = 300, - points = 9, - }, - [10] = { - name = "aluminumoxide", - amount = 50, - info = {}, - costs = { - ["aluminum"] = 60, - ["glass"] = 30, - }, - type = "item", - slot = 10, - threshold = 300, - points = 10, - }, - [11] = { - name = "armor", - amount = 50, - info = {}, - costs = { - ["iron"] = 33, - ["steel"] = 44, - ["plastic"] = 55, - ["aluminum"] = 22, - }, - type = "item", - slot = 11, - threshold = 350, - points = 11, - }, - [12] = { - name = "drill", - amount = 50, - info = {}, - costs = { - ["iron"] = 50, - ["steel"] = 50, - ["screwdriverset"] = 3, - ["advancedlockpick"] = 2, - }, - type = "item", - slot = 12, - threshold = 1750, - points = 12, - }, -} - -Config.AttachmentCraftingLocation = vector3(88.91, 3743.88, 40.77) -- Only needed if not using target - -Config.AttachmentCrafting = { - ["items"] = { - [1] = { - name = "pistol_extendedclip", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 140, - ["steel"] = 250, - ["rubber"] = 60, - }, - type = "item", - slot = 1, - threshold = 0, - points = 1, - }, - [2] = { - name = "pistol_suppressor", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 165, - ["steel"] = 285, - ["rubber"] = 75, - }, - type = "item", - slot = 2, - threshold = 10, - points = 2, - }, - [3] = { - name = "smg_extendedclip", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 190, - ["steel"] = 305, - ["rubber"] = 85, - }, - type = "item", - slot = 3, - threshold = 25, - points = 3, - }, - [4] = { - name = "microsmg_extendedclip", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 205, - ["steel"] = 340, - ["rubber"] = 110, - }, - type = "item", - slot = 4, - threshold = 50, - points = 4, - }, - [5] = { - name = "smg_drum", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 230, - ["steel"] = 365, - ["rubber"] = 130, - }, - type = "item", - slot = 5, - threshold = 75, - points = 5, - }, - [6] = { - name = "smg_scope", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 255, - ["steel"] = 390, - ["rubber"] = 145, - }, - type = "item", - slot = 6, - threshold = 100, - points = 6, - }, - [7] = { - name = "assaultrifle_extendedclip", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 270, - ["steel"] = 435, - ["rubber"] = 155, - ["smg_extendedclip"] = 1, - }, - type = "item", - slot = 7, - threshold = 150, - points = 7, - }, - [8] = { - name = "assaultrifle_drum", - amount = 50, - info = {}, - costs = { - ["metalscrap"] = 300, - ["steel"] = 469, - ["rubber"] = 170, - ["smg_extendedclip"] = 2, - }, - type = "item", - slot = 8, - threshold = 200, - points = 8, - }, - } -} - -MaxInventorySlots = 41 +Config.MaxInventoryWeight = 250000 -- Max weight a player can carry (default 120kg, written in grams) +Config.MaxInventorySlots = 41 -- Max inventory slots for a player +Config.CleanupDropTime = 15 * 60 -- How many seconds it takes for drops to be untouched before being deleted +Config.MaxDropViewDistance = 8.5 -- The distance in GTA Units that a drop can be seen +Config.UseItemDrop = false -- This will enable item object to spawn on drops instead of markers +Config.ItemDropObject = `prop_nigel_bag_pickup` -- if Config.UseItemDrop is true, this will be the prop that spawns for the item BackEngineVehicles = { [`ninef`] = true, @@ -367,8 +49,9 @@ BackEngineVehicles = { } Config.MaximumAmmoValues = { - ["pistol"] = 250, - ["smg"] = 250, - ["shotgun"] = 200, - ["rifle"] = 250, + ["pistol"] = 48, + ["smg"] = 120, + ["shotgun"] = 12, + ["rifle"] = 180, + ["musket"] = 35, } diff --git a/lj-inventory/server/decay.lua b/lj-inventory/server/decay.lua index 1b5822c..17d4463 100644 --- a/lj-inventory/server/decay.lua +++ b/lj-inventory/server/decay.lua @@ -1,6 +1,7 @@ local QBCore = exports['qb-core']:GetCoreObject() local TimeAllowed = 60 * 60 * 24 * 1 -- Maths for 1 day dont touch its very important and could break everything + function ConvertQuality(item) local StartDate = item.created local DecayRate = QBCore.Shared.Items[item.name:lower()]["decay"] ~= nil and QBCore.Shared.Items[item.name:lower()]["decay"] or 0.0 @@ -22,11 +23,11 @@ QBCore.Functions.CreateCallback('inventory:server:ConvertQuality', function(sour local src = source local data = {} local Player = QBCore.Functions.GetPlayer(src) - for k, item in pairs(inventory) do + for _, item in pairs(inventory) do if item.created then if QBCore.Shared.Items[item.name:lower()]["decay"] ~= nil or QBCore.Shared.Items[item.name:lower()]["decay"] ~= 0 then if item.info then - if type(item.info) == "string" then + if type(item.info) == "string" then item.info = {} end if item.info.quality == nil then @@ -49,16 +50,16 @@ QBCore.Functions.CreateCallback('inventory:server:ConvertQuality', function(sour item.info.quality = 100 else local info = {quality = 100} - item.info = info + item.info = info end end end end if other then - for k, item in pairs(other["inventory"]) do + for _, item in pairs(other["inventory"]) do if item.created then if QBCore.Shared.Items[item.name:lower()]["decay"] ~= nil or QBCore.Shared.Items[item.name:lower()]["decay"] ~= 0 then - if item.info then + if item.info then if item.info.quality == nil then item.info.quality = 100 end @@ -79,7 +80,7 @@ QBCore.Functions.CreateCallback('inventory:server:ConvertQuality', function(sour item.info.quality = 100 else local info = {quality = 100} - item.info = info + item.info = info end end end diff --git a/lj-inventory/server/main.lua b/lj-inventory/server/main.lua index 16e5466..4215a4e 100644 --- a/lj-inventory/server/main.lua +++ b/lj-inventory/server/main.lua @@ -6,36 +6,414 @@ local Trunks = {} local Gloveboxes = {} local Stashes = {} local ShopItems = {} +local UsableItems = {} --- Functions +---Loads the inventory for the player with the citizenid that is provided +local function LoadInventory(source, citizenid) + local inventory = MySQL.prepare.await('SELECT inventory FROM players WHERE citizenid = ?', { citizenid }) + local loadedInventory = {} + local missingItems = {} + + if not inventory then return loadedInventory end + + inventory = json.decode(inventory) + if table.type(inventory) == "empty" then return loadedInventory end + + for _, item in pairs(inventory) do + if item then + local itemInfo = QBCore.Shared.Items[item.name:lower()] + if itemInfo then + loadedInventory[item.slot] = { + name = itemInfo['name'], + amount = item.amount, + info = item.info or '', + label = itemInfo['label'], + description = itemInfo['description'] or '', + weight = itemInfo['weight'], + type = itemInfo['type'], + unique = itemInfo['unique'], + useable = itemInfo['useable'], + image = itemInfo['image'], + shouldClose = itemInfo['shouldClose'], + slot = item.slot, + combinable = itemInfo['combinable'] + } + else + missingItems[#missingItems + 1] = item.name:lower() + end + end + end + if #missingItems > 0 then + print(("The following items were removed for player %s as they no longer exist"):format(GetPlayerName(source))) + QBCore.Debug(missingItems) + end + + return loadedInventory +end +exports("LoadInventory", LoadInventory) + +---Saves the inventory for the player with the provided source or PlayerData is they're offline +local function SaveInventory(source, offline) + local PlayerData + if not offline then + local Player = QBCore.Functions.GetPlayer(source) + + if not Player then return end + + PlayerData = Player.PlayerData + else + PlayerData = source -- for offline users, the playerdata gets sent over the source variable + end + + local items = PlayerData.items + local ItemsJson = {} + if items and table.type(items) ~= "empty" then + for slot, item in pairs(items) do + if items[slot] then + ItemsJson[#ItemsJson+1] = { + name = item.name, + amount = item.amount, + info = item.info, + type = item.type, + slot = slot, + } + end + end + MySQL.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { json.encode(ItemsJson), PlayerData.citizenid }) + else + MySQL.prepare('UPDATE players SET inventory = ? WHERE citizenid = ?', { '[]', PlayerData.citizenid }) + end +end +exports("SaveInventory", SaveInventory) + +---Gets the totalweight of the items provided +local function GetTotalWeight(items) + local weight = 0 + if not items then return 0 end + for _, item in pairs(items) do + weight += item.weight * item.amount + end + return tonumber(weight) +end +exports("GetTotalWeight", GetTotalWeight) + +---Gets the slots that the provided item is in +local function GetSlotsByItem(items, itemName) + local slotsFound = {} + if not items then return slotsFound end + for slot, item in pairs(items) do + if item.name:lower() == itemName:lower() then + slotsFound[#slotsFound+1] = slot + end + end + return slotsFound +end +exports("GetSlotsByItem", GetSlotsByItem) + +---Get the first slot where the item is located +local function GetFirstSlotByItem(items, itemName) + if not items then return nil end + for slot, item in pairs(items) do + if item.name:lower() == itemName:lower() then + return tonumber(slot) + end + end + return nil +end +exports("GetFirstSlotByItem", GetFirstSlotByItem) + +---Add an item to the inventory of the player +local function AddItem(source, item, amount, slot, info) + local Player = QBCore.Functions.GetPlayer(source) + + if not Player then return false end + + local totalWeight = GetTotalWeight(Player.PlayerData.items) + local itemInfo = QBCore.Shared.Items[item:lower()] + if not itemInfo and not Player.Offline then + QBCore.Functions.Notify(source, "Item does not exist", 'error') + return false + end + + amount = tonumber(amount) or 1 + slot = tonumber(slot) or GetFirstSlotByItem(Player.PlayerData.items, item) + + if itemInfo['type'] == 'weapon' and not info then + info = { + serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) + } + end + if (totalWeight + (itemInfo['weight'] * amount)) <= Config.MaxInventoryWeight then + if (slot and Player.PlayerData.items[slot]) and (Player.PlayerData.items[slot].name:lower() == item:lower()) and (itemInfo['type'] == 'item' and not itemInfo['unique']) then + Player.PlayerData.items[slot].amount = Player.PlayerData.items[slot].amount + amount + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if Player.Offline then return true end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'AddItem', 'green', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** got item: [slot:' .. slot .. '], itemname: ' .. Player.PlayerData.items[slot].name .. ', added amount: ' .. amount .. ', new total amount: ' .. Player.PlayerData.items[slot].amount) + + return true + elseif not itemInfo['unique'] and slot or slot and Player.PlayerData.items[slot] == nil then + Player.PlayerData.items[slot] = { name = itemInfo['name'], amount = amount, info = info or '', label = itemInfo['label'], description = itemInfo['description'] or '', weight = itemInfo['weight'], type = itemInfo['type'], unique = itemInfo['unique'], useable = itemInfo['useable'], image = itemInfo['image'], shouldClose = itemInfo['shouldClose'], slot = slot, combinable = itemInfo['combinable'] } + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if Player.Offline then return true end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'AddItem', 'green', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** got item: [slot:' .. slot .. '], itemname: ' .. Player.PlayerData.items[slot].name .. ', added amount: ' .. amount .. ', new total amount: ' .. Player.PlayerData.items[slot].amount) -local function recipeContains(recipe, fromItem) - for k, v in pairs(recipe.accept) do - if v == fromItem.name then return true + elseif itemInfo['unique'] or (not slot or slot == nil) or itemInfo['type'] == 'weapon' then + for i = 1, Config.MaxInventorySlots, 1 do + if Player.PlayerData.items[i] == nil then + Player.PlayerData.items[i] = { name = itemInfo['name'], amount = amount, info = info or '', label = itemInfo['label'], description = itemInfo['description'] or '', weight = itemInfo['weight'], type = itemInfo['type'], unique = itemInfo['unique'], useable = itemInfo['useable'], image = itemInfo['image'], shouldClose = itemInfo['shouldClose'], slot = i, combinable = itemInfo['combinable'] } + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if Player.Offline then return true end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'AddItem', 'green', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** got item: [slot:' .. i .. '], itemname: ' .. Player.PlayerData.items[i].name .. ', added amount: ' .. amount .. ', new total amount: ' .. Player.PlayerData.items[i].amount) + + return true + end + end end + elseif not Player.Offline then + QBCore.Functions.Notify(source, "Inventory too full", 'error') end + return false +end +exports("AddItem", AddItem) + +---Remove an item from the inventory of the player +local function RemoveItem(source, item, amount, slot) + local Player = QBCore.Functions.GetPlayer(source) + + if not Player then return false end + + amount = tonumber(amount) or 1 + slot = tonumber(slot) + + if slot then + if Player.PlayerData.items[slot].amount > amount then + Player.PlayerData.items[slot].amount = Player.PlayerData.items[slot].amount - amount + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if not Player.Offline then + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'RemoveItem', 'red', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** lost item: [slot:' .. slot .. '], itemname: ' .. Player.PlayerData.items[slot].name .. ', removed amount: ' .. amount .. ', new total amount: ' .. Player.PlayerData.items[slot].amount) + end + + return true + elseif Player.PlayerData.items[slot].amount == amount then + Player.PlayerData.items[slot] = nil + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if Player.Offline then return true end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'RemoveItem', 'red', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** lost item: [slot:' .. slot .. '], itemname: ' .. item .. ', removed amount: ' .. amount .. ', item removed') + + return true + end + else + local slots = GetSlotsByItem(Player.PlayerData.items, item) + local amountToRemove = amount + + if not slots then return false end + + for _, _slot in pairs(slots) do + if Player.PlayerData.items[_slot].amount > amountToRemove then + Player.PlayerData.items[_slot].amount = Player.PlayerData.items[_slot].amount - amountToRemove + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if not Player.Offline then + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'RemoveItem', 'red', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** lost item: [slot:' .. _slot .. '], itemname: ' .. Player.PlayerData.items[_slot].name .. ', removed amount: ' .. amount .. ', new total amount: ' .. Player.PlayerData.items[_slot].amount) + end + + return true + elseif Player.PlayerData.items[_slot].amount == amountToRemove then + Player.PlayerData.items[_slot] = nil + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + + if Player.Offline then return true end + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'RemoveItem', 'red', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** lost item: [slot:' .. _slot .. '], itemname: ' .. item .. ', removed amount: ' .. amount .. ', item removed') + + return true + end + end + end return false end +exports("RemoveItem", RemoveItem) + +---Get the item with the slot +local function GetItemBySlot(source, slot) + local Player = QBCore.Functions.GetPlayer(source) + slot = tonumber(slot) + return Player.PlayerData.items[slot] +end +exports("GetItemBySlot", GetItemBySlot) -local function hasCraftItems(source, CostItems, amount) +---Get the item from the inventory of the player with the provided source by the name of the item +local function GetItemByName(source, item) local Player = QBCore.Functions.GetPlayer(source) - for k, v in pairs(CostItems) do - if Player.Functions.GetItemByName(k) ~= nil then - if Player.Functions.GetItemByName(k).amount < (v * amount) then - return false + item = tostring(item):lower() + local slot = GetFirstSlotByItem(Player.PlayerData.items, item) + return Player.PlayerData.items[slot] +end +exports("GetItemByName", GetItemByName) + +---Get the item from the inventory of the player with the provided source by the name of the item in an array for all slots that the item is in +local function GetItemsByName(source, item) + local Player = QBCore.Functions.GetPlayer(source) + item = tostring(item):lower() + local items = {} + local slots = GetSlotsByItem(Player.PlayerData.items, item) + for _, slot in pairs(slots) do + if slot then + items[#items+1] = Player.PlayerData.items[slot] + end + end + return items +end +exports("GetItemsByName", GetItemsByName) + +---Clear the inventory of the player with the provided source and filter any items out of the clearing of the inventory to keep (optional) +local function ClearInventory(source, filterItems) + local Player = QBCore.Functions.GetPlayer(source) + local savedItemData = {} + + if filterItems then + local filterItemsType = type(filterItems) + if filterItemsType == "string" then + local item = GetItemByName(source, filterItems) + + if item then + savedItemData[item.slot] = item + end + elseif filterItemsType == "table" and table.type(filterItems) == "array" then + for i = 1, #filterItems do + local item = GetItemByName(source, filterItems[i]) + + if item then + savedItemData[item.slot] = item + end end - else - return false end end + + Player.Functions.SetPlayerData("items", savedItemData) + + if Player.Offline then return end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'ClearInventory', 'red', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** inventory cleared') +end +exports("ClearInventory", ClearInventory) + +---Sets the items playerdata to the provided items param +local function SetInventory(source, items) + local Player = QBCore.Functions.GetPlayer(source) + + Player.Functions.SetPlayerData("items", items) + + if Player.Offline then return end + + TriggerEvent('qb-log:server:CreateLog', 'playerinventory', 'SetInventory', 'blue', '**' .. GetPlayerName(source) .. ' (citizenid: ' .. Player.PlayerData.citizenid .. ' | id: ' .. source .. ')** items set: ' .. json.encode(items)) +end +exports("SetInventory", SetInventory) + +---Set the data of a specific item +local function SetItemData(source, itemName, key, val) + if not itemName or not key then return false end + + local Player = QBCore.Functions.GetPlayer(source) + + if not Player then return end + + local item = GetItemByName(source, itemName) + + if not item then return false end + + item[key] = val + Player.PlayerData.items[item.slot] = item + Player.Functions.SetPlayerData("items", Player.PlayerData.items) + return true end +exports("SetItemData", SetItemData) + +---Checks if you have an item or not +local function HasItem(source, items, amount) + local Player = QBCore.Functions.GetPlayer(source) + if not Player then return false end + local isTable = type(items) == 'table' + local isArray = isTable and table.type(items) == 'array' or false + local totalItems = #items + local count = 0 + local kvIndex = 2 + if isTable and not isArray then + totalItems = 0 + for _ in pairs(items) do totalItems += 1 end + kvIndex = 1 + end + if isTable then + for k, v in pairs(items) do + local itemKV = {k, v} + local item = GetItemByName(source, itemKV[kvIndex]) + if item and ((amount and item.amount >= amount) or (not isArray and item.amount >= v) or (not amount and isArray)) then + count += 1 + end + end + if count == totalItems then + return true + end + else -- Single item as string + local item = GetItemByName(source, items) + if item and (not amount or (item and amount and item.amount >= amount)) then + return true + end + end + return false +end +exports("HasItem", HasItem) + +---Create a usable item with a callback on use +local function CreateUsableItem(itemName, data) + UsableItems[itemName] = data +end +exports("CreateUsableItem", CreateUsableItem) + +---Get the usable item data for the specified item +local function GetUsableItem(itemName) + return UsableItems[itemName] +end +exports("GetUsableItem", GetUsableItem) + +---Use an item from the UsableItems table if a callback is present +local function UseItem(itemName, ...) + local callback = UsableItems[itemName] + + if not callback then return end + + callback(...) +end +exports("UseItem", UseItem) + + + +-- Functions + +local function recipeContains(recipe, fromItem) + for k, v in pairs(recipe.accept) do + if v == fromItem.name then + return true + end + end + + return false +end local function IsVehicleOwned(plate) local result = MySQL.Sync.fetchScalar('SELECT 1 from player_vehicles WHERE plate = ?', {plate}) - if result then return true else return false end + return result end -- Shop Items @@ -69,49 +447,49 @@ end local function GetStashItems(stashId) local items = {} local result = MySQL.Sync.fetchScalar('SELECT items FROM stashitems WHERE stash = ?', {stashId}) - if result then - local stashItems = json.decode(result) - if stashItems then - for k, item in pairs(stashItems) do - local itemInfo = QBCore.Shared.Items[item.name:lower()] - if itemInfo then - items[item.slot] = { - name = itemInfo["name"], - amount = tonumber(item.amount), - info = item.info or "", - label = itemInfo["label"], - description = itemInfo["description"] or "", - weight = itemInfo["weight"], - type = itemInfo["type"], - unique = itemInfo["unique"], - useable = itemInfo["useable"], - image = itemInfo["image"], - slot = item.slot, - } - end - end + if not result then return items end + + local stashItems = json.decode(result) + if not stashItems then return items end + + for _, item in pairs(stashItems) do + local itemInfo = QBCore.Shared.Items[item.name:lower()] + if itemInfo then + items[item.slot] = { + name = itemInfo["name"], + amount = tonumber(item.amount), + info = item.info or "", + label = itemInfo["label"], + description = itemInfo["description"] or "", + weight = itemInfo["weight"], + type = itemInfo["type"], + unique = itemInfo["unique"], + useable = itemInfo["useable"], + image = itemInfo["image"], + slot = item.slot, + } end end return items end local function SaveStashItems(stashId, items) - if Stashes[stashId].label ~= "Stash-None" then - if items then - for slot, item in pairs(items) do - item.description = nil - end - MySQL.Async.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['stash'] = stashId, - ['items'] = json.encode(items) - }) - Stashes[stashId].isOpen = false - end + if Stashes[stashId].label == "Stash-None" or not items then return end + + for _, item in pairs(items) do + item.description = nil end + + MySQL.insert('INSERT INTO stashitems (stash, items) VALUES (:stash, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['stash'] = stashId, + ['items'] = json.encode(items) + }) + + Stashes[stashId].isOpen = false end local function AddToStash(stashId, slot, otherslot, itemName, amount, info, created) - local amount = tonumber(amount) + amount = tonumber(amount) or 1 local ItemData = QBCore.Shared.Items[itemName] if not ItemData.unique then if Stashes[stashId].items[slot] and Stashes[stashId].items[slot].name == itemName then @@ -169,15 +547,12 @@ local function AddToStash(stashId, slot, otherslot, itemName, amount, info, crea end local function RemoveFromStash(stashId, slot, itemName, amount) - local amount = tonumber(amount) - if Stashes[stashId].items[slot] ~= nil and Stashes[stashId].items[slot].name == itemName then + amount = tonumber(amount) or 1 + if Stashes[stashId].items[slot] and Stashes[stashId].items[slot].name == itemName then if Stashes[stashId].items[slot].amount > amount then Stashes[stashId].items[slot].amount = Stashes[stashId].items[slot].amount - amount else Stashes[stashId].items[slot] = nil - if next(Stashes[stashId].items) == nil then - Stashes[stashId].items = {} - end end else Stashes[stashId].items[slot] = nil @@ -191,53 +566,53 @@ end local function GetOwnedVehicleItems(plate) local items = {} local result = MySQL.Sync.fetchScalar('SELECT items FROM trunkitems WHERE plate = ?', {plate}) - if result then - local trunkItems = json.decode(result) - if trunkItems then - for k, item in pairs(trunkItems) do - local itemInfo = QBCore.Shared.Items[item.name:lower()] - if itemInfo then - items[item.slot] = { - name = itemInfo["name"], - amount = tonumber(item.amount), - info = item.info or "", - label = itemInfo["label"], - description = itemInfo["description"] or "", - weight = itemInfo["weight"], - type = itemInfo["type"], - unique = itemInfo["unique"], - useable = itemInfo["useable"], - image = itemInfo["image"], - slot = item.slot, - } - end - end + if not result then return items end + + local trunkItems = json.decode(result) + if not trunkItems then return items end + + for _, item in pairs(trunkItems) do + local itemInfo = QBCore.Shared.Items[item.name:lower()] + if itemInfo then + items[item.slot] = { + name = itemInfo["name"], + amount = tonumber(item.amount), + info = item.info or "", + label = itemInfo["label"], + description = itemInfo["description"] or "", + weight = itemInfo["weight"], + type = itemInfo["type"], + unique = itemInfo["unique"], + useable = itemInfo["useable"], + image = itemInfo["image"], + slot = item.slot, + } end end return items end local function SaveOwnedVehicleItems(plate, items) - if Trunks[plate].label ~= "Trunk-None" then - if items ~= nil then - for slot, item in pairs(items) do - item.description = nil - end - MySQL.Async.insert('INSERT INTO trunkitems (plate, items) VALUES (:plate, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['plate'] = plate, - ['items'] = json.encode(items) - }) - Trunks[plate].isOpen = false - end + if Trunks[plate].label == "Trunk-None" or not items then return end + + for _, item in pairs(items) do + item.description = nil end + + MySQL.insert('INSERT INTO trunkitems (plate, items) VALUES (:plate, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['plate'] = plate, + ['items'] = json.encode(items) + }) + + Trunks[plate].isOpen = false end local function AddToTrunk(plate, slot, otherslot, itemName, amount, info, created) - local amount = tonumber(amount) + amount = tonumber(amount) or 1 local ItemData = QBCore.Shared.Items[itemName] if not ItemData.unique then - if Trunks[plate].items[slot] ~= nil and Trunks[plate].items[slot].name == itemName then + if Trunks[plate].items[slot] and Trunks[plate].items[slot].name == itemName then Trunks[plate].items[slot].amount = Trunks[plate].items[slot].amount + amount else local itemInfo = QBCore.Shared.Items[itemName:lower()] @@ -257,7 +632,7 @@ local function AddToTrunk(plate, slot, otherslot, itemName, amount, info, create } end else - if Trunks[plate].items[slot] ~= nil and Trunks[plate].items[slot].name == itemName then + if Trunks[plate].items[slot] and Trunks[plate].items[slot].name == itemName then local itemInfo = QBCore.Shared.Items[itemName:lower()] Trunks[plate].items[otherslot] = { name = itemInfo["name"], @@ -292,17 +667,15 @@ local function AddToTrunk(plate, slot, otherslot, itemName, amount, info, create end local function RemoveFromTrunk(plate, slot, itemName, amount) - if Trunks[plate].items[slot] ~= nil and Trunks[plate].items[slot].name == itemName then + amount = tonumber(amount) or 1 + if Trunks[plate].items[slot] and Trunks[plate].items[slot].name == itemName then if Trunks[plate].items[slot].amount > amount then Trunks[plate].items[slot].amount = Trunks[plate].items[slot].amount - amount else Trunks[plate].items[slot] = nil - if next(Trunks[plate].items) == nil then - Trunks[plate].items = {} - end end else - Trunks[plate].items[slot]= nil + Trunks[plate].items[slot] = nil if Trunks[plate].items == nil then Trunks[plate].items[slot] = nil end @@ -313,53 +686,53 @@ end local function GetOwnedVehicleGloveboxItems(plate) local items = {} local result = MySQL.Sync.fetchScalar('SELECT items FROM gloveboxitems WHERE plate = ?', {plate}) - if result then - local gloveboxItems = json.decode(result) - if gloveboxItems then - for k, item in pairs(gloveboxItems) do - local itemInfo = QBCore.Shared.Items[item.name:lower()] - if itemInfo then - items[item.slot] = { - name = itemInfo["name"], - amount = tonumber(item.amount), - info = item.info or "", - label = itemInfo["label"], - description = itemInfo["description"] or "", - weight = itemInfo["weight"], - type = itemInfo["type"], - unique = itemInfo["unique"], - useable = itemInfo["useable"], - image = itemInfo["image"], - slot = item.slot, - } - end - end + if not result then return items end + + local gloveboxItems = json.decode(result) + if not gloveboxItems then return items end + + for _, item in pairs(gloveboxItems) do + local itemInfo = QBCore.Shared.Items[item.name:lower()] + if itemInfo then + items[item.slot] = { + name = itemInfo["name"], + amount = tonumber(item.amount), + info = item.info or "", + label = itemInfo["label"], + description = itemInfo["description"] or "", + weight = itemInfo["weight"], + type = itemInfo["type"], + unique = itemInfo["unique"], + useable = itemInfo["useable"], + image = itemInfo["image"], + slot = item.slot, + } end end return items end local function SaveOwnedGloveboxItems(plate, items) - if Gloveboxes[plate].label ~= "Glovebox-None" then - if items ~= nil then - for slot, item in pairs(items) do - item.description = nil - end - MySQL.Async.insert('INSERT INTO gloveboxitems (plate, items) VALUES (:plate, :items) ON DUPLICATE KEY UPDATE items = :items', { - ['plate'] = plate, - ['items'] = json.encode(items) - }) - Gloveboxes[plate].isOpen = false - end + if Gloveboxes[plate].label == "Glovebox-None" or not items then return end + + for _, item in pairs(items) do + item.description = nil end + + MySQL.insert('INSERT INTO gloveboxitems (plate, items) VALUES (:plate, :items) ON DUPLICATE KEY UPDATE items = :items', { + ['plate'] = plate, + ['items'] = json.encode(items) + }) + + Gloveboxes[plate].isOpen = false end local function AddToGlovebox(plate, slot, otherslot, itemName, amount, info, created) - local amount = tonumber(amount) + amount = tonumber(amount) or 1 local ItemData = QBCore.Shared.Items[itemName] if not ItemData.unique then - if Gloveboxes[plate].items[slot] ~= nil and Gloveboxes[plate].items[slot].name == itemName then + if Gloveboxes[plate].items[slot] and Gloveboxes[plate].items[slot].name == itemName then Gloveboxes[plate].items[slot].amount = Gloveboxes[plate].items[slot].amount + amount else local itemInfo = QBCore.Shared.Items[itemName:lower()] @@ -379,7 +752,7 @@ local function AddToGlovebox(plate, slot, otherslot, itemName, amount, info, cre } end else - if Gloveboxes[plate].items[slot] ~= nil and Gloveboxes[plate].items[slot].name == itemName then + if Gloveboxes[plate].items[slot] and Gloveboxes[plate].items[slot].name == itemName then local itemInfo = QBCore.Shared.Items[itemName:lower()] Gloveboxes[plate].items[otherslot] = { name = itemInfo["name"], @@ -414,17 +787,15 @@ local function AddToGlovebox(plate, slot, otherslot, itemName, amount, info, cre end local function RemoveFromGlovebox(plate, slot, itemName, amount) - if Gloveboxes[plate].items[slot] ~= nil and Gloveboxes[plate].items[slot].name == itemName then + amount = tonumber(amount) or 1 + if Gloveboxes[plate].items[slot] and Gloveboxes[plate].items[slot].name == itemName then if Gloveboxes[plate].items[slot].amount > amount then Gloveboxes[plate].items[slot].amount = Gloveboxes[plate].items[slot].amount - amount else Gloveboxes[plate].items[slot] = nil - if next(Gloveboxes[plate].items) == nil then - Gloveboxes[plate].items = {} - end end else - Gloveboxes[plate].items[slot]= nil + Gloveboxes[plate].items[slot] = nil if Gloveboxes[plate].items == nil then Gloveboxes[plate].items[slot] = nil end @@ -433,8 +804,8 @@ end -- Drop items local function AddToDrop(dropId, slot, itemName, amount, info) - local amount = tonumber(amount) - if Drops[dropId].items[slot] ~= nil and Drops[dropId].items[slot].name == itemName then + amount = tonumber(amount) or 1 + if Drops[dropId].items[slot] and Drops[dropId].items[slot].name == itemName then Drops[dropId].items[slot].amount = Drops[dropId].items[slot].amount + amount else local itemInfo = QBCore.Shared.Items[itemName:lower()] @@ -456,14 +827,12 @@ local function AddToDrop(dropId, slot, itemName, amount, info) end local function RemoveFromDrop(dropId, slot, itemName, amount) - if Drops[dropId].items[slot] ~= nil and Drops[dropId].items[slot].name == itemName then + amount = tonumber(amount) or 1 + if Drops[dropId].items[slot] and Drops[dropId].items[slot].name == itemName then if Drops[dropId].items[slot].amount > amount then Drops[dropId].items[slot].amount = Drops[dropId].items[slot].amount - amount else Drops[dropId].items[slot] = nil - if next(Drops[dropId].items) == nil then - Drops[dropId].items = {} - end end else Drops[dropId].items[slot] = nil @@ -474,10 +843,10 @@ local function RemoveFromDrop(dropId, slot, itemName, amount) end local function CreateDropId() - if Drops ~= nil then + if Drops then local id = math.random(10000, 99999) local dropid = id - while Drops[dropid] ~= nil do + while Drops[dropid] do id = math.random(10000, 99999) dropid = id end @@ -490,10 +859,14 @@ local function CreateDropId() end local function CreateNewDrop(source, fromSlot, toSlot, itemAmount) + itemAmount = tonumber(itemAmount) or 1 local Player = QBCore.Functions.GetPlayer(source) - local itemData = Player.Functions.GetItemBySlot(fromSlot) + local itemData = GetItemBySlot(source, fromSlot) + + if not itemData then return end + local coords = GetEntityCoords(GetPlayerPed(source)) - if Player.Functions.RemoveItem(itemData.name, itemAmount, itemData.slot) then + if RemoveItem(source, itemData.name, itemAmount, itemData.slot) then TriggerClientEvent("inventory:client:CheckWeapon", source, itemData.name) local itemInfo = QBCore.Shared.Items[itemData.name:lower()] local dropId = CreateDropId() @@ -521,13 +894,81 @@ local function CreateNewDrop(source, fromSlot, toSlot, itemAmount) TriggerClientEvent('Radio.Set', source, false) end else - TriggerClientEvent("QBCore:Notify", source, "You don't have this item!", "error") - return + QBCore.Functions.Notify(source, "You don't have this item!", "error") end end -- Events +AddEventHandler('QBCore:Server:PlayerLoaded', function(Player) + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "AddItem", function(item, amount, slot, info) + return AddItem(Player.PlayerData.source, item, amount, slot, info) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "RemoveItem", function(item, amount, slot) + return RemoveItem(Player.PlayerData.source, item, amount, slot) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "GetItemBySlot", function(slot) + return GetItemBySlot(Player.PlayerData.source, slot) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "GetItemByName", function(item) + return GetItemByName(Player.PlayerData.source, item) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "GetItemsByName", function(item) + return GetItemsByName(Player.PlayerData.source, item) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "ClearInventory", function(filterItems) + ClearInventory(Player.PlayerData.source, filterItems) + end) + + QBCore.Functions.AddPlayerMethod(Player.PlayerData.source, "SetInventory", function(items) + SetInventory(Player.PlayerData.source, items) + end) +end) + +AddEventHandler('onResourceStart', function(resourceName) + if resourceName ~= GetCurrentResourceName() then return end + local Players = QBCore.Functions.GetQBPlayers() + for k in pairs(Players) do + QBCore.Functions.AddPlayerMethod(k, "AddItem", function(item, amount, slot, info) + return AddItem(k, item, amount, slot, info) + end) + + QBCore.Functions.AddPlayerMethod(k, "RemoveItem", function(item, amount, slot) + return RemoveItem(k, item, amount, slot) + end) + + QBCore.Functions.AddPlayerMethod(k, "GetItemBySlot", function(slot) + return GetItemBySlot(k, slot) + end) + + QBCore.Functions.AddPlayerMethod(k, "GetItemByName", function(item) + return GetItemByName(k, item) + end) + + QBCore.Functions.AddPlayerMethod(k, "GetItemsByName", function(item) + return GetItemsByName(k, item) + end) + + QBCore.Functions.AddPlayerMethod(k, "ClearInventory", function(filterItems) + ClearInventory(k, filterItems) + end) + + QBCore.Functions.AddPlayerMethod(k, "SetInventory", function(items) + SetInventory(k, items) + end) + end +end) + +RegisterNetEvent('QBCore:Server:UpdateObject', function() + if source ~= '' then return end -- Safety check if the event was not called from the server. + QBCore = exports['qb-core']:GetCoreObject() +end) + RegisterNetEvent('inventory:server:addTrunkItems', function(plate, items) Trunks[plate] = {} Trunks[plate].items = items @@ -535,7 +976,6 @@ end) RegisterNetEvent('inventory:server:combineItem', function(item, fromItem, toItem) local src = source - local ply = QBCore.Functions.GetPlayer(src) -- Check that inputs are not nil -- Most commonly when abusing this exploit, this values are left as @@ -543,8 +983,8 @@ RegisterNetEvent('inventory:server:combineItem', function(item, fromItem, toItem if toItem == nil then return end -- Check that they have the items - local fromItem = ply.Functions.GetItemByName(fromItem) - local toItem = ply.Functions.GetItemByName(toItem) + fromItem = GetItemByName(src, fromItem) + toItem = GetItemByName(src, toItem) if fromItem == nil then return end if toItem == nil then return end @@ -556,50 +996,22 @@ RegisterNetEvent('inventory:server:combineItem', function(item, fromItem, toItem if not recipeContains(recipe, fromItem) then return end TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[item], 'add') - ply.Functions.AddItem(item, 1) - ply.Functions.RemoveItem(fromItem.name, 1) - ply.Functions.RemoveItem(toItem.name, 1) -end) - -RegisterNetEvent('inventory:server:CraftItems', function(itemName, itemCosts, amount, toSlot, points) - local src = source - local Player = QBCore.Functions.GetPlayer(src) - local amount = tonumber(amount) - if itemName ~= nil and itemCosts ~= nil then - for k, v in pairs(itemCosts) do - Player.Functions.RemoveItem(k, (v*amount)) - end - Player.Functions.AddItem(itemName, amount, toSlot) - Player.Functions.SetMetaData("craftingrep", Player.PlayerData.metadata["craftingrep"]+(points*amount)) - TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, false) - end -end) - -RegisterNetEvent('inventory:server:CraftAttachment', function(itemName, itemCosts, amount, toSlot, points) - local src = source - local Player = QBCore.Functions.GetPlayer(src) - local amount = tonumber(amount) - if itemName ~= nil and itemCosts ~= nil then - for k, v in pairs(itemCosts) do - Player.Functions.RemoveItem(k, (v*amount)) - end - Player.Functions.AddItem(itemName, amount, toSlot) - Player.Functions.SetMetaData("attachmentcraftingrep", Player.PlayerData.metadata["attachmentcraftingrep"]+(points*amount)) - TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, false) - end + AddItem(src, item, 1) + RemoveItem(src, fromItem.name, 1) + RemoveItem(src, toItem.name, 1) end) RegisterNetEvent('inventory:server:SetIsOpenState', function(IsOpen, type, id) - if not IsOpen then - if type == "stash" then - Stashes[id].isOpen = false - elseif type == "trunk" then - Trunks[id].isOpen = false - elseif type == "glovebox" then - Gloveboxes[id].isOpen = false - elseif type == "drop" then - Drops[id].isOpen = false - end + if IsOpen then return end + + if type == "stash" then + Stashes[id].isOpen = false + elseif type == "trunk" then + Trunks[id].isOpen = false + elseif type == "glovebox" then + Gloveboxes[id].isOpen = false + elseif type == "drop" then + Drops[id].isOpen = false end end) @@ -751,29 +1163,23 @@ RegisterNetEvent('inventory:server:OpenInventory', function(name, id, other) secondInv.maxweight = 900000 secondInv.inventory = other.items secondInv.slots = other.slots - elseif name == "crafting" then - secondInv.name = "crafting" + elseif name == "dryhook" then + secondInv.name = "dryhook-"..id secondInv.label = other.label - secondInv.maxweight = 900000 - secondInv.inventory = other.items - secondInv.slots = #other.items - elseif name == "attachment_crafting" then - secondInv.name = "attachment_crafting" - secondInv.label = other.label - secondInv.maxweight = 900000 + secondInv.maxweight = 10000 secondInv.inventory = other.items - secondInv.slots = #other.items + secondInv.slots = other.slots elseif name == "otherplayer" then local OtherPlayer = QBCore.Functions.GetPlayer(tonumber(id)) if OtherPlayer then secondInv.name = "otherplayer-"..id secondInv.label = "Player-"..id - secondInv.maxweight = QBCore.Config.Player.MaxWeight + secondInv.maxweight = Config.MaxInventoryWeight secondInv.inventory = OtherPlayer.PlayerData.items if Player.PlayerData.job.name == "police" and Player.PlayerData.job.onduty then - secondInv.slots = QBCore.Config.Player.MaxInvSlots + secondInv.slots = Config.MaxInventorySlots else - secondInv.slots = QBCore.Config.Player.MaxInvSlots - 1 + secondInv.slots = Config.MaxInventorySlots - 1 end Wait(250) end @@ -791,7 +1197,7 @@ RegisterNetEvent('inventory:server:OpenInventory', function(name, id, other) if Drops[id] and not Drops[id].isOpen then secondInv.name = id secondInv.label = "Dropped-"..tostring(id) - secondInv.maxweight = 100000 + secondInv.maxweight = 10000000 secondInv.inventory = Drops[id].items secondInv.slots = 30 Drops[id].isOpen = src @@ -799,7 +1205,7 @@ RegisterNetEvent('inventory:server:OpenInventory', function(name, id, other) else secondInv.name = "none-inv" secondInv.label = "Dropped-None" - secondInv.maxweight = 100000 + secondInv.maxweight = 10000000 secondInv.inventory = {} secondInv.slots = 0 end @@ -809,7 +1215,7 @@ RegisterNetEvent('inventory:server:OpenInventory', function(name, id, other) TriggerClientEvent("inventory:client:OpenInventory", src, {}, Player.PlayerData.items) end else - TriggerClientEvent('QBCore:Notify', src, 'Not Accessible', 'error') + QBCore.Functions.Notify(src, 'Not Accessible', 'error') end end) @@ -827,6 +1233,13 @@ RegisterNetEvent('inventory:server:SaveInventory', function(type, id) Gloveboxes[id].isOpen = false end elseif type == "stash" then + local indexstart, indexend = string.find(id, 'Backpack_') + if indexstart and indexend then + TriggerEvent('keep-backpack:server:saveBackpack', source, id, Stashes[id].items, function(close) + Stashes[id].isOpen = close + end) + return + end SaveStashItems(id, Stashes[id].items) elseif type == "drop" then if Drops[id] then @@ -839,30 +1252,27 @@ RegisterNetEvent('inventory:server:SaveInventory', function(type, id) end end) --- RegisterNetEvent('inventory:server:UseItemSlot', function(slot) --- local src = source --- local Player = QBCore.Functions.GetPlayer(src) --- local itemData = Player.Functions.GetItemBySlot(slot) --- if itemData then --- local itemInfo = QBCore.Shared.Items[itemData.name] --- if itemData.type == "weapon" then --- if itemData.info.quality then --- if itemData.info.quality > 0 then --- TriggerClientEvent("inventory:client:UseWeapon", src, itemData, true) --- else --- TriggerClientEvent("inventory:client:UseWeapon", src, itemData, false) --- end --- else --- TriggerClientEvent("inventory:client:UseWeapon", src, itemData, true) --- end --- TriggerClientEvent('inventory:client:ItemBox', src, itemInfo, "use") --- elseif itemData.useable then --- TriggerClientEvent("QBCore:Client:UseItem", src, itemData) --- TriggerClientEvent('inventory:client:ItemBox', src, itemInfo, "use") --- end --- end --- end) +--[[ + +* Not Used for some Reason | Haven't found out Why... + +RegisterNetEvent('inventory:server:UseItemSlot', function(slot) + local src = source + local itemData = GetItemBySlot(src, slot) + + if not itemData then return end + + local itemInfo = QBCore.Shared.Items[itemData.name] + if itemData.type == "weapon" then + TriggerClientEvent("inventory:client:UseWeapon", src, itemData, itemData.info.quality and itemData.info.quality > 0) + TriggerClientEvent('inventory:client:ItemBox', src, itemInfo, "use") + elseif itemData.useable then + UseItem(itemData.name, src, itemData) + TriggerClientEvent('inventory:client:ItemBox', src, itemInfo, "use") + end +end) +]] RegisterNetEvent('inventory:server:UseItemSlot', function(slot) local src = source @@ -922,44 +1332,44 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to fromSlot = tonumber(fromSlot) toSlot = tonumber(toSlot) - if (fromInventory == "player" or fromInventory == "hotbar") and (QBCore.Shared.SplitStr(toInventory, "-")[1] == "itemshop" or toInventory == "crafting") then + if (fromInventory == "player" or fromInventory == "hotbar") and (QBCore.Shared.SplitStr(toInventory, "-")[1] == "itemshop") then return end if fromInventory == "player" or fromInventory == "hotbar" then - local fromItemData = Player.Functions.GetItemBySlot(fromSlot) - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + local fromItemData = GetItemBySlot(src, fromSlot) + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + local toItemData = GetItemBySlot(src, toSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) - Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) + RemoveItem(src, toItemData.name, toAmount, toSlot) + AddItem(src, toItemData.name, toAmount, fromSlot, toItemData.info) end else --Player.PlayerData.items[fromSlot] = nil end - Player.Functions.AddItem(fromItemData.name, fromAmount, toSlot, fromItemData.info, fromItemData.created) + AddItem(src, fromItemData.name, fromAmount, toSlot, fromItemData.info) elseif QBCore.Shared.SplitStr(toInventory, "-")[1] == "otherplayer" then local playerId = tonumber(QBCore.Shared.SplitStr(toInventory, "-")[2]) local OtherPlayer = QBCore.Functions.GetPlayer(playerId) local toItemData = OtherPlayer.PlayerData.items[toSlot] - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then --Player.PlayerData.items[fromSlot] = toItemData local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - OtherPlayer.Functions.RemoveItem(itemInfo["name"], toAmount, fromSlot) - Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) + RemoveItem(playerId, itemInfo["name"], toAmount, fromSlot) + AddItem(src, toItemData.name, toAmount, fromSlot, toItemData.info) TriggerEvent("qb-log:server:CreateLog", "robbing", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | *"..src.."*) swapped item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** with name: **" .. fromItemData.name .. "**, amount: **" .. fromAmount.. "** with player: **".. GetPlayerName(OtherPlayer.PlayerData.source) .. "** (citizenid: *"..OtherPlayer.PlayerData.citizenid.."* | id: *"..OtherPlayer.PlayerData.source.."*)") end else @@ -967,20 +1377,20 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to TriggerEvent("qb-log:server:CreateLog", "robbing", "Dropped Item", "red", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | *"..src.."*) dropped new item; name: **"..itemInfo["name"].."**, amount: **" .. fromAmount .. "** to player: **".. GetPlayerName(OtherPlayer.PlayerData.source) .. "** (citizenid: *"..OtherPlayer.PlayerData.citizenid.."* | id: *"..OtherPlayer.PlayerData.source.."*)") end local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] - OtherPlayer.Functions.AddItem(itemInfo["name"], fromAmount, toSlot, fromItemData.info, fromItemData.created) + AddItem(playerId, itemInfo["name"], fromAmount, toSlot, fromItemData.info) elseif QBCore.Shared.SplitStr(toInventory, "-")[1] == "trunk" then local plate = QBCore.Shared.SplitStr(toInventory, "-")[2] local toItemData = Trunks[plate].items[toSlot] - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then --Player.PlayerData.items[fromSlot] = toItemData local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then RemoveFromTrunk(plate, fromSlot, itemInfo["name"], toAmount) - Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) + AddItem(src, toItemData.name, toAmount, fromSlot, toItemData.info) TriggerEvent("qb-log:server:CreateLog", "trunk", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** with name: **" .. fromItemData.name .. "**, amount: **" .. fromAmount .. "** - plate: *" .. plate .. "*") end else @@ -992,16 +1402,16 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to elseif QBCore.Shared.SplitStr(toInventory, "-")[1] == "glovebox" then local plate = QBCore.Shared.SplitStr(toInventory, "-")[2] local toItemData = Gloveboxes[plate].items[toSlot] - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then --Player.PlayerData.items[fromSlot] = toItemData local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then RemoveFromGlovebox(plate, fromSlot, itemInfo["name"], toAmount) - Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) + AddItem(src, toItemData.name, toAmount, fromSlot, toItemData.info) TriggerEvent("qb-log:server:CreateLog", "glovebox", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** with name: **" .. fromItemData.name .. "**, amount: **" .. fromAmount .. "** - plate: *" .. plate .. "*") end else @@ -1013,13 +1423,13 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to elseif QBCore.Shared.SplitStr(toInventory, "-")[1] == "stash" then local stashId = QBCore.Shared.SplitStr(toInventory, "-")[2] local toItemData = Stashes[stashId].items[toSlot] - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then --Player.PlayerData.items[fromSlot] = toItemData local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then --RemoveFromStash(stashId, fromSlot, itemInfo["name"], toAmount) RemoveFromStash(stashId, toSlot, itemInfo["name"], toAmount) @@ -1038,11 +1448,11 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to local toItemData = exports['qb-traphouse']:GetInventoryData(traphouseId, toSlot) local IsItemValid = exports['qb-traphouse']:CanItemBeSaled(fromItemData.name:lower()) if IsItemValid then - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then exports['qb-traphouse']:RemoveHouseItem(traphouseId, fromSlot, itemInfo["name"], toAmount) Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) @@ -1057,6 +1467,39 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to else TriggerClientEvent('QBCore:Notify', src, "You can\'t sell this item..", 'error') end + elseif QBCore.Shared.SplitStr(toInventory, "-")[1] == "dryhook" then + -- Drying Buds + local dryBudId = QBCore.Shared.SplitStr(toInventory, "-")[2] + local toItemData = exports['qb-customdrugs']:GetInventoryData(dryBudId, toSlot) + local IsItemValid = exports['qb-customdrugs']:CanItemBeDried(fromItemData.name:lower()) + local isItemDrying = exports['qb-customdrugs']:isItemAlreadyDrying(dryBudId) + print(tostring(isitemDrying)) + if not isItemDrying then + if IsItemValid then + TriggerClientEvent('okokNotify:Alert', source, "Plant Drying", "You put up your plant to dry", 5000, 'success') + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) + TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) + if toItemData then + local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] + toAmount = tonumber(toAmount) or toItemData.amount + if toItemData.name ~= fromItemData.name then + exports['qb-customdrugs']:RemoveDryBud(dryBudId, fromSlot, itemInfo["name"], toAmount) + AddItem(src, toItemData.name, toAmount, fromSlot, toItemData.info) + TriggerEvent("qb-log:server:CreateLog", "DryingBuds", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** with name: **" .. fromItemData.name .. "**, amount: **" .. fromAmount .. "** - Hook: *" .. dryBudId .. "*") + end + else + local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] + TriggerEvent("qb-log:server:CreateLog", "DryingBuds", "Dropped Item", "red", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) dropped new item; name: **"..itemInfo["name"].."**, amount: **" .. fromAmount .. "** - traphouse: *" .. dryBudId .. "*") + end + local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] + exports['qb-customdrugs']:AddDryBud(dryBudId, toSlot, itemInfo["name"], fromAmount, fromItemData.info, src) + else + --TriggerClientEvent('QBCore:Notify', src, "You can\'t dry this item..", 'error') + TriggerClientEvent('okokNotify:Alert', source, "What?", "You can't dry this here...", 5000, 'error') + end + else + TriggerClientEvent('okokNotify:Alert', source, "Space Occupied", "Something is on the hook already!", 5000, 'error') + end else -- drop toInventory = tonumber(toInventory) @@ -1064,11 +1507,11 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to CreateNewDrop(src, fromSlot, toSlot, fromAmount) else local toItemData = Drops[toInventory].items[toSlot] - Player.Functions.RemoveItem(fromItemData.name, fromAmount, fromSlot) + RemoveItem(src, fromItemData.name, fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", src, fromItemData.name) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then Player.Functions.AddItem(toItemData.name, toAmount, fromSlot, toItemData.info, toItemData.created) RemoveFromDrop(toInventory, fromSlot, itemInfo["name"], toAmount) @@ -1086,24 +1529,24 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to end end else - TriggerClientEvent("QBCore:Notify", src, "You don\'t have this item!", "error") + QBCore.Functions.Notify(src, "You don\'t have this item!", "error") end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "otherplayer" then local playerId = tonumber(QBCore.Shared.SplitStr(fromInventory, "-")[2]) local OtherPlayer = QBCore.Functions.GetPlayer(playerId) local fromItemData = OtherPlayer.PlayerData.items[fromSlot] - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) - OtherPlayer.Functions.RemoveItem(itemInfo["name"], fromAmount, fromSlot) + local toItemData = GetItemBySlot(src, toSlot) + RemoveItem(playerId, itemInfo["name"], fromAmount, fromSlot) TriggerClientEvent("inventory:client:CheckWeapon", OtherPlayer.PlayerData.source, fromItemData.name) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) OtherPlayer.Functions.AddItem(itemInfo["name"], toAmount, fromSlot, toItemData.info, toItemData.created) TriggerEvent("qb-log:server:CreateLog", "robbing", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** from player: **".. GetPlayerName(OtherPlayer.PlayerData.source) .. "** (citizenid: *"..OtherPlayer.PlayerData.citizenid.."* | *"..OtherPlayer.PlayerData.source.."*)") end @@ -1113,15 +1556,15 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to Player.Functions.AddItem(fromItemData.name, fromAmount, toSlot, fromItemData.info, fromItemData.created) else local toItemData = OtherPlayer.PlayerData.items[toSlot] - OtherPlayer.Functions.RemoveItem(itemInfo["name"], fromAmount, fromSlot) + RemoveItem(playerId, itemInfo["name"], fromAmount, fromSlot) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - OtherPlayer.Functions.RemoveItem(itemInfo["name"], toAmount, toSlot) + RemoveItem(playerId, itemInfo["name"], toAmount, toSlot) OtherPlayer.Functions.AddItem(itemInfo["name"], toAmount, fromSlot, toItemData.info, toItemData.created) end else @@ -1131,22 +1574,22 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to OtherPlayer.Functions.AddItem(itemInfo["name"], fromAmount, toSlot, fromItemData.info, fromItemData.created) end else - TriggerClientEvent("QBCore:Notify", src, "Item doesn\'t exist??", "error") + QBCore.Functions.Notify(src, "Item doesn\'t exist??", "error") end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "trunk" then local plate = QBCore.Shared.SplitStr(fromInventory, "-")[2] local fromItemData = Trunks[plate].items[fromSlot] - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) + local toItemData = GetItemBySlot(src, toSlot) RemoveFromTrunk(plate, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) AddToTrunk(plate, fromSlot, toSlot, itemInfo["name"], toAmount, toItemData.info, toItemData.created) TriggerEvent("qb-log:server:CreateLog", "trunk", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** plate: *" .. plate .. "*") else @@ -1160,10 +1603,10 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to local toItemData = Trunks[plate].items[toSlot] RemoveFromTrunk(plate, fromSlot, itemInfo["name"], fromAmount) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] RemoveFromTrunk(plate, toSlot, itemInfo["name"], toAmount) @@ -1176,22 +1619,22 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to AddToTrunk(plate, toSlot, fromSlot, itemInfo["name"], fromAmount, fromItemData.info, fromItemData.created) end else - TriggerClientEvent("QBCore:Notify", src, "Item doesn\'t exist??", "error") + QBCore.Functions.Notify(src, "Item doesn\'t exist??", "error") end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "glovebox" then local plate = QBCore.Shared.SplitStr(fromInventory, "-")[2] local fromItemData = Gloveboxes[plate].items[fromSlot] - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) + local toItemData = GetItemBySlot(src, toSlot) RemoveFromGlovebox(plate, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) AddToGlovebox(plate, fromSlot, toSlot, itemInfo["name"], toAmount, toItemData.info, toItemData.created) TriggerEvent("qb-log:server:CreateLog", "glovebox", "Swapped", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src..")* swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; name: **"..itemInfo["name"].."**, amount: **" .. toAmount .. "** plate: *" .. plate .. "*") else @@ -1205,10 +1648,10 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to local toItemData = Gloveboxes[plate].items[toSlot] RemoveFromGlovebox(plate, fromSlot, itemInfo["name"], fromAmount) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] RemoveFromGlovebox(plate, toSlot, itemInfo["name"], toAmount) @@ -1222,22 +1665,22 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to AddToGlovebox(plate, toSlot, fromSlot, itemInfo["name"], fromAmount, fromItemData.info, fromItemData.created) end else - TriggerClientEvent("QBCore:Notify", src, "Item doesn\'t exist??", "error") + QBCore.Functions.Notify(src, "Item doesn\'t exist??", "error") end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "stash" then local stashId = QBCore.Shared.SplitStr(fromInventory, "-")[2] local fromItemData = Stashes[stashId].items[fromSlot] - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) + local toItemData = GetItemBySlot(src, toSlot) RemoveFromStash(stashId, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) AddToStash(stashId, fromSlot, toSlot, itemInfo["name"], toAmount, toItemData.info, toItemData.created) TriggerEvent("qb-log:server:CreateLog", "stash", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; name: **"..fromItemData.name.."**, amount: **" .. fromAmount .. "** stash: *" .. stashId .. "*") else @@ -1252,10 +1695,10 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to local toItemData = Stashes[stashId].items[toSlot] RemoveFromStash(stashId, fromSlot, itemInfo["name"], fromAmount) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] RemoveFromStash(stashId, toSlot, itemInfo["name"], toAmount) @@ -1268,22 +1711,22 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to AddToStash(stashId, toSlot, fromSlot, itemInfo["name"], fromAmount, fromItemData.info, fromItemData.created) end else - TriggerClientEvent("QBCore:Notify", src, "Item doesn\'t exist??", "error") + QBCore.Functions.Notify(src, "Item doesn\'t exist??", "error") end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "traphouse" then local traphouseId = QBCore.Shared.SplitStr(fromInventory, "-")[2] local fromItemData = exports['qb-traphouse']:GetInventoryData(traphouseId, fromSlot) - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) + local toItemData = GetItemBySlot(src, toSlot) exports['qb-traphouse']:RemoveHouseItem(traphouseId, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) exports['qb-traphouse']:AddHouseItem(traphouseId, fromSlot, itemInfo["name"], toAmount, toItemData.info, src) TriggerEvent("qb-log:server:CreateLog", "stash", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; name: **"..fromItemData.name.."**, amount: **" .. fromAmount .. "** stash: *" .. traphouseId .. "*") else @@ -1296,9 +1739,9 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to else local toItemData = exports['qb-traphouse']:GetInventoryData(traphouseId, toSlot) exports['qb-traphouse']:RemoveHouseItem(traphouseId, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] exports['qb-traphouse']:RemoveHouseItem(traphouseId, toSlot, itemInfo["name"], toAmount) @@ -1311,6 +1754,47 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to else TriggerClientEvent("QBCore:Notify", src, "Item doesn't exist??", "error") end + elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "dryhook" then + local dryBudId = QBCore.Shared.SplitStr(fromInventory, "-")[2] + local fromItemData = exports['qb-customdrugs']:GetInventoryData(dryBudId, fromSlot) + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then + local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] + if toInventory == "player" or toInventory == "hotbar" then + local toItemData = GetItemBySlot(src, toSlot) + exports['qb-customdrugs']:RemoveDryBud(dryBudId, fromSlot, itemInfo["name"], fromAmount) + if toItemData then + local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] + toAmount = tonumber(toAmount) or toItemData.amount + if toItemData.name ~= fromItemData.name then + RemoveItem(src, toItemData.name, toAmount, toSlot) + exports['qb-customdrugs']:AddDryBud(dryBudId, fromSlot, itemInfo["name"], toAmount, toItemData.info, src) + TriggerEvent("qb-log:server:CreateLog", "stash", "Swapped Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) swapped item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** with item; name: **"..fromItemData.name.."**, amount: **" .. fromAmount .. "** Hook: *" .. dryBudId .. "*") + else + TriggerEvent("qb-log:server:CreateLog", "stash", "Stacked Item", "orange", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) stacked item; name: **"..toItemData.name.."**, amount: **" .. toAmount .. "** from hook: *" .. dryBudId .. "*") + end + else + TriggerEvent("qb-log:server:CreateLog", "stash", "Received Item", "green", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) received item; name: **"..fromItemData.name.."**, amount: **" .. fromAmount.. "** hook: *" .. dryBudId .. "*") + end + AddItem(src, fromItemData.name, fromAmount, toSlot, fromItemData.info) + else + local toItemData = exports['qb-customdrugs']:GetInventoryData(dryBudId, toSlot) + exports['qb-customdrugs']:RemoveDryBud(dryBudId, fromSlot, itemInfo["name"], fromAmount) + if toItemData then + local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] + toAmount = tonumber(toAmount) or toItemData.amount + if toItemData.name ~= fromItemData.name then + local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] + exports['qb-customdrugs']:RemoveDryBud(dryBudId, toSlot, itemInfo["name"], toAmount) + exports['qb-customdrugs']:AddDryBud(dryBudId, fromSlot, itemInfo["name"], toAmount, toItemData.info, src) + end + end + local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] + exports['qb-customdrugs']:AddDryBud(dryBudId, toSlot, itemInfo["name"], fromAmount, fromItemData.info, src) + end + else + QBCore.Functions.Notify(src, "Item doesn't exist??", "error") + end elseif QBCore.Shared.SplitStr(fromInventory, "-")[1] == "itemshop" then local shopType = QBCore.Shared.SplitStr(fromInventory, "-")[2] local itemData = ShopItems[shopType].items[fromSlot] @@ -1318,93 +1802,57 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to local bankBalance = Player.PlayerData.money["bank"] local price = tonumber((itemData.price*fromAmount)) - if QBCore.Shared.SplitStr(shopType, "_")[1] == "Dealer" then - if QBCore.Shared.SplitStr(itemData.name, "_")[1] == "weapon" then - price = tonumber(itemData.price) - if Player.Functions.RemoveMoney("cash", price, "dealer-item-bought") then - itemData.info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) - Player.Functions.AddItem(itemData.name, 1, toSlot, itemData.info) - TriggerClientEvent('qb-drugs:client:updateDealerItems', src, itemData, 1) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") - TriggerEvent("qb-log:server:CreateLog", "dealers", "Dealer item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) - else - TriggerClientEvent('QBCore:Notify', src, "You don\'t have enough cash..", "error") - end - else - if Player.Functions.RemoveMoney("cash", price, "dealer-item-bought") then - Player.Functions.AddItem(itemData.name, fromAmount, toSlot, itemData.info) - TriggerClientEvent('qb-drugs:client:updateDealerItems', src, itemData, fromAmount) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") - TriggerEvent("qb-log:server:CreateLog", "dealers", "Dealer item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) - else - TriggerClientEvent('QBCore:Notify', src, "You don't have enough cash..", "error") - end - end - elseif QBCore.Shared.SplitStr(shopType, "_")[1] == "Itemshop" then + if QBCore.Shared.SplitStr(shopType, "_")[1] == "Itemshop" then if Player.Functions.RemoveMoney("cash", price, "itemshop-bought-item") then if QBCore.Shared.SplitStr(itemData.name, "_")[1] == "weapon" then itemData.info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) + itemData.info.quality = 100 end - Player.Functions.AddItem(itemData.name, fromAmount, toSlot, itemData.info) + AddItem(src, itemData.name, fromAmount, toSlot, itemData.info) TriggerClientEvent('qb-shops:client:UpdateShop', src, QBCore.Shared.SplitStr(shopType, "_")[2], itemData, fromAmount) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") + QBCore.Functions.Notify(src, itemInfo["label"] .. " bought!", "success") TriggerEvent("qb-log:server:CreateLog", "shops", "Shop item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) elseif bankBalance >= price then Player.Functions.RemoveMoney("bank", price, "itemshop-bought-item") if QBCore.Shared.SplitStr(itemData.name, "_")[1] == "weapon" then itemData.info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) + itemData.info.quality = 100 end - Player.Functions.AddItem(itemData.name, fromAmount, toSlot, itemData.info) + AddItem(src, itemData.name, fromAmount, toSlot, itemData.info) TriggerClientEvent('qb-shops:client:UpdateShop', src, QBCore.Shared.SplitStr(shopType, "_")[2], itemData, fromAmount) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") + QBCore.Functions.Notify(src, itemInfo["label"] .. " bought!", "success") TriggerEvent("qb-log:server:CreateLog", "shops", "Shop item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) else - TriggerClientEvent('QBCore:Notify', src, "You don't have enough cash..", "error") + QBCore.Functions.Notify(src, "You don't have enough cash..", "error") end else if Player.Functions.RemoveMoney("cash", price, "unkown-itemshop-bought-item") then - Player.Functions.AddItem(itemData.name, fromAmount, toSlot, itemData.info) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") + AddItem(src, itemData.name, fromAmount, toSlot, itemData.info) + QBCore.Functions.Notify(src, itemInfo["label"] .. " bought!", "success") TriggerEvent("qb-log:server:CreateLog", "shops", "Shop item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) elseif bankBalance >= price then Player.Functions.RemoveMoney("bank", price, "unkown-itemshop-bought-item") - Player.Functions.AddItem(itemData.name, fromAmount, toSlot, itemData.info) - TriggerClientEvent('QBCore:Notify', src, itemInfo["label"] .. " bought!", "success") + AddItem(src, itemData.name, fromAmount, toSlot, itemData.info) + QBCore.Functions.Notify(src, itemInfo["label"] .. " bought!", "success") TriggerEvent("qb-log:server:CreateLog", "shops", "Shop item bought", "green", "**"..GetPlayerName(src) .. "** bought a " .. itemInfo["label"] .. " for $"..price) else - TriggerClientEvent('QBCore:Notify', src, "You don\'t have enough cash..", "error") + QBCore.Functions.Notify(src, "You don\'t have enough cash..", "error") end end - elseif fromInventory == "crafting" then - local itemData = Config.CraftingItems[fromSlot] - if hasCraftItems(src, itemData.costs, fromAmount) then - TriggerClientEvent("inventory:client:CraftItems", src, itemData.name, itemData.costs, fromAmount, toSlot, itemData.points) - else - TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, true) - TriggerClientEvent('QBCore:Notify', src, "You don't have the right items..", "error") - end - elseif fromInventory == "attachment_crafting" then - local itemData = Config.AttachmentCrafting["items"][fromSlot] - if hasCraftItems(src, itemData.costs, fromAmount) then - TriggerClientEvent("inventory:client:CraftAttachment", src, itemData.name, itemData.costs, fromAmount, toSlot, itemData.points) - else - TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, true) - TriggerClientEvent('QBCore:Notify', src, "You don't have the right items..", "error") - end else -- drop fromInventory = tonumber(fromInventory) local fromItemData = Drops[fromInventory].items[fromSlot] - local fromAmount = tonumber(fromAmount) ~= nil and tonumber(fromAmount) or fromItemData.amount - if fromItemData ~= nil and fromItemData.amount >= fromAmount then + fromAmount = tonumber(fromAmount) or fromItemData.amount + if fromItemData and fromItemData.amount >= fromAmount then local itemInfo = QBCore.Shared.Items[fromItemData.name:lower()] if toInventory == "player" or toInventory == "hotbar" then - local toItemData = Player.Functions.GetItemBySlot(toSlot) + local toItemData = GetItemBySlot(src, toSlot) RemoveFromDrop(fromInventory, fromSlot, itemInfo["name"], fromAmount) - if toItemData ~= nil then - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + if toItemData then + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then - Player.Functions.RemoveItem(toItemData.name, toAmount, toSlot) + RemoveItem(src, toItemData.name, toAmount, toSlot) AddToDrop(fromInventory, toSlot, itemInfo["name"], toAmount, toItemData.info) if itemInfo["name"] == "radio" then TriggerClientEvent('Radio.Set', src, false) @@ -1416,16 +1864,16 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to else TriggerEvent("qb-log:server:CreateLog", "drop", "Received Item", "green", "**".. GetPlayerName(src) .. "** (citizenid: *"..Player.PlayerData.citizenid.."* | id: *"..src.."*) received item; name: **"..fromItemData.name.."**, amount: **" .. fromAmount.. "** - dropid: *" .. fromInventory .. "*") end - Player.Functions.AddItem(fromItemData.name, fromAmount, toSlot, fromItemData.info) + AddItem(src, fromItemData.name, fromAmount, toSlot, fromItemData.info) else toInventory = tonumber(toInventory) local toItemData = Drops[toInventory].items[toSlot] RemoveFromDrop(fromInventory, fromSlot, itemInfo["name"], fromAmount) --Player.PlayerData.items[toSlot] = fromItemData - if toItemData ~= nil then + if toItemData then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] --Player.PlayerData.items[fromSlot] = toItemData - local toAmount = tonumber(toAmount) ~= nil and tonumber(toAmount) or toItemData.amount + toAmount = tonumber(toAmount) or toItemData.amount if toItemData.name ~= fromItemData.name then local itemInfo = QBCore.Shared.Items[toItemData.name:lower()] RemoveFromDrop(toInventory, toSlot, itemInfo["name"], toAmount) @@ -1444,7 +1892,7 @@ RegisterNetEvent('inventory:server:SetInventoryData', function(fromInventory, to end end else - TriggerClientEvent("QBCore:Notify", src, "Item doesn't exist??", "error") + QBCore.Functions.Notify(src, "Item doesn't exist??", "error") end end end) @@ -1459,73 +1907,117 @@ end) RegisterServerEvent("inventory:server:GiveItem", function(target, name, amount, slot) local src = source local Player = QBCore.Functions.GetPlayer(src) - local OtherPlayer = QBCore.Functions.GetPlayer(tonumber(target)) + target = tonumber(target) + local OtherPlayer = QBCore.Functions.GetPlayer(target) local dist = #(GetEntityCoords(GetPlayerPed(src))-GetEntityCoords(GetPlayerPed(target))) - if Player == OtherPlayer then return TriggerClientEvent('QBCore:Notify', src, "You can't give yourself an item?") end - if dist > 2 then return TriggerClientEvent('QBCore:Notify', src, "You are too far away to give items!") end - local item = Player.Functions.GetItemBySlot(slot) - if not item then TriggerClientEvent('QBCore:Notify', src, "Item you tried giving not found!"); return end - if item.name ~= name then TriggerClientEvent('QBCore:Notify', src, "Incorrect item found try again!"); return end + if Player == OtherPlayer then return QBCore.Functions.Notify(src, "You can't give yourself an item?") end + if dist > 2 then return QBCore.Functions.Notify(src, "You are too far away to give items!") end + local item = GetItemBySlot(src, slot) + if not item then QBCore.Functions.Notify(src, "Item you tried giving not found!"); return end + if item.name ~= name then QBCore.Functions.Notify(src, "Incorrect item found try again!"); return end if amount <= item.amount then if amount == 0 then amount = item.amount end - if Player.Functions.RemoveItem(item.name, amount, item.slot) then - if OtherPlayer.Functions.AddItem(item.name, amount, false, item.info, item.created) then + if RemoveItem(src, item.name, amount, item.slot) then + if AddItem(target, item.name, amount, false, item.info) then TriggerClientEvent('inventory:client:ItemBox',target, QBCore.Shared.Items[item.name], "add") - TriggerClientEvent('QBCore:Notify', target, "You Received "..amount..' '..item.label.." From "..Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname) + QBCore.Functions.Notify(target, "You Received "..amount..' '..item.label.." From "..Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname) TriggerClientEvent("inventory:client:UpdatePlayerInventory", target, true) TriggerClientEvent('inventory:client:ItemBox',src, QBCore.Shared.Items[item.name], "remove") - TriggerClientEvent('QBCore:Notify', src, "You gave " .. OtherPlayer.PlayerData.charinfo.firstname.." "..OtherPlayer.PlayerData.charinfo.lastname.. " " .. amount .. " " .. item.label .."!") + QBCore.Functions.Notify(src, "You gave " .. OtherPlayer.PlayerData.charinfo.firstname.." "..OtherPlayer.PlayerData.charinfo.lastname.. " " .. amount .. " " .. item.label .."!") TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, true) TriggerClientEvent('qb-inventory:client:giveAnim', src) TriggerClientEvent('qb-inventory:client:giveAnim', target) else - Player.Functions.AddItem(item.name, amount, item.slot, item.info, item.created) - TriggerClientEvent('QBCore:Notify', src, "The other players inventory is full!", "error") - TriggerClientEvent('QBCore:Notify', target, "Your inventory is full!", "error") + AddItem(src, item.name, amount, item.slot, item.info) + QBCore.Functions.Notify(src, "The other players inventory is full!", "error") + QBCore.Functions.Notify(target, "Your inventory is full!", "error") TriggerClientEvent("inventory:client:UpdatePlayerInventory", src, false) TriggerClientEvent("inventory:client:UpdatePlayerInventory", target, false) end else - TriggerClientEvent('QBCore:Notify', src, "You do not have enough of the item", "error") + QBCore.Functions.Notify(src, "You do not have enough of the item", "error") end else - TriggerClientEvent('QBCore:Notify', src, "You do not have enough items to transfer") + QBCore.Functions.Notify(src, "You do not have enough items to transfer") + end +end) + +RegisterNetEvent('inventory:server:snowball', function(action) + if action == "add" then + AddItem(source, "weapon_snowball") + elseif action == "remove" then + RemoveItem(source, "weapon_snowball") end end) -- callback -QBCore.Functions.CreateCallback('qb-inventory:server:GetStashItems', function(source, cb, stashId) +QBCore.Functions.CreateCallback('qb-inventory:server:GetStashItems', function(_, cb, stashId) cb(GetStashItems(stashId)) end) +QBCore.Functions.CreateCallback('QBCore:HasItem', function(source, cb, items, amount) + print("^3QBCore:HasItem is deprecated, please use QBCore.Functions.HasItem, it can be used on both server- and client-side and uses the same arguments.^0") + local retval = false + local Player = QBCore.Functions.GetPlayer(source) + if not Player then return cb(false) end + local isTable = type(items) == 'table' + local isArray = isTable and table.type(items) == 'array' or false + local totalItems = #items + local count = 0 + local kvIndex = 2 + if isTable and not isArray then + totalItems = 0 + for _ in pairs(items) do totalItems += 1 end + kvIndex = 1 + end + if isTable then + for k, v in pairs(items) do + local itemKV = {k, v} + local item = GetItemByName(source, itemKV[kvIndex]) + if item and ((amount and item.amount >= amount) or (not amount and not isArray and item.amount >= v) or (not amount and isArray)) then + count += 1 + end + end + if count == totalItems then + retval = true + end + else -- Single item as string + local item = GetItemByName(source, items) + if item and not amount or (item and amount and item.amount >= amount) then + retval = true + end + end + cb(retval) +end) + -- command QBCore.Commands.Add("resetinv", "Reset Inventory (Admin Only)", {{name="type", help="stash/trunk/glovebox"},{name="id/plate", help="ID of stash or license plate"}}, true, function(source, args) local invType = args[1]:lower() table.remove(args, 1) local invId = table.concat(args, " ") - if invType ~= nil and invId ~= nil then + if invType and invId then if invType == "trunk" then - if Trunks[invId] ~= nil then + if Trunks[invId] then Trunks[invId].isOpen = false end elseif invType == "glovebox" then - if Gloveboxes[invId] ~= nil then + if Gloveboxes[invId] then Gloveboxes[invId].isOpen = false end elseif invType == "stash" then - if Stashes[invId] ~= nil then + if Stashes[invId] then Stashes[invId].isOpen = false end else - TriggerClientEvent('QBCore:Notify', source, "Not a valid type..", "error") + QBCore.Functions.Notify(source, "Not a valid type..", "error") end else - TriggerClientEvent('QBCore:Notify', source, "Arguments not filled out correctly..", "error") + QBCore.Functions.Notify(source, "Arguments not filled out correctly..", "error") end end, "admin") @@ -1533,12 +2025,12 @@ QBCore.Commands.Add("rob", "Rob Player", {}, false, function(source, args) TriggerClientEvent("police:client:RobPlayer", source) end) -QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help="Player ID"},{name="item", help="Name of the item (not a label)"}, {name="amount", help="Amount of items"}}, true, function(source, args) - local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) - local amount = tonumber(args[3]) +QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help="Player ID"},{name="item", help="Name of the item (not a label)"}, {name="amount", help="Amount of items"}}, false, function(source, args) + local id = tonumber(args[1]) + local Player = QBCore.Functions.GetPlayer(id) local itemData = QBCore.Shared.Items[tostring(args[2]):lower()] + local amount = tonumber(args[3]) if Player then - if amount > 0 then if itemData then -- check iteminfo local info = {} @@ -1550,36 +2042,98 @@ QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help=" info.gender = Player.PlayerData.charinfo.gender info.nationality = Player.PlayerData.charinfo.nationality elseif itemData["name"] == "driver_license" then + info.citizenid = Player.PlayerData.citizenid info.firstname = Player.PlayerData.charinfo.firstname info.lastname = Player.PlayerData.charinfo.lastname info.birthdate = Player.PlayerData.charinfo.birthdate + info.gender = Player.PlayerData.charinfo.gender + info.nationality = Player.PlayerData.charinfo.nationality info.type = "Class C Driver License" + elseif itemData["name"] == "weaponlicense" then + info.citizenid = Player.PlayerData.citizenid + info.firstname = Player.PlayerData.charinfo.firstname + info.lastname = Player.PlayerData.charinfo.lastname + info.birthdate = Player.PlayerData.charinfo.birthdate + info.gender = Player.PlayerData.charinfo.gender + info.nationality = Player.PlayerData.charinfo.nationality + info.type = "Class One Weapon License" + elseif itemData["name"] == "huntinglicense" then + info.citizenid = Player.PlayerData.citizenid + info.firstname = Player.PlayerData.charinfo.firstname + info.lastname = Player.PlayerData.charinfo.lastname + info.birthdate = Player.PlayerData.charinfo.birthdate + info.gender = Player.PlayerData.charinfo.gender + info.nationality = Player.PlayerData.charinfo.nationality + info.type = "Hunting License" + elseif itemData["name"] == "fishinglicense" then + info.citizenid = Player.PlayerData.citizenid + info.firstname = Player.PlayerData.charinfo.firstname + info.lastname = Player.PlayerData.charinfo.lastname + info.birthdate = Player.PlayerData.charinfo.birthdate + info.gender = Player.PlayerData.charinfo.gender + info.nationality = Player.PlayerData.charinfo.nationality + info.type = "Deep Sea Fishing License" + elseif itemData["name"] == "waterslicense" then + info.citizenid = Player.PlayerData.citizenid + info.firstname = Player.PlayerData.charinfo.firstname + info.lastname = Player.PlayerData.charinfo.lastname + info.birthdate = Player.PlayerData.charinfo.birthdate + info.gender = Player.PlayerData.charinfo.gender + info.nationality = Player.PlayerData.charinfo.nationality + info.type = "Waters License" elseif itemData["type"] == "weapon" then amount = 1 info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) + info.quality = 100 elseif itemData["name"] == "harness" then info.uses = 20 + elseif itemData["name"] == "laptop_blue" then + info.uses = 3 + elseif itemData["name"] == "laptop_red" then + info.uses = 3 + elseif itemData["name"] == "laptop_gold" then + info.uses = 3 + elseif itemData["name"] == "laptop_pink" then + info.uses = 3 + elseif itemData["name"] == "dabcartfull" then + info.uses = 5 + elseif itemData["name"] == "crfleecacard" then + info.uses = 3 elseif itemData["name"] == "markedbills" then info.worth = math.random(5000, 10000) elseif itemData["name"] == "labkey" then info.lab = exports["qb-methlab"]:GenerateRandomLab() + elseif itemData.name == 'tendanivel1' then + info = { + tendaid = math.random(111,999), + tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, + } + Player.Functions.AddItem('tendanivel1', 1, nil, info, {["quality"] = 100}) + elseif itemData.name == 'tendanivel2' then + info = { + tendaid = math.random(111,999), + tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, + } + Player.Functions.AddItem('tendanivel2', 1, nil, info, {["quality"] = 100}) + elseif itemData.name == 'tendanivel3' then + info = { + tendaid = math.random(111,999), + tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, + } + Player.Functions.AddItem('tendanivel3', 1, nil, info, {["quality"] = 100}) elseif itemData["name"] == "printerdocument" then info.url = "https://cdn.discordapp.com/attachments/870094209783308299/870104331142189126/Logo_-_Display_Picture_-_Stylized_-_Red.png" end - - if Player.Functions.AddItem(itemData["name"], amount, false, info) then - TriggerClientEvent('QBCore:Notify', source, "You Have Given " ..GetPlayerName(tonumber(args[1])).." "..amount.." "..itemData["name"].. "", "success") + if AddItem(id, itemData["name"], amount, false, info) then + QBCore.Functions.Notify(source, "You Have Given " ..GetPlayerName(id).." "..amount.." "..itemData["name"].. "", "success") else - TriggerClientEvent('QBCore:Notify', source, "Can't give item!", "error") + QBCore.Functions.Notify(source, "Can't give item!", "error") end else - TriggerClientEvent('QBCore:Notify', source, "Item Does Not Exist", "error") + QBCore.Functions.Notify(source, "Item Does Not Exist", "error") end - else - TriggerClientEvent('QBCore:Notify', source, "Invalid Amount", "error") - end else - TriggerClientEvent('QBCore:Notify', source, "Player Is Not Online", "error") + QBCore.Functions.Notify(source, "Player Is Not Online", "error") end end, "admin") @@ -1597,7 +2151,7 @@ QBCore.Commands.Add("randomitems", "Give Random Items (God Only)", {}, false, fu if randitem["unique"] then amount = 1 end - if Player.Functions.AddItem(randitem["name"], amount) then + if AddItem(source, randitem["name"], amount) then TriggerClientEvent('inventory:client:ItemBox', source, QBCore.Shared.Items[randitem["name"]], 'add') Wait(500) end @@ -1606,25 +2160,93 @@ end, "god") -- item -QBCore.Functions.CreateUseableItem("snowball", function(source, item) - local Player = QBCore.Functions.GetPlayer(source) - local itemData = Player.Functions.GetItemBySlot(item.slot) - if Player.Functions.GetItemBySlot(item.slot) then - TriggerClientEvent("inventory:client:UseSnowball", source, itemData.amount) +QBCore.Commands.Add('clearinv', 'Clear Players Inventory (Admin Only)', { { name = 'id', help = 'Player ID' } }, false, function(source, args) + local playerId = args[1] ~= '' and tonumber(args[1]) or source + local Player = QBCore.Functions.GetPlayer(playerId) + if Player then + ClearInventory(playerId) + else + QBCore.Functions.Notify(source, "Player not online", 'error') + end +end, 'admin') + +CreateUsableItem("driver_license", function(source, item) + local playerPed = GetPlayerPed(source) + local playerCoords = GetEntityCoords(playerPed) + local players = QBCore.Functions.GetPlayers() + for _, v in pairs(players) do + local targetPed = GetPlayerPed(v) + local dist = #(playerCoords - GetEntityCoords(targetPed)) + if dist < 3.0 then + TriggerClientEvent('chat:addMessage', v, { + template = '', + args = { + "Drivers License", + item.info.firstname, + item.info.lastname, + item.info.birthdate, + item.info.type + } + } ) + end end end) -QBCore.Functions.CreateUseableItem("driver_license", function(source, item) - local PlayerPed = GetPlayerPed(source) - local PlayerCoords = GetEntityCoords(PlayerPed) +QBCore.Functions.CreateUseableItem("weaponlicense", function(source, item) + for k, v in pairs(QBCore.Functions.GetPlayers()) do + local PlayerPed = GetPlayerPed(source) + local TargetPed = GetPlayerPed(v) + local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) + if dist < 3.0 then + TriggerClientEvent('chat:addMessage', v, { + template = '', + args = { + "Weapon License", + item.info.citizenid, + item.info.firstname, + item.info.lastname, + item.info.birthdate, + item.info.type + } + } + ) + end + end +end) + +QBCore.Functions.CreateUseableItem("huntinglicense", function(source, item) + for k, v in pairs(QBCore.Functions.GetPlayers()) do + local PlayerPed = GetPlayerPed(source) + local TargetPed = GetPlayerPed(v) + local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) + if dist < 3.0 then + TriggerClientEvent('chat:addMessage', v, { + template = '', + args = { + "Hunting License", + item.info.citizenid, + item.info.firstname, + item.info.lastname, + item.info.birthdate, + item.info.type + } + } + ) + end + end +end) + +QBCore.Functions.CreateUseableItem("fishinglicense", function(source, item) for k, v in pairs(QBCore.Functions.GetPlayers()) do + local PlayerPed = GetPlayerPed(source) local TargetPed = GetPlayerPed(v) - local dist = #(PlayerCoords - GetEntityCoords(TargetPed)) + local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) if dist < 3.0 then TriggerClientEvent('chat:addMessage', v, { - template = '', + template = '', args = { - "Drivers License", + "Fishing License", + item.info.citizenid, item.info.firstname, item.info.lastname, item.info.birthdate, @@ -1636,12 +2258,35 @@ QBCore.Functions.CreateUseableItem("driver_license", function(source, item) end end) -QBCore.Functions.CreateUseableItem("id_card", function(source, item) - local PlayerPed = GetPlayerPed(source) - local PlayerCoords = GetEntityCoords(PlayerPed) +QBCore.Functions.CreateUseableItem("waterslicense", function(source, item) for k, v in pairs(QBCore.Functions.GetPlayers()) do + local PlayerPed = GetPlayerPed(source) local TargetPed = GetPlayerPed(v) - local dist = #(PlayerCoords - GetEntityCoords(TargetPed)) + local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) + if dist < 3.0 then + TriggerClientEvent('chat:addMessage', v, { + template = '', + args = { + "Waters License", + item.info.citizenid, + item.info.firstname, + item.info.lastname, + item.info.birthdate, + item.info.type + } + } + ) + end + end +end) + +CreateUsableItem("id_card", function(source, item) + local playerPed = GetPlayerPed(source) + local playerCoords = GetEntityCoords(playerPed) + local players = QBCore.Functions.GetPlayers() + for _, v in pairs(players) do + local targetPed = GetPlayerPed(v) + local dist = #(playerCoords - GetEntityCoords(targetPed)) if dist < 3.0 then local gender = "Man" if item.info.gender == 1 then @@ -1663,3 +2308,17 @@ QBCore.Functions.CreateUseableItem("id_card", function(source, item) end end end) + +-- Threads + +CreateThread(function() + while true do + for k, v in pairs(Drops) do + if v and (v.createdTime + Config.CleanupDropTime < os.time()) and not Drops[k].isOpen then + Drops[k] = nil + TriggerClientEvent("inventory:client:RemoveDropItem", -1, k) + end + end + Wait(60 * 1000) + end +end) From 7db887de5ba72624e8002cab67c4a67dd3a24bb7 Mon Sep 17 00:00:00 2001 From: Fast-Lane RolePlay Date: Sun, 21 Aug 2022 08:54:39 -0400 Subject: [PATCH 2/2] Server Sided Properties Fixed License Items to be like LJ Branch Solved GiveItem Additions(Removed Community Based Items/Factors) Added SpawnOnGround Event from LJ Branch --- lj-inventory/server/main.lua | 221 ++++++++++------------------------- 1 file changed, 60 insertions(+), 161 deletions(-) diff --git a/lj-inventory/server/main.lua b/lj-inventory/server/main.lua index 4215a4e..f439c45 100644 --- a/lj-inventory/server/main.lua +++ b/lj-inventory/server/main.lua @@ -1233,13 +1233,6 @@ RegisterNetEvent('inventory:server:SaveInventory', function(type, id) Gloveboxes[id].isOpen = false end elseif type == "stash" then - local indexstart, indexend = string.find(id, 'Backpack_') - if indexstart and indexend then - TriggerEvent('keep-backpack:server:saveBackpack', source, id, Stashes[id].items, function(close) - Stashes[id].isOpen = close - end) - return - end SaveStashItems(id, Stashes[id].items) elseif type == "drop" then if Drops[id] then @@ -2025,12 +2018,12 @@ QBCore.Commands.Add("rob", "Rob Player", {}, false, function(source, args) TriggerClientEvent("police:client:RobPlayer", source) end) -QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help="Player ID"},{name="item", help="Name of the item (not a label)"}, {name="amount", help="Amount of items"}}, false, function(source, args) - local id = tonumber(args[1]) - local Player = QBCore.Functions.GetPlayer(id) - local itemData = QBCore.Shared.Items[tostring(args[2]):lower()] +QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help="Player ID"},{name="item", help="Name of the item (not a label)"}, {name="amount", help="Amount of items"}}, true, function(source, args) + local Player = QBCore.Functions.GetPlayer(tonumber(args[1])) local amount = tonumber(args[3]) + local itemData = QBCore.Shared.Items[tostring(args[2]):lower()] if Player then + if amount > 0 then if itemData then -- check iteminfo local info = {} @@ -2042,98 +2035,36 @@ QBCore.Commands.Add("giveitem", "Give An Item (Admin Only)", {{name="id", help=" info.gender = Player.PlayerData.charinfo.gender info.nationality = Player.PlayerData.charinfo.nationality elseif itemData["name"] == "driver_license" then - info.citizenid = Player.PlayerData.citizenid info.firstname = Player.PlayerData.charinfo.firstname info.lastname = Player.PlayerData.charinfo.lastname info.birthdate = Player.PlayerData.charinfo.birthdate - info.gender = Player.PlayerData.charinfo.gender - info.nationality = Player.PlayerData.charinfo.nationality info.type = "Class C Driver License" - elseif itemData["name"] == "weaponlicense" then - info.citizenid = Player.PlayerData.citizenid - info.firstname = Player.PlayerData.charinfo.firstname - info.lastname = Player.PlayerData.charinfo.lastname - info.birthdate = Player.PlayerData.charinfo.birthdate - info.gender = Player.PlayerData.charinfo.gender - info.nationality = Player.PlayerData.charinfo.nationality - info.type = "Class One Weapon License" - elseif itemData["name"] == "huntinglicense" then - info.citizenid = Player.PlayerData.citizenid - info.firstname = Player.PlayerData.charinfo.firstname - info.lastname = Player.PlayerData.charinfo.lastname - info.birthdate = Player.PlayerData.charinfo.birthdate - info.gender = Player.PlayerData.charinfo.gender - info.nationality = Player.PlayerData.charinfo.nationality - info.type = "Hunting License" - elseif itemData["name"] == "fishinglicense" then - info.citizenid = Player.PlayerData.citizenid - info.firstname = Player.PlayerData.charinfo.firstname - info.lastname = Player.PlayerData.charinfo.lastname - info.birthdate = Player.PlayerData.charinfo.birthdate - info.gender = Player.PlayerData.charinfo.gender - info.nationality = Player.PlayerData.charinfo.nationality - info.type = "Deep Sea Fishing License" - elseif itemData["name"] == "waterslicense" then - info.citizenid = Player.PlayerData.citizenid - info.firstname = Player.PlayerData.charinfo.firstname - info.lastname = Player.PlayerData.charinfo.lastname - info.birthdate = Player.PlayerData.charinfo.birthdate - info.gender = Player.PlayerData.charinfo.gender - info.nationality = Player.PlayerData.charinfo.nationality - info.type = "Waters License" elseif itemData["type"] == "weapon" then amount = 1 info.serie = tostring(QBCore.Shared.RandomInt(2) .. QBCore.Shared.RandomStr(3) .. QBCore.Shared.RandomInt(1) .. QBCore.Shared.RandomStr(2) .. QBCore.Shared.RandomInt(3) .. QBCore.Shared.RandomStr(4)) - info.quality = 100 elseif itemData["name"] == "harness" then info.uses = 20 - elseif itemData["name"] == "laptop_blue" then - info.uses = 3 - elseif itemData["name"] == "laptop_red" then - info.uses = 3 - elseif itemData["name"] == "laptop_gold" then - info.uses = 3 - elseif itemData["name"] == "laptop_pink" then - info.uses = 3 - elseif itemData["name"] == "dabcartfull" then - info.uses = 5 - elseif itemData["name"] == "crfleecacard" then - info.uses = 3 elseif itemData["name"] == "markedbills" then info.worth = math.random(5000, 10000) elseif itemData["name"] == "labkey" then info.lab = exports["qb-methlab"]:GenerateRandomLab() - elseif itemData.name == 'tendanivel1' then - info = { - tendaid = math.random(111,999), - tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, - } - Player.Functions.AddItem('tendanivel1', 1, nil, info, {["quality"] = 100}) - elseif itemData.name == 'tendanivel2' then - info = { - tendaid = math.random(111,999), - tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, - } - Player.Functions.AddItem('tendanivel2', 1, nil, info, {["quality"] = 100}) - elseif itemData.name == 'tendanivel3' then - info = { - tendaid = math.random(111,999), - tendaOwner = Player.PlayerData.charinfo.firstname.." "..Player.PlayerData.charinfo.lastname, - } - Player.Functions.AddItem('tendanivel3', 1, nil, info, {["quality"] = 100}) elseif itemData["name"] == "printerdocument" then info.url = "https://cdn.discordapp.com/attachments/870094209783308299/870104331142189126/Logo_-_Display_Picture_-_Stylized_-_Red.png" end - if AddItem(id, itemData["name"], amount, false, info) then - QBCore.Functions.Notify(source, "You Have Given " ..GetPlayerName(id).." "..amount.." "..itemData["name"].. "", "success") + + if Player.Functions.AddItem(itemData["name"], amount, false, info) then + TriggerClientEvent('QBCore:Notify', source, "You Have Given " ..GetPlayerName(tonumber(args[1])).." "..amount.." "..itemData["name"].. "", "success") else - QBCore.Functions.Notify(source, "Can't give item!", "error") + TriggerClientEvent('QBCore:Notify', source, "Can't give item!", "error") end else - QBCore.Functions.Notify(source, "Item Does Not Exist", "error") + TriggerClientEvent('QBCore:Notify', source, "Item Does Not Exist", "error") end + else + TriggerClientEvent('QBCore:Notify', source, "Invalid Amount", "error") + end else - QBCore.Functions.Notify(source, "Player Is Not Online", "error") + TriggerClientEvent('QBCore:Notify', source, "Player Is Not Online", "error") end end, "admin") @@ -2158,8 +2089,6 @@ QBCore.Commands.Add("randomitems", "Give Random Items (God Only)", {}, false, fu end end, "god") --- item - QBCore.Commands.Add('clearinv', 'Clear Players Inventory (Admin Only)', { { name = 'id', help = 'Player ID' } }, false, function(source, args) local playerId = args[1] ~= '' and tonumber(args[1]) or source local Player = QBCore.Functions.GetPlayer(playerId) @@ -2170,83 +2099,19 @@ QBCore.Commands.Add('clearinv', 'Clear Players Inventory (Admin Only)', { { name end end, 'admin') -CreateUsableItem("driver_license", function(source, item) - local playerPed = GetPlayerPed(source) - local playerCoords = GetEntityCoords(playerPed) - local players = QBCore.Functions.GetPlayers() - for _, v in pairs(players) do - local targetPed = GetPlayerPed(v) - local dist = #(playerCoords - GetEntityCoords(targetPed)) - if dist < 3.0 then - TriggerClientEvent('chat:addMessage', v, { - template = '', - args = { - "Drivers License", - item.info.firstname, - item.info.lastname, - item.info.birthdate, - item.info.type - } - } ) - end - end -end) +-- Item's -QBCore.Functions.CreateUseableItem("weaponlicense", function(source, item) +QBCore.Functions.CreateUseableItem("driver_license", function(source, item) + local PlayerPed = GetPlayerPed(source) + local PlayerCoords = GetEntityCoords(PlayerPed) for k, v in pairs(QBCore.Functions.GetPlayers()) do - local PlayerPed = GetPlayerPed(source) local TargetPed = GetPlayerPed(v) - local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) + local dist = #(PlayerCoords - GetEntityCoords(TargetPed)) if dist < 3.0 then TriggerClientEvent('chat:addMessage', v, { - template = '', + template = '', args = { - "Weapon License", - item.info.citizenid, - item.info.firstname, - item.info.lastname, - item.info.birthdate, - item.info.type - } - } - ) - end - end -end) - -QBCore.Functions.CreateUseableItem("huntinglicense", function(source, item) - for k, v in pairs(QBCore.Functions.GetPlayers()) do - local PlayerPed = GetPlayerPed(source) - local TargetPed = GetPlayerPed(v) - local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) - if dist < 3.0 then - TriggerClientEvent('chat:addMessage', v, { - template = '', - args = { - "Hunting License", - item.info.citizenid, - item.info.firstname, - item.info.lastname, - item.info.birthdate, - item.info.type - } - } - ) - end - end -end) - -QBCore.Functions.CreateUseableItem("fishinglicense", function(source, item) - for k, v in pairs(QBCore.Functions.GetPlayers()) do - local PlayerPed = GetPlayerPed(source) - local TargetPed = GetPlayerPed(v) - local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) - if dist < 3.0 then - TriggerClientEvent('chat:addMessage', v, { - template = '', - args = { - "Fishing License", - item.info.citizenid, + "Drivers License", item.info.firstname, item.info.lastname, item.info.birthdate, @@ -2258,21 +2123,27 @@ QBCore.Functions.CreateUseableItem("fishinglicense", function(source, item) end end) -QBCore.Functions.CreateUseableItem("waterslicense", function(source, item) +QBCore.Functions.CreateUseableItem("id_card", function(source, item) + local PlayerPed = GetPlayerPed(source) + local PlayerCoords = GetEntityCoords(PlayerPed) for k, v in pairs(QBCore.Functions.GetPlayers()) do - local PlayerPed = GetPlayerPed(source) local TargetPed = GetPlayerPed(v) - local dist = #(GetEntityCoords(PlayerPed) - GetEntityCoords(TargetPed)) + local dist = #(PlayerCoords - GetEntityCoords(TargetPed)) if dist < 3.0 then + local gender = "Man" + if item.info.gender == 1 then + gender = "Woman" + end TriggerClientEvent('chat:addMessage', v, { - template = '', + template = '', args = { - "Waters License", + "ID Card", item.info.citizenid, item.info.firstname, item.info.lastname, item.info.birthdate, - item.info.type + gender, + item.info.nationality } } ) @@ -2309,6 +2180,34 @@ CreateUsableItem("id_card", function(source, item) end end) +-- Factor Event + +RegisterNetEvent("inventory:server:spawnOnGround", function(source, itemData, itemAmount) + local coords = GetEntityCoords(GetPlayerPed(source)) + local itemInfo = QBCore.Shared.Items[itemData.name:lower()] + local dropId = CreateDropId() + Drops[dropId] = {} + Drops[dropId].items = {} + + Drops[dropId].items[1] = { + name = itemInfo["name"], + amount = itemAmount, + info = itemData.info ~= nil and itemData.info or "", + label = itemInfo["label"], + description = itemInfo["description"] ~= nil and itemInfo["description"] or "", + weight = itemInfo["weight"], + type = itemInfo["type"], + unique = itemInfo["unique"], + useable = itemInfo["useable"], + image = itemInfo["image"], + slot = 1, + id = dropId, + } + local Ply = QBCore.Functions.GetPlayer(source) + TriggerEvent("qb-log:server:CreateLog", "drop", "New Item Spawn as Drop", "red", "**".. GetPlayerName(source) .. "** (citizenid: *"..Ply.PlayerData.citizenid.."* | id: *"..source.."*) overflowed inventory into drop; name: **"..itemData.name.."**, amount: **" .. itemAmount .. "**") + TriggerClientEvent("inventory:client:AddDropItem", -1, dropId, source, coords) +end) + -- Threads CreateThread(function()