279 lines
8.8 KiB
Lua
279 lines
8.8 KiB
Lua
if Config.Inventory ~= 'qb-inventory' then return end
|
|
|
|
-- ════════════════════════════════════════
|
|
-- QB-INVENTORY INTEGRATION (ADVANCED)
|
|
-- ════════════════════════════════════════
|
|
|
|
local Inventory = {}
|
|
Inventory.Config = {
|
|
ItemName = Config.ItemName or 'phone',
|
|
RequireItem = Config.ItemRequired ~= false,
|
|
DebugMode = Config.Debug or false
|
|
}
|
|
|
|
-- ════════════════════════════════════════
|
|
-- UTILITY FUNCTIONS
|
|
-- ════════════════════════════════════════
|
|
|
|
local function Log(type, message, ...)
|
|
if not Inventory.Config.DebugMode then return end
|
|
|
|
local prefix = '^2[Inventory]^7'
|
|
if type == 'error' then prefix = '^1[Inventory ERROR]^7' end
|
|
if type == 'warn' then prefix = '^3[Inventory WARNING]^7' end
|
|
|
|
print(string.format('%s %s', prefix, string.format(message, ...)))
|
|
end
|
|
|
|
local function ValidatePlayer(source)
|
|
local src = tonumber(source)
|
|
if not src or src == 0 then
|
|
Log('error', 'Invalid source: %s', tostring(source))
|
|
return nil
|
|
end
|
|
|
|
local Player = Core.Functions.GetPlayer(src)
|
|
if not Player then
|
|
Log('error', 'Player not found for source: %s', src)
|
|
return nil
|
|
end
|
|
|
|
return Player
|
|
end
|
|
|
|
-- ════════════════════════════════════════
|
|
-- INVENTORY FUNCTIONS
|
|
-- ════════════════════════════════════════
|
|
|
|
function Inventory.GetAllItems(source)
|
|
local Player = ValidatePlayer(source)
|
|
if not Player then return {} end
|
|
|
|
return Player.PlayerData.items or {}
|
|
end
|
|
|
|
function Inventory.GetItemsByName(source, itemName)
|
|
itemName = itemName or Inventory.Config.ItemName
|
|
|
|
local items = {}
|
|
local inventory = Inventory.GetAllItems(source)
|
|
|
|
for slot, item in pairs(inventory) do
|
|
if item and item.name == itemName then
|
|
items[#items + 1] = {
|
|
slot = slot,
|
|
name = item.name,
|
|
amount = item.amount or 1,
|
|
info = item.info or {},
|
|
CodemPhoneNumber = item.info?.CodemPhoneNumber,
|
|
CodemFormattedNumber = item.info?.CodemFormattedNumber
|
|
}
|
|
end
|
|
end
|
|
|
|
-- Log('debug', 'Found %d item(s) for player %s', #items, source)
|
|
return items
|
|
end
|
|
|
|
function Inventory.GetPhoneItem(source)
|
|
if not Inventory.Config.RequireItem then
|
|
Log('debug', 'Item requirement disabled, returning true')
|
|
return true
|
|
end
|
|
|
|
local Player = ValidatePlayer(source)
|
|
if not Player then return false end
|
|
|
|
local item = Player.Functions.GetItemByName(Inventory.Config.ItemName)
|
|
if not item then
|
|
Log('warn', 'Player %s does not have phone item', source)
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function Inventory.HasPhoneWithNumber(source, phoneNumber)
|
|
local phones = Inventory.GetItemsByName(source, Inventory.Config.ItemName)
|
|
|
|
if #phones == 0 then
|
|
Log('debug', 'Player %s has no phone items', source)
|
|
return {
|
|
success = false,
|
|
itemAmount = 0,
|
|
}
|
|
end
|
|
|
|
local foundPhoneWithDifferentNumber = false
|
|
local differentNumber = nil
|
|
|
|
for i = 1, #phones do
|
|
local phone = phones[i]
|
|
|
|
if phone.CodemPhoneNumber then
|
|
if phone.CodemPhoneNumber == phoneNumber then
|
|
Log('debug', 'Player %s has phone with number %s', source, phoneNumber)
|
|
return {
|
|
success = true,
|
|
myPhone = true
|
|
}
|
|
else
|
|
foundPhoneWithDifferentNumber = true
|
|
differentNumber = phone.CodemPhoneNumber or nil
|
|
end
|
|
end
|
|
end
|
|
|
|
if foundPhoneWithDifferentNumber then
|
|
Log('debug', 'Player %s has phone but with different number: %s (expected: %s)', source, differentNumber,
|
|
phoneNumber)
|
|
return {
|
|
success = true,
|
|
myPhone = false,
|
|
differentNumber = differentNumber
|
|
}
|
|
end
|
|
|
|
Log('debug', 'Player %s has phone but no number assigned', source)
|
|
return {
|
|
success = true,
|
|
myPhone = false,
|
|
firstSetup = true
|
|
}
|
|
end
|
|
|
|
function Inventory.HasAnyPhone(source)
|
|
local phones = Inventory.GetItemsByName(source, Inventory.Config.ItemName)
|
|
|
|
if #phones == 0 then
|
|
Log('debug', 'Player %s has no phone items', source)
|
|
return false
|
|
end
|
|
|
|
Log('debug', 'Player %s has %d phone item(s)', source, #phones)
|
|
return true
|
|
end
|
|
|
|
function Inventory.SetPhoneNumber(source, phoneNumber)
|
|
local Player = ValidatePlayer(source)
|
|
if not Player then return false end
|
|
|
|
if not phoneNumber then
|
|
Log('error', 'SetPhoneNumber called without phone number')
|
|
return false
|
|
end
|
|
|
|
local items = Player.PlayerData.items
|
|
local updated = false
|
|
|
|
for slot, item in pairs(items) do
|
|
if item and item.name == Inventory.Config.ItemName then
|
|
if item.info?.CodemPhoneNumber then
|
|
Log('debug', 'Skipping phone in slot %s (already has number)', slot)
|
|
goto continue
|
|
end
|
|
|
|
item.info = item.info or {}
|
|
item.info.CodemPhoneNumber = phoneNumber
|
|
item.info.CodemFormattedNumber = FormatPhoneNumber(phoneNumber)
|
|
|
|
Log('debug', 'Assigned number %s to phone in slot %s', phoneNumber, slot)
|
|
updated = true
|
|
break
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
|
|
if updated then
|
|
Player.Functions.SetInventory(items, true)
|
|
Log('debug', 'Phone number successfully set for player %s', source)
|
|
else
|
|
Log('warn', 'Could not find available phone to assign number for player %s', source)
|
|
end
|
|
|
|
return updated
|
|
end
|
|
|
|
function Inventory.UpdatePhoneMetadata(source, phoneNumber, metadata)
|
|
local Player = ValidatePlayer(source)
|
|
if not Player then return false end
|
|
|
|
local items = Player.PlayerData.items
|
|
local updated = false
|
|
|
|
for slot, item in pairs(items) do
|
|
if item and item.name == Inventory.Config.ItemName and item.info?.CodemPhoneNumber == phoneNumber then
|
|
item.info = item.info or {}
|
|
|
|
for key, value in pairs(metadata) do
|
|
if value == "DELETE" or value == nil then
|
|
item.info[key] = nil
|
|
else
|
|
item.info[key] = value
|
|
end
|
|
end
|
|
|
|
Log('debug', 'Updated metadata for phone %s in slot %s', phoneNumber, slot)
|
|
updated = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if updated then
|
|
Player.Functions.SetInventory(items, true)
|
|
end
|
|
|
|
return updated
|
|
end
|
|
|
|
function Inventory.RemoveInventoryItem(source, itemname, amount)
|
|
local Player = ValidatePlayer(source)
|
|
if not Player then return false end
|
|
|
|
local removed = Player.Functions.RemoveItem(itemname, amount)
|
|
if removed then
|
|
Log('debug', 'Removed %d of item %s from player %s', amount, itemname, source)
|
|
else
|
|
Log('warn', 'Failed to remove item %s from player %s', itemname, source)
|
|
end
|
|
|
|
return removed
|
|
end
|
|
|
|
Citizen.CreateThread(function()
|
|
while Core == nil or not Core.Functions.CreateUseableItem do
|
|
Citizen.Wait(100)
|
|
end
|
|
Core.Functions.CreateUseableItem(Inventory.Config.ItemName, function(source, item)
|
|
if item then
|
|
TriggerClientEvent("codem-phone:PhoneUsed", source, item)
|
|
end
|
|
end)
|
|
if Config.BatterySystem.enable then
|
|
Core.Functions.CreateUseableItem(Config.BatterySystem.powerBankItemName, function(source, item)
|
|
TriggerClientEvent("codem-phone:UsePowerBank", source)
|
|
Inventory.RemoveInventoryItem(source, Config.BatterySystem.powerBankItemName, 1)
|
|
end)
|
|
end
|
|
end)
|
|
|
|
|
|
RPC.Register('codem-phone:inventory:HasPhoneItem', function(source, phoneNumber)
|
|
return Inventory.HasPhoneWithNumber(source, phoneNumber)
|
|
end)
|
|
|
|
RPC.Register('codem-phone:inventory:HasAnyPhone', function(source)
|
|
return Inventory.HasAnyPhone(source)
|
|
end)
|
|
|
|
RPC.Register('codem-phone:inventory:GetPhoneItem', function(source)
|
|
return Inventory.GetPhoneItem(source)
|
|
end)
|
|
|
|
|
|
GetPlayerInventoryItem = Inventory.GetPhoneItem
|
|
SetPhoneNumber = Inventory.SetPhoneNumber
|
|
UpdatePhoneMetadata = Inventory.UpdatePhoneMetadata
|
|
GetItemsByName = Inventory.GetItemsByName
|