392 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			392 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| FM.player = {}
 | |
| 
 | |
| function string.split(str, delimiter)
 | |
|     local result = {}
 | |
|     local from = 1
 | |
|     local delim_from, delim_to = string.find(str, delimiter, from)
 | |
| 
 | |
|     while delim_from do
 | |
|         table.insert(result, string.sub(str, from, delim_from - 1))
 | |
|         from = delim_to + 1
 | |
|         delim_from, delim_to = string.find(str, delimiter, from)
 | |
|     end
 | |
| 
 | |
|     table.insert(result, string.sub(str, from))
 | |
|     return result
 | |
| end
 | |
| 
 | |
| local function isNewQBInv()
 | |
|     local version = GetResourceMetadata(Resources.QBInv or 'qb-inventory', 'version', 0)
 | |
|     if not version then return false end
 | |
| 
 | |
|     local vNums = {}
 | |
| 
 | |
|     for num in version:gmatch("(%d+)") do
 | |
|         vNums[#vNums + 1] = tonumber(num)
 | |
|     end
 | |
| 
 | |
|     return vNums and vNums[1] >= 2
 | |
| end
 | |
| 
 | |
| local function getPlayerBySrc(src)
 | |
|     if not src then return end
 | |
| 
 | |
|     local _fwp = ESX and ESX.GetPlayerFromId(src) or QB and QB.Functions.GetPlayer(src) or nil
 | |
|     if not _fwp or not type(_fwp) == 'table' then return end
 | |
| 
 | |
|     _fwp.source = QB and _fwp.PlayerData.source or _fwp.source
 | |
|     return _fwp
 | |
| end
 | |
| 
 | |
| local function getPlayerByIdentifier(identifier)
 | |
|     if not identifier then return end
 | |
|     local _fwp = ESX and ESX.GetPlayerFromIdentifier(identifier) or QB and QB.Functions.GetPlayerByCitizenId(identifier) or nil
 | |
|     if not _fwp or not type(_fwp) == 'table' then return end
 | |
| 
 | |
|     _fwp.source = QB and _fwp.PlayerData.source or _fwp.source
 | |
|     return _fwp
 | |
| end
 | |
| 
 | |
| ---@param id number|string
 | |
| function FM.player.get(id)
 | |
|     local _fwp = type(id) == 'number' and getPlayerBySrc(id) or type(id) == 'string' and getPlayerByIdentifier(id) or nil
 | |
|     if not _fwp or type(_fwp) ~= 'table' then return end
 | |
| 
 | |
|     local p = {
 | |
|         src = _fwp.source
 | |
|     }
 | |
| 
 | |
|     ---@param item string
 | |
|     ---@param amount number
 | |
|     ---@param metadata? any
 | |
|     ---@param ignoreCheck? boolean
 | |
|     p.addItem = function(item, amount, metadata, ignoreCheck)
 | |
|         if not item or not amount then return false end
 | |
|         if not ignoreCheck and not p.canAddItem(item, amount) then return false end
 | |
| 
 | |
|         if OXInv then
 | |
|             OXInv:AddItem(_fwp.source, item, amount, metadata)
 | |
| 
 | |
|             return true
 | |
|         elseif ESX then
 | |
|             if CHEZZAInv and string.find(item:lower(), 'weapon') then
 | |
|                 _fwp.addWeapon(item, 0)
 | |
|             else
 | |
|                 _fwp.addInventoryItem(item, amount)
 | |
|             end
 | |
| 
 | |
|             return true
 | |
|         elseif QB then
 | |
|             return _fwp.Functions.AddItem(item, amount, nil, metadata)
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     ---@param amount number
 | |
|     ---@param moneyType? string
 | |
|     ---@param transactionData? { type?: 'deposit' | 'withdraw' | 'transfer' | 'interest' | 'payment', reason?: string, fromIban?: string }
 | |
|     p.addMoney = function(amount, moneyType, transactionData)
 | |
|         moneyType = moneyType or Defaults.MONEY
 | |
|         if not amount then return end
 | |
| 
 | |
|         if transactionData and moneyType == 'bank' then
 | |
|             if GetResourceState(Resources.RX_BANKING.name) == 'started' then
 | |
|                 local personalAcc = exports[Resources.RX_BANKING.name]:GetPlayerPersonalAccount(p.getIdentifier())
 | |
|                 if personalAcc then
 | |
|                     exports[Resources.RX_BANKING.name]:CreateTransaction(amount, transactionData.type, transactionData.fromIban, personalAcc.iban, transactionData.reason)
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
| 
 | |
|         if ESX then _fwp.addAccountMoney(moneyType, amount)
 | |
|         elseif QB then _fwp.Functions.AddMoney(moneyType, amount) end
 | |
|     end
 | |
| 
 | |
|     p.canAddItem = function(item, amount)
 | |
|         if not item or not amount then return false end
 | |
| 
 | |
|         if OXInv then return OXInv:CanCarryItem(_fwp.source, item, amount)
 | |
|         elseif QBInv and isNewQBInv() then return QBInv:CanAddItem(_fwp.source, item, amount)
 | |
|         elseif QSInv then return QSInv:CanCarryItem(_fwp.source, item, amount)
 | |
|         elseif ESX then return _fwp.canCarryItem(item, amount)
 | |
|         elseif QB then return true end
 | |
|     end
 | |
| 
 | |
|     ---@param moneyType? string
 | |
|     ---@return number | nil amount
 | |
|     p.getMoney = function(moneyType)
 | |
|         moneyType = moneyType or Defaults.MONEY
 | |
| 
 | |
|         if ESX then
 | |
|             local acc = _fwp.getAccount(moneyType)
 | |
|             if not acc then FM.console.err('Money Type not found: '..moneyType) return 0 end
 | |
| 
 | |
|             return acc.money
 | |
|         elseif QB then
 | |
|             local money = _fwp.PlayerData.money[moneyType]
 | |
|             if money == nil then FM.console.err('Money Type not found: '..moneyType) return 0 end
 | |
| 
 | |
|             return money
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     ---@return string identifier
 | |
|     p.getIdentifier = function()
 | |
|         if ESX then return _fwp.getIdentifier()
 | |
|         elseif QB then return _fwp.PlayerData.citizenid end
 | |
|     end
 | |
| 
 | |
|     ---@return { name: string, label: string, grade: number, gradeLabel: string } job
 | |
|     p.getJob = function()
 | |
|         if ESX then
 | |
|             return {
 | |
|                 name = _fwp.job.name,
 | |
|                 label = _fwp.job.label,
 | |
|                 grade = _fwp.job.grade,
 | |
|                 gradeLabel = _fwp.job.grade_label
 | |
|             }
 | |
|         elseif QB then
 | |
|             return {
 | |
|                 name = _fwp.PlayerData.job.name,
 | |
|                 label = _fwp.PlayerData.job.label,
 | |
|                 grade = _fwp.PlayerData.job.grade.level,
 | |
|                 gradeLabel = _fwp.PlayerData.job.grade.name
 | |
|             }
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     ---@return { name: string, label: string, grade: number, gradeLabel: string } | nil gang
 | |
|     p.getGang = function()
 | |
|         if ESX then
 | |
|             local job = p.getJob()
 | |
|             if not job then return end
 | |
| 
 | |
|             return {
 | |
|                 name = job.name,
 | |
|                 label = job.label,
 | |
|                 grade = job.grade,
 | |
|                 gradeLabel = job.gradeLabel
 | |
|             }
 | |
|         elseif QB then
 | |
|             return {
 | |
|                 name = _fwp.PlayerData.gang.name,
 | |
|                 label = _fwp.PlayerData.gang.label,
 | |
|                 grade = _fwp.PlayerData.gang.grade.level,
 | |
|                 gradeLabel = _fwp.PlayerData.gang.grade.name
 | |
|             }
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     ---@param item string
 | |
|     ---@return { name: string, label: string, amount: number } item
 | |
|     p.getItem = function(item)
 | |
|         if not item then return end
 | |
| 
 | |
|         if OXInv then
 | |
|             item = OXInv:GetItem(_fwp.source, item, nil, false)
 | |
|             if not item then return end
 | |
| 
 | |
|             return {
 | |
|                 name = item.name,
 | |
|                 label = item.label,
 | |
|                 amount = item.count
 | |
|             }
 | |
|         elseif ESX then
 | |
|             if CHEZZAInv and string.find(item:lower(), 'weapon') then
 | |
|                 local loadoutNum, weapon = _fwp.getWeapon(item)
 | |
| 
 | |
|                 if weapon then
 | |
|                     item = weapon
 | |
|                     item.count = 1 -- CHEZZAInv compatibility fix
 | |
|                 end
 | |
|             else
 | |
|                 item = _fwp.getInventoryItem(item)
 | |
|             end
 | |
| 
 | |
|             if not item then return end
 | |
| 
 | |
|             return {
 | |
|                 name = item.name,
 | |
|                 label = item.label,
 | |
|                 amount = item.count
 | |
|             }
 | |
|         elseif QB then
 | |
|             item = _fwp.Functions.GetItemByName(item)
 | |
|             if not item then return end
 | |
| 
 | |
|             return {
 | |
|                 name = item.name,
 | |
|                 label = item.label,
 | |
|                 amount = item.amount
 | |
|             }
 | |
|         end
 | |
|     end
 | |
| 
 | |
|     ---@return { [slot]: { name: string, amount: number, label: string, metadata?: any } } inventory
 | |
|     p.getItems = function()
 | |
|         local inventory = {}
 | |
| 
 | |
|         if OXInv then
 | |
|             local items = OXInv:GetInventory(_fwp.source).items
 | |
| 
 | |
|             for slot, item in pairs(items) do
 | |
|                 inventory[slot] = {
 | |
|                     name = item.name,
 | |
|                     label = item.label,
 | |
|                     amount = item.count,
 | |
|                     metadata = item.metadata,
 | |
|                 }
 | |
|             end
 | |
|         elseif QSInv then
 | |
|             local items = QSInv:GetInventory(_fwp.source)
 | |
|             for itemName, itemData in pairs(items) do
 | |
|                 inventory[itemData.slot] = {
 | |
|                     name = itemName,
 | |
|                     label = itemData.label,
 | |
|                     amount = itemData.count,
 | |
|                     metadata = itemData.info,
 | |
|                 }
 | |
|             end
 | |
|         elseif COREInv then
 | |
|             local items = COREInv:getInventory()
 | |
|             for _, item in pairs(items) do
 | |
|                 inventory[item.slot] = {
 | |
|                     name = item.name,
 | |
|                     label = item.label,
 | |
|                     amount = item.amount,
 | |
|                     metadata = item.metadata,
 | |
|                 }
 | |
|             end
 | |
|         elseif ESX then
 | |
|             local items = _fwp.getInventory()
 | |
|             for slot, item in pairs(items) do
 | |
|                 inventory[slot] = {
 | |
|                     name = item.name,
 | |
|                     label = item.label,
 | |
|                     amount = item.count
 | |
|                 }
 | |
|             end
 | |
|         elseif QB then
 | |
|             local items = _fwp.PlayerData.items
 | |
|             for slot, item in pairs(items) do
 | |
|                 if item.amount == nil then item.amount = item.count end -- Simple QBox compatibility fix
 | |
| 
 | |
|                 inventory[slot] = {
 | |
|                     name = item.name,
 | |
|                     label = item.label,
 | |
|                     amount = item.amount,
 | |
|                     metadata = item.info,
 | |
|                 }
 | |
|             end
 | |
|         end
 | |
| 
 | |
|         return inventory
 | |
|     end
 | |
| 
 | |
|     ---@return string firstName
 | |
|     p.getFirstName = function()
 | |
|         if ESX then return string.split(_fwp.getName(), ' ')[1]
 | |
|         elseif QB then return _fwp.PlayerData.charinfo.firstname end
 | |
|     end
 | |
| 
 | |
|     ---@return string lastName
 | |
|     p.getLastName = function()
 | |
|         if ESX then return string.split(_fwp.getName(), ' ')[2]
 | |
|         elseif QB then return _fwp.PlayerData.charinfo.lastname end
 | |
|     end
 | |
| 
 | |
|     ---@return string fullName
 | |
|     p.getFullName = function()
 | |
|         if ESX then return _fwp.getName()
 | |
|         elseif QB then return _fwp.PlayerData.charinfo.firstname .. ' ' .. _fwp.PlayerData.charinfo.lastname end
 | |
|     end
 | |
| 
 | |
|     ---@param item string
 | |
|     ---@param amount number
 | |
|     ---@return boolean
 | |
|     p.hasItemAmount = function(item, amount)
 | |
|         if not item then return end
 | |
| 
 | |
|         item = p.getItem(item)
 | |
|         return item and item.amount >= amount or false
 | |
|     end
 | |
| 
 | |
|     ---@return boolean
 | |
|     p.isAdmin = function()
 | |
|         if ESX then
 | |
|             if _fwp.getGroup() == Defaults.ADMIN_ESX then
 | |
|                 return true
 | |
|             end
 | |
|         elseif QB then
 | |
|             if QB.Functions.HasPermission(_fwp.source, Defaults.ADMIN_QB) or QB.Functions.HasPermission(_fwp.source, Defaults.GOD_QB) then
 | |
|                 return true
 | |
|             end
 | |
|         end
 | |
| 
 | |
|         return IsPlayerAceAllowed(_fwp.source, 'command')
 | |
| 
 | |
|         -- Want custom admin group? Uncomment below and add the group in server.cfg
 | |
|         -- IN SERVER.CFG: add_ace group.admin fmLib.admin allow
 | |
|         -- return IsPlayerAceAllowed(_fwp.source, 'fmLib.admin')
 | |
|     end
 | |
| 
 | |
|     ---@return string | table group
 | |
|     p.getGroup = function()
 | |
|         if ESX then return _fwp.getGroup()
 | |
|         elseif QB then return QB.Functions.GetPermission(_fwp.source) end
 | |
|     end
 | |
| 
 | |
|     ---@param message string
 | |
|     ---@param type? 'success'|'error'
 | |
|     p.notify = function(message, type)
 | |
|         if not message then return end
 | |
| 
 | |
|         if ESX then TriggerClientEvent('esx:showNotification', _fwp.source, message, type)
 | |
|         elseif QB then TriggerClientEvent('QBCore:Notify', _fwp.source, message, type) end
 | |
|     end
 | |
| 
 | |
|     ---@param item string
 | |
|     ---@param amount number
 | |
|     ---@param slotId? number
 | |
|     ---@param metadata? any
 | |
|     p.removeItem = function(item, amount, slotId, metadata)
 | |
|         if not item or not amount then return end
 | |
| 
 | |
|         if OXInv then OXInv:RemoveItem(_fwp.source, item, amount, metadata, slotId)
 | |
|         elseif ESX then _fwp.removeInventoryItem(item, amount)
 | |
|         elseif QB then _fwp.Functions.RemoveItem(item, amount) end
 | |
|     end
 | |
| 
 | |
|     ---@param amount number
 | |
|     ---@param moneyType? string
 | |
|     ---@param transactionData? { type?: 'deposit' | 'withdraw' | 'transfer' | 'interest' | 'payment', reason?: string, toIban?: string }
 | |
|     p.removeMoney = function(amount, moneyType, transactionData)
 | |
|         moneyType = moneyType or Defaults.MONEY
 | |
|         if not amount then return end
 | |
| 
 | |
|         if transactionData and moneyType == 'bank' then
 | |
|             if GetResourceState(Resources.RX_BANKING.name) == 'started' then
 | |
|                 local personalAcc = exports[Resources.RX_BANKING.name]:GetPlayerPersonalAccount(p.getIdentifier())
 | |
|                 if personalAcc then
 | |
|                     exports[Resources.RX_BANKING.name]:CreateTransaction(amount, transactionData.type, personalAcc.iban, transactionData.toIban, transactionData.reason)
 | |
|                 end
 | |
|             end
 | |
|         end
 | |
| 
 | |
|         if ESX then _fwp.removeAccountMoney(moneyType, amount)
 | |
|         elseif QB then _fwp.Functions.RemoveMoney(moneyType, amount) end
 | |
|     end
 | |
| 
 | |
|     return p
 | |
| end
 | |
| 
 | |
| --[[
 | |
|     INTERNAL EVENT HANDLERS
 | |
|     DO NOT USE
 | |
| --]]
 | |
| 
 | |
| FM.callback.register('fm:internal:getGang', function(src)
 | |
|     return FM.player.get(src).getGang()
 | |
| end)
 | |
| 
 | |
| -- Aliases
 | |
| FM.p = FM.player
 | 
