mirror of
https://github.com/jimathy/jim_bridge.git
synced 2026-08-16 21:46:03 +01:00
I am still alive
This commit is contained in:
@@ -57,6 +57,7 @@ function triggerCallback(callbackName, ...)
|
|||||||
p:resolve(cbResult)
|
p:resolve(cbResult)
|
||||||
end, ...)
|
end, ...)
|
||||||
result = Citizen.Await(p)
|
result = Citizen.Await(p)
|
||||||
|
Wait(10)
|
||||||
elseif isStarted(ESXExport) then
|
elseif isStarted(ESXExport) then
|
||||||
local p = promise.new()
|
local p = promise.new()
|
||||||
ESX.TriggerServerCallback(callbackName, function(cbResult)
|
ESX.TriggerServerCallback(callbackName, function(cbResult)
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ function openMenu(Menu, data)
|
|||||||
Menu[k].args = Menu[k].params.args or {}
|
Menu[k].args = Menu[k].params.args or {}
|
||||||
end
|
end
|
||||||
if Menu[k].isMenuHeader then
|
if Menu[k].isMenuHeader then
|
||||||
Menu[k].disabled = true
|
Menu[k].readOnly = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local menuID = 'Menu'
|
local menuID = 'Menu'
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ if isStarted(QBXExport) or isStarted(QBExport) then
|
|||||||
elseif isStarted(OXCoreExport) then
|
elseif isStarted(OXCoreExport) then
|
||||||
Vehicles = {}
|
Vehicles = {}
|
||||||
for k, v in pairs(Ox.GetVehicleData()) do
|
for k, v in pairs(Ox.GetVehicleData()) do
|
||||||
Vehicles[k] = { model = k, price = v.price, name = v.name, brand = v.make }
|
Vehicles[k] = { model = k, hash = GetHashKey(k), price = v.price, name = v.name, brand = v.make }
|
||||||
end
|
end
|
||||||
vehResource = OXCoreExport
|
vehResource = OXCoreExport
|
||||||
|
|
||||||
@@ -159,6 +159,7 @@ elseif isStarted(ESXExport) then
|
|||||||
Vehicles = Vehicles or {}
|
Vehicles = Vehicles or {}
|
||||||
Vehicles[v.model] = {
|
Vehicles[v.model] = {
|
||||||
model = v.model,
|
model = v.model,
|
||||||
|
hash = GetHashKey(v.model),
|
||||||
price = v.price,
|
price = v.price,
|
||||||
name = v.name,
|
name = v.name,
|
||||||
brand = GetMakeNameFromVehicleModel(v.model):lower():gsub("^%l", string.upper)
|
brand = GetMakeNameFromVehicleModel(v.model):lower():gsub("^%l", string.upper)
|
||||||
|
|||||||
@@ -12,6 +12,14 @@
|
|||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
CraftLock = false
|
CraftLock = false
|
||||||
|
|
||||||
|
-- helper filter table for crafting menus
|
||||||
|
local excludeKeys = {
|
||||||
|
amount = true, metadata = true, description = true, info = true,
|
||||||
|
job = true, gang = true, oneUse = true, slot = true,
|
||||||
|
blueprintRef = true, craftingLevel = true, craftedItems = true,
|
||||||
|
hasCrafted = true, exp = true, anim = true, time = true,
|
||||||
|
}
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Crafting Menu
|
-- Crafting Menu
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
@@ -73,6 +81,7 @@ function craftingMenu(data)
|
|||||||
for i = 1, #Recipes do
|
for i = 1, #Recipes do
|
||||||
for k in pairs(Recipes[i]) do
|
for k in pairs(Recipes[i]) do
|
||||||
if k == "hasCrafted" and not data.craftable.craftedItems then
|
if k == "hasCrafted" and not data.craftable.craftedItems then
|
||||||
|
-- Retreive list of already crafted items from playermetadata to see if we should class this recipe as "new"
|
||||||
craftedItems = GetMetadata(nil, "craftedItems") or {}
|
craftedItems = GetMetadata(nil, "craftedItems") or {}
|
||||||
data.craftable.craftedItems = craftedItems
|
data.craftable.craftedItems = craftedItems
|
||||||
end
|
end
|
||||||
@@ -88,12 +97,6 @@ function craftingMenu(data)
|
|||||||
for i = 1, #Recipes do
|
for i = 1, #Recipes do
|
||||||
if not Recipes[i]["amount"] then Recipes[i]["amount"] = 1 end
|
if not Recipes[i]["amount"] then Recipes[i]["amount"] = 1 end
|
||||||
for k, _ in pairs(Recipes[i]) do
|
for k, _ in pairs(Recipes[i]) do
|
||||||
local excludeKeys = {
|
|
||||||
amount = true, metadata = true, description = true, info = true,
|
|
||||||
job = true, gang = true, oneUse = true, slot = true,
|
|
||||||
blueprintRef = true, craftingLevel = true, craftedItems = true,
|
|
||||||
hasCrafted = true, exp = true, anim = true, time = true,
|
|
||||||
}
|
|
||||||
if not excludeKeys[k] then
|
if not excludeKeys[k] then
|
||||||
local hasjob = true
|
local hasjob = true
|
||||||
if Recipes[i].job then
|
if Recipes[i].job then
|
||||||
@@ -203,48 +206,79 @@ end
|
|||||||
--- })
|
--- })
|
||||||
--- ```
|
--- ```
|
||||||
function multiCraft(data)
|
function multiCraft(data)
|
||||||
local Menu = {}
|
local max = 0
|
||||||
local amounts = Config.Crafting.MultiCraftAmounts
|
local stashName = nil
|
||||||
local metadata = data.metadata or nil
|
for i = 1, 100 do
|
||||||
|
|
||||||
-- Header for the multi-craft menu.
|
|
||||||
Menu[#Menu + 1] = {
|
|
||||||
isMenuHeader = true,
|
|
||||||
icon = invImg(metadata and metadata.image or data.item),
|
|
||||||
header = metadata and metadata.label or Items[data.item].label,
|
|
||||||
}
|
|
||||||
|
|
||||||
for k in pairsByKeys(amounts) do
|
|
||||||
local settext = ""
|
|
||||||
local itemTable = {}
|
local itemTable = {}
|
||||||
for l, b in pairs(data.craft[data.item]) do
|
for l, b in pairs(data.craft[data.item]) do
|
||||||
itemTable[l] = (b * k)
|
debugPrint("")
|
||||||
settext = settext..(settext ~= "" and br or "")..Items[l].label..(b * k > 1 and " x"..b * k or "")
|
itemTable[l] = (b * i)
|
||||||
Wait(0)
|
|
||||||
end
|
end
|
||||||
local disable, stashname = checkHasItem(data.stashName, itemTable)
|
|
||||||
Menu[#Menu + 1] = {
|
if data.stashName then
|
||||||
isMenuHeader = not disable,
|
debugPrint("")
|
||||||
arrow = disable,
|
local hasItems, stashname = checkHasItem(data.stashName, itemTable)
|
||||||
header = "Craft - x"..(k * data.craft.amount),
|
if hasItems == true then
|
||||||
txt = settext,
|
max += 1
|
||||||
onSelect = function()
|
stashName = stashname
|
||||||
makeItem({
|
else
|
||||||
item = data.item,
|
break
|
||||||
craft = data.craft,
|
end
|
||||||
craftable = data.craftable,
|
else
|
||||||
amount = k,
|
debugPrint("")
|
||||||
coords = data.coords,
|
local has, _ = hasItem(itemTable, nil, nil)
|
||||||
stashName = stashname,
|
if has then
|
||||||
stashTable = data.stashName,
|
max += 1
|
||||||
onBack = data.onBack,
|
else
|
||||||
metadata = data.metadata,
|
break
|
||||||
})
|
end
|
||||||
end,
|
end
|
||||||
}
|
Wait(10)
|
||||||
end
|
end
|
||||||
|
|
||||||
openMenu(Menu, { header = data.craftable.Header, onBack = function() craftingMenu(data) end })
|
local dialog = createInput(data.craftable.Header, {
|
||||||
|
((Config.System.Menu == "ox") and {
|
||||||
|
type = "slider",
|
||||||
|
label = "How many to craft?",
|
||||||
|
required = true,
|
||||||
|
default = 1,
|
||||||
|
min = 1,
|
||||||
|
max = max
|
||||||
|
}) or nil,
|
||||||
|
((Config.System.Menu == "qb") and {
|
||||||
|
type = "number",
|
||||||
|
label = "How many to craft?"..br.."Max: "..max,
|
||||||
|
name = "amount",
|
||||||
|
isRecuired = true,
|
||||||
|
default = 1,
|
||||||
|
}) or nil,
|
||||||
|
})
|
||||||
|
|
||||||
|
if dialog then
|
||||||
|
if Config.System.Menu == "ox" then
|
||||||
|
|
||||||
|
end
|
||||||
|
if Config.System.Menu == "qb" then
|
||||||
|
if dialog["amount"] > max or dialog["amount"] < 1 or dialog["amount"] == nil or dialog["amount"] == "" then
|
||||||
|
triggerNotify(nil, "Invalid Amount", "error")
|
||||||
|
craftingMenu(data)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
makeItem({
|
||||||
|
item = data.item,
|
||||||
|
craft = data.craft,
|
||||||
|
craftable = data.craftable,
|
||||||
|
amount = dialog["amount"] or dialog[1],
|
||||||
|
coords = data.coords,
|
||||||
|
stashName = stashName or nil,
|
||||||
|
--stashTable = data.stashName,
|
||||||
|
onBack = data.onBack,
|
||||||
|
metadata = data.metadata,
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
@@ -300,12 +334,6 @@ function makeItem(data)
|
|||||||
|
|
||||||
for i = 1, craftAmount do
|
for i = 1, craftAmount do
|
||||||
for k, v in pairs(data.craft) do
|
for k, v in pairs(data.craft) do
|
||||||
local excludeKeys = {
|
|
||||||
amount = true, info = true, metadata = true, description = true,
|
|
||||||
job = true, gang = true, oneUse = true, slot = true,
|
|
||||||
blueprintRef = true, craftingLevel = true, craftedItems = true,
|
|
||||||
hasCrafted = true, exp = true, anim = true, time = true,
|
|
||||||
}
|
|
||||||
if not excludeKeys[k] then
|
if not excludeKeys[k] then
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
for l, b in pairs(v) do
|
for l, b in pairs(v) do
|
||||||
@@ -392,6 +420,7 @@ end
|
|||||||
--- @param craftable table The crafting recipe and details.
|
--- @param craftable table The crafting recipe and details.
|
||||||
--- @param stashName string|table The stash name(s) to remove ingredients from.
|
--- @param stashName string|table The stash name(s) to remove ingredients from.
|
||||||
--- @param metadata table (optional) Metadata for the crafted item.
|
--- @param metadata table (optional) Metadata for the crafted item.
|
||||||
|
--- @usage
|
||||||
RegisterNetEvent(getScript()..":Crafting:GetItem", function(ItemMake, craftable, stashName, metadata)
|
RegisterNetEvent(getScript()..":Crafting:GetItem", function(ItemMake, craftable, stashName, metadata)
|
||||||
local src = source
|
local src = source
|
||||||
local hasItems, hasTable = hasItem(ItemMake, 1, src)
|
local hasItems, hasTable = hasItem(ItemMake, 1, src)
|
||||||
@@ -424,188 +453,6 @@ RegisterNetEvent(getScript()..":Crafting:GetItem", function(ItemMake, craftable,
|
|||||||
end
|
end
|
||||||
addItem(ItemMake, craftable.amount or 1, metadata, src)
|
addItem(ItemMake, craftable.amount or 1, metadata, src)
|
||||||
-- Optionally, add experience here:
|
-- Optionally, add experience here:
|
||||||
|
-- for example:
|
||||||
-- if isStarted("core_skills") then exports["core_skills"]:AddExperience(src, 2) end
|
-- if isStarted("core_skills") then exports["core_skills"]:AddExperience(src, 2) end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
-- Selling Menu and Animation
|
|
||||||
-------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Opens a selling menu with available items and prices.
|
|
||||||
---
|
|
||||||
--- @param data table Contains selling menu data:
|
|
||||||
--- - sellTable (`table`) Table with Header and Items (item names and prices).
|
|
||||||
--- - ped (optional) (`number`) Ped entity involved.
|
|
||||||
--- - onBack (optional) (`function`) Callback for returning.
|
|
||||||
--- @usage
|
|
||||||
--- ```lua
|
|
||||||
--- sellMenu({
|
|
||||||
--- sellTable = {
|
|
||||||
--- Header = "Sell Items",
|
|
||||||
--- Items = {
|
|
||||||
--- ["gold_ring"] = 100,
|
|
||||||
--- ["diamond"] = 500,
|
|
||||||
--- },
|
|
||||||
--- },
|
|
||||||
--- ped = pedEntity,
|
|
||||||
--- onBack = function() print("Returning to previous menu") end,
|
|
||||||
--- })
|
|
||||||
--- ```
|
|
||||||
function sellMenu(data)
|
|
||||||
local origData = data
|
|
||||||
local Menu = {}
|
|
||||||
if data.sellTable.Items then
|
|
||||||
local itemList = {}
|
|
||||||
for k, v in pairs(data.sellTable.Items) do itemList[k] = 1 end
|
|
||||||
local _, hasTable = hasItem(itemList)
|
|
||||||
for k, v in pairsByKeys(data.sellTable.Items) do
|
|
||||||
Menu[#Menu + 1] = {
|
|
||||||
isMenuHeader = not hasTable[k].hasItem,
|
|
||||||
icon = invImg(k),
|
|
||||||
header = Items[k].label..(hasTable[k].hasItem and "💰 (x"..hasTable[k].count..")" or ""),
|
|
||||||
txt = Loc[Config.Lan].info["sell_all"]..v.." "..Loc[Config.Lan].info["sell_each"],
|
|
||||||
onSelect = function()
|
|
||||||
sellAnim({ item = k, price = v, ped = data.ped, onBack = function() sellMenu(data) end })
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for k, v in pairsByKeys(data.sellTable) do
|
|
||||||
if type(v) == "table" then
|
|
||||||
Menu[#Menu + 1] = {
|
|
||||||
arrow = true,
|
|
||||||
header = k,
|
|
||||||
txt = "Amount of items: "..countTable(v.Items),
|
|
||||||
onSelect = function()
|
|
||||||
v.onBack = function() sellMenu(origData) end
|
|
||||||
v.sellTable = data.sellTable[k]
|
|
||||||
sellMenu(v)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
openMenu(Menu, {
|
|
||||||
header = data.sellTable.Header or "Amount of items: "..countTable(data.sellTable.Items),
|
|
||||||
headertxt = data.sellTable.Header and "Amount of items: "..countTable(data.sellTable.Items) or "",
|
|
||||||
canClose = true,
|
|
||||||
onBack = data.onBack,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Plays the selling animation and processes the sale transaction.
|
|
||||||
---
|
|
||||||
--- Checks if the player has the item, plays animations, triggers the server event for selling,
|
|
||||||
--- and then calls the onBack callback if provided.
|
|
||||||
---
|
|
||||||
--- @param data table Contains:
|
|
||||||
--- `- item: The item to sell.
|
|
||||||
--- `- price: Price per item.
|
|
||||||
--- `- ped (optional): Ped entity involved.
|
|
||||||
--- `- onBack (optional): Callback to call on completion.
|
|
||||||
---@usage
|
|
||||||
--- ```lua
|
|
||||||
--- sellAnim({
|
|
||||||
--- item = "gold_ring",
|
|
||||||
--- price = 100,
|
|
||||||
--- ped = pedEntity,
|
|
||||||
--- onBack = function() sellMenu(data) end,
|
|
||||||
--- })
|
|
||||||
--- ```
|
|
||||||
function sellAnim(data)
|
|
||||||
if not hasItem(data.item, 1) then
|
|
||||||
triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Remove any attached clipboard objects.
|
|
||||||
for _, obj in pairs(GetGamePool('CObject')) do
|
|
||||||
for _, model in pairs({ `p_cs_clipboard` }) do
|
|
||||||
if GetEntityModel(obj) == model and IsEntityAttachedToEntity(data.ped, obj) then
|
|
||||||
DeleteObject(obj)
|
|
||||||
DetachEntity(obj, 0, 0)
|
|
||||||
SetEntityAsMissionEntity(obj, true, true)
|
|
||||||
Wait(100)
|
|
||||||
DeleteEntity(obj)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
TriggerServerEvent(getScript().."Sellitems", data)
|
|
||||||
lookEnt(data.ped)
|
|
||||||
local dict = "mp_common"
|
|
||||||
playAnim(dict, "givetake2_a", 0.3, 2)
|
|
||||||
playAnim(dict, "givetake2_b", 0.3, 2, data.ped)
|
|
||||||
Wait(2000)
|
|
||||||
StopAnimTask(PlayerPedId(), dict, "givetake2_a", 0.5)
|
|
||||||
StopAnimTask(data.ped, dict, "givetake2_b", 0.5)
|
|
||||||
if data.onBack then data.onBack() end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Server event handler for processing item sales.
|
|
||||||
--- Removes sold items from inventory and funds the player based on the sale.
|
|
||||||
RegisterNetEvent(getScript().."Sellitems", function(data)
|
|
||||||
local src = source
|
|
||||||
local hasItems, hasTable = hasItem(data.item, 1, src)
|
|
||||||
if hasItems then
|
|
||||||
removeItem(data.item, hasTable[data.item].count, src)
|
|
||||||
TriggerEvent(getScript()..":server:FundPlayer", (hasTable[data.item].count * data.price), "cash", src)
|
|
||||||
else
|
|
||||||
triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error", src)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
-- Shop Interface
|
|
||||||
-------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Opens a shop interface for the player.
|
|
||||||
---
|
|
||||||
--- Checks job/gang restrictions, then uses the active inventory system to open the shop.
|
|
||||||
--- @param data table Contains:
|
|
||||||
--- - shop (`string`) The shop identifier.
|
|
||||||
--- - items (`table`) The items available in the shop.
|
|
||||||
--- - coords (`vector3`) where the shop is located.
|
|
||||||
--- - job/gang (optional) (`string`) Job or gang requirements.
|
|
||||||
---@usage
|
|
||||||
--- ```lua
|
|
||||||
--- openShop({
|
|
||||||
--- shop = "weapon_shop",
|
|
||||||
--- items = weaponShopItems,
|
|
||||||
--- coords = vector3(100.0, 200.0, 300.0),
|
|
||||||
--- job = "police",
|
|
||||||
--- })
|
|
||||||
--- ```
|
|
||||||
function openShop(data)
|
|
||||||
if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end
|
|
||||||
|
|
||||||
if isStarted(OXInv) then
|
|
||||||
exports[OXInv]:openInventory('shop', { type = data.shop })
|
|
||||||
|
|
||||||
elseif isStarted(QBInv) then
|
|
||||||
if QBInvNew then
|
|
||||||
TriggerServerEvent(getScript()..':server:OpenShopNewQB', data.shop)
|
|
||||||
else
|
|
||||||
TriggerServerEvent(Config.General.JimShops and "jim-shops:ShopOpen" or "inventory:server:OpenInventory", "shop", data.items.label, data.items)
|
|
||||||
end
|
|
||||||
|
|
||||||
--elseif isStarted(OrigenInv) then -- Needs testing, not sure if i did this right
|
|
||||||
-- exports[OrigenInv]:openInventory('shop', data.shop, data.items)
|
|
||||||
|
|
||||||
else
|
|
||||||
TriggerServerEvent(Config.General.JimShops and "jim-shops:ShopOpen" or "inventory:server:OpenInventory", "shop", data.items.label, data.items)
|
|
||||||
end
|
|
||||||
lookEnt(data.coords)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Server event handler for opening a shop using the new QB inventory system.
|
|
||||||
RegisterNetEvent(getScript()..':server:OpenShopNewQB', function(data)
|
|
||||||
exports[QBInv]:OpenShop(source, data)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
|
||||||
-- Server Callback Registration
|
|
||||||
-------------------------------------------------------------
|
|
||||||
if isServer() then
|
|
||||||
createCallback(getScript()..':server:canCarry', function(source, itemTable) local result = canCarry(itemTable, source) return result end)
|
|
||||||
end
|
|
||||||
@@ -515,6 +515,37 @@ function ensureNetToEnt(entNetID)
|
|||||||
return entity
|
return entity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function sendLog(text)
|
||||||
|
local Player = getPlayer()
|
||||||
|
local coords = GetEntityCoords(PlayerPedId())
|
||||||
|
local _, _, _, hour, min, sec = GetLocalTime()
|
||||||
|
local data = {
|
||||||
|
script = debug.getinfo(2, "nSl"),
|
||||||
|
coords = coords,
|
||||||
|
localTime = { hour = hour, min = min, sec = sec },
|
||||||
|
firstname = Player.firstname,
|
||||||
|
lastname = Player.lastname,
|
||||||
|
source = Player.source,
|
||||||
|
id = Player.citizenId,
|
||||||
|
text = text,
|
||||||
|
}
|
||||||
|
|
||||||
|
debugPrint("^5Log Message^7: "..getScript().." - "..Player.firstname.." "..Player.lastname.."("..Player.source..") ["..Player.citizenId.."]", text)
|
||||||
|
TriggerServerEvent(getScript()..":server:sendlog", data)
|
||||||
|
end
|
||||||
|
|
||||||
|
function sendServerLog(data)
|
||||||
|
local hour, min, sec = os.date('%H'), os.date('%M'), os.date('%S')
|
||||||
|
data.serverTime = { house = hour, min = min, sec = sec }
|
||||||
|
--jsonPrint(data)
|
||||||
|
debugPrint("^5Log Message^7: "..getScript().." - "..data.firstname.." "..data.lastname.."("..data.source..") ["..data.id.."]", data.text)
|
||||||
|
|
||||||
|
-- Add your logger here
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent(getScript()..":server:sendlog", sendServerLog)
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Material and Prop Functions
|
-- Material and Prop Functions
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|||||||
@@ -97,13 +97,34 @@ function createInput(title, opts)
|
|||||||
default = opts[i].default,
|
default = opts[i].default,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
if opts[i].type == "slider" then
|
||||||
|
options[currentNum] = {
|
||||||
|
type = opts[i].type,
|
||||||
|
label = opts[i].label,
|
||||||
|
isRequired = opts[i].required,
|
||||||
|
min = opts[i].min,
|
||||||
|
max = opts[i].max,
|
||||||
|
default = opts[i].default,
|
||||||
|
}
|
||||||
|
end
|
||||||
::skip::
|
::skip::
|
||||||
end
|
end
|
||||||
dialog = exports[OXLibExport]:inputDialog(title, options)
|
dialog = exports[OXLibExport]:inputDialog(title, options)
|
||||||
return dialog
|
return dialog
|
||||||
elseif Config.System.Menu == "qb" then
|
elseif Config.System.Menu == "qb" then
|
||||||
dialog = exports['qb-input']:ShowInput({ header = title, submitText = "Accept", inputs = opts })
|
for k, v in pairs(opts) do
|
||||||
|
currentNum += 1
|
||||||
|
if opts[k] == nil then
|
||||||
|
currentNum -= 1
|
||||||
|
else
|
||||||
|
options[currentNum] = opts[k]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dialog = exports['qb-input']:ShowInput(
|
||||||
|
{ header = title, submitText = "Accept", inputs = options }
|
||||||
|
)
|
||||||
return dialog
|
return dialog
|
||||||
|
|
||||||
elseif Config.System.Menu == "gta" then
|
elseif Config.System.Menu == "gta" then
|
||||||
WarMenu.CreateMenu(tostring(opts),
|
WarMenu.CreateMenu(tostring(opts),
|
||||||
title,
|
title,
|
||||||
|
|||||||
@@ -59,7 +59,11 @@ function hasItem(items, amount, src)
|
|||||||
debugPrint(foundMessage)
|
debugPrint(foundMessage)
|
||||||
hasTable[item] = { hasItem = count >= amt, count = count }
|
hasTable[item] = { hasItem = count >= amt, count = count }
|
||||||
end
|
end
|
||||||
for k, v in pairs(hasTable) do if not v.hasItem then return false, hasTable end end
|
for k, v in pairs(hasTable) do
|
||||||
|
if not v.hasItem then
|
||||||
|
return false, hasTable
|
||||||
|
end
|
||||||
|
end
|
||||||
return true, hasTable
|
return true, hasTable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
• Granting random rewards from a reward pool.
|
• Granting random rewards from a reward pool.
|
||||||
• Checking if a player can carry specific items based on weight.
|
• Checking if a player can carry specific items based on weight.
|
||||||
]]
|
]]
|
||||||
|
validTokens = {}
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Registering Usable Items
|
-- Registering Usable Items
|
||||||
@@ -74,7 +75,7 @@ function invImg(item)
|
|||||||
elseif isStarted(QBInv) then
|
elseif isStarted(QBInv) then
|
||||||
imgLink = "nui://"..QBInv.."/html/images/"..(Items[item].image or "")
|
imgLink = "nui://"..QBInv.."/html/images/"..(Items[item].image or "")
|
||||||
else
|
else
|
||||||
print("^4ERROR^7: ^2No Inventory detected for invImg - Check exports.lua")
|
print("^4ERROR^7: ^2No Inventory detected for invImg - Check starter.lua")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return imgLink
|
return imgLink
|
||||||
@@ -103,7 +104,8 @@ function addItem(item, amount, info, src)
|
|||||||
if src then
|
if src then
|
||||||
TriggerEvent(getScript()..":server:toggleItem", true, item, amount, src, info)
|
TriggerEvent(getScript()..":server:toggleItem", true, item, amount, src, info)
|
||||||
else
|
else
|
||||||
TriggerServerEvent(getScript()..":server:toggleItem", true, item, amount, nil, info)
|
TriggerServerEvent(getScript()..":server:toggleItem", true, item, amount, currentToken, info)
|
||||||
|
currentToken = nil -- clear client cached token
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -159,7 +161,25 @@ RegisterNetEvent(getScript()..":server:toggleItem", function(give, item, amount,
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local src = newsrc or source
|
local src = source or newsrc
|
||||||
|
if (give == true or give == 1) then
|
||||||
|
if newsrc == nil then -- must be coming from client this would be blank
|
||||||
|
debugPrint("^1Auth^7: ^1No token recieved^7")
|
||||||
|
dupeWarn(src, item, "Auth: Player "..src.." attempted to spawn "..item.." without an auth token")
|
||||||
|
else
|
||||||
|
if type(newsrc) ~= "number" then -- checks if the newsrc is a source or token, if number its coming form the server itself
|
||||||
|
debugPrint("^1Auth^7: ^2Auth token received^7, ^2checking against server cache^7..")
|
||||||
|
if newsrc ~= validTokens[src] then
|
||||||
|
debugPrint("^1Auth^7: ^1Tokens don't match! ^7", newsrc, validTokens[src])
|
||||||
|
dupeWarn(src, item, "Auth: "..src.." attempted to spawn "..item.." with an incorrect auth token")
|
||||||
|
else
|
||||||
|
debugPrint("^1Auth^7: ^2Client and Server Auth tokens match^7!", newsrc, validTokens[src])
|
||||||
|
validTokens[src] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local action = (tostring(give) == "true" and "addItem" or "removeItem")
|
local action = (tostring(give) == "true" and "addItem" or "removeItem")
|
||||||
local remamount = amount or 1
|
local remamount = amount or 1
|
||||||
if item == nil then return end
|
if item == nil then return end
|
||||||
@@ -599,4 +619,62 @@ function canCarry(itemTable, src)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return resultTable
|
return resultTable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
-- Server Callback Registration
|
||||||
|
-------------------------------------------------------------
|
||||||
|
currentToken = nil
|
||||||
|
if isServer() then
|
||||||
|
createCallback(getScript()..":server:canCarry", function(source, itemTable)
|
||||||
|
local result = canCarry(itemTable, source)
|
||||||
|
return result
|
||||||
|
end)
|
||||||
|
|
||||||
|
local AuthEvent = getScript()..":"..keyGen()..keyGen()..keyGen()..keyGen()..":"..keyGen()..keyGen()..keyGen()..keyGen()
|
||||||
|
validTokens = validTokens or {}
|
||||||
|
|
||||||
|
createCallback(AuthEvent, function(source)
|
||||||
|
local src = source
|
||||||
|
local token = keyGen()..keyGen()..keyGen()..keyGen() -- Use a secure random generator here
|
||||||
|
debugPrint("^1Auth^7:^2 Player Source^7: "..src.." ^2requested new token^7:", token)
|
||||||
|
validTokens[src] = token
|
||||||
|
timeOutAuth(validTokens[src], src) -- Give script 10 seconds, then clear token
|
||||||
|
return token
|
||||||
|
end)
|
||||||
|
|
||||||
|
function timeOutAuth(token, src)
|
||||||
|
local token = token
|
||||||
|
SetTimeout(10000, function()
|
||||||
|
if token == validTokens[src] then
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
print("^7Clearing token for player ^1"..src.."^7", token)
|
||||||
|
print("^7This shouldn't happen unless a token has been called by a player or script and it hasn't been used")
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent(getScript()..":clearAuthToken", function()
|
||||||
|
local src = source
|
||||||
|
debugPrint("^1Auth^7: ^2Manually removing token for Player Source^7:", src, validTokens[src])
|
||||||
|
validTokens[src] = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
receivedEvent = {}
|
||||||
|
createCallback(getScript()..":callback:GetAuthEvent", function(source)
|
||||||
|
local src = source
|
||||||
|
debugPrint("^1Auth^7: ^2Player Source^7: "..src.." ^2requested ^3AuthEvent^7", AuthEvent)
|
||||||
|
if not receivedEvent[src] then receivedEvent[src] = true
|
||||||
|
return AuthEvent
|
||||||
|
else
|
||||||
|
print("^1Auth^7: ^1Player ^7"..src.." ^1tried to request auth token more than once^7")
|
||||||
|
return ""
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
onResourceStart(function()
|
||||||
|
debugPrint("^1Auth^7: ^2Requesting ^3Auth Event^7")
|
||||||
|
AuthEvent = triggerCallback(getScript()..":callback:GetAuthEvent")
|
||||||
|
end, true)
|
||||||
|
end
|
||||||
|
|||||||
@@ -22,15 +22,21 @@ function createTempCam(ent, coords)
|
|||||||
triggerNotify(nil, "ModCam Created", "success")
|
triggerNotify(nil, "ModCam Created", "success")
|
||||||
end
|
end
|
||||||
local camCoords = nil
|
local camCoords = nil
|
||||||
|
local pointCoords = nil
|
||||||
if type(ent) ~= "vector3" then
|
if type(ent) ~= "vector3" then
|
||||||
camCoords = GetOffsetFromEntityInWorldCoords(ent, 1.0, -0.3, 0.8)
|
camCoords = GetOffsetFromEntityInWorldCoords(ent, 1.0, -0.3, 0.8)
|
||||||
else
|
else
|
||||||
camCoords = ent
|
camCoords = ent
|
||||||
end
|
end
|
||||||
-- Create the camera with specified parameters
|
|
||||||
cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z + 0.5, 1.0, 0.0, 0.0, 60.00, false, 0)
|
cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z + 0.5, 1.0, 0.0, 0.0, 60.00, false, 0)
|
||||||
-- Point the camera at the target coordinates
|
|
||||||
PointCamAtCoord(cam, coords)
|
if type(coords) == "number" then
|
||||||
|
SetCamCoord(cam, GetCamCoord(cam) + vec3(0, 0, 1.0))
|
||||||
|
PointCamAtEntity(cam, coords)
|
||||||
|
else
|
||||||
|
PointCamAtCoord(cam, coords)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return cam
|
return cam
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -137,11 +137,11 @@ end
|
|||||||
--- ```
|
--- ```
|
||||||
function loadScriptBank(bank)
|
function loadScriptBank(bank)
|
||||||
local timeout = 2000
|
local timeout = 2000
|
||||||
debugPrint("^6Debug^7: ^2Loading ^3Script ^2AudioBank^7...")
|
debugPrint("^6Bridge^7: ^2Loading ^3Script ^2AudioBank^7...")
|
||||||
while not RequestScriptAudioBank(bank, 0) do Wait(10) timeout -= 10 if timeout <= 0 then break end end
|
while not RequestScriptAudioBank(bank, false) do Wait(10) timeout -= 10 if timeout <= 0 then break end end
|
||||||
|
|
||||||
local success = RequestScriptAudioBank(bank, 0)
|
local success = RequestScriptAudioBank(bank, false)
|
||||||
debugPrint("^6Debug^7: "..(success and "^3Successfully ^2loaded^7: '^4" or "^1Failed to ^2load^7: '^4")..bank.."^7'")
|
debugPrint("^6Bridge^7: "..(success and "^3Successfully ^2loaded^7: '^4" or "^1Failed to ^2load^7: '^4")..bank.."^7'")
|
||||||
return success
|
return success
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -159,14 +159,14 @@ end
|
|||||||
--- ```
|
--- ```
|
||||||
function loadAmbientBank(bank)
|
function loadAmbientBank(bank)
|
||||||
local timeout = 2000
|
local timeout = 2000
|
||||||
debugPrint("^6Debug^7: ^2Loading ^3Ambient ^2AudioBank^7...")
|
debugPrint("^6Bridge^7: ^2Loading ^3Ambient ^2AudioBank^7...")
|
||||||
while not RequestAmbientAudioBank(bank, 0) do
|
while not RequestAmbientAudioBank(bank, 0) do
|
||||||
Wait(10)
|
Wait(10)
|
||||||
timeout -= 10
|
timeout -= 10
|
||||||
if timeout <= 0 then break end
|
if timeout <= 0 then break end
|
||||||
end
|
end
|
||||||
local success = RequestAmbientAudioBank(bank, 0)
|
local success = RequestAmbientAudioBank(bank, 0)
|
||||||
debugPrint("^6Debug^7: "..(success and "^3Successfully ^2loaded^7: '^4" or "^1Failed to ^2load^7: '^4")..bank.."^7'")
|
debugPrint("^6Bridge^7: "..(success and "^3Successfully ^2loaded^7: '^4" or "^1Failed to ^2load^7: '^4")..bank.."^7'")
|
||||||
return success
|
return success
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -224,16 +224,18 @@ end
|
|||||||
--- ```lua
|
--- ```lua
|
||||||
--- playGameSound('DLC_HEIST_HACKING_SNAKE_SOUNDS', 'Beep', vector3(0, 0, 0), false, 15.0)
|
--- playGameSound('DLC_HEIST_HACKING_SNAKE_SOUNDS', 'Beep', vector3(0, 0, 0), false, 15.0)
|
||||||
--- ```
|
--- ```
|
||||||
function playGameSound(bank, sound, coords, synced, range)
|
function playGameSound(audioBank, soundSet, soundRef, coords, synced, range)
|
||||||
debugPrint("^6Debug^7: ^2Attempting to play: ^3"..sound.." ^7(^4"..bank.."^7')")
|
debugPrint("^6Bridge^7: ^2Attempting to play: ^3"..soundRef.." ^7('^4"..audioBank.."^7')")
|
||||||
|
loadScriptBank(audioBank)
|
||||||
local range = range or 10.0
|
local range = range or 10.0
|
||||||
local soundId = GetSoundId()
|
local soundId = GetSoundId()
|
||||||
while not soundId do Wait(10) end
|
while not soundId do Wait(10) end
|
||||||
if type(coords) == "vector3" or type(coords) == "vector4" then
|
if type(coords) == "vector3" or type(coords) == "vector4" then
|
||||||
debugPrint("^6Debug^7: ^2Playing sound from Coord^7: "..formatCoord(coords.xyz))
|
debugPrint("^6Bridge^7: ^2Playing sound from Coord^7: "..formatCoord(coords.xyz))
|
||||||
PlaySoundFromCoord(soundId, sound, coords.x, coords.y, coords.z, bank, synced, range, 0)
|
PlaySoundFromCoord(soundId, soundRef, coords.x, coords.y, coords.z, soundSet, synced, range, 0)
|
||||||
else
|
else
|
||||||
debugPrint("^6Debug^7: ^2Playing sound from Entity^7: ^4"..coords.."^7")
|
debugPrint("^6Bridge^7: ^2Playing sound from Entity^7: ^4"..coords.."^7")
|
||||||
PlaySoundFromEntity(soundId, sound, coords, bank, synced, 0)
|
PlaySoundFromEntity(soundId, soundRef, coords, soundSet, synced, 1.0)
|
||||||
end
|
end
|
||||||
|
ReleaseScriptAudioBank(audioBank)
|
||||||
end
|
end
|
||||||
@@ -31,6 +31,60 @@ function makeVeh(model, coords)
|
|||||||
return veh
|
return veh
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local distanceVehicles = {}
|
||||||
|
--- Creates a vehicle that spawns when the player enters a designated polyzone area.
|
||||||
|
---
|
||||||
|
--- This function sets up a circular polyzone; when the player enters the zone, the vehicle is spawned,
|
||||||
|
--- and when the player exits, the vehicle is deleted.
|
||||||
|
---
|
||||||
|
---@param data table A table containing vehicle data.
|
||||||
|
--- - **vehicle** `string`: The model name or hash of the vehicle to spawn.
|
||||||
|
--- - **coords** `vector4`: The coordinates where the vehicle will be placed. Should include x, y, z, and w (heading).
|
||||||
|
---@param freeze boolean (optional) Whether to freeze the vehicle in place. Defaults to `false`.
|
||||||
|
---@param synced boolean (optional) Whether the vehicle should be synced across clients. Defaults to `false`.
|
||||||
|
function makeDistVehicle(data, radius, onEnter, onExit)
|
||||||
|
local vehicle = nil
|
||||||
|
local zoneId = keyGen() .. keyGen()
|
||||||
|
local zone = createCirclePoly({
|
||||||
|
name = zoneId,
|
||||||
|
coords = vec3(data.coords.x, data.coords.y, data.coords.z),
|
||||||
|
radius = radius,
|
||||||
|
onEnter = function()
|
||||||
|
vehicle = makeVeh(data.model, data.coords)
|
||||||
|
if onEnter then
|
||||||
|
debugPrint("makeDistVehicle onEnter running")
|
||||||
|
onEnter(vehicle)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
onExit = function()
|
||||||
|
deleteVehicle(vehicle)
|
||||||
|
if onExit then
|
||||||
|
debugPrint("makeDistVehicle onExit running")
|
||||||
|
onExit(vehicle)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
debug = debugMode,
|
||||||
|
})
|
||||||
|
distanceVehicles[zoneId] = { zone = zone, vehicle = vehicle }
|
||||||
|
return zoneId
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Removes a specific distance-based vehicle spawning zone.
|
||||||
|
---
|
||||||
|
---@param zoneId string The unique identifier of the zone to remove.
|
||||||
|
function removeDistVehicleZone(zoneId)
|
||||||
|
if distanceVehicles[zoneId].zone then
|
||||||
|
removePolyZone(distanceVehicles[zoneId].zone) -- Adjust this if your polyzone library uses a different removal method.
|
||||||
|
if distanceVehicles[zoneId].vehicle then
|
||||||
|
deleteVehicle(distanceVehicles[zoneId].vehicle)
|
||||||
|
end
|
||||||
|
distanceVehicles[zoneId] = nil
|
||||||
|
print("Removed polyzone for zoneId: " .. zoneId)
|
||||||
|
else
|
||||||
|
print("No zone found with zoneId: " .. zoneId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Attempts to gain network control of a vehicle and set it as a mission entity.
|
--- Attempts to gain network control of a vehicle and set it as a mission entity.
|
||||||
---
|
---
|
||||||
--- This function forces synchronization of a vehicle with other players by requesting network control and setting the vehicle as a mission entity.
|
--- This function forces synchronization of a vehicle with other players by requesting network control and setting the vehicle as a mission entity.
|
||||||
@@ -67,6 +121,20 @@ function pushVehicle(entity)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Deletes a spawned vehicle.
|
||||||
|
---
|
||||||
|
---@param vehicle number The handle of the vehicle entity to delete.
|
||||||
|
function deleteVehicle(vehicle)
|
||||||
|
if vehicle then
|
||||||
|
debugPrint("^6Bridge^7: ^2Destroying Vehicle^7: '^6" .. vehicle .. "^7'")
|
||||||
|
if IsEntityAttachedToEntity(vehicle, PlayerPedId()) then
|
||||||
|
SetEntityAsMissionEntity(vehicle)
|
||||||
|
DetachEntity(vehicle, true, true)
|
||||||
|
end
|
||||||
|
DeleteVehicle(vehicle)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Cleans up all created vehicles when the resource stops.
|
--- Cleans up all created vehicles when the resource stops.
|
||||||
onResourceStop(function(r)
|
onResourceStop(function(r)
|
||||||
for i = 1, #Vehicles do DeleteVehicle(Vehicles[i]) end
|
for i = 1, #Vehicles do DeleteVehicle(Vehicles[i]) end
|
||||||
|
|||||||
@@ -220,7 +220,6 @@ function fundPlayer(fund, moneyType, newsrc)
|
|||||||
debugPrint("^6Bridge^7: ^2Funding Player: '^2"..fund.."^7'", moneyType, fundResource)
|
debugPrint("^6Bridge^7: ^2Funding Player: '^2"..fund.."^7'", moneyType, fundResource)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
RegisterNetEvent(getScript()..":server:FundPlayer", fundPlayer)
|
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Item Consumption & Effects
|
-- Item Consumption & Effects
|
||||||
@@ -458,7 +457,7 @@ function getPlayer(source)
|
|||||||
--gangBoss = info.gang.isboss,
|
--gangBoss = info.gang.isboss,
|
||||||
onDuty = info.job.onDuty,
|
onDuty = info.job.onDuty,
|
||||||
--account = info.charinfo.account,
|
--account = info.charinfo.account,
|
||||||
--citizenId = info.citizenid,
|
citizenId = info.citizenid,
|
||||||
}
|
}
|
||||||
|
|
||||||
elseif isStarted(OXCoreExport) then
|
elseif isStarted(OXCoreExport) then
|
||||||
@@ -468,9 +467,20 @@ function getPlayer(source)
|
|||||||
chunk()
|
chunk()
|
||||||
local player = Ox.GetPlayer(src)
|
local player = Ox.GetPlayer(src)
|
||||||
Player = {
|
Player = {
|
||||||
|
firstname = player.firstName,
|
||||||
|
lastname = player.lastName ,
|
||||||
name = ('%s %s'):format(player.firstName, player.lastName),
|
name = ('%s %s'):format(player.firstName, player.lastName),
|
||||||
cash = exports[OXInv]:Search(src, 'count', "money"),
|
cash = exports[OXInv]:Search(src, 'count', "money"),
|
||||||
bank = 0,
|
bank = 0,
|
||||||
|
source = src,
|
||||||
|
--job = OxPlayer.getGroups(),
|
||||||
|
--jobBoss = info.job.isboss,
|
||||||
|
--gang = OxPlayer.getGroups(),
|
||||||
|
--gangBoss = info.gang.isboss,
|
||||||
|
--onDuty = info.job.onduty,
|
||||||
|
--account = info.charinfo.account,
|
||||||
|
citizenId = player.stateId,
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif isStarted(QBXExport) then
|
elseif isStarted(QBXExport) then
|
||||||
local info = exports[QBXExport]:GetPlayer(src)
|
local info = exports[QBXExport]:GetPlayer(src)
|
||||||
@@ -513,7 +523,7 @@ function getPlayer(source)
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("^4ERROR^7: ^2No Core detected for getPlayer() - Check exports.lua")
|
print("^4ERROR^7: ^2No Core detected for getPlayer() - Check starter.lua")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- Client-side: Get current player info.
|
-- Client-side: Get current player info.
|
||||||
@@ -527,7 +537,9 @@ function getPlayer(source)
|
|||||||
Player = {
|
Player = {
|
||||||
firstname = info.firstName,
|
firstname = info.firstName,
|
||||||
lastname = info.lastName,
|
lastname = info.lastName,
|
||||||
|
name = info.firstName.." "..info.lastName,
|
||||||
|
cash = cash,
|
||||||
|
bank = bank,
|
||||||
source = GetPlayerServerId(PlayerId()),
|
source = GetPlayerServerId(PlayerId()),
|
||||||
job = info.job.name,
|
job = info.job.name,
|
||||||
--jobBoss = info.job.isboss,
|
--jobBoss = info.job.isboss,
|
||||||
@@ -535,30 +547,23 @@ function getPlayer(source)
|
|||||||
--gangBoss = info.gang.isboss,
|
--gangBoss = info.gang.isboss,
|
||||||
onDuty = info.job.onDuty,
|
onDuty = info.job.onDuty,
|
||||||
--account = info.charinfo.account,
|
--account = info.charinfo.account,
|
||||||
--citizenId = info.citizenid,
|
citizenId = info.identifier,
|
||||||
|
|
||||||
name = info.firstName.." "..info.lastName,
|
|
||||||
cash = cash,
|
|
||||||
bank = bank,
|
|
||||||
}
|
}
|
||||||
elseif isStarted(OXCoreExport) then
|
elseif isStarted(OXCoreExport) then
|
||||||
--local info = exports[OXCoreExport]:GetPlayerData()
|
|
||||||
|
|
||||||
Player = {
|
Player = {
|
||||||
firstname = OxPlayer.get("firstName"),
|
firstname = OxPlayer.get("firstName"),
|
||||||
lastname = OxPlayer.get("lastName"),
|
lastname = OxPlayer.get("lastName"),
|
||||||
name = OxPlayer.get("firstName").." "..OxPlayer.get("lastName"),
|
name = OxPlayer.get("firstName").." "..OxPlayer.get("lastName"),
|
||||||
cash = exports[OXInv]:Search('count', "money"),
|
cash = exports[OXInv]:Search('count', "money"),
|
||||||
bank = 0,
|
bank = 0,
|
||||||
--source = info.source,
|
source = GetPlayerServerId(PlayerId()),
|
||||||
job = OxPlayer.getGroups(),
|
job = OxPlayer.getGroups(),
|
||||||
--jobBoss = info.job.isboss,
|
--jobBoss = info.job.isboss,
|
||||||
gang = OxPlayer.getGroups(),
|
gang = OxPlayer.getGroups(),
|
||||||
--gangBoss = info.gang.isboss,
|
--gangBoss = info.gang.isboss,
|
||||||
--onDuty = info.job.onduty,
|
--onDuty = info.job.onduty,
|
||||||
--account = info.charinfo.account,
|
--account = info.charinfo.account,
|
||||||
citizenId = OxPlayer.get("stateId"),
|
citizenId = OxPlayer.userId,
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif isStarted(QBXExport) then
|
elseif isStarted(QBXExport) then
|
||||||
local info = exports[QBXExport]:GetPlayerData()
|
local info = exports[QBXExport]:GetPlayerData()
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ function debugScaleForm(textTable, loc)
|
|||||||
local size = vec2(0.18, totalHeight + boxPadding * 2)
|
local size = vec2(0.18, totalHeight + boxPadding * 2)
|
||||||
|
|
||||||
-- Draw background rectangle.
|
-- Draw background rectangle.
|
||||||
DrawRect(loc.x + size.x / 2, loc.y + size.y / 2, size.x, size.y, 0, 0, 0, 255)
|
DrawRect(loc.x + size.x / 2, loc.y + size.y / 2, size.x, size.y, 0, 0, 0, 200)
|
||||||
|
|
||||||
-- Render each line of text.
|
-- Render each line of text.
|
||||||
for i = 1, #textTable do
|
for i = 1, #textTable do
|
||||||
|
|||||||
206
shared/shops.lua
Normal file
206
shared/shops.lua
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
-------------------------------------------------------------
|
||||||
|
-- Selling Menu and Animation
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Opens a selling menu with available items and prices.
|
||||||
|
---
|
||||||
|
--- @param data table Contains selling menu data:
|
||||||
|
--- - sellTable (`table`) Table with Header and Items (item names and prices).
|
||||||
|
--- - ped (optional) (`number`) Ped entity involved.
|
||||||
|
--- - onBack (optional) (`function`) Callback for returning.
|
||||||
|
--- @usage
|
||||||
|
--- ```lua
|
||||||
|
--- sellMenu({
|
||||||
|
--- sellTable = {
|
||||||
|
--- Header = "Sell Items",
|
||||||
|
--- Items = {
|
||||||
|
--- ["gold_ring"] = 100,
|
||||||
|
--- ["diamond"] = 500,
|
||||||
|
--- },
|
||||||
|
--- },
|
||||||
|
--- ped = pedEntity,
|
||||||
|
--- onBack = function() print("Returning to previous menu") end,
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
function sellMenu(data)
|
||||||
|
local origData = data
|
||||||
|
local Menu = {}
|
||||||
|
if data.sellTable.Items then
|
||||||
|
local itemList = {}
|
||||||
|
for k, v in pairs(data.sellTable.Items) do itemList[k] = 1 end
|
||||||
|
local _, hasTable = hasItem(itemList)
|
||||||
|
for k, v in pairsByKeys(data.sellTable.Items) do
|
||||||
|
Menu[#Menu + 1] = {
|
||||||
|
isMenuHeader = not hasTable[k].hasItem,
|
||||||
|
icon = invImg(k),
|
||||||
|
header = Items[k].label..(hasTable[k].hasItem and "💰 (x"..hasTable[k].count..")" or ""),
|
||||||
|
txt = Loc[Config.Lan].info["sell_all"]..v.." "..Loc[Config.Lan].info["sell_each"],
|
||||||
|
onSelect = function()
|
||||||
|
sellAnim({ item = k, price = v, ped = data.ped, onBack = function() sellMenu(data) end })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for k, v in pairsByKeys(data.sellTable) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
Menu[#Menu + 1] = {
|
||||||
|
arrow = true,
|
||||||
|
header = k,
|
||||||
|
txt = "Amount of items: "..countTable(v.Items),
|
||||||
|
onSelect = function()
|
||||||
|
v.onBack = function() sellMenu(origData) end
|
||||||
|
v.sellTable = data.sellTable[k]
|
||||||
|
sellMenu(v)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
openMenu(Menu, {
|
||||||
|
header = data.sellTable.Header or "Amount of items: "..countTable(data.sellTable.Items),
|
||||||
|
headertxt = data.sellTable.Header and "Amount of items: "..countTable(data.sellTable.Items) or "",
|
||||||
|
canClose = true,
|
||||||
|
onBack = data.onBack,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Plays the selling animation and processes the sale transaction.
|
||||||
|
---
|
||||||
|
--- Checks if the player has the item, plays animations, triggers the server event for selling,
|
||||||
|
--- and then calls the onBack callback if provided.
|
||||||
|
---
|
||||||
|
--- @param data table Contains:
|
||||||
|
--- `- item: The item to sell.
|
||||||
|
--- `- price: Price per item.
|
||||||
|
--- `- ped (optional): Ped entity involved.
|
||||||
|
--- `- onBack (optional): Callback to call on completion.
|
||||||
|
---@usage
|
||||||
|
--- ```lua
|
||||||
|
--- sellAnim({
|
||||||
|
--- item = "gold_ring",
|
||||||
|
--- price = 100,
|
||||||
|
--- ped = pedEntity,
|
||||||
|
--- onBack = function() sellMenu(data) end,
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
function sellAnim(data)
|
||||||
|
if not hasItem(data.item, 1) then
|
||||||
|
triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove any attached clipboard objects.
|
||||||
|
for _, obj in pairs(GetGamePool('CObject')) do
|
||||||
|
for _, model in pairs({ `p_cs_clipboard` }) do
|
||||||
|
if GetEntityModel(obj) == model and IsEntityAttachedToEntity(data.ped, obj) then
|
||||||
|
DeleteObject(obj)
|
||||||
|
DetachEntity(obj, 0, 0)
|
||||||
|
SetEntityAsMissionEntity(obj, true, true)
|
||||||
|
Wait(100)
|
||||||
|
DeleteEntity(obj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
TriggerServerEvent(getScript().."Sellitems", data)
|
||||||
|
lookEnt(data.ped)
|
||||||
|
local dict = "mp_common"
|
||||||
|
playAnim(dict, "givetake2_a", 0.3, 2)
|
||||||
|
playAnim(dict, "givetake2_b", 0.3, 2, data.ped)
|
||||||
|
Wait(2000)
|
||||||
|
StopAnimTask(PlayerPedId(), dict, "givetake2_a", 0.5)
|
||||||
|
StopAnimTask(data.ped, dict, "givetake2_b", 0.5)
|
||||||
|
if data.onBack then data.onBack() end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Server event handler for processing item sales.
|
||||||
|
--- Removes sold items from inventory and funds the player based on the sale.
|
||||||
|
RegisterNetEvent(getScript().."Sellitems", function(data)
|
||||||
|
local src = source
|
||||||
|
local hasItems, hasTable = hasItem(data.item, 1, src)
|
||||||
|
if hasItems then
|
||||||
|
removeItem(data.item, hasTable[data.item].count, src)
|
||||||
|
fundPlayer((hasTable[data.item].count * data.price), "cash", src)
|
||||||
|
else
|
||||||
|
triggerNotify(nil, Loc[Config.Lan].error["dont_have"].." "..Items[data.item].label, "error", src)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-------------------------------------------------------------
|
||||||
|
-- Shop Interface
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Opens a shop interface for the player.
|
||||||
|
---
|
||||||
|
--- Checks job/gang restrictions, then uses the active inventory system to open the shop.
|
||||||
|
--- @param data table Contains:
|
||||||
|
--- - shop (`string`) The shop identifier.
|
||||||
|
--- - items (`table`) The items available in the shop.
|
||||||
|
--- - coords (`vector3`) where the shop is located.
|
||||||
|
--- - job/gang (optional) (`string`) Job or gang requirements.
|
||||||
|
---@usage
|
||||||
|
--- ```lua
|
||||||
|
--- openShop({
|
||||||
|
--- shop = "weapon_shop",
|
||||||
|
--- items = weaponShopItems,
|
||||||
|
--- coords = vector3(100.0, 200.0, 300.0),
|
||||||
|
--- job = "police",
|
||||||
|
--- })
|
||||||
|
--- ```
|
||||||
|
function openShop(data)
|
||||||
|
if (data.job or data.gang) and not jobCheck(data.job or data.gang) then return end
|
||||||
|
|
||||||
|
if isStarted(OXInv) then
|
||||||
|
exports[OXInv]:openInventory('shop', { type = data.shop })
|
||||||
|
|
||||||
|
elseif isStarted(QBInv) then
|
||||||
|
if QBInvNew then
|
||||||
|
TriggerServerEvent(getScript()..':server:OpenShopNewQB', data.shop)
|
||||||
|
else
|
||||||
|
TriggerServerEvent(Config.General.JimShops and "jim-shops:ShopOpen" or "inventory:server:OpenInventory", "shop", data.items.label, data.items)
|
||||||
|
end
|
||||||
|
|
||||||
|
--elseif isStarted(OrigenInv) then -- Needs testing, not sure if i did this right
|
||||||
|
-- exports[OrigenInv]:openInventory('shop', data.shop, data.items)
|
||||||
|
|
||||||
|
else
|
||||||
|
TriggerServerEvent(Config.General.JimShops and "jim-shops:ShopOpen" or "inventory:server:OpenInventory", "shop", data.items.label, data.items)
|
||||||
|
end
|
||||||
|
lookEnt(data.coords)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Server event handler for opening a shop using the new QB inventory system.
|
||||||
|
RegisterNetEvent(getScript()..':server:OpenShopNewQB', function(data)
|
||||||
|
exports[QBInv]:OpenShop(source, data)
|
||||||
|
end)
|
||||||
|
|
||||||
|
--- Registers a shop with the active inventory system.
|
||||||
|
--- Supports either OXInv or QBInv (with QBInvNew flag).
|
||||||
|
---
|
||||||
|
--- @param name string Unique shop identifier.
|
||||||
|
--- @param label string Display name for the shop.
|
||||||
|
--- @param items table List of available shop items.
|
||||||
|
--- @param society string|nil (Optional) Society identifier for shared shops.
|
||||||
|
--- @usage
|
||||||
|
--- ```lua
|
||||||
|
--- registerShop("weaponShop", "Weapon Shop", weaponItems, "society_weapons")
|
||||||
|
--- ```
|
||||||
|
function registerShop(name, label, items, society)
|
||||||
|
if isStarted(OXInv) then
|
||||||
|
debugPrint("^6Bridge^7: ^2Registering ^3OX ^2Store^7:", name, label)
|
||||||
|
exports[OXInv]:RegisterShop(name, {
|
||||||
|
name = label,
|
||||||
|
inventory = items,
|
||||||
|
society = society,
|
||||||
|
})
|
||||||
|
elseif isStarted(QBInv) and QBInvNew then
|
||||||
|
debugPrint("^6Bridge^7: ^2Registering ^3QB ^2Store^7:", name, label)
|
||||||
|
exports[QBInv]:CreateShop({
|
||||||
|
name = name,
|
||||||
|
label = label,
|
||||||
|
slots = #items,
|
||||||
|
items = items,
|
||||||
|
society = society,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
36
shared/skillcheck.lua
Normal file
36
shared/skillcheck.lua
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
|
||||||
|
function skillCheck(data)
|
||||||
|
local result = false
|
||||||
|
|
||||||
|
if Config.System.skillCheck == "qb" then
|
||||||
|
local Skillbar = exports["qb-minigames"]:Skillbar()
|
||||||
|
if Skillbar then
|
||||||
|
result = true
|
||||||
|
else
|
||||||
|
result = false
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif Config.System.skillCheck == "ox" then
|
||||||
|
local Skillbar = exports[OXLibExport]:skillCheck(
|
||||||
|
{
|
||||||
|
"easy",
|
||||||
|
"easy",
|
||||||
|
"easy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4"
|
||||||
|
})
|
||||||
|
if Skillbar then
|
||||||
|
result = true
|
||||||
|
else
|
||||||
|
result = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
result = true
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
@@ -99,7 +99,7 @@ function checkHasItem(stashes, itemTable)
|
|||||||
for item, amount in pairs(itemTable) do
|
for item, amount in pairs(itemTable) do
|
||||||
debugPrint("^6Bridge^7: ^2Checking "..(name and " '^3"..name.."^7'" or "").." ingredients - ^6"..item.."^7")
|
debugPrint("^6Bridge^7: ^2Checking "..(name and " '^3"..name.."^7'" or "").." ingredients - ^6"..item.."^7")
|
||||||
if stashhasItem(stashCache[name].items, item, amount) then
|
if stashhasItem(stashCache[name].items, item, amount) then
|
||||||
successes = successes + 1
|
successes += 1
|
||||||
if successes == itemCount then
|
if successes == itemCount then
|
||||||
return true, name
|
return true, name
|
||||||
end
|
end
|
||||||
@@ -271,7 +271,6 @@ function stashRemoveItem(stashItems, stashName, items)
|
|||||||
|
|
||||||
if isStarted(OXInv) then
|
if isStarted(OXInv) then
|
||||||
for k, v in pairs(items) do
|
for k, v in pairs(items) do
|
||||||
debugPrint("^6Bridge^7: ^2Removing item from ^3Stash^2 with ^7"..OXInv, k, v)
|
|
||||||
if type(stashName) == "table" then
|
if type(stashName) == "table" then
|
||||||
for _, name in pairs(stashName) do
|
for _, name in pairs(stashName) do
|
||||||
local success = exports[OXInv]:RemoveItem(name, k, v)
|
local success = exports[OXInv]:RemoveItem(name, k, v)
|
||||||
|
|||||||
@@ -119,9 +119,8 @@ function createEntityTarget(entity, opts, dist)
|
|||||||
item = opts[i].item or nil,
|
item = opts[i].item or nil,
|
||||||
groups = opts[i].job or opts[i].gang,
|
groups = opts[i].job or opts[i].gang,
|
||||||
onSelect = opts[i].action,
|
onSelect = opts[i].action,
|
||||||
canInteract = function(_, distance)
|
distance = dist,
|
||||||
return distance < dist and true or false
|
canInteract = opts[i].canInteract or nil,
|
||||||
end
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
exports[OXTargetExport]:addLocalEntity(entity, options)
|
exports[OXTargetExport]:addLocalEntity(entity, options)
|
||||||
@@ -223,9 +222,8 @@ function createBoxTarget(data, opts, dist)
|
|||||||
item = opts[i].item or nil,
|
item = opts[i].item or nil,
|
||||||
groups = opts[i].job or opts[i].gang,
|
groups = opts[i].job or opts[i].gang,
|
||||||
onSelect = opts[i].onSelect or opts[i].action,
|
onSelect = opts[i].onSelect or opts[i].action,
|
||||||
canInteract = function(_, distance)
|
distance = dist,
|
||||||
return distance < dist and true or false
|
canInteract = opts[i].canInteract or nil,
|
||||||
end
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
if not data[5].useZ then
|
if not data[5].useZ then
|
||||||
@@ -324,9 +322,8 @@ function createCircleTarget(data, opts, dist)
|
|||||||
item = opts[i].item or nil,
|
item = opts[i].item or nil,
|
||||||
groups = opts[i].job or opts[i].gang,
|
groups = opts[i].job or opts[i].gang,
|
||||||
onSelect = opts[i].onSelect or opts[i].action,
|
onSelect = opts[i].onSelect or opts[i].action,
|
||||||
canInteract = function(_, distance)
|
distance = dist,
|
||||||
return distance < dist
|
canInteract = opts[i].canInteract or nil,
|
||||||
end
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
local target = exports[OXTargetExport]:addSphereZone({
|
local target = exports[OXTargetExport]:addSphereZone({
|
||||||
@@ -385,9 +382,8 @@ function createModelTarget(models, opts, dist)
|
|||||||
item = opts[i].item or nil,
|
item = opts[i].item or nil,
|
||||||
groups = opts[i].job or opts[i].gang,
|
groups = opts[i].job or opts[i].gang,
|
||||||
onSelect = opts[i].action,
|
onSelect = opts[i].action,
|
||||||
canInteract = function(_, distance)
|
distance = dist,
|
||||||
return distance < dist and true or false
|
canInteract = opts[i].canInteract or nil,
|
||||||
end
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
exports[OXTargetExport]:addModel(models, options)
|
exports[OXTargetExport]:addModel(models, options)
|
||||||
|
|||||||
@@ -128,14 +128,15 @@ end
|
|||||||
function setVehicleProperties(vehicle, props)
|
function setVehicleProperties(vehicle, props)
|
||||||
if checkDifferences(vehicle, props) then
|
if checkDifferences(vehicle, props) then
|
||||||
if not DoesEntityExist(vehicle) then
|
if not DoesEntityExist(vehicle) then
|
||||||
print("Unable to set vehicle properties for '"..vehicle.."' (entity does not exist)")
|
print("Unable to set vehicle properties for '"..vehicle.."' (^1entity does not exist^7)")
|
||||||
end
|
end
|
||||||
|
|
||||||
if isStarted(QBExport) and not isStarted(QBXExport) then
|
if isStarted(QBExport) and not isStarted(QBXExport) then
|
||||||
Core.Functions.SetVehicleProperties(vehicle, props)
|
Core.Functions.SetVehicleProperties(vehicle, props)
|
||||||
debugPrint("^6Bridge^7: ^2Setting Vehicle Properties ^7[^6"..QBExport.."^7] - [^3"..vehicle.."^7] - [^3"..GetEntityModel(vehicle).."^7/^3"..props.model.."^7] - [^3"..props.plate.."^7]")
|
debugPrint("^6Bridge^7: ^2Setting Vehicle Properties ^7[^6"..QBExport.."^7] - [^3"..vehicle.."^7] - [^3"..GetEntityModel(vehicle).."^7/^3"..props.model.."^7] - [^3"..props.plate.."^7]")
|
||||||
else
|
elseif isStarted(OXLibExport) then
|
||||||
TriggerServerEvent(getScript()..":ox:setVehicleProperties", VehToNet(vehicle), props)
|
lib.setVehicleProperties(vehicle, props, false)
|
||||||
|
debugPrint("^6Bridge^7: ^2Setting Vehicle Properties ^7[^6"..OXLibExport.."^7] - [^3"..vehicle.."^7] - [^3"..GetEntityModel(vehicle).."^7/^3"..props.model.."^7] - [^3"..props.plate.."^7]")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
debugPrint("^6Bridge^7: ^2No Changes Found ^7 [^3"..vehicle.."^7] - [^3"..GetEntityModel(vehicle).."^7/^3"..props.model.."^7] - [^3"..props.plate.."^7]")
|
debugPrint("^6Bridge^7: ^2No Changes Found ^7 [^3"..vehicle.."^7] - [^3"..GetEntityModel(vehicle).."^7/^3"..props.model.."^7] - [^3"..props.plate.."^7]")
|
||||||
@@ -158,7 +159,7 @@ end
|
|||||||
function checkDifferences(vehicle, newProps)
|
function checkDifferences(vehicle, newProps)
|
||||||
local oldProps = getVehicleProperties(vehicle)
|
local oldProps = getVehicleProperties(vehicle)
|
||||||
debugPrint("^6Bridge^7: ^2Finding differences in ^3Vehicle Properties^7")
|
debugPrint("^6Bridge^7: ^2Finding differences in ^3Vehicle Properties^7")
|
||||||
local differencesFound = false
|
local differencesFound = true
|
||||||
|
|
||||||
for k in pairs(oldProps) do
|
for k in pairs(oldProps) do
|
||||||
if json.encode(oldProps[k]) ~= json.encode(newProps[k]) then
|
if json.encode(oldProps[k]) ~= json.encode(newProps[k]) then
|
||||||
@@ -199,7 +200,7 @@ AddStateBagChangeHandler(getScript()..':setVehicleProperties', '', function(bagN
|
|||||||
local networked = not bagName:find('localEntity')
|
local networked = not bagName:find('localEntity')
|
||||||
debugPrint("^6Bridge^7: ^2Setting Vehicle Properties ^7[^6"..OXLibExport.."^7] - [^3"..entity.."^7] - [^3"..GetEntityModel(entity).."^7] - [^3"..value.plate.."^7]")
|
debugPrint("^6Bridge^7: ^2Setting Vehicle Properties ^7[^6"..OXLibExport.."^7] - [^3"..entity.."^7] - [^3"..GetEntityModel(entity).."^7] - [^3"..value.plate.."^7]")
|
||||||
|
|
||||||
if networked and NetworkGetEntityOwner(entity) ~= cache.playerId then return end
|
if networked then return end
|
||||||
|
|
||||||
if lib.setVehicleProperties(entity, value) then
|
if lib.setVehicleProperties(entity, value) then
|
||||||
Entity(entity).state:set('setVehicleProperties', nil, true)
|
Entity(entity).state:set('setVehicleProperties', nil, true)
|
||||||
|
|||||||
@@ -119,7 +119,18 @@ if isServer() then
|
|||||||
--- ```lua
|
--- ```lua
|
||||||
--- TriggerEvent(getScript()..":server:makeOXStash", name, label, slots, weight, owner, coords)
|
--- TriggerEvent(getScript()..":server:makeOXStash", name, label, slots, weight, owner, coords)
|
||||||
--- ```
|
--- ```
|
||||||
RegisterNetEvent(getScript()..":server:makeOXStash", function(name, label, slots, weight, owner, coords)
|
RegisterNetEvent(getScript()..":server:makeOXStash", function(name, label, slots, weight, owner, coords, token)
|
||||||
|
local src = source or nil
|
||||||
|
if src then
|
||||||
|
debugPrint("^1Auth^7: ^2Auth token received^7, ^2checking against server cache^7..")
|
||||||
|
if token ~= validTokens[src] then
|
||||||
|
debugPrint("^1Auth^7: ^1Tokens don't match! ^7", token, validTokens[src])
|
||||||
|
else
|
||||||
|
debugPrint("^1Auth^7: ^2Client and Server Auth tokens match^7!", token, validTokens[src])
|
||||||
|
validTokens[src] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
registerStash(name, label, slots, weight, owner, coords)
|
registerStash(name, label, slots, weight, owner, coords)
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -71,9 +71,11 @@ for _, v in pairs({ -- This is a specific load order
|
|||||||
'input.lua',
|
'input.lua',
|
||||||
'notify.lua',
|
'notify.lua',
|
||||||
'drawText.lua',
|
'drawText.lua',
|
||||||
|
'skillcheck.lua',
|
||||||
|
|
||||||
-- Crafting / Shops / Stashes
|
-- Crafting / Shops / Stashes
|
||||||
'crafting.lua',
|
'crafting.lua',
|
||||||
|
'shops.lua',
|
||||||
'stashcontrol.lua',
|
'stashcontrol.lua',
|
||||||
|
|
||||||
-- Kind of "other"
|
-- Kind of "other"
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1.2
|
2.0
|
||||||
Reference in New Issue
Block a user