نظام الطعام والمطاعم في FiveM: برمجة المطابخ
تشغيل مطاعم داخل اللعبة في FiveM. وصفات الطهي، واجهات الكاشير، وظائف التوصيل وأفضل سكربتات الطعام لإحياء مشهد الطعام في مدينتك.
Agency Scripts
المؤسس والمطور الرئيسي في Agency Scripts
لماذا تعزز أنظمة المطاعم اللعب التمثيلي
تُعد أنظمة الطعام والمطاعم من أكثر الميزات الاجتماعية تفاعلاً التي يمكنك إضافتها إلى خادم FiveM للعب الأدوار. على عكس الأنشطة الفردية مثل التعدين أو الصيد، تخلق المطاعم نقاط تجمع عضوية حيث يطبخ اللاعبون ويقدمون الطعام ويتناولونه معًا. يوفر نظام المطاعم المصمم جيدًا للاعبين المدنيين وظيفة ذات معنى لا تنطوي على الجريمة، ويوفر سببًا للشخصيات لزيارة المواقع بانتظام، ويُدخل اقتصادًا من خلال شراء المكونات. كما تخلق المطاعم سلاسل توريد عند دمجها مع سكريبتات الزراعة أو الصيد، مما يعني أن لاعبًا يزرع الطماطم، وآخر يوصلها، وثالث يطهوها في برغر. هذه الحلقة التفاعلية في طريقة اللعب هي ما يميز الخادم الحي عن الخادم الذي يكرر اللاعبون فيه نفس المسار مرارًا وتكرارًا. يمكن أن توفر عناصر الطعام نفسها تعزيزات مؤقتة للصحة أو القدرة على التحمل أو تجديد الدرع، مما يجعل المطاعم ذات صلة بكل لاعب على الخادم بغض النظر عن وظيفته أو فصيله.
تكوين المطعم وتصميم القائمة
ابدأ بتعريف مواقع مطاعمك، قوائم الطعام، والمكونات المطلوبة لكل طبق. تتيح التهيئة المعتمدة على البيانات لمالكي السيرفر إضافة مطاعم جديدة دون تعديل المنطق الأساسي. يجب أن يكون لكل مطعم هوية فريدة من خلال عروض القائمة، الديكورات الداخلية، وزي موظفي NPC. هيكل تهيئتك بحيث يسرد كل عنصر في القائمة مكوناته المطلوبة، وقت التحضير، سعر البيع، وأي تأثيرات تعزيز يمنحها للمستهلك. تعني هذه الطريقة أن موازنة اقتصاد الطعام تعتمد على تعديل قيم التهيئة بدلاً من إعادة كتابة الكود:
Config.Restaurants = {
['burgershot'] = {
label = 'Burger Shot',
blip = { sprite = 106, color = 1, scale = 0.8 },
zones = {
counter = vector3(-1196.42, -894.04, 13.98),
kitchen = vector3(-1199.71, -897.12, 13.98),
storage = vector3(-1202.84, -899.35, 13.98),
},
menu = {
{
item = 'bleeder_burger',
label = 'Bleeder Burger',
price = 25,
ingredients = {
{ item = 'raw_patty', amount = 2 },
{ item = 'burger_bun', amount = 1 },
{ item = 'lettuce', amount = 1 },
{ item = 'cheese_slice', amount = 2 },
},
craftTime = 8000,
buffs = {
hunger = 45,
thirst = 5,
armor_regen = { amount = 2, duration = 120 }
}
},
{
item = 'heartstopper',
label = 'Heart Stopper',
price = 40,
ingredients = {
{ item = 'raw_patty', amount = 3 },
{ item = 'burger_bun', amount = 1 },
{ item = 'bacon', amount = 4 },
{ item = 'cheese_slice', amount = 3 },
{ item = 'onion_ring', amount = 2 },
},
craftTime = 12000,
buffs = {
hunger = 80,
thirst = -10,
stamina_boost = { amount = 15, duration = 180 }
}
},
},
requiredJob = 'burgershot',
},
}
ال zones جدول يفصل المطعم إلى مناطق وظيفية. منطقة العداد هي حيث يطلب الزبائن الطعام ويتلقونه. منطقة المطبخ مقصورة على الموظفين الذين يستخدمونها لطهي الأصناف. منطقة التخزين هي حيث تُخزن وتُدار المكونات. هذا الفصل المكاني يفرض سير عمل واقعي حيث لا يمكن للطباخ تقديم الطعام مباشرة من الموقد، مما يخلق تعاوناً طبيعياً بين موظفي الواجهة الأمامية والمطبخ.
آليات الطهي وتدفق الحرفية
يجب أن يشعر عملية الطهي بالتفاعل دون أن تكون مملة. عندما يبدأ اللاعب في طهي عنصر، تحقق من وجود جميع المكونات المطلوبة في مخزون المطعم، اخصمها، وابدأ شريط تقدم أو تسلسل لعبة مصغرة. تعمل أشرطة التقدم البسيطة للعناصر الأساسية، لكن إضافة ألعاب مهارة للأطباق المميزة تخلق إحساسًا بالإتقان وتمنع استغلال الطهي أثناء عدم النشاط. يجب أن تستخدم حركة الطهي السيناريوهات الأصلية المناسبة في GTA مثل الشواء أو عداد المطبخ لتوصيل بصري لما يفعله اللاعب للمشاهدين القريبين:
function StartCooking(restaurantId, menuIndex)
local restaurant = Config.Restaurants[restaurantId]
local recipe = restaurant.menu[menuIndex]
-- Check ingredients in storage
local hasAll = lib.callback.await('restaurant:checkIngredients', false,
restaurantId, recipe.ingredients)
if not hasAll then
lib.notify({ description = 'Missing ingredients!', type = 'error' })
return
end
-- Lock player into cooking animation
local playerPed = PlayerPedId()
local animDict = 'mini@repair'
lib.requestAnimDict(animDict)
TaskPlayAnim(playerPed, animDict, 'fixing_a_player', 8.0, -8.0,
-1, 1, 0, false, false, false)
-- Cooking progress with skill check
local success = lib.skillCheck(
{'easy', 'easy', 'medium'},
{'w', 'a', 's', 'd'}
)
ClearPedTasks(playerPed)
if success then
TriggerServerEvent('restaurant:finishCooking', restaurantId, menuIndex)
lib.notify({ description = 'Cooked: ' .. recipe.label, type = 'success' })
else
-- Failed cooking wastes some ingredients
TriggerServerEvent('restaurant:failedCooking', restaurantId, menuIndex)
lib.notify({ description = 'Burnt the food! Some ingredients wasted.',
type = 'error' })
end
end
تضيف آلية فحص المهارة عنصر المخاطرة والمكافأة للطهي. يجب أن تهدر المحاولات الفاشلة جزءًا من المكونات بدلاً من كلها، حتى لا يعاقب اللاعبون الجدد بشدة مع تحفيز تحسين المهارة. يمكنك تعديل الصعوبة بناءً على قيمة الطبق، مما يجعل العناصر الرخيصة سهلة الطهي والأطباق المميزة باهظة الثمن تتطلب اهتمامًا حقيقيًا. هذا يخلق تقدمًا طبيعيًا حيث يبدأ الموظفون الجدد بالعناصر البسيطة ويتدرجون إلى القائمة المميزة.
سلسلة توريد المكونات
تحتاج المطاعم إلى تدفق ثابت من المكونات، وكيفية حصول اللاعبين على تلك المكونات تحدد جزءًا رئيسيًا من حلقة اللعب. هناك ثلاثة أساليب شائعة: الشراء من بائعي الجملة NPC، الحصول من مزارع يديرها اللاعبون أو الصيد، ونموذج هجين. الأسلوب بالجملة أبسط في التنفيذ ويضمن التوفر، لكنه يفتقر إلى تفاعل اللاعب. الحصول من لاعبين آخرين يخلق علاقات اقتصادية غنية لكنه يعرض المطعم للتوقف عندما يكون الموردون غير متصلين. النموذج الهجين هو الأفضل: المكونات الأساسية مثل الخبز، الزيت، والتوابل تأتي من NPC، بينما المكونات المميزة مثل اللحوم الطازجة، الخضروات العضوية، والصلصات الخاصة يجب الحصول عليها من أنشطة اللاعبين. هذا يضمن أن المطاعم يمكنها العمل دائمًا على مستوى أساسي مع مكافأة سلسلة التوريد الكاملة عند اتصال كل الأجزاء. نفذ نظام تخزين لكل مطعم يتتبع كميات المكونات ويسمح للمديرين بوضع طلبات جملة تخصم من حساب المطعم المصرفي:
RegisterNetEvent('restaurant:orderSupplies', function(restaurantId, order)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
-- Verify player is manager rank
if Player.PlayerData.job.name ~= restaurantId then return end
if Player.PlayerData.job.grade.level < 3 then
TriggerClientEvent('QBCore:Notify', src,
'Only managers can order supplies', 'error')
return
end
-- Calculate total cost
local totalCost = 0
for _, item in ipairs(order) do
local wholesalePrice = Config.WholesalePrices[item.name]
if wholesalePrice then
totalCost = totalCost + (wholesalePrice * item.amount)
end
end
-- Deduct from restaurant bank account
local balance = exports['qb-management']:GetAccount(restaurantId)
if balance < totalCost then
TriggerClientEvent('QBCore:Notify', src,
'Insufficient restaurant funds', 'error')
return
end
exports['qb-management']:RemoveMoney(restaurantId, totalCost)
-- Add items to restaurant storage
for _, item in ipairs(order) do
AddToRestaurantStorage(restaurantId, item.name, item.amount)
end
TriggerClientEvent('QBCore:Notify', src,
string.format('Order placed! $%d deducted', totalCost), 'success')
end)
تدفق طلبات العملاء والخدمة
يجب أن تكون تجربة العميل سلسة سواء كانوا يطلبون من كاشير NPC أو موظف لاعب. عند اقتراب العميل من منطقة العداد، عرض واجهة قائمة تظهر العناصر المتاحة مع أسعارها وأي أوصاف لتعزيزات نشطة. بالنسبة للمطاعم التي يعمل بها اللاعبون، يجب توجيه الطلب إلى شاشة المطبخ حتى يرى الطهاة الطلبات الواردة في الوقت الحقيقي. نفذ نظام قائمة انتظار الطلبات الذي يتتبع كل طلب من وضعه حتى التحضير والتسليم. هذا يخلق محاكاة للوجبات السريعة حيث يتكدس المطبخ خلال فترات الذروة، مضيفًا ضغطًا حقيقيًا على دور الطهي. عرض حالة الطلب للعملاء بمؤشرات بسيطة: تم الطلب، جاري الطهي، جاهز للاستلام. عند جاهزية الطعام، أخطر العميل ودعه يستلمه من العداد. لتجربة مميزة، اسمح للنادلين اللاعبين بتوصيل الطعام مباشرة إلى العملاء الجالسين على الطاولات، مع كسب إكراميات بناءً على سرعة الخدمة.
تعزيزات الطعام وتأثيرات الاستهلاك
يجب أن توفر عناصر الطعام فوائد لعب ذات مغزى تتجاوز مجرد استعادة الجوع. نفذ نظام تعزيز حيث تمنح الأطعمة المختلفة تعديلات مؤقتة للإحصائيات تشجع اللاعبين على تناول الطعام بشكل استراتيجي قبل الأنشطة. وجبة تعزز القدرة على التحمل قبل مطاردة سيرًا على الأقدام، طبق يعيد تجديد الدرع قبل عملية سطو، أو وجبة تعافي صحة مع مرور الوقت بعد قتال، كلها تجعل عناصر الطعام ذات قيمة حقيقية في اقتصاد الخادم. تتبع التعزيزات النشطة لكل لاعب وعرضها في Agency HUD حتى يعرف اللاعبون التأثيرات التي لديهم حاليًا ومتى تنتهي صلاحيتها:
local activeBuffs = {}
function ApplyFoodBuff(buffType, amount, duration)
-- Remove existing buff of same type
if activeBuffs[buffType] then
activeBuffs[buffType].active = false
end
activeBuffs[buffType] = {
amount = amount,
endTime = GetGameTimer() + (duration * 1000),
active = true
}
-- Send buff data to HUD
SendNUIMessage({
action = 'addBuff',
buffType = buffType,
amount = amount,
duration = duration
})
-- Create buff application thread
CreateThread(function()
local buff = activeBuffs[buffType]
while buff.active and GetGameTimer() < buff.endTime do
if buffType == 'armor_regen' then
local current = GetPedArmour(PlayerPedId())
if current < 100 then
SetPedArmour(PlayerPedId(), math.min(100, current + amount))
end
elseif buffType == 'stamina_boost' then
RestorePlayerStamina(PlayerId(), amount * 0.1)
elseif buffType == 'health_regen' then
local current = GetEntityHealth(PlayerPedId())
local max = GetEntityMaxHealth(PlayerPedId())
if current < max then
SetEntityHealth(PlayerPedId(), math.min(max, current + amount))
end
end
Wait(1000)
end
activeBuffs[buffType] = nil
SendNUIMessage({ action = 'removeBuff', buffType = buffType })
end)
end
وازن تعزيزات الطعام بعناية بحيث تعزز طريقة اللعب دون أن تصبح إلزامية. يجب أن توفر التعزيزات ميزة ملحوظة دون أن تكون قوية جدًا بحيث يشعر اللاعبون بأنهم مضطرون للأكل قبل كل نشاط. حافظ على مدة معتدلة، بين دقيقتين وخمس دقائق، حتى تظل اقتصاديات التعزيز نشطة. فكر في إضافة تناقص العوائد إذا تم استهلاك نفس الطعام مرارًا خلال فترة قصيرة لمنع استغلال تراكم التعزيزات.
إدارة الموظفين والرواتب
يحتاج نظام المطعم إلى هيكل تنظيمي مناسب مع أدوار وصلاحيات مختلفة. حدد ثلاث مستويات على الأقل: عامل، مشرف، ومدير. يمكن للعاملين طهي العناصر وخدمة الزبائن. يمكن للمشرفين القيام بكل ما يفعله العاملون بالإضافة إلى إدارة تخزين المكونات والموافقة على الطلبات. يمتلك المديرون السيطرة الكاملة بما في ذلك توظيف وفصل الموظفين، تحديد الأسعار، والوصول إلى حساب البنك الخاص بالمطعم. اربط الرواتب بإيرادات المطعم بحيث يكسب الموظفون أجرًا أساسيًا بالإضافة إلى عمولة على العناصر التي يطهونها أو يخدمونها شخصياً. هذا يحفز المشاركة النشطة بدلاً من تسجيل الدخول أثناء عدم النشاط. تتبع إحصائيات الموظف الفردية مثل العناصر المطهوة، الزبائن المخدومين، والإيرادات المتولدة لإنشاء لوحات المتصدرين ومراجعات الأداء التي تضيف عمقًا لتجربة الوظيفة.
تحسين الأداء
تتضمن أنظمة المطاعم عدة مناطق تفاعل، شخصيات NPC، أشياء دعائم، وتتبع الطلبات في الوقت الحقيقي الذي قد يجهد أداء العميل إذا لم يتم تحسينه بعناية. استخدم تفاعلات نظام الهدف بدلاً من فحوصات المسافة المعتمدة على العلامات لإلغاء حسابات الإحداثيات لكل إطار. قم بعرض دعائم داخل المطعم فقط عندما يكون اللاعبون داخل المبنى باستخدام IsPlayerInScope التحققات. قم بتجميع رسائل NUI الخاصة بك لعرض قائمة الطلبات بدلاً من إرسال تحديثات فردية لكل تغيير في الطلب. على جانب الخادم، قم بتخزين مخزونات المطاعم في الذاكرة واكتب إلى قاعدة البيانات بفاصل زمني بدلاً من بعد كل تغيير في المكونات. عندما تكون عدة مطاعم نشطة في نفس الوقت، قم بتوزيع دورات مزامنة قاعدة البيانات لتجنب ارتفاعات الكتابة. قم بتنظيف جميع العلامات، الدعائم، وكيانات NPC عند توقف المورد لمنع تراكم الكيانات اليتيمة عبر إعادة تشغيل الموارد. اختبر نظامك تحت الحمل مع تشغيل عدة مطاعم، وعمل عدة طهاة في نفس الوقت، وتدفق مستمر من طلبات العملاء لتحديد نقاط الاختناق قبل أن يكتشفها اللاعبون.