نظام تأجير السيارات في FiveM: برمجة المركبات المؤقتة
إضافة مركبات للإيجار إلى خادم FiveM الخاص بك. مفاتيح مؤقتة، ودائع، منطق الإرجاع التلقائي وأفضل سكربتات الإيجار لشبكات QBCore وESX والوظائف المستقلة.
Agency Scripts
المؤسس والمطور الرئيسي في Agency Scripts
لماذا تعزز أنظمة الإيجار اللعب التمثيلي
ليس كل لاعب في خادم لعب الأدوار يمتلك مركبة، خاصة الشخصيات الجديدة التي بدأت للتو. يملأ نظام تأجير السيارات والدراجات هذه الفجوة من خلال توفير وسائل نقل مؤقتة بأسعار معقولة، مما يخلق فرص لعب أدوار طبيعية عند مكاتب التأجير ويمنح اللاعبين الجدد حرية استكشاف الخريطة دون الاعتماد على النقل العام أو المشي. بالإضافة إلى النقل الأساسي، تدعم أنظمة التأجير لعب الأدوار السياحي حيث يستأجر الزوار سيارات مكشوفة للقيادة ذات المناظر الخلابة، ووظائف التوصيل التي تتطلب أنواع مركبات محددة، وسيناريوهات الأحداث حيث يحتاج اللاعبون إلى مركبات متطابقة للرحلات المنظمة أو السباقات. كما يولد النظام دخلًا سلبيًا لاقتصاد الخادم من خلال رسوم الإيجار، وودائع الأضرار، وغرامات التأخير في الإرجاع.
تكوين الأسطول وفئات المركبات
نظم أسطول الإيجار الخاص بك إلى فئات تلبي احتياجات وميزانيات اللاعبين المختلفة. توفر المركبات الاقتصادية وسائل نقل أساسية بأسعار معقولة، تقدم السيارات متوسطة النطاق المزيد من الراحة والأداء، تلبي المركبات الفاخرة تجارب الرفاهية، وتوفر الدراجات النارية بديلًا ذا عجلتين للاعبين. يجب أن تحتوي كل فئة على خيارات مركبات متعددة مع أسعار واضحة. تضمّن معدلات إيجار بالساعة واليوم حتى يتمكن اللاعبون من اختيار الخيار الأكثر اقتصادية لاحتياجاتهم. عرّف الأسطول في جدول تكوين يحدد كل مركبة متاحة مع سعر الإيجار، الوديعة المطلوبة، الفئة، ونموذج الظهور:
Config.RentalLocations = {
['airport'] = {
label = 'LS Airport Car Rental',
pedModel = 's_f_y_airhostess_01',
pedCoords = vector4(-1037.34, -2736.82, 20.17, 238.52),
spawnPoint = vector4(-1029.12, -2728.91, 20.17, 148.76),
returnZone = vector3(-1035.00, -2730.00, 20.17),
returnRadius = 10.0,
categories = {'economy', 'midrange', 'premium', 'motorcycle'},
},
['downtown'] = {
label = 'Downtown Bike Rental',
pedModel = 'a_m_y_business_02',
pedCoords = vector4(-259.68, -892.41, 31.08, 69.24),
spawnPoint = vector4(-264.30, -888.12, 31.08, 339.87),
returnZone = vector3(-260.00, -890.00, 31.08),
returnRadius = 8.0,
categories = {'motorcycle', 'bicycle'},
},
}
Config.RentalFleet = {
economy = {
{model = 'blista', label = 'Blista', priceHour = 150, priceDay = 800, deposit = 500},
{model = 'asea', label = 'Asea', priceHour = 120, priceDay = 650, deposit = 400},
{model = 'stanier', label = 'Stanier', priceHour = 130, priceDay = 700, deposit = 450},
},
midrange = {
{model = 'schafter2', label = 'Schafter', priceHour = 300, priceDay = 1600, deposit = 1000},
{model = 'oracle', label = 'Oracle', priceHour = 280, priceDay = 1500, deposit = 900},
},
premium = {
{model = 'felon', label = 'Felon GT', priceHour = 600, priceDay = 3200, deposit = 2500},
{model = 'exemplar', label = 'Exemplar', priceHour = 550, priceDay = 3000, deposit = 2000},
},
motorcycle = {
{model = 'pcj', label = 'PCJ-600', priceHour = 100, priceDay = 500, deposit = 300},
{model = 'sanchez', label = 'Sanchez', priceHour = 80, priceDay = 400, deposit = 250},
},
bicycle = {
{model = 'cruiser', label = 'Cruiser Bike', priceHour = 30, priceDay = 150, deposit = 50},
{model = 'tribike', label = 'Tri-Cycles Race', priceHour = 25, priceDay = 120, deposit = 50},
},
}
عملية الإيجار وواجهة NUI
يبدأ التفاعل مع الإيجار عندما يقترب اللاعب من NPC عداد الإيجار. باستخدام نظام استهداف أو فحص القرب، افتح قائمة NUI تعرض فئات المركبات المتاحة مع خيارات التصفية. يجب أن يعرض كل إعلان مركبة اسم الطراز، معاينة صورة إذا أمكن، أسعار الساعة واليوم، الوديعة المطلوبة، وحالة التوفر. عندما يختار اللاعب مركبة ويؤكد مدة الإيجار، يعالج الخادم المعاملة. الرسوم الإجمالية هي رسوم الإيجار للمدة المختارة بالإضافة إلى وديعة الأضرار. يتم احتجاز الوديعة من قبل النظام وتُرد عند إعادة المركبة دون أضرار. نفذ تأكيد الإيجار كحدث خادم يتحقق من أن لدى اللاعب أموال كافية، ويتأكد من توفر المركبة المختارة، ويخصم الرسوم من اللاعب، وينشئ مركبة الإيجار في نقطة الظهور المحددة:
RegisterNetEvent('rental:server:rentVehicle', function(locationId, vehicleModel, duration)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local location = Config.RentalLocations[locationId]
if not location then return end
-- Check if player already has an active rental
if ActiveRentals[Player.PlayerData.citizenid] then
TriggerClientEvent('QBCore:Notify', src, 'You already have an active rental', 'error')
return
end
-- Find vehicle config
local vehicleConfig = nil
for _, category in pairs(Config.RentalFleet) do
for _, v in ipairs(category) do
if v.model == vehicleModel then
vehicleConfig = v
break
end
end
if vehicleConfig then break end
end
if not vehicleConfig then return end
-- Calculate cost
local rentalFee = duration == 'day' and vehicleConfig.priceDay or vehicleConfig.priceHour
local totalCost = rentalFee + vehicleConfig.deposit
if Player.Functions.GetMoney('bank') < totalCost then
TriggerClientEvent('QBCore:Notify', src, 'Insufficient funds. Need $' .. totalCost, 'error')
return
end
-- Charge player
Player.Functions.RemoveMoney('bank', totalCost, 'vehicle-rental')
-- Generate rental plate
local plate = 'RNT' .. math.random(10000, 99999)
-- Store active rental
ActiveRentals[Player.PlayerData.citizenid] = {
model = vehicleModel,
plate = plate,
deposit = vehicleConfig.deposit,
rentalFee = rentalFee,
startTime = os.time(),
duration = duration,
expiresAt = os.time() + (duration == 'day' and 86400 or 3600),
locationId = locationId,
initialHealth = 1000,
}
TriggerClientEvent('rental:client:spawnVehicle', src, vehicleModel, plate, location.spawnPoint)
TriggerClientEvent('QBCore:Notify', src, 'Vehicle rented! Return before your time expires.', 'success')
end)
آليات وديعة الضرر والإرجاع
يخلق نظام وديعة الضرر المساءلة حول كيفية تعامل اللاعبين مع مركبات الإيجار. عند إرجاع المركبة، قارن قيم صحتها الحالية بالقيم الأولية المسجلة عند وقت الإيجار. لدى مركبات GTA قيم صحة منفصلة للمحرك، الهيكل، والمكونات الفردية، مما يمنحك تحكمًا دقيقًا في تقييم الضرر. احسب تكلفة الإصلاح بناءً على الضرر الذي تعرضت له واطرحها من الوديعة قبل رد الباقي. إذا تجاوز الضرر مبلغ الوديعة، لا يحصل اللاعب على رد وقد يُفرض عليه رسوم إضافية. إذا أُرجعت المركبة في حالة مثالية، يتم رد كامل الوديعة. يشجع هذا النظام على القيادة الحذرة دون أن يكون عقابيًا للخدوش الطفيفة التي لا مفر منها في فيزياء قيادة GTA:
RegisterNetEvent('rental:server:returnVehicle', function(vehicleNet)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local citizenid = Player.PlayerData.citizenid
local rental = ActiveRentals[citizenid]
if not rental then return end
local vehicle = NetworkGetEntityFromNetworkId(vehicleNet)
if not DoesEntityExist(vehicle) then return end
-- Check plate matches
local plate = GetVehicleNumberPlateText(vehicle)
if plate:trim() ~= rental.plate then
TriggerClientEvent('QBCore:Notify', src, 'This is not your rental vehicle', 'error')
return
end
-- Calculate damage
local bodyHealth = GetVehicleBodyHealth(vehicle)
local engineHealth = GetVehicleEngineHealth(vehicle)
local damagePercent = 1.0 - ((bodyHealth + engineHealth) / 2000.0)
local repairCost = math.floor(rental.deposit * damagePercent)
-- Calculate late fee
local lateFee = 0
if os.time() > rental.expiresAt then
local overHours = math.ceil((os.time() - rental.expiresAt) / 3600)
lateFee = overHours * 200
end
-- Refund deposit minus costs
local refund = math.max(0, rental.deposit - repairCost - lateFee)
if refund > 0 then
Player.Functions.AddMoney('bank', refund, 'rental-deposit-refund')
end
DeleteEntity(vehicle)
ActiveRentals[citizenid] = nil
local message = string.format('Vehicle returned. Deposit: $%d | Repairs: $%d | Late fee: $%d | Refund: $%d',
rental.deposit, repairCost, lateFee, refund)
TriggerClientEvent('QBCore:Notify', src, message, refund > 0 and 'success' or 'warning')
end)
نظام انتهاء الصلاحية والإرجاع التلقائي
يجب ألا تستمر المركبات المؤجرة إلى أجل غير مسمى. نفذ نظام مؤقت يتتبع موعد انتهاء كل إيجار ويتخذ الإجراءات المناسبة. أرسل للاعب إشعارًا قبل ثلاثين دقيقة من الانتهاء، ثم آخر عند عشر دقائق، وتحذيرًا نهائيًا عند خمس دقائق. عند انتهاء الإيجار، ابدأ في فرض رسوم تأخير بالدقيقة حتى حد أقصى. إذا فشل اللاعب في إعادة المركبة خلال فترة السماح بعد الانتهاء، يتم إلغاء ظهور المركبة تلقائيًا ومصادرة كامل التأمين. هذا يمنع تراكم المركبات المؤجرة المهجورة على الخادم. يجب أن يتم فحص انتهاء الصلاحية على الخادم بفاصل منتظم، مع المرور على جميع الإيجارات النشطة واتخاذ الإجراءات المناسبة بناءً على الوقت المتبقي. خزّن معرف الشبكة للمركبة حتى تتمكن من حذفها عن بُعد إذا لزم الأمر، وتعامل مع الحالة التي تم فيها تدمير المركبة قبل انتهاء الإيجار بإغلاق الإيجار تلقائيًا مع مصادرة التأمين بالكامل.
مواقع تأجير متعددة
ضع مواقع الإيجار في نقاط استراتيجية حول الخريطة حيث يكون النقل المؤقت منطقيًا أكثر. المطار خيار واضح، يخدم اللاعبين الذين وصلوا للتو إلى المدينة. المواقع في وسط المدينة بالقرب من المباني الحكومية تخدم اللاعبين الذين يحضرون جلسات المحكمة أو اجتماعات العمل. مواقع الشاطئ تقدم دراجات نارية ودراجات هوائية للأنشطة الترفيهية على طول الساحل. يمكن لكل موقع أن يقدم مجموعة فرعية مختلفة من الأسطول، مع وجود المطار الذي يحتوي على النطاق الكامل من الاقتصادي إلى المميز، بينما مواقع الشاطئ تخزن فقط الدراجات النارية والدراجات الهوائية. خصص نموذج NPC في كل موقع ليتناسب مع البيئة. تستخدم إيجارات المطار نموذج عمل احترافي، إيجارات الشاطئ تستخدم نموذج راكب أمواج عادي، ومواقع وسط المدينة تستخدم موظفًا يرتدي بدلة. هذا الاهتمام بالتفاصيل يجعل كل موقع إيجار يشعر كعمل تجاري مميز بدلاً من نسخ متطابقة من نفس النظام.
تتبع GPS ومكافحة السرقة
يجب أن تحتوي المركبات المؤجرة على تتبع GPS مدمج يسمح لشركة الإيجار واللاعب بتحديد موقع المركبة في أي وقت. عرض موقع المركبة المؤجرة على خريطة اللاعب بأيقونة مميزة. إذا تحركت المركبة خارج حدود قابلة للتكوين، أرسل إشعار تحذيري. نفذ تدابير مضادة للسرقة تمنع اللاعبين الآخرين من تخزين أو إيواء مركبة مؤجرة، مما يضمن بقائها تحت سيطرة نظام الإيجار. عندما يحاول اللاعب وضع مركبة مؤجرة في جراجهم الشخصي، يجب أن يمنع النظام الإجراء مع إشعار يشرح أن المركبات المؤجرة لا يمكن تخزينها. بالنسبة للدراجات النارية والدراجات الهوائية، أضف قفلًا افتراضيًا لا يمكن فتحه إلا من قبل اللاعب المستأجر، مما يمنع السرقة العرضية. إذا سُرقت مركبة مؤجرة، يجب أن يتمكن اللاعب المستأجر من الإبلاغ عنها عبر تطبيق هاتف، مما يؤدي إلى إرسال إشارة GPS تساعده في تحديد موقع المركبة. تتبع إجمالي الأميال أثناء الإيجار لفرض رسوم إضافية محتملة على الإيجارات ذات الأميال العالية، مضيفًا طبقة أخرى من إدارة تأجير المركبات الواقعية.
تكامل الأعمال وتأجير اللاعبين المملوك
لخوادم تحتوي على نظام ملكية أعمال، اسمح للاعبين بشراء وتشغيل أعمال إيجار خاصة بهم. يحدد مالك العمل تكوين الأسطول بشراء مركبات لإضافتها إلى مجموعة الإيجار، يحدد الأسعار، يوظف موظفين للعمل على الكاونتر، ويجمع الإيرادات من الإيجارات. يجب أن يكون لدى مالكي الأعمال لوحة إدارة تعرض الإيجارات النشطة، الإيرادات اليومية، معدلات استخدام الأسطول، وتكاليف الصيانة للمركبات التي تتعرض لأضرار عبر عدة إيجارات. يمكن للموظفين التعامل مع عمليات الاستقبال مثل معالجة الإيجارات والعودة، فحص المركبات المعادة للأضرار، وتصعيد النزاعات إلى المالك. يحول هذا النهج المدفوع باللاعبين نظام الإيجار من ميكانيكية لعبة ثابتة إلى عمل ديناميكي يعكس روح ريادة الأعمال في خوادم لعب الأدوار ويخلق فرص عمل للاعبين الذين يفضلون أدوار خدمة العملاء على اللعب عالي الحركة.