Skip to content

Instantly share code, notes, and snippets.

@ISKinGeR
Last active July 18, 2025 22:41
Show Gist options
  • Save ISKinGeR/2ea3077d338a8864f9636147d4468f14 to your computer and use it in GitHub Desktop.
Save ISKinGeR/2ea3077d338a8864f9636147d4468f14 to your computer and use it in GitHub Desktop.
Adding the Handling function for pending Shop Deposits for mythic framework (not professional but it work fine!)
-- replace DoMerge & DoMove in ur inventory.lua
-- path: resources\[mythic]\mythic-inventory\server\inventory.lua
-- KR method <3
-- DoMerge function
function DoMerge(source, data, cb)
CreateThread(function()
local player = Fetch:Source(source)
local char = player:GetData("Character")
local item = itemsDatabase[data.name]
local cash = char:GetData("Cash")
local entityFrom = LoadedEntitys[tonumber(data.invTypeFrom)]
local entityTo = LoadedEntitys[tonumber(data.invTypeTo)]
local invWeight = Inventory.Items:GetWeights(data.ownerTo, data.invTypeTo)
local totWeight = invWeight + (data.countTo * itemsDatabase[data.name].weight)
if data.ownerFrom == nil or data.slotFrom == nil or data.invTypeFrom == nil or data.ownerTo == nil or data.slotTo == nil or data.invTypeTo == nil then
cb({ reason = "Invalid Move Data" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
if totWeight > getCapacity(data.invTypeTo, data.vehClassTo, data.vehModelTo, data.capacityOverrideTo) and data.ownerFrom ~= data.ownerTo then
cb({ reason = "Inventory Over Weight" })
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
return
end
if data.countTo <= 0 then
cb({ reason = "Can't Move 0 - Naughty Boy" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
if entityFrom.shop then
local cost = math.ceil((item.price * tonumber(data.countTo)))
local paymentType = (cash >= cost and 'cash' or (Banking.Balance:Has(char:GetData("BankAccount"), cost) and 'bank' or nil))
if entityFrom.free or paymentType ~= nil then
if -- Check if the item is either not a gun, or if it is that they have a Weapons license
(item.type ~= 2
or (
item.type == 2
and (not item.requiresLicense or item.requiresLicense and Weapons:IsEligible(source))
))
and (not item.qualification or hasValue(char:GetData("Qualifications"), item.qualification))
then
local paid = entityFrom.free
if not paid then
if paymentType == 'cash' then
paid = Wallet:Modify(source, -(math.abs(cost)))
else
paid = Banking.Balance:Charge(char:GetData("BankAccount"), cost, {
type = 'bill',
title = 'Store Purchase',
description = string.format('Bought x%s %s', data.countTo, item.label),
data = {}
})
Phone.Notification:Add(source, "Bill Payment Successful", false, os.time() * 1000, 3000, "bank", {})
end
if paid then
local isOwned = tonumber(data.ownerFrom:match("^shop:(%d+)$")) or false
local moneyShitForOwner = isOwned or entityFrom.id
local priceforStore = (cost * STORE_SHARE_AMOUNT) / tonumber(data.countTo)
local datatableForStore = string.format("%s %s ($%s/each)", data.countTo, data.name, priceforStore)
local function updateDeposit(accountKey, amount, isGov, shopName, itemCount, dataEntry)
pendingShopDeposits[accountKey] = pendingShopDeposits[accountKey] or { amount = 0, transactions = 0, itemsCount = 0, DATA = {} }
pendingShopDeposits[accountKey].amount += amount
pendingShopDeposits[accountKey].transactions += 1
pendingShopDeposits[accountKey].itemsCount += itemCount
pendingShopDeposits[accountKey].shopname = shopName
pendingShopDeposits[accountKey].isGov = isGov or false
table.insert(pendingShopDeposits[accountKey].DATA, dataEntry)
end
local ownerAmount = math.floor(cost * STORE_SHARE_AMOUNT)
updateDeposit(storeBankAccounts[moneyShitForOwner], ownerAmount, false, data.ownerFrom, data.countTo, datatableForStore)
local govAmount = math.ceil(cost * (1.0 - STORE_SHARE_AMOUNT))
updateDeposit(_govAccount, govAmount, true, data.ownerFrom, data.countTo, datatableForStore)
end
end
if paid then
local insData = Inventory:CreateItem(char:GetData("SID"), data.name, data.countTo, data.slotTo, {}, data.invTypeTo, false)
CreateStoreLog(data.ownerFrom, data.name, data.countTo or 1, char:GetData("SID"), insData.metadata, insData.id)
end
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return cb({ success = true })
else
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
cb({ reason = "Ineligible To Purchase Item" })
end
else
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
cb({ reason = "Not Enough Cash" })
end
else
local slotFrom = Inventory:GetSlot(data.ownerFrom, data.slotFrom, data.invTypeFrom)
local slotTo = Inventory:GetSlot(data.ownerTo, data.slotTo, data.invTypeTo)
if slotFrom == nil or slotTo == nil then
cb({ reason = "Item No Longer In That Slot" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
MySQL.query.await('UPDATE inventory SET slot = ?, name = ?, dropped = ? WHERE name = ? AND slot = ? AND item_id = ?', {
data.slotTo,
string.format("%s-%s", data.ownerTo, data.invTypeTo),
data.invTypeTo == 10 and 1 or 0,
string.format("%s-%s", data.ownerFrom, data.invTypeFrom),
data.slotFrom,
data.name,
})
if data.ownerFrom ~= data.ownerTo then
if data.invTypeFrom == 1 then
local plyr = Fetch:SID(data.ownerFrom)
if data.ownerFrom == data.ownerTo then
if item.type == 2 then
if (not item.isStackable and item.isStackable ~= -1) or data.countTo == slotFrom.Count then
TriggerClientEvent(
"Weapons:Client:Move",
plyr:GetData("Source"),
data.slotFrom,
data.slotTo
)
end
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotFrom,
(slotFrom.Count - data.countTo)
)
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotTo,
((slotTo?.Count or 0) + data.countTo)
)
end
elseif item.type == 10 then
TriggerClientEvent(
"Inventory:Container:Move",
plyr:GetData("Source"),
data.slotFrom,
data.slotTo
)
end
else
if not item.isStackable or data.countTo == slotFrom.Count then
if item.type == 2 then
TriggerClientEvent(
"Weapons:Client:Remove",
plyr:GetData("Source"),
slotFrom,
data.slotFrom,
{
owner = data.ownerTo,
type = data.invTypeTo,
slot = data.slotTo,
}
)
elseif item.type == 10 then
TriggerClientEvent(
"Inventory:Container:Remove",
plyr:GetData("Source"),
slotFrom,
data.slotFrom
)
end
else
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotFrom,
(slotFrom.Count - data.countTo)
)
end
end
end
end
if data.invTypeTo == 1 then
local plyr = Fetch:SID(data.ownerTo)
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotTo,
((slotTo?.Count or 0) + data.countTo)
)
end
end
if data.inventory.position ~= nil then
CreateDZIfNotExist(source, data.inventory.position)
end
end
if data.ownerFrom ~= data.ownerTo and WEAPON_PROPS[item.name] ~= nil then
_refreshAttchs[data.ownerFrom] = source
_refreshAttchs[data.ownerTo] = source
end
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return cb({ success = true })
end
end)
end
-- DoMove function
function DoMove(source, data, cb)
CreateThread(function()
local player = Fetch:Source(source)
local char = player:GetData("Character")
local item = itemsDatabase[data.name]
local cash = char:GetData("Cash")
local entityFrom = LoadedEntitys[tonumber(data.invTypeFrom)]
local entityTo = LoadedEntitys[tonumber(data.invTypeTo)]
local invWeight = Inventory.Items:GetWeights(data.ownerTo, data.invTypeTo)
local totWeight = invWeight + (data.countTo * itemsDatabase[data.name].weight)
if data.ownerFrom == nil or data.slotFrom == nil or data.invTypeFrom == nil or data.ownerTo == nil or data.slotTo == nil or data.invTypeTo == nil then
cb({ reason = "Invalid Move Data" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
if totWeight > getCapacity(data.invTypeTo, data.vehClassTo, data.vehModelTo, data.capacityOverrideTo) and data.ownerFrom ~= data.ownerTo then
cb({ reason = "Inventory Over Weight" })
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
return
end
if data.countTo <= 0 then
cb({ reason = "Can't Move 0 - Naughty Boy" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
if entityFrom.shop then
local cost = math.ceil((item.price * tonumber(data.countTo)))
local paymentType = (cash >= cost and 'cash' or (Banking.Balance:Has(char:GetData("BankAccount"), cost) and 'bank' or nil))
if entityFrom.free or paymentType ~= nil then
if -- Check if the item is either not a gun, or if it is that they have a Weapons license
(item.type ~= 2
or (
item.type == 2
and (not item.requiresLicense or item.requiresLicense and Weapons:IsEligible(source))
))
and (not item.qualification or hasValue(char:GetData("Qualifications"), item.qualification))
then
local paid = entityFrom.free
if not paid then
if paymentType == 'cash' then
paid = Wallet:Modify(source, -(math.abs(cost)))
else
paid = Banking.Balance:Charge(char:GetData("BankAccount"), cost, {
type = 'bill',
title = 'Store Purchase',
description = string.format('Bought x%s %s', data.countTo, item.label),
data = {}
})
Phone.Notification:Add(source, "Bill Payment Successful", string.format('Bought x%s %s', data.countTo, item.label), os.time() * 1000, 3000, "bank", {})
end
if paid then
local isOwned = tonumber(data.ownerFrom:match("^shop:(%d+)$")) or false
local moneyShitForOwner = isOwned or entityFrom.id
local priceforStore = (cost * STORE_SHARE_AMOUNT) / tonumber(data.countTo)
local datatableForStore = string.format("%s %s ($%s/each)", data.countTo, data.name, priceforStore)
local function updateDeposit(accountKey, amount, isGov, shopName, itemCount, dataEntry)
pendingShopDeposits[accountKey] = pendingShopDeposits[accountKey] or { amount = 0, transactions = 0, itemsCount = 0, DATA = {} }
pendingShopDeposits[accountKey].amount += amount
pendingShopDeposits[accountKey].transactions += 1
pendingShopDeposits[accountKey].itemsCount += itemCount
pendingShopDeposits[accountKey].shopname = shopName
pendingShopDeposits[accountKey].isGov = isGov or false
table.insert(pendingShopDeposits[accountKey].DATA, dataEntry)
end
local ownerAmount = math.floor(cost * STORE_SHARE_AMOUNT)
updateDeposit(storeBankAccounts[moneyShitForOwner], ownerAmount, false, data.ownerFrom, data.countTo, datatableForStore)
local govAmount = math.ceil(cost * (1.0 - STORE_SHARE_AMOUNT))
updateDeposit(_govAccount, govAmount, true, data.ownerFrom, data.countTo, datatableForStore)
end
end
if paid then
local insData = Inventory:CreateItem(char:GetData("SID"), data.name, data.countTo, data.slotTo, {}, data.invTypeTo, false)
CreateStoreLog(data.ownerFrom, data.name, data.countTo or 1, char:GetData("SID"), insData.metadata, insData.id)
end
if data.ownerFrom ~= data.ownerTo and WEAPON_PROPS[item.name] ~= nil then
_refreshAttchs[data.ownerFrom] = source
_refreshAttchs[data.ownerTo] = source
end
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return cb({ success = true })
else
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
cb({ reason = "Ineligible To Purchase Item" })
end
else
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
cb({ reason = "Not Enough Cash" })
end
else
local slotFrom = Inventory:GetSlot(data.ownerFrom, data.slotFrom, data.invTypeFrom)
local slotTo = Inventory:GetSlot(data.ownerTo, data.slotTo, data.invTypeTo)
if slotFrom == nil then
cb({ reason = "Item No Longer In That Slot" })
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return
end
if data.isSplit then
local itemIds = MySQL.query.await('SELECT id FROM inventory WHERE name = ? AND slot = ? AND item_id = ? ORDER BY id ASC LIMIT ?', {
string.format("%s-%s", data.ownerFrom, data.invTypeFrom),
data.slotFrom,
data.name,
data.countTo
})
local params = {}
for k, v in ipairs(itemIds) do
table.insert(params, v.id)
end
MySQL.query.await(string.format('UPDATE inventory SET slot = ?, name = ?, dropped = ? WHERE id IN (%s)', table.concat(params, ',')), {
data.slotTo,
string.format("%s-%s", data.ownerTo, data.invTypeTo),
data.invTypeTo == 10 and 1 or 0
})
else
MySQL.query.await('UPDATE inventory SET slot = ?, name = ?, dropped = ? WHERE name = ? AND slot = "?" AND item_id = ?', {
data.slotTo,
string.format("%s-%s", data.ownerTo, data.invTypeTo),
(data.invTypeTo == 10 and 1 or 0),
string.format("%s-%s", data.ownerFrom, data.invTypeFrom),
data.slotFrom,
data.name,
})
end
if data.ownerFrom ~= data.ownerTo then
if data.invTypeFrom == 1 then
local plyr = Fetch:SID(data.ownerFrom)
if data.ownerFrom == data.ownerTo then
if item.type == 2 then
if (not item.isStackable and item.isStackable ~= -1) or data.countTo == slotFrom.Count then
TriggerClientEvent(
"Weapons:Client:Move",
plyr:GetData("Source"),
data.slotFrom,
data.slotTo
)
end
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotFrom,
(slotFrom.Count - data.countTo)
)
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotTo,
((slotTo?.Count or 0) + data.countTo)
)
end
elseif item.type == 10 then
TriggerClientEvent(
"Inventory:Container:Move",
plyr:GetData("Source"),
data.slotFrom,
data.slotTo
)
end
else
if not item.isStackable or data.countTo == slotFrom.Count then
if item.type == 2 then
TriggerClientEvent(
"Weapons:Client:Remove",
plyr:GetData("Source"),
slotFrom,
data.slotFrom,
{
owner = data.ownerTo,
type = data.invTypeTo,
slot = data.slotTo,
}
)
elseif item.type == 10 then
TriggerClientEvent(
"Inventory:Container:Remove",
plyr:GetData("Source"),
slotFrom,
data.slotFrom
)
end
else
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotFrom,
(slotFrom.Count - data.countTo)
)
end
end
end
end
if data.invTypeTo == 1 then
local plyr = Fetch:SID(data.ownerTo)
if item.isThrowable then
TriggerClientEvent(
"Weapons:Client:UpdateCount",
plyr:GetData("Source"),
data.slotTo,
((slotTo?.Count or 0) + data.countTo)
)
end
end
if data.inventory.position ~= nil then
CreateDZIfNotExist(source, data.inventory.position)
end
end
if data.ownerFrom ~= data.ownerTo and WEAPON_PROPS[item.name] ~= nil then
_refreshAttchs[data.ownerFrom] = source
_refreshAttchs[data.ownerTo] = source
end
sendRefreshForClient(source, data.ownerFrom, data.invTypeFrom, data.slotFrom)
sendRefreshForClient(source, data.ownerTo, data.invTypeTo, data.slotTo)
return cb({ success = true })
end
end)
end
-- put this in ur Startup.lua, not matter which line just put it there
-- path: resources\[mythic]\mythic-inventory\server\startup.lua
-- KR method <3
Citizen.CreateThread(function()
while true do
local depositsToProcess = pendingShopDeposits
pendingShopDeposits = {}
if depositsToProcess and next(depositsToProcess) then
for accountId, depositData in pairs(depositsToProcess) do
local f = Banking.Accounts:Get(accountId)
if f ~= nil then
local description = string.format(
"%s - Sold %d items",
depositData.shopname or "Unknown",
depositData.itemsCount or 0
)
local title = depositData.tax and "Shop Tax" or "Shop Earnings"
local dataDetails = {}
if depositData.DATA and type(depositData.DATA) == "table" then
for _, detail in ipairs(depositData.DATA) do
table.insert(dataDetails, detail)
end
end
Banking.Balance:Deposit(f.Account, tonumber(depositData.amount), {
type = "deposit",
title = title,
description = description,
data = dataDetails,
}, true)
else
Logger:Error("Banking", string.format("Account ID %s not found for pending deposit.", accountId))
end
end
end
Citizen.Wait(60 * 1000 * 10)
end
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment