سكريبت نظام القطارات FiveM: مسارات ومحطات سكك حديد مخصصة
أحضر القطارات إلى الحياة في FiveM. مسارات مخصصة، محركات قابلة للتحكم، مقاعد للركاب وأفضل سكريبتات القطارات لتجربة نقل غامرة في اللعب التمثيلي.
Agency Scripts
المؤسس والمطور الرئيسي في Agency Scripts
النقل العام كبنية تحتية للخادم
نظام القطارات والنقل العام يحول سيرفرك في FiveM من مدينة مركزة على السيارات إلى منطقة حضرية حية مع نقل جماعي وظيفي. القطارات التي تعمل وفق جداول على شبكة السكك الحديدية الموجودة في GTA، الحافلات التي تتبع مسارات عبر شوارع المدينة، ومحطات المترو التي توفر سفرًا سريعًا بين الأحياء كلها تساهم في عالم يشعر بالحياة الحقيقية. يستفيد كل لاعب في السيرفر من النقل العام بغض النظر عن الثروة أو الوظيفة. اللاعبون الجدد الذين لا يستطيعون شراء سيارة يمكنهم ركوب الحافلة للوصول إلى مواقع العمل. اللاعبون المتمرسون يستخدمون المترو خلال أوقات الذروة لتجنب الطرق المزدحمة. اللاعبون المجرمون يستخدمون النقل للتنقل في المدينة بدون مركبة شخصية يمكن تتبعها. يخلق نظام النقل أيضًا فرص عمل فريدة لسائقي الحافلات، قادة القطارات، وموظفي هيئة النقل الذين يحافظون على الجداول، يجمعون الأجرة، ويديرون الحوادث على الشبكة. من الناحية التقنية، القطارات والحافلات التي تعمل على مسارات ثابتة تملأ العالم بكيانات متحركة تجعل المدينة تبدو مشغولة دون الحاجة إلى زيادة عدد اللاعبين.
تكوين مسار وجدول القطار
يحتوي GTA V على شبكة سكك حديدية مدمجة تحيط بالخريطة، ويجب أن يستفيد نظام القطار الخاص بك من هذه المسارات القائمة لتحقيق أقصى توافق. عرّف مسارات القطار كسلسلة من محطات التوقف على طول المسار مع أوقات الوصول والمغادرة المحسوبة من سرعة القطار المتوسطة بين المحطات. كل محطة تحتاج إلى منطقة منصة يصعد وينزل منها اللاعبون، نقطة تفاعل آلة التذاكر، ولوحات عرض تُظهر الوصولات القادمة. قم بتكوين خدمات قطار متعددة تعمل في نفس الوقت على مقاطع مختلفة من الشبكة، مع جداول زمنية تتكرر بدورة قابلة للتكوين تتوافق مع تقدم يوم-ليل في خادمك:
Config.TrainSystem = {
ticketPrice = 50,
speedMultiplier = 1.0,
despawnDistance = 500.0,
announceArrival = true,
announceDeparture = true,
}
Config.TrainRoutes = {
['metro_line_1'] = {
label = 'Metro Line 1 - City Loop',
model = 'metrotrain',
carriages = 3,
frequency = 300, -- seconds between departures
stations = {
{
name = 'Los Santos Central',
coords = vector3(268.09, -1204.28, 38.90),
platform = vector3(264.55, -1200.12, 38.90),
stopDuration = 20,
announceText = 'Now arriving at Los Santos Central Station',
},
{
name = 'Strawberry',
coords = vector3(36.81, -1393.78, 29.36),
platform = vector3(40.22, -1389.45, 29.36),
stopDuration = 15,
announceText = 'Now arriving at Strawberry Station',
},
{
name = 'Del Perro',
coords = vector3(-1359.88, -474.17, 15.02),
platform = vector3(-1355.44, -470.89, 15.02),
stopDuration = 15,
announceText = 'Now arriving at Del Perro Station',
},
{
name = 'Rockford Hills',
coords = vector3(-512.47, -680.33, 33.42),
platform = vector3(-508.12, -676.88, 33.42),
stopDuration = 15,
announceText = 'Now arriving at Rockford Hills Station',
},
{
name = 'Burton',
coords = vector3(-283.66, -324.78, 10.07),
platform = vector3(-279.33, -321.44, 10.07),
stopDuration = 15,
announceText = 'Now arriving at Burton Station',
},
},
},
}
Config.BusRoutes = {
['route_1'] = {
label = 'Route 1 - Downtown Express',
model = 'bus',
frequency = 180,
stops = {
{ name = 'Legion Square', coords = vector3(208.24, -935.88, 30.69),
stopDuration = 12 },
{ name = 'Pillbox Hospital', coords = vector3(311.44, -592.33, 43.29),
stopDuration = 12 },
{ name = 'Alta Street', coords = vector3(-226.87, -381.44, 30.05),
stopDuration = 12 },
{ name = 'Vinewood Blvd', coords = vector3(302.33, 193.67, 104.38),
stopDuration = 12 },
},
},
}
ال frequency القيمة تحدد مدى تكرار انطلاق قطار جديد من المحطة الأولى على المسار. يمكن لعدة قطارات العمل على نفس المسار في نفس الوقت، مفصولة بفاصل التردد. ال stopDuration في كل محطة يمنح اللاعبين وقتًا كافيًا للصعود أو النزول، مع إعلان صوتي عند وصول القطار ونغمة تحذير المغادرة قبل ثوانٍ قليلة من رحيله.
توليد وتحريك كيان القطار
إنشاء والتحكم في القطارات في FiveM يتطلب وظائف أصلية محددة تختلف عن التعامل العادي مع المركبات. استخدم CreateMissionTrain لإنشاء القطارات على شبكة السكك الحديدية، التي تضعها تلقائيًا على أقرب مسار وتتولى فيزياء تتبع السكك. تحكم في سرعة القطار باستخدام SetTrainSpeed و SetTrainCruiseSpeed، وجلب القطارات إلى التوقف في المحطات عن طريق تقليل السرعة تدريجياً عند اقترابها من إحداثيات الرصيف. يجب أن يتوقف القطار بدقة عند موقع الرصيف بحيث تتماشى الأبواب مع مناطق الصعود، مما يتطلب حسابات دقيقة لتقليل السرعة بناءً على المسافة إلى المحطة التالية:
local activeTrains = {}
function SpawnTrain(routeId)
local route = Config.TrainRoutes[routeId]
if not route then return end
local firstStation = route.stations[1]
local variation = 24 -- metro train variation
-- Create the mission train
local train = CreateMissionTrain(variation, firstStation.coords.x,
firstStation.coords.y, firstStation.coords.z, true)
if not DoesEntityExist(train) then
print('[Transit] Failed to spawn train for route: ' .. routeId)
return
end
SetTrainSpeed(train, 0.0)
SetTrainCruiseSpeed(train, 0.0)
SetEntityAsMissionEntity(train, true, true)
-- Store train state
activeTrains[routeId] = {
entity = train,
route = route,
currentStation = 1,
state = 'stopped', -- stopped, departing, moving, arriving
stateTimer = GetGameTimer(),
passengers = {},
}
return train
end
-- Train movement controller
CreateThread(function()
while true do
for routeId, trainData in pairs(activeTrains) do
local train = trainData.entity
if not DoesEntityExist(train) then
activeTrains[routeId] = nil
goto continue
end
local station = trainData.route.stations[trainData.currentStation]
local elapsed = GetGameTimer() - trainData.stateTimer
if trainData.state == 'stopped' then
if elapsed >= (station.stopDuration * 1000) then
-- Depart from station
trainData.state = 'departing'
trainData.stateTimer = GetGameTimer()
AnnounceToPassengers(trainData, 'Doors closing. Next stop: '
.. GetNextStationName(trainData))
end
elseif trainData.state == 'departing' then
local speed = math.min(15.0, elapsed * 0.005)
SetTrainCruiseSpeed(train, speed)
SetTrainSpeed(train, speed)
if speed >= 15.0 then
trainData.state = 'moving'
end
elseif trainData.state == 'moving' then
local nextIdx = trainData.currentStation + 1
if nextIdx > #trainData.route.stations then
nextIdx = 1
end
local nextStation = trainData.route.stations[nextIdx]
local trainCoords = GetEntityCoords(train)
local dist = #(trainCoords - nextStation.coords)
if dist < 200.0 then
trainData.state = 'arriving'
trainData.stateTimer = GetGameTimer()
AnnounceToPassengers(trainData, nextStation.announceText)
end
elseif trainData.state == 'arriving' then
local nextIdx = trainData.currentStation + 1
if nextIdx > #trainData.route.stations then
nextIdx = 1
end
local nextStation = trainData.route.stations[nextIdx]
local trainCoords = GetEntityCoords(train)
local dist = #(trainCoords - nextStation.coords)
-- Gradually slow down
local speed = math.max(0.0, dist * 0.08)
SetTrainCruiseSpeed(train, speed)
SetTrainSpeed(train, speed)
if dist < 3.0 then
SetTrainSpeed(train, 0.0)
SetTrainCruiseSpeed(train, 0.0)
trainData.currentStation = nextIdx
trainData.state = 'stopped'
trainData.stateTimer = GetGameTimer()
end
end
:continue:
end
Wait(100)
end
end)
ركوب الركاب وإصدار التذاكر
عندما يتوقف قطار في محطة، عرض مطالبات التفاعل للاعبين القريبين للسماح لهم بالصعود. تحقق من أن اللاعب لديه تذكرة صالحة أو تصريح مرور قبل السماح له بالصعود. يمكن شراء التذاكر من آلات التذاكر في كل محطة باستخدام واجهة NUI بسيطة تعرض المسارات والأسعار المتاحة. بمجرد الصعود، يتم نقل اللاعب إلى داخل عربة القطار وتعيين موقعه نسبة إلى كيان القطار ليتحرك معه. تعمل الديكورات الداخلية المدمجة في GTA للتطبيقات الأساسية، لكن الديكورات المخصصة باستخدام الأجسام المرفقة أو الحالات توفر تجربة أفضل مع مقاعد، مناطق وقوف، ونوافذ تعرض المناظر المارة. تتبع المحطة التي صعد منها كل راكب ليحسب النظام فروق الأجرة بناءً على المسافة. عرض اسم المحطة التالية ووقت الوصول المقدر داخل العربة عبر عنصر نص ثلاثي الأبعاد أو عرض NUI مرفق يتحدث مع تقدم القطار في مساره.
نظام الحافلات وسائقو NPC
تكمل الحافلات شبكة القطارات بتغطية المناطق التي لا تصل إليها السكك الحديدية. استدعِ حافلات يقودها NPC تتبع مسارات محددة مسبقًا عبر شوارع المدينة، وتتوقف عند محطات الحافلات المعلّمة لاصطحاب وإسقاط اللاعبين. يستخدم سائق NPC نظام المهام في GTA للتنقل بين المحطات باستخدام TaskVehicleDriveToCoordLongrange مع أعلام قيادة مناسبة للامتثال لقوانين المرور والتوقف في المواقع المخصصة. عند كل توقف، ينتظر الحافلة لمدة محددة بينما يصعد أو ينزل اللاعبون، ثم يواصل سائق NPC إلى التوقف التالي. عرض معلومات المسار عند مواقع توقف الحافلات تظهر رقم المسار، الوجهة، والوقت المقدر للانتظار حتى وصول الحافلة التالية. للنسخة التي يقودها اللاعب، اسمح للاعبين الذين لديهم وظيفة سلطة النقل بقيادة الحافلات يدويًا، مع كسب أجر لكل راكب يتم نقله وأجر إضافي للحفاظ على الالتزام بالجدول الزمني.
خريطة النقل وواجهة المحطة
إنشاء خريطة نقل يمكن للاعبين الوصول إليها من هواتفهم، أكشاك المحطات، أو شاشات مواقف الحافلات. يجب أن تعرض الخريطة جميع الخطوط النشطة ملونة حسب الخط، مواقع المحطات مع مؤشرات التبديل حيث تتصل خطوط متعددة، ومواقع القطارات في الوقت الحقيقي التي يتم تحديثها كل بضع ثوانٍ. يجب أن تعرض واجهة المحطة في الأكشاك الوقت الحالي، الوصولات القادمة لكل خط يخدم تلك المحطة، أي انقطاعات أو تأخيرات في الخدمة، وواجهة شراء التذاكر. نفذ خريطة النقل كطبقة NUI تعرض شبكة السكك الحديدية بشكل تخطيطي بدلاً من جغرافي، مشابه لخرائط المترو الحقيقية التي تعطي الأولوية للوضوح على الدقة الجغرافية. أضف مؤشرات في الوقت الحقيقي تظهر موقع كل قطار كنقطة متحركة على طول خط مساره، مما يمنح اللاعبين تغذية راجعة فورية حول مدة انتظارهم للخدمة القادمة.
نظام الأجرة وبطاقات التنقل
نفذ نظام أجرة متدرج مع تذاكر رحلة واحدة، تصاريح يومية، واشتراكات شهرية. تكلف التذاكر الفردية الأجرة الأساسية وتنتهي صلاحيتها بعد رحلة واحدة. تسمح التصاريح اليومية بركوب غير محدود لمدة أربع وعشرين ساعة داخل اللعبة بسعر ثابت يصبح اقتصادياً بعد ثلاث أو أربع رحلات. توفر التصاريح الشهرية أفضل قيمة لكل رحلة للركاب المنتظمين وتُخزن كعنصر في مخزون اللاعب مع طابع زمني لانتهاء الصلاحية. تحقق من الأجرة عند بوابات دخول المحطات باستخدام التفاعلات المستهدفة على حواجز الدوران، وعلى الحافلات من خلال تفاعل السائق عند الصعود. بالنسبة للتسعير بناءً على المسافة، احسب الأجرة عند خروج الراكب بناءً على عدد المحطات التي تم قطعها. اللاعبون بدون تذاكر صالحة الذين يُقبض عليهم خلال عمليات تفتيش عشوائية من قبل موظفي هيئة النقل يتلقون غرامات، مما يضيف عنصر تنفيذ للعب دور وظيفة هيئة النقل.
الأداء والمزامنة
القطارات والحافلات هي كيانات كبيرة يجب مزامنتها عبر جميع العملاء، مما يجعلها ميزات حساسة للأداء تتطلب تحسينًا دقيقًا. استخدم إدارة الحالة على جانب الخادم للتحكم في مواقع القطارات وبث التحديثات إلى العملاء، مما يسمح لكل عميل بعرض كيان القطار محليًا بناءً على الإحداثيات المستلمة. قم بإزالة كيانات القطار للاعبين الذين يبعدون عن أي محطة أو خط سكة حديد لتقليل عبء العرض، ولا تولدها إلا عندما يدخل اللاعب منطقة شبكة السكك الحديدية. يجب أن يكون سائقو الحافلات NPC نشطين فقط عندما يكون اللاعبون قريبين، مع استخدام الحافلات البعيدة لتقريب الموقع المبسط بدلاً من مسار AI الكامل. حدد العدد الإجمالي للقطارات والحافلات المتزامنة عبر الخادم لمنع تدهور الأداء خلال ساعات الذروة. وزع أوقات المغادرة عبر مسارات مختلفة حتى لا تولد مركبات متعددة في نفس الوقت. قم بتنظيف جميع كيانات النقل عند إعادة تشغيل المورد وطبق منطق الاسترداد الذي يعيد حساب مواقع القطارات بناءً على الجدول الزمني عند بدء المورد، بحيث تظهر القطارات في المواقع الصحيحة فورًا بدلاً من البدء من المحطة الأولى في كل مرة.