FiveM Mekanik Sistemi: Modifiye, Tamir ve Araç Meslekleri
Eksiksiz bir FiveM tamirci sistemi oluşturun. Tamir, modifiye, çekici ile bağlama, dükkan arayüzleri ve QBCore ile ESX sunucuları için en iyi tamirci scriptleri.
Agency Scripts
Agency Scripts Kurucusu ve Baş Geliştiricisi
Mekanik Mesleği Mimarisi Tasarımı
Mekanik mesleği sistemi, bir FiveM roleplay sunucusu için geliştirilebilecek en popüler ve tatmin edici özelliklerden biridir. Yalnızca şunu çağıran basit onarım scriptlerinin aksine SetVehicleFixed(), düzgün bir mekanik sistemi, özel roller, parça envanterleri ve rol yapmayı teşvik eden oyuncular arası etkileşimlerle eksiksiz bir meslek ekonomisi sunar. Mimari, harita genelinde her biri farklı oyuncu gruplarına ait olabilecek birden fazla mekanik dükkanını ve kimin hangi onarımları yapabileceğini belirleyen bir meslek kademesi hiyerarşisini hesaba katmalıdır. Temelde, dükkan konumlarını, her kademedeki mevcut hizmetleri, parça fiyatlandırmasını ve motor değişimi veya turbo montajı gibi gelişmiş onarımların kilidini açmak için gereken meslek kademelerini tanımlayan ortak bir yapılandırmaya ihtiyacınız vardır. Sistem, QBCore, ESX veya özel bir çözüm olsun, sunucunuzun mevcut meslek altyapısıyla entegre olmalıdır, böylece oyuncular doğru maaş bordrosu yönetimi ve mesai durumu takibiyle mekanik rolüne giriş ve çıkış yapabilir.
Meslek Rütbeleri ve Yetki Sistemi
Kademeli bir meslek rütbe sistemi, mekanik mesleğinize derinlik katar ve oyuncuları rütbeleri tırmanmaya teşvik eder. Belirli izinlere sahip net rütbeler tanımlayarak başlayın: bir stajyer yalnızca araçları yıkayabilir ve küçük gövde hasarlarını onarabilir, standart bir mekanik motor onarımlarını ve lastik değişimlerini yapabilir, kıdemli bir mekanik performans tuning ve boyama işlemlerinin kilidini açar, dükkan sahibi ise çalışanları yönetebilir ve hizmet fiyatlandırmasını belirleyebilir. Hem istemcinin hem de sunucunun bunlara tutarlı bir şekilde başvurabilmesi için bu rütbe tanımlarını paylaşımlı bir config içinde saklayın. İşte rütbeleri izin verilen hizmetlerle eşleştiren örnek bir yapılandırma:
Config.MechanicGrades = {
[0] = {
label = 'Trainee',
services = {'wash', 'body_minor'},
payMultiplier = 0.7
},
[1] = {
label = 'Mechanic',
services = {'wash', 'body_minor', 'body_major', 'engine_repair', 'tire_replace', 'brake_repair'},
payMultiplier = 1.0
},
[2] = {
label = 'Senior Mechanic',
services = {'wash', 'body_minor', 'body_major', 'engine_repair', 'tire_replace',
'brake_repair', 'spray_paint', 'performance_tune', 'turbo_install'},
payMultiplier = 1.3
},
[3] = {
label = 'Shop Owner',
services = 'all',
payMultiplier = 1.5,
canManage = true
}
}
Config.ServicePrices = {
wash = 200,
body_minor = 800,
body_major = 2500,
engine_repair = 3500,
tire_replace = 1200,
brake_repair = 1500,
spray_paint = 5000,
performance_tune = 15000,
turbo_install = 25000
}
Server tarafında, herhangi bir hizmetin yürütülmesine izin vermeden önce daima oyuncunun rütbesini doğrulayın. Hangi hizmetlerin mevcut olduğunu bildirmesi konusunda client tarafına asla güvenmeyin; çünkü bir hileci NUI'yi değiştirerek herhangi bir hizmet talebi gönderebilir. Server callback'i, onarıma devam etmeden önce oyuncunun mevcut mesleğini, rütbe seviyesini ve talep edilen hizmetin rütbesine ait hizmet listesinde yer alıp almadığını kontrol etmelidir.
Araç Tamir Mekanikleri ve Parça Sistemi
Gerçekçi tamir mekanikleri tek bir native çağrısının ötesine geçer. Bir aracı anında tamir etmek yerine, tamir sürecini zaman alan ve mekaniğin envanterinden parça tüketen adımlara bölün. Bir oyuncu arabasını motor tamiri için getirdiğinde, mekaniğin kişisel envanterinde veya dükkanın ortak deposunda doğru parçalara sahip olması gerekir. Tamirin zaman almasını simüle etmek için bir ilerleme çubuğu sistemi kullanın; bu, müşterinin beklediği ve mekanikle etkileşime girdiği doğal rol yapma anları yaratır. Tamir mantığı, native fonksiyonları kullanarak belirli araç bileşenlerini hedeflemelidir; böylece kaporta hasarını onarmadan motoru tamir edebilir veya motor sağlığını etkilemeden lastikleri değiştirebilirsiniz:
local RepairFunctions = {
engine_repair = function(vehicle)
local parts = {'engine_oil', 'spark_plugs', 'coolant'}
if not HasRequiredParts(parts) then
return false, 'Missing required parts'
end
RemovePartsFromInventory(parts)
-- Animate the repair
TaskTurnPedToFaceEntity(PlayerPedId(), vehicle, 1000)
Wait(1000)
if not StartProgressBar('Repairing engine...', 15000, 'mechanic_repair') then
return false, 'Repair cancelled'
end
SetVehicleEngineHealth(vehicle, 1000.0)
SetVehicleEngineOn(vehicle, true, true, false)
return true
end,
body_major = function(vehicle)
local parts = {'body_panel', 'filler_putty', 'paint_primer'}
if not HasRequiredParts(parts) then
return false, 'Missing required parts'
end
RemovePartsFromInventory(parts)
if not StartProgressBar('Repairing body damage...', 20000, 'mechanic_repair') then
return false, 'Repair cancelled'
end
SetVehicleBodyHealth(vehicle, 1000.0)
SetVehicleDeformationFixed(vehicle)
return true
end,
tire_replace = function(vehicle, tireIndex)
local parts = {'tire_set'}
if not HasRequiredParts(parts) then
return false, 'Missing required parts'
end
RemovePartsFromInventory(parts)
if not StartProgressBar('Replacing tire...', 8000, 'mechanic_repair') then
return false, 'Repair cancelled'
end
SetVehicleTyreFixed(vehicle, tireIndex)
return true
end
}
Parça sistemi, sunucunuzda ek bir ekonomi katmanı oluşturur. Parçaları NPC toptancılarında stoklayın veya oyuncuların endüstriyel konumlarda üretmesine izin verin. Mekanik dükkanları parçaları toptan fiyatlarla toplu olarak satın alabilir ve ortak bir dükkan envanterinde saklayabilir; bu da dükkan sahibinin işlerin sorunsuz yürümesi için tedarik zincirini yönetmesi gerektiği anlamına gelir. Bu arz ve talep dinamiği, rol deneyimine muazzam bir derinlik katar.
Sprey Boyama ve Kozmetik Hizmetleri
Sprey boyama, bir tamirhanenin sunabileceği görsel açıdan en tatmin edici hizmetlerden biridir ve bunu iyi bir şekilde uygulamak, çeşitli araç rengi native fonksiyonlarıyla çalışmayı gerektirir. FiveM, birincil renk, ikincil renk, sedefli (pearlescent), jant rengi ve özel RGB değerleri için native'ler sunar. Tamircinin önceden ayarlanmış renkler arasından seçim yapmasını veya ekstra bir ücret karşılığında özel RGB değerleri girmesini sağlayan bir renk seçici UI oluşturun. Tamirci seçeneklere göz atarken NUI, rengi araca geçici olarak uygulayarak gerçek zamanlı bir önizleme göstermelidir. Tamirci boyama işlemini onayladıktan ve müşteri ödeme yaptıktan sonra sunucu tarafındaki renk uygulamasının nasıl yönetileceği aşağıda açıklanmıştır:
RegisterNetEvent('mechanic:server:applyPaint', function(netId, paintData, customerId)
local src = source
local Mechanic = QBCore.Functions.GetPlayer(src)
local Customer = QBCore.Functions.GetPlayer(customerId)
if not Mechanic or not Customer then return end
if Mechanic.PlayerData.job.name ~= 'mechanic' then return end
local gradeServices = Config.MechanicGrades[Mechanic.PlayerData.job.grade.level].services
if gradeServices ~= 'all' and not TableContains(gradeServices, 'spray_paint') then
return TriggerClientEvent('QBCore:Notify', src, 'Not authorized', 'error')
end
local price = paintData.isCustomRGB and Config.ServicePrices.spray_paint * 1.5
or Config.ServicePrices.spray_paint
if Customer.Functions.RemoveMoney('cash', price, 'mechanic-paint') then
local shopCut = math.floor(price * 0.6)
local mechanicCut = price - shopCut
Mechanic.Functions.AddMoney('cash', mechanicCut, 'mechanic-paint-commission')
AddToShopFunds(Mechanic.PlayerData.job.grade.level >= 3 and src, shopCut)
TriggerClientEvent('mechanic:client:applyPaint', customerId, netId, paintData)
TriggerClientEvent('QBCore:Notify', src, 'Paint applied - earned $' .. mechanicCut, 'success')
TriggerClientEvent('QBCore:Notify', customerId, 'Vehicle painted for $' .. price, 'success')
else
TriggerClientEvent('QBCore:Notify', src, 'Customer cannot afford this', 'error')
end
end)
Temel boyanın ötesinde, livery uygulaması, neon ışık montajı ve cam filmini ayrı kozmetik hizmetler olarak eklemeyi düşünün. Her hizmetin kendi parça gereksinimleri ve fiyat noktası olmalıdır. Örneğin neon ışıklar, parça envanterinden neon kitleri gerektirir ve şu SetVehicleNeonLightEnabled ve SetVehicleNeonLightsColour görsel efekti uygulamak için native'ler. Cam filmi uygulaması şunu kullanır: SetVehicleWindowTint yerel sunucu kuralları ile sınırlandırılabilecek farklı cam filmi seviyeleri ile; bu da polise yasa dışı cam filmleri nedeniyle oyuncuları kenara çekme gerekçesi sunar.
Performans Yükseltmeleri ve Tuning
Performans tuning, mekaniklerin sunucuda gerçekten öne çıkabileceği ve yüksek kazançlar elde edebileceği alandır. FiveM, şu kaynak üzerinden kapsamlı araç modifikasyonu native'leri sunar: SetVehicleMod bir mod type ve mod index kabul eden function. Mod türleri motor yükseltmelerini (tip 11), frenleri (tip 12), şanzımanı (tip 13), süspansiyonu (tip 15), zırhı (tip 16) ve turboyu (tip 18) kapsar. Her mod türü, aracın performansını kademeli olarak artıran birden fazla seviyeye sahiptir. Mevcut araç için mevcut yükseltmeleri, her seviyenin maliyetini ve ideal olarak hız, ivmelenme, frenleme ve yol tutuşu için önceki ve sonraki değerleri gösteren bir istatistik karşılaştırmasını içeren bir modifiye arayüzü oluşturun:
function GetAvailableUpgrades(vehicle)
local upgrades = {}
local modTypes = {
{type = 11, label = 'Engine', icon = 'fa-engine'},
{type = 12, label = 'Brakes', icon = 'fa-brake'},
{type = 13, label = 'Transmission', icon = 'fa-gears'},
{type = 15, label = 'Suspension', icon = 'fa-car'},
{type = 16, label = 'Armor', icon = 'fa-shield'},
{type = 18, label = 'Turbo', icon = 'fa-bolt'}
}
SetVehicleModKit(vehicle, 0)
for _, mod in ipairs(modTypes) do
local currentLevel = GetVehicleMod(vehicle, mod.type)
local maxLevel = GetNumVehicleMods(vehicle, mod.type)
local isTurbo = mod.type == 18
table.insert(upgrades, {
type = mod.type,
label = mod.label,
icon = mod.icon,
currentLevel = currentLevel,
maxLevel = isTurbo and 1 or maxLevel,
installed = isTurbo and IsToggleModOn(vehicle, mod.type) or currentLevel >= 0,
price = CalculateUpgradePrice(mod.type, currentLevel + 1)
})
end
return upgrades
end
function ApplyPerformanceUpgrade(vehicle, modType, level)
SetVehicleModKit(vehicle, 0)
if modType == 18 then
ToggleVehicleMod(vehicle, 18, true)
else
SetVehicleMod(vehicle, modType, level, false)
end
end
Performans yükseltmeleri; turbo kitleri, yarış şanzımanları veya spor fren tertibatları gibi yüksek değerli parçalar gerektirmelidir. Bu parçalar uzman tedarikçilerden temin edilebilir veya uygun yeteneklere sahip oyuncular tarafından üretilebilir, bu da sunucu ekonomisini zenginleştiren meslekler arası bağımlılıklar oluşturur. İstemcilerin parasını ödemedikleri veya parçalarına sahip olmadıkları modifikasyonları uygulamasını önlemek için yükseltme isteklerini her zaman sunucuda doğrulayın.
Faturalandırma Sistemi ve Gelir Paylaşımı
Kullanışlı bir faturalandırma sistemi, tüm tamirci deneyimini birbirine bağlar; mekanik, müşteri ve dükkan arasındaki finansal işlemleri yönetir. Bir mekanik bir hizmeti tamamladığında, gerçekleştirilen her işlemi ve maliyetini listeleyen ayrıntılı bir fatura oluşturun. Faturayı müşteriye, ödeme işlenmeden önce onaylaması gereken bir bildirim veya NUI açılır penceresi aracılığıyla gösterin. Geliri işi yapan mekanik ile dükkanın işletme hesabı arasında bölün; paylaşım oranı dükkan sahibi tarafından yapılandırılabilsin. İşte fatura oluşturma ve ödeme işlemlerini yürüten server taraflı bir faturalandırma sistemi:
local activeInvoices = {}
RegisterNetEvent('mechanic:server:createInvoice', function(customerId, services)
local src = source
local Mechanic = QBCore.Functions.GetPlayer(src)
local Customer = QBCore.Functions.GetPlayer(customerId)
if not Mechanic or not Customer then return end
if Mechanic.PlayerData.job.name ~= 'mechanic' then return end
local totalPrice = 0
local lineItems = {}
for _, service in ipairs(services) do
local price = Config.ServicePrices[service.name]
if price then
totalPrice = totalPrice + price
table.insert(lineItems, {
name = service.label,
price = price
})
end
end
local invoiceId = 'INV-' .. os.time() .. '-' .. math.random(1000, 9999)
activeInvoices[invoiceId] = {
mechanic = src,
customer = customerId,
total = totalPrice,
items = lineItems,
shopId = Mechanic.PlayerData.metadata.currentShop,
timestamp = os.time()
}
TriggerClientEvent('mechanic:client:showInvoice', customerId, invoiceId, lineItems, totalPrice)
end)
RegisterNetEvent('mechanic:server:payInvoice', function(invoiceId)
local src = source
local invoice = activeInvoices[invoiceId]
if not invoice or invoice.customer ~= src then return end
local Customer = QBCore.Functions.GetPlayer(src)
local Mechanic = QBCore.Functions.GetPlayer(invoice.mechanic)
if Customer.Functions.RemoveMoney('cash', invoice.total, 'mechanic-invoice') then
local mechanicShare = math.floor(invoice.total * 0.4)
local shopShare = invoice.total - mechanicShare
if Mechanic then
Mechanic.Functions.AddMoney('cash', mechanicShare, 'mechanic-wage')
TriggerClientEvent('QBCore:Notify', invoice.mechanic,
'Received $' .. mechanicShare .. ' for services', 'success')
end
UpdateShopBalance(invoice.shopId, shopShare)
activeInvoices[invoiceId] = nil
TriggerClientEvent('QBCore:Notify', src, 'Paid $' .. invoice.total, 'success')
else
TriggerClientEvent('QBCore:Notify', src, 'Not enough cash', 'error')
end
end)
Sunucunuzda bir kripto sistemi varsa nakit, banka transferleri ve hatta kripto para dahil olmak üzere birden fazla ödeme yöntemini desteklemeyi değerlendirin. Dükkan sahiplerinin gelir geçmişlerini inceleyebilmeleri, en iyi performans gösteren tamircilerini belirleyebilmeleri ve şüpheli faturalandırma modellerini tespit edebilmeleri için tüm işlemleri bir veritabanı günlüğünde takip edin. Bu finansal takip ayrıca vergi sistemlerini ve devletin tamirci dükkanlarını denetleyebileceği kamu roleplay etkileşimlerini de mümkün kılar.
Stash ve Mağaza Envanteri Yönetimi
Her tamirhanenin, parçaların depolandığı ve görevdeki tüm çalışanların erişebildiği paylaşımlı bir zulaya ihtiyacı vardır. Yalnızca yetkili mekaniklerin erişebileceği dükkana özel bir zula oluşturmak için ox_inventory, qb-inventory veya özel bir çözüm olsun, sunucunuzun envanter sistemiyle entegre edin. Dükkan sahibi, toptan tedarikçi bir NPC'den parça sipariş edebilmelidir; bu işlem dükkanın işletme hesabından para düşer ve yapılandırılabilir bir teslimat gecikmesinin ardından parçaları zulaya ekler. Bu gecikme, gerçek dünyadaki tedarik zinciri lojistiğini simüle eder ve anında stok yenilenmesini önler. Dükkan sahibinin hangi tamircinin hangi parçaları aldığını görebilmesi ve iç hırsızlığın önlenmesi için zulaya erişimi bir logda takip edin. Client tarafında zulayı açmak için dükkanın içindeki alet dolabı veya parça rafı gibi belirli bir prop üzerinde hedef (target) etkileşimi kullanın. Zulayı; tamircilerin turbo gövdesi, çark ve wastegate'i birleştirerek eksiksiz bir turbo kiti oluşturması gibi ham maddelerden karmaşık parçaları monte edebileceği bir crafting sistemiyle birleştirerek mesleğe beceriye dayalı bir katman daha ekleyin.
Çekici ve Yol Yardımı
Mekanik mesleğini çekici ve yol yardım hizmetlerini kapsayacak şekilde genişletmek, mesleğin aktivitesini ve gelir potansiyelini büyük ölçüde artırır. Mekanikler dükkanlarından bir çekici alabilmeli, yolda kalan bir oyuncunun konumuna gidebilmeli ve arızalı aracı bağlamak için şunu kullanabilmelidir: AttachEntityToEntity native ve onarım için dükkana geri çekin. Oyuncuların telefonları aracılığıyla yol yardımı talep edebileceği ve görevdeki tüm tamircilerin görebileceği bir harita blip'i oluşturan bir sevk sistemi uygulayın. Çağrıyı ilk kabul eden tamirci işi alır ve müşterinin konumuna bir GPS rotası çizilir. Bağlama sistemi için, çekilen aracın kasa üzerinde düzgün durmasını sağlamak amacıyla çekici modeline göre uygun ofset konumlarını hesaplayın. Çekici hizmetine mesafeye dayalı bir ücret ekleyin, böylece daha uzun çekimler müşteriye daha pahalıya mal olur, tamircileri kendi bölgelerindeki çağrılarla ilgilenmeye teşvik ederken aynı zamanda haritanın diğer ucundaki kazançlı uzun mesafe işlerini almalarına olanak tanır.