- UID
- 67
- 在线时间
- 小时
- 阅读权限
- 70
- 注册时间
- 2021-3-17
- 最后登录
- 1970-1-1
【高级】合伙人
|
为了让玩家在离开ATM或银行后菜单自动关闭,并确保ATM和银行具有相同的功能,我们需要修改代码来监测玩家与ATM和银行的距离。并在离开范围时关闭菜单。
### config.lua
Config = {}
-- 银行图标显示设置
Config.Banks = {
{name = "Bank 1", coords = vector3(150.1, -1040.1, 29.3)},
{name = "Bank 2", coords = vector3(-1212.98, -330.84, 37.78)}
-- 可以添加更多银行座标
}
-- ATM模型自动检测设置
Config.ATMModels = {
'prop_atm_01', 'prop_atm_02', 'prop_atm_03'
}
-- 银行卡 item 名称
Config.BankCardItem = "bank_card"
-- 转账金额选项
Config.TransferAmounts = {1000, 2000, 3000, 4000, 5000}
-- 贷款金额选项
Config.LoanAmounts = {1000, 2000, 3000, 4000, 5000} -- 可自定义金额
-- 最长贷款还款期限(月)
Config.MaxLoanMonths = 12
-- 每月利息(百分比)
Config.MonthlyInterestRate = 2
-- OX通知和UI设置
Config.Notification = function(msg)
exports.ox_lib:notify({type = 'success', description = msg})
end
-- 交互范围
Config.InteractDistance = 3.0
### server.lua
local ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
local playerLoans = {}
RegisterNetEvent('bank:transfer')
AddEventHandler('bank:transfer', function(targetId, targetCard, amount)
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
local tPlayer = ESX.GetPlayerFromId(targetId)
if xPlayer.getAccount('bank').money >= amount then
if hasBankCard(tPlayer, targetCard) then
xPlayer.removeAccountMoney('bank', amount)
tPlayer.addAccountMoney('bank', amount)
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'success', description = '转账成功!'})
TriggerClientEvent('ox_lib:notify', tPlayer.source, {type = 'info', description = '你收到了' .. amount .. '银行转账!'})
else
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'error', description = '目标玩家没有有效的银行卡!'})
end
else
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'error', description = '银行余额不足!'})
end
end)
RegisterNetEvent('bank:loan')
AddEventHandler('bank:loan', function(amount, months)
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if not isValidLoanAmount(amount) then
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'error', description = '无效的贷款金额.'})
return
end
if months < 1 or months > Config.MaxLoanMonths then
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'error', description = '无效的贷款期限.'})
return
end
local interest = (Config.MonthlyInterestRate / 100) * amount * months
local totalRepay = amount + interest
playerLoans[src] = {
amount = amount,
repay = totalRepay,
dueDate = os.time() + (months * 30 * 24 * 60 * 60) -- 以秒为单位计算
}
xPlayer.addAccountMoney('bank', amount)
TriggerClientEvent('ox_lib:notify', xPlayer.source, {type = 'success', description = '贷款成功! 总还款金额: ' .. totalRepay})
end)
ESX.RegisterServerCallback('bank:getLoanInfo', function(source, cb)
local src = source
cb(playerLoans[src])
end)
function hasBankCard(player, card)
return player.getInventoryItem(Config.BankCardItem).count > 0
end
function isValidLoanAmount(amount)
for _, v in ipairs(Config.LoanAmounts) do
if amount == v then
return true
end
end
return amount > 0
end
-- 定时检查贷款是否逾期
Citizen.CreateThread(function()
while true do
for src, loan in pairs(playerLoans) do
if os.time() > loan.dueDate then
TriggerClientEvent('ox_lib:notify', src, {type = 'error', description = '贷款已逾期,请尽快还款!'})
-- 可以在此增加进一步处理逾期贷款的逻辑
end
end
Citizen.Wait(60000) -- 每分钟检查一次
end
end)
### client.lua
local ESX = nil
local isNearATM = false
local isNearBank = false
local menuOpen = false
Citizen.CreateThread(function()
while ESX == nil do
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
Citizen.Wait(10)
end
for _, bank in ipairs(Config.Banks) do
local blip = AddBlipForCoord(bank.coords.x, bank.coords.y, bank.coords.z)
SetBlipSprite(blip, 108)
SetBlipDisplay(blip, 4)
SetBlipScale(blip, 1.0)
SetBlipColour(blip, 2)
SetBlipAsShortRange(blip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(bank.name)
EndTextCommandSetBlipName(blip)
end
Citizen.CreateThread(function()
local atmModels = {}
for i = 1, #Config.ATMModels do
table.insert(atmModels, GetHashKey(Config.ATMModels[i]))
end
exports.ox_target:addModel({
models = atmModels,
options = {
{
event = 'bank:openMenu',
icon = 'fas fa-credit-card',
label = '打开菜单'
}
}
})
for _, bank in ipairs(Config.Banks) do
exports.ox_target:addBoxZone({
name = bank.name,
coords = bank.coords,
size = vec3(3, 3, 3),
options = {
{
event = 'bank:openMenu',
icon = 'fas fa-university',
label = '打开菜单'
}
}
})
end
end)
end)
RegisterNetEvent('bank:openMenu')
AddEventHandler('bank:openMenu', function()
openMenu()
end)
-- Integration with ox_inventory to check for bank card
AddEventHandler('ox_inventory:itemUsed', function(item)
if item.name == Config.BankCardItem then
if isNearATM or isNearBank then
TriggerEvent('bank:openMenu')
end
end
end)
Citizen.CreateThread(function()
while true do
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
isNearATM, isNearBank = false, false
for _, bank in ipairs(Config.Banks) do
if #(playerCoords - bank.coords) < Config.InteractDistance then
isNearBank = true
break
end
end
for _, model in ipairs(Config.ATMModels) do
local hash = GetHashKey(model)
if IsModelInCdimage(hash) then
local atmObject = GetClosestObjectOfType(playerCoords, Config.InteractDistance, hash, false, false, false)
if atmObject ~= 0 then
isNearATM = true
break
end
end
end
-- 关闭菜单如果玩家离开交互范围
if menuOpen and not (isNearATM or isNearBank) then
ESX.UI.Menu.CloseAll()
menuOpen = false
end
Citizen.Wait(1000) -- 每秒检查一次
end
end)
function openMenu()
menuOpen = true
ESX.TriggerServerCallback('bank:getLoanInfo', function(loan)
local elements = {
{label = '转账', value = 'transfer'},
{label = '收款', value = 'withdraw'},
{label = '贷款', value = 'loan'},
{label = '查询贷款信息', value = 'loan_info'}
}
ESX.UI.Menu.Open(
'default', GetCurrentResourceName(), 'bank_menu',
{
title = '银行/ATM菜单',
align = 'top-left',
elements = elements
},
function(data, menu)
if data.current.value == 'transfer' then
showTransferMenu()
elseif data.current.value == 'withdraw' then
showWithdrawMenu()
elseif data.current.value == 'loan' then
showLoanMenu()
elseif data.current.value == 'loan_info' then
showLoanInfoMenu(loan)
end
end,
function(data, menu)
menu.close()
menuOpen = false
end
)
end)
end
function showTransferMenu()
local elements = {
{label = '输入转账金额', value = 'amount'},
{label = '输入目标玩家ID', value = 'target_id'},
{label = '输入目标银行卡号', value = 'target_card'}
}
ESX.UI.Menu.Open(
'dialog', GetCurrentResourceName(), 'transfer_menu',
{
title = '转账'
},
function(data, menu)
local amount = tonumber(data.value)
if amount == nil then
ESX.ShowNotification('请输入有效金额')
else
menu.close()
ESX.UI.Menu.Open(
'dialog', GetCurrentResourceName(), 'transfer_target_id',
{
title = '输入目标玩家ID'
},
function(data2, menu2)
local target_id = tonumber(data2.value)
if target_id == nil then
ESX.ShowNotification('请输入有效的玩家ID')
else
menu2.close()
ESX.UI.Menu.Open(
'dialog', GetCurrentResourceName(), 'transfer_target_card',
{
title = '输入目标银行卡号'
},
function(data3, menu3)
local target_card = data3.value
if target_card == nil then
ESX.ShowNotification('请输入有效的银行卡号')
else
menu3.close()
TriggerServerEvent('bank:transfer', target_id, target_card, amount)
end
end,
function(data3, menu3)
menu3.close()
end
)
end
end,
function(data2, menu2)
menu2.close()
end
)
end
end,
function(data, menu)
menu.close()
end
)
end
function showWithdrawMenu()
-- 收款逻辑实现,同样方式处理
end
function showLoanMenu()
local elements = {}
for _, amount in ipairs(Config.LoanAmounts) do
table.insert(elements, {label = tostring(amount), value = amount})
end
ESX.UI.Menu.Open(
'default', GetCurrentResourceName(), 'loan_menu',
{
title = '选择贷款金额',
align = 'top-left',
elements = elements
},
function(data, menu)
local amount = data.current.value
ESX.UI.Menu.Open(
'dialog', GetCurrentResourceName(), 'loan_months',
{
title = '输入还款期限 (月)'
},
function(data2, menu2)
local months = tonumber(data2.value)
if months == nil or months < 1 or months > Config.MaxLoanMonths then
ESX.ShowNotification('请输入有效的还款期限 (1到'..Config.MaxLoanMonths..'月)')
else
menu2.close()
TriggerServerEvent('bank:loan', amount, months)
end
end,
function(data2, menu2)
menu2.close()
end
)
end,
function(data, menu)
menu.close()
end
)
end
function showLoanInfoMenu(loan)
if loan then
ESX.ShowNotification('贷款金额: '..loan.amount..'\n总还款金额: '..loan.repay..'\n还款截止日期: '..os.date('%Y-%m-%d %H:%M:%S', loan.dueDate))
else
ESX.ShowNotification('您没有未偿还的贷款.')
end
end
### fxmanifest.lua
确保 `fxmanifest.lua` 文件中加载了所有必要的资源:
fx_version 'cerulean'
game 'gta5'
author 'YourName'
description 'ESX Bank Plugin with ox_target Integration'
version '1.0.0'
shared_scripts {
'@es_extended/locale.lua',
'config.lua'
}
client_scripts {
'client.lua'
}
server_scripts {
'@mysql-async/lib/MySQL.lua',
'server.lua'
}
dependencies {
'es_extended',
'ox_lib',
'ox_target'
}
lua54 'yes'
### 说明:
1. **服务器端**:服务器端代码处理转账、贷款请求,并且维护玩家贷款信息。
2. **客户端**:客户端代码生成菜单并与 `ox_target` 交互。菜单选项通过 `ESX.UI.Menu` API 实现,确保用户可以进行转账、贷款等操作。
3. **自动关闭菜单**:在客户端代码中增加了检查玩家是否仍在ATM或银行范围内,如果离开范围则自动关闭菜单。
4. **菜单功能一致性**:确保ATM和银行的菜单功能一致。
通过以上更新,玩家在离开ATM或银行的交互范围时,菜单会自动关闭,而且不论是ATM还是银行,都具有相同的菜单功能。 |
|