سكريبتات البنوك وأجهزة الصراف الآلي في FiveM: أنظمة مالية واقعية
ابنِ اقتصادًا واقعيًا مع سكريبتات البنوك وأجهزة الصراف الآلي في FiveM. منطق التحويل، أفكار واجهة المستخدم، أفضل الموارد المجانية والمميزة، بالإضافة إلى تكامل الأُطر.
Agency Scripts
المؤسس والمطور الرئيسي في Agency Scripts
هيكل نظام البنك
نظام مصرفي هو العمود الفقري المالي لأي خادم دور FiveM، يدير كل شيء من إيداعات النقود البسيطة إلى التحويلات المعقدة بين اللاعبين وحسابات المنظمات المشتركة. تتضمن معظم الأُطُر مثل QBCore و ESX إدارة مالية أساسية، لكن نظام مصرفي مخصص يوسع ذلك بإدارة حسابات صحيحة، تسجيل المعاملات، وواجهة صراف آلي مصقولة تغمر اللاعبين في الجانب المالي من الدور. تنقسم البنية إلى ثلاث طبقات: تخزن قاعدة البيانات أرصدة الحسابات وسجلات المعاملات، يتحقق الخادم من كل عملية مالية ويفرض قواعد العمل، ويوفر العميل واجهات الصراف الآلي ومنضدة البنك عبر NUI. يجب أن تمر كل عملية مالية عبر جانب الخادم لأن التلاعب المالي من جانب العميل هو أهم ثغرة استغلال في خوادم FiveM. حتى عرض الرصيد يجب أن يأتي من استدعاء خادم، وليس من بيانات مخزنة على العميل يمكن التلاعب بها.
مخطط قاعدة البيانات للبنوك
قاعدة بياناتك المصرفية يجب أن تدعم الحسابات الشخصية، والحسابات المشتركة للمنظمات والشركات، وسجل معاملات شامل. سجل المعاملات ليس اختياريًا لأنه يخدم غرضين: ميزة للاعبين وأداة إدارية للتحقيق في استغلال الأموال. صمم مخططك ليتعامل مع عمليات عالية الكثافة لأن الخوادم المزدحمة يمكن أن تعالج مئات المعاملات في الدقيقة خلال ساعات الذروة:
CREATE TABLE IF NOT EXISTS bank_accounts (
id INT AUTO_INCREMENT PRIMARY KEY,
account_number VARCHAR(20) UNIQUE NOT NULL,
owner_citizenid VARCHAR(50) NOT NULL,
account_type ENUM('personal', 'business', 'gang', 'shared') DEFAULT 'personal',
balance BIGINT DEFAULT 0,
account_name VARCHAR(100) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_frozen BOOLEAN DEFAULT FALSE,
INDEX idx_owner (owner_citizenid),
INDEX idx_type (account_type)
);
CREATE TABLE IF NOT EXISTS bank_transactions (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
account_id INT NOT NULL,
type ENUM('deposit', 'withdraw', 'transfer_in', 'transfer_out', 'paycheck', 'purchase') NOT NULL,
amount BIGINT NOT NULL,
balance_after BIGINT NOT NULL,
description VARCHAR(255) DEFAULT NULL,
other_account VARCHAR(20) DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_account (account_id),
INDEX idx_created (created_at),
FOREIGN KEY (account_id) REFERENCES bank_accounts(id)
);
CREATE TABLE IF NOT EXISTS bank_account_access (
account_id INT NOT NULL,
citizenid VARCHAR(50) NOT NULL,
permission ENUM('view', 'withdraw', 'full') DEFAULT 'view',
PRIMARY KEY (account_id, citizenid),
FOREIGN KEY (account_id) REFERENCES bank_accounts(id)
);
ال bank_account_access جدول يتيح الحسابات المشتركة حيث يمكن لعدة لاعبين الحصول على مستويات أذونات مختلفة. قد يكون لقائد العصابة وصول كامل إلى خزينة العصابة بينما يمكن للأعضاء العاديين فقط عرض الرصيد. باستخدام BIGINT لحقول الرصيد لمنع مشاكل الفائض على الخوادم التي تحتوي على اقتصادات متضخمة حيث يمكن أن تصل أرصدة اللاعبين إلى المليارات.
منطق المعاملات على جانب الخادم
يجب أن تكون كل معاملة مالية ذرية ومُحققة على الخادم. استخدم معاملات قاعدة البيانات لضمان عدم إنشاء أو تدمير المال أثناء التحويلات. عندما يرسل اللاعب A مالاً إلى اللاعب B، يجب أن تنجح كل من الخصم من A والإضافة إلى B معاً، أو لا يُطبق أي منهما. نفذ فحوصات تحقق لرصيد كافٍ، حالة الحساب المجمد، حدود التحويل اليومية، والحد الأدنى لمبالغ المعاملات. هنا تنفيذ تحويل آمن:
RegisterNetEvent('banking:server:transfer', function(targetAccount, amount, description)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
amount = math.floor(tonumber(amount) or 0)
if amount <= 0 then
TriggerClientEvent('QBCore:Notify', src, 'Invalid amount', 'error')
return
end
local citizenid = Player.PlayerData.citizenid
local senderAccount = GetPlayerPrimaryAccount(citizenid)
if not senderAccount or senderAccount.is_frozen then
TriggerClientEvent('QBCore:Notify', src, 'Account unavailable', 'error')
return
end
if senderAccount.balance < amount then
TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds', 'error')
return
end
-- Check daily transfer limit
local todayTransfers = GetDailyTransferTotal(senderAccount.id)
if todayTransfers + amount > Config.DailyTransferLimit then
TriggerClientEvent('QBCore:Notify', src, 'Daily limit exceeded', 'error')
return
end
-- Atomic transfer using database transaction
local success = MySQL.transaction.await({
{
query = 'UPDATE bank_accounts SET balance = balance - ? WHERE id = ? AND balance >= ?',
values = {amount, senderAccount.id, amount}
},
{
query = 'UPDATE bank_accounts SET balance = balance + ? WHERE account_number = ?',
values = {amount, targetAccount}
},
{
query = 'INSERT INTO bank_transactions (account_id, type, amount, balance_after, description, other_account) VALUES (?, "transfer_out", ?, (SELECT balance FROM bank_accounts WHERE id = ?), ?, ?)',
values = {senderAccount.id, amount, senderAccount.id, description or 'Transfer', targetAccount}
},
})
if success then
TriggerClientEvent('QBCore:Notify', src, 'Transfer complete: $' .. amount, 'success')
TriggerClientEvent('banking:client:refreshBalance', src)
else
TriggerClientEvent('QBCore:Notify', src, 'Transfer failed', 'error')
end
end)
لاحظ WHERE balance >= ? شرط في استعلام الخصم، يعمل كحارس نهائي ضد حالات التنافس حيث يمكن أن تؤدي تحويلتان متزامنتان إلى سحب زائد من الحساب. هذا الفحص على مستوى قاعدة البيانات ضروري حتى لو كنت تتحقق من الرصيد في Lua، لأن عدة طلبات قد تصل بين تحققك والتحديث الفعلي.
واجهة مستخدم ATM
واجهة الصراف الآلي هي لوحة NUI مدمجة توفر وصولًا سريعًا لوظائف البنك الأساسية: التحقق من الرصيد، إيداع النقود، سحب النقود، وتحويل الأموال. حافظ على التصميم نظيفًا ومألوفًا لأن اللاعبين يتوقعون بشكل غريزي أن يعمل الصراف الآلي مثل نظيره في العالم الحقيقي. عرض الرصيد الحالي بشكل بارز في الأعلى، مع أزرار الإجراءات أدناه لكل عملية. يجب أن تتضمن واجهات الإيداع والسحب أزرار مبالغ محددة مسبقًا للقيم الشائعة مثل $100 و $500 و $1000 و $5000 إلى جانب حقل إدخال مبلغ مخصص. بالنسبة للتحويلات، وفر حقولًا لرقم حساب المستلم والمبلغ، مع حقل ملاحظة اختياري. عرض خطوة تأكيد قبل تنفيذ أي معاملة لمنع النقرات العرضية التي قد تكلف اللاعبين أموالًا. تضمين قائمة بالمعاملات الأخيرة تعرض آخر 10 إدخالات حتى يتمكن اللاعبون من التحقق من نشاطهم المالي دون الحاجة لزيارة فرع بنك كامل. يجب أن يشعر واجهة الصراف الآلي بالسرعة، لذا استرجع بيانات الرصيد والمعاملات في رد اتصال واحد عند فتح القائمة بدلاً من طلبات منفصلة لكل معلومة.
إعداد التفاعل مع ATM
ضع نقاط تفاعل الصراف الآلي في مواقع الصراف الآلي الموجودة في جميع أنحاء خريطة GTA. يوفر FiveM قائمة بهاشات نماذج الصراف الآلي التي يمكنك التكرار عليها للعثور على جميع نماذج الصراف الآلي في عالم اللعبة. استخدم نظام استهداف مثل ox_target لتفاعل نظيف، أو اعتمد على فحوصات القرب بالقرب من كل نموذج صراف آلي. عند تفاعل اللاعب مع الصراف الآلي، شغّل رسومًا متحركة للاعب وهو يستخدم الصراف، ثم افتح لوحة NUI:
local atmModels = {
'prop_atm_01', 'prop_atm_02', 'prop_atm_03',
'prop_fleeca_atm', 'v_5_b_atm1'
}
-- Using ox_target for ATM interaction
for _, model in ipairs(atmModels) do
exports.ox_target:addModel(GetHashKey(model), {
{
name = 'use_atm',
icon = 'fas fa-credit-card',
label = 'Use ATM',
onSelect = function(data)
local ped = PlayerPedId()
local atmCoords = GetEntityCoords(data.entity)
-- Face the ATM
TaskTurnPedToFaceCoord(ped, atmCoords.x, atmCoords.y, atmCoords.z, 1000)
Wait(1000)
-- Play ATM animation
RequestAnimDict('mini@atmenter')
while not HasAnimDictLoaded('mini@atmenter') do Wait(10) end
TaskPlayAnim(ped, 'mini@atmenter', 'enter', 8.0, -8.0, -1, 0, 0, false, false, false)
-- Open ATM UI
QBCore.Functions.TriggerCallback('banking:server:getAccountData', function(data)
SetNuiFocus(true, true)
SendNUIMessage({
action = 'openATM',
balance = data.balance,
transactions = data.recentTransactions,
accountNumber = data.accountNumber
})
end)
end
}
})
end
سجل المعاملات والكشوفات
سجل المعاملات يحول نظامك المصرفي من آلة إيداع وسحب بسيطة إلى أداة إدارة مالية كاملة. يجب أن يتمكن اللاعبون من عرض سجل معاملاتهم الكامل في فروع البنوك، مع تصفية حسب نطاق التاريخ أو نوع المعاملة أو المبلغ. يجب أن يعرض كل إدخال معاملة التاريخ، النوع، المبلغ، الرصيد الناتج، الوصف، والطرف الآخر المعني في التحويلات. طبق الترقيم على جانب الخادم لأن تحميل آلاف المعاملات دفعة واحدة سيجمد إطار NUI ويرفع استخدام ذاكرة الخادم. أرجع 20-30 معاملة في كل صفحة ودع اللاعب يحمل المزيد حسب الحاجة. بالنسبة لفروع البنوك، قدم ميزات إضافية تتجاوز ما توفره أجهزة الصراف الآلي، مثل فتح حسابات جديدة، إدارة أذونات الحساب المشترك، إنشاء كشوف حساب لفترة محددة، والتقديم على قروض إذا كان خادمك يدعم هذه الميكانيكية. خزّن أوصاف المعاملات كسلاسل قابلة للقراءة البشرية بحيث تظهر المعاملات الآلية من الوظائف، مشتريات المتاجر، والضرائب الحكومية جميعها بإدخالات واضحة يمكن للاعبين فهمها بدون سياق.
آليات سرقة البنوك
سرقات البنوك هي واحدة من أكثر الأحداث إثارة في أي خادم لعب أدوار، حيث تخلق سيناريوهات عالية المخاطر تشمل المجرمين، الشرطة، مفاوضي الرهائن، والمارة. يشمل نظام السرقة المصمم جيدًا عدة مراحل: مراقبة البنك، بدء السرقة، اختراق أو حفر أنظمة الأمان من خلال ألعاب مصغرة، تحميل الغنائم، والهروب مع مطاردة الشرطة. ابدأ بتحديد البنوك التي يمكن سرقتها، مستوى صعوبتها، مؤقتات التهدئة، والأدوات المطلوبة. يجب أن تتطلب السرقة أدوات محددة مثل الثيرمايت لأبواب الخزنة، أجهزة الاختراق للوحات الأمان، وحقائب السفر لحمل الغنائم. نفذ ألعاب مصغرة بتدرج صعوبة لكل طبقة أمان، حيث يؤدي فشل الاختراق إلى إطلاق إنذارات إضافية أو إغلاق الخزنة أكثر:
Config.BankRobberies = {
['fleeca_1'] = {
label = 'Fleeca Bank - Legion Square',
coords = vector3(149.73, -1042.65, 29.37),
vault = vector3(144.87, -1044.16, 29.37),
tier = 1, -- 1=Fleeca, 2=Paleto, 3=Pacific Standard
cooldown = 7200, -- 2 hours
minPolice = 3,
requiredItems = {'electronickit', 'thermite'},
reward = { min = 40000, max = 80000, markedBills = true },
securityLayers = {
{ type = 'hack', difficulty = 'easy', time = 30 },
{ type = 'thermite', time = 10 },
{ type = 'drill', time = 45 },
},
},
['pacific_standard'] = {
label = 'Pacific Standard Bank',
coords = vector3(255.85, 225.60, 101.88),
vault = vector3(262.20, 222.10, 101.68),
tier = 3,
cooldown = 14400, -- 4 hours
minPolice = 6,
requiredItems = {'electronickit', 'thermite', 'advancedlaptop'},
reward = { min = 200000, max = 400000, markedBills = true },
securityLayers = {
{ type = 'hack', difficulty = 'hard', time = 20 },
{ type = 'hack', difficulty = 'hard', time = 20 },
{ type = 'thermite', time = 8 },
{ type = 'drill', time = 60 },
{ type = 'hack', difficulty = 'expert', time = 15 },
},
},
}
استخدم الفواتير المعلمة كمكافأة للسرقة بدلاً من النقود النظيفة، مما يجبر المجرمين على غسيل الأموال من خلال حلقات لعب إضافية مثل مواقع غسيل الأموال أو تبادلات الأموال القذرة. هذا يوسع دور لعب السرقة إلى ما بعد السطو نفسه ويخلق فرصًا لتحقيقات الشرطة. قم بإخطار نظام إرسال الشرطة عند بدء السرقة وتتبع تقدم السرقة على الخادم حتى يتمكن الضباط من الاستجابة تكتيكيًا بناءً على مدى تقدم المجرمين.
تدابير الأمان ومكافحة الاستغلال
تُعد الأنظمة المالية الهدف الأساسي للمستغلين لأن المال يترجم مباشرة إلى القوة داخل اللعبة. بالإضافة إلى التحقق من جانب الخادم الذي تم مناقشته سابقًا، قم بتنفيذ عدة طبقات أمان إضافية. أضف تحديد المعدل لجميع أحداث البنوك بحيث لا يستطيع لاعب واحد إرسال مئات طلبات الإيداع أو التحويل في الثانية. سجّل كل معاملة مالية مع معرفات اللاعب المصدر والطابع الزمني حتى يتمكن المسؤولون من تتبع تدفق الأموال وتحديد استغلال التكرار. نفذ نظام عكس المعاملات يمكن للمسؤولين استخدامه للتراجع عن المعاملات الاحتيالية عند اكتشاف الاستغلالات. حدد حدودًا قصوى للمعاملة الواحدة وحدودًا تراكمية يومية تتناسب مع عمر حساب اللاعب وإجمالي وقت اللعب، مما يجعل الحسابات الجديدة أقل فائدة لغسيل الأموال. راقب الأنماط المشبوهة مثل التحويلات السريعة ذهابًا وإيابًا بين حسابين، الإيداعات التي تطابق بالضبط مبلغ السحب من لاعب آخر خلال ثوانٍ، أو زيادة الرصيد بدون سجلات معاملات مقابلة. أرسل تنبيهات عبر Discord webhook عند اكتشاف نشاط مشبوه حتى يتمكن فريق الإشراف من التحقيق في الوقت الفعلي دون انتظار تقارير اللاعبين. فكر في تنفيذ نظام حساب مجمد حيث يمكن للمسؤول قفل الحسابات أثناء التحقيقات، مما يمنع إنفاق أو تحويل الأموال المستغلة أثناء حل المشكلة.
الدمج مع اقتصاد الخادم
يجب أن يكون نظامك المصرفي مركزًا رئيسيًا لكل التدفقات المالية على الخادم. وجه رواتب الوظائف عبر النظام المصرفي حتى يتلقى اللاعبون رواتبهم كإيداع بنكي مع سجل معاملات واضح يوضح الوظيفة التي دفعت لهم والمبلغ. اربط مشتريات المتجر بسحب بنكي عند الدفع بالبطاقة بدلاً من النقد، مما يخلق أثرًا ورقيًا يضيف واقعية ويعطي اللاعبين سببًا لاستخدام النظام المصرفي بخلاف التخزين البسيط. نفذ الفوترة التلقائية للتكاليف المتكررة مثل ضرائب الممتلكات، تأمين المركبات، ونفقات تشغيل الأعمال التي تخصم من حساب اللاعب البنكي بانتظام. إذا كان حساب اللاعب لا يحتوي على أموال كافية للدفع التلقائي، يجب على النظام تسجيل فشل الدفع وتحفيز عواقب مثل تحذيرات مصادرة الممتلكات أو انقطاع التأمين. اربط النظام المصرفي بموارد الهاتف حتى يتمكن اللاعبون من التحقق من رصيدهم، عرض المعاملات الأخيرة، وإجراء تحويلات سريعة دون الحاجة لزيارة ماكينة صراف آلي أو فرع بنك فعليًا. هذا التكامل يحول النظام المصرفي من ميزة معزولة إلى النظام العصبي المالي الذي يربط كل نشاط اقتصادي على خادمك.