Bloga Geri Dön
Tutorial7 dk. okuma

FiveM Otomat Scripti: Yiyecek, İçecek ve Daha Fazlası

FiveM sunucunuza çalışan otomatlar ekleyin. Atıştırmalıklar, içecekler, özel eşyalar, prop yerleşimi ve dakikalar içinde kurulabilen en iyi otomat scriptleri.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Otomatlar Sunucunuza Neden Derinlik Katar

Otomatlar ve otomatik mağaza sistemleri, her roleplay ekonomisinde kritik bir rol oynar. Bir mağaza görevlisinin çevrimiçi olmasına gerek kalmadan yiyecek, su, sigara ve temel malzemeler gibi temel eşyalara 7/24 erişim sağlarlar. Kolaylık sağlamanın ötesinde, oyuncuların bir araya geldiği doğal toplanma noktaları oluşturarak benzinliklerde, hastanelerde ve ofis binalarında kendiliğinden gelişen roleplay karşılaşmalarına zemin hazırlarlar. İyi uygulanmış bir otomat sistemi, basit bir satın alma menüsünün çok ötesine geçer. Gerçekçi satın alma animasyonları, kıtlık hissi yaratan stok yönetimi, arz ve talebe göre tepki veren dinamik fiyatlandırma, farklı ürün kategorileri satan farklı makine türleri, suç roleplay'i için soygun mekanikleri ve oyunculara anlamlı iş imkanları sağlayan stok yenileme meslekleri içerir. Bu rehber, prop algılamadan envanter entegrasyonuna ve ekonomi yönetimine kadar eksiksiz bir otomat ve mağaza sisteminin oluşturulmasını kapsar.

Otomat Proplarını Tespit Etme ve Yapılandırma

GTA V dünyası, etkileşimli nesnelere dönüştürebileceğiniz otomat propları ile doludur. Başlıca prop modelleri şunlardır: prop_vend_soda_01 ve prop_vend_soda_02 meşrubat otomatları için, prop_vend_water_01 su sebilleri için, prop_vend_coffe_01 kahve makineleri için ve prop_vend_snak_01 atıştırmalık otomatları için. Harita genelindeki her otomat konumuna etkileşim noktalarını manuel olarak yerleştirmek yerine, oyuncunun yakınındaki bu prop modellerini tarayan yarıçap tabanlı bir algılama sistemi kullanın. Bir oyuncu etkileşim menzilindeki eşleşen herhangi bir prop'a yaklaştığında, sistem bir komut istemi veya target bölgesini etkinleştirir. Bu yaklaşım, manuel yapılandırma olmadan haritadaki tüm bu prop örnekleriyle otomatik olarak çalışır ve hatta bu modelleri içeren özel MLO iç mekanlarını bile algılar. Her prop türü için farklı ürün katalogları tanımlayın; böylece meşrubat otomatları yalnızca içecek, atıştırmalık otomatları yiyecek ve kahve otomatları kahve çeşitleri satar.

-- shared/config.lua
Config = {}

Config.InteractDistance = 1.5
Config.UseAnimation     = true
Config.AnimDuration     = 3000 -- ms

Config.Machines = {
    soda = {
        models = {
            `prop_vend_soda_01`,
            `prop_vend_soda_02`,
        },
        label = 'Soda Machine',
        items = {
            {name = 'cola',       label = 'Cola',        price = 5,  stock = 20},
            {name = 'sprunk',     label = 'Sprunk',      price = 5,  stock = 20},
            {name = 'ecola',      label = 'E-Cola',      price = 6,  stock = 15},
            {name = 'energydrink',label = 'Energy Drink', price = 8,  stock = 10},
        },
    },
    snack = {
        models = {`prop_vend_snak_01`},
        label = 'Snack Machine',
        items = {
            {name = 'chips',      label = 'Chips',       price = 4,  stock = 25},
            {name = 'candy',      label = 'Candy Bar',   price = 3,  stock = 30},
            {name = 'sandwich',   label = 'Sandwich',    price = 7,  stock = 15},
            {name = 'granola',    label = 'Granola Bar',  price = 5,  stock = 20},
        },
    },
    coffee = {
        models = {`prop_vend_coffe_01`},
        label = 'Coffee Machine',
        items = {
            {name = 'coffee',     label = 'Black Coffee', price = 4,  stock = 30},
            {name = 'latte',      label = 'Latte',       price = 6,  stock = 20},
            {name = 'espresso',   label = 'Espresso',    price = 5,  stock = 25},
        },
    },
    water = {
        models = {`prop_vend_water_01`},
        label = 'Water Cooler',
        items = {
            {name = 'water',      label = 'Water Bottle', price = 3,  stock = 40},
        },
    },
}

Client Tarafı Etkileşim ve Animasyon Sistemi

Bir oyuncu bir otomat makinesine yaklaşıp etkileşim tuşuna bastığında, sürükleyici bir satın alma deneyimi oluşturmak için sırasıyla birkaç işlem gerçekleşir. İlk olarak, oyuncunun animasyonun ortasında uzaklaşmasını önlemek için hareketi kısıtlanır. Ardından oyuncu karakteri şunu kullanarak makineye doğru döner: TaskTurnPedToFaceEntity. Satın alma animasyonu şu kullanılarak oynatılır: MINI@SPRUNK otomat makineleri için animasyon sözlüğü veya ANIM@AM_HOLD_UP@MALE genel etkileşimler için. Makinenin kendisi şunu kullanarak bir ses efekti çalar: PlaySoundFromEntity mekanik ürün verme sesini simüle etmek için. Animasyon tamamlandıktan sonra istemci sunucuya bir satın alma isteği gönderir; sunucu işlemi doğrular ve öğeyi oyuncunun envanterine ekler. Otomatta bozuk para yuvası etkileşimi varsa, animasyon sırasında oyuncunun eline şununla küçük bir prop eki ekleyin: AttachEntityToEntity ekstra görsel doğruluk için. Tüm sekans yaklaşık 3 saniye sürmelidir: Gerçekçi hissettirecek kadar uzun, ancak oyuncuları bunaltmayacak kadar kısa.

-- client/interaction.lua
local isBuying = false

function PurchaseFromMachine(machineEntity, machineType, itemIndex)
    if isBuying then return end
    isBuying = true

    local ped = PlayerPedId()
    local machineCoords = GetEntityCoords(machineEntity)

    -- Face the machine
    TaskTurnPedToFaceEntity(ped, machineEntity, 1000)
    Wait(1000)

    -- Play animation
    if Config.UseAnimation then
        RequestAnimDict('mini@sprunk')
        while not HasAnimDictLoaded('mini@sprunk') do Wait(10) end

        TaskPlayAnim(ped, 'mini@sprunk', 'plyr_buy_drink_pt1',
            8.0, -8.0, 2000, 0, 0, false, false, false)
        Wait(1500)

        TaskPlayAnim(ped, 'mini@sprunk', 'plyr_buy_drink_pt2',
            8.0, -8.0, 1500, 0, 0, false, false, false)

        -- Machine sound effect
        PlaySoundFromEntity(-1, 'vending_machine_purchase',
            machineEntity, 'dlc_vw_table_games', false, 0)
        Wait(1500)
    end

    -- Request purchase from server
    TriggerServerEvent('vendingmachine:purchase', machineType, itemIndex)

    ClearPedTasks(ped)
    isBuying = false
end

Sunucu Taraflı Stok Yönetimi ve Ekonomi

Stok yönetimi, otomatları sınırsız eşya dağıtıcılardan dinamik ekonomik unsurlara dönüştürür. Her otomat konumu kendi envanterini bağımsız olarak takip eder. Bir otomat belirli bir ürünü tükettiğinde, oyuncular satın alma menüsünde ürünün tükendiğini görür. Stok seviyeleri sunucu yeniden başlatmalarında veritabanında korunur. Bir stok yenileme mesleği, oyuncuların depodan malzeme alıp şehirdeki boş otomatlara taşıyan teslimat şoförleri olarak çalışmasına olanak tanır. Bu durum eksiksiz bir ekonomik döngü oluşturur: Tedarikçiler makineleri doldurur, makineler tüketicilere satış yapar, gelir makine sahibine geri döner ve teslimat şoförü maaş kazanır. Dinamik fiyatlandırma ise stok azaldıkça popüler ürünlerin fiyatının kademeli olarak arttığı ve makine yeniden doldurulduğunda fiyatların sıfırlandığı başka bir katman ekler. Bu sayede tüketim alışkanlıkları doğal biçimde dengelenir ve talep gören bir ürünün stoğu azaldığında aciliyet hissi yaratılır.

-- server/stock.lua
local machineStock = {}

function GetMachineKey(machineType, coords)
    return machineType .. ':' ..
        math.floor(coords.x) .. ':' ..
        math.floor(coords.y) .. ':' ..
        math.floor(coords.z)
end

function GetStock(machineKey, itemIndex)
    if not machineStock[machineKey] then
        -- Load from database or initialize defaults
        machineStock[machineKey] = {}
    end
    return machineStock[machineKey][itemIndex] or
        Config.Machines[machineKey:match('^(%w+):')].items[itemIndex].stock
end

RegisterNetEvent('vendingmachine:purchase', function(machineType, itemIndex)
    local src = source
    local config = Config.Machines[machineType]
    if not config or not config.items[itemIndex] then return end

    local item = config.items[itemIndex]
    local machineKey = machineType -- simplified; use coords in production

    -- Check stock
    local stock = GetStock(machineKey, itemIndex)
    if stock <= 0 then
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'Sold Out',
            description = item.label .. ' is out of stock',
            type = 'error'
        })
        return
    end

    -- Calculate dynamic price
    local basePrice = item.price
    local stockRatio = stock / item.stock
    local dynamicPrice = math.ceil(basePrice * (1 + (1 - stockRatio) * 0.5))

    -- Deduct money
    local paid = exports['framework']:RemoveMoney(src, dynamicPrice, 'cash')
    if not paid then
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'No Cash',
            description = 'You need $' .. dynamicPrice,
            type = 'error'
        })
        return
    end

    -- Add item to inventory
    local added = exports['ox_inventory']:AddItem(src, item.name, 1)
    if not added then
        exports['framework']:AddMoney(src, dynamicPrice, 'cash')
        return
    end

    -- Decrease stock
    machineStock[machineKey] = machineStock[machineKey] or {}
    machineStock[machineKey][itemIndex] = stock - 1

    TriggerClientEvent('ox_lib:notify', src, {
        title = 'Purchased',
        description = item.label .. ' - $' .. dynamicPrice,
        type = 'success'
    })
end)

Suç Roleplay'i için Soygun Mekanikleri

Otomatlar, suç karakterleri için doğal bir soygun hedefi oluşturur. Suçluların içerideki nakit parayı çalmak için makineleri kırmalarına olanak tanıyan bir maymuncuk veya levye mekaniği uygulayın. Soygun zaman almalı, kilit açma bulmacası gibi bir mini oyun gerektirmeli, yakındaki oyuncuları uyaran ve potansiyel olarak polis bildirimi tetikleyen bir ses çıkarmalı ve makinenin son stok yenilemesinden veya soygundan bu yana işlediği satın alma miktarına bağlı olarak değişken bir ödül vermelidir. Soygun ödülünün gerçekçi olması ve gerçek ekonomik faaliyete dayanması için makine başına nakit birikimini oyuncuların gerçek satın alımlarına göre takip edin. Başarılı bir soygunun ardından makine hasarlı duruma geçer ve bir tamirci tarafından onarılana kadar veya bekleme süresinin ardından otomatik olarak düzelene kadar satın alma işlemlerini gerçekleştiremez. Bu durum, suç faaliyetlerinin tüm topluluğu etkileyen sonuçlar doğurmasını sağlar ve tamirciler için tamir işi yaratarak ekonomik ekosistemi daha da zenginleştirir.

Oyuncuya Ait Dükkanlar ve Özel Mağaza Vitrinleri

Otomat altyapısını, oyuncuların sahip olduğu işletmeler için tam teşekküllü bir satış noktası sistemine genişletin. İşletme sahipleri, mülklerine özel mağaza tezgahları yerleştirebilir, hangi eşyaları satacaklarını yapılandırabilir, kendi fiyatlarını belirleyebilir ve envanterlerini bir yönetim NUI'si aracılığıyla yönetebilirler. Mağaza sistemi, otomatlarla aynı temel satın alma ve stok mekaniklerini kullanır, ancak gelir takibi, gider yönetimi, çalışan izinleri ve kar raporları içeren bir işletme sahibi katmanı ekler. İşletmede mesaiye giren çalışanlar, rol etkileşimleri için satışları manuel olarak işlemek üzere kasaya erişebilirken, hiçbir çalışan bulunmadığında otomatik sistem satışları yönetir. Otomatik satışlardan elde edilen gelir, sunucunun hükümet kasasına aktarılan yapılandırılabilir bir vergi yüzdesi düşüldükten sonra işletmenin banka hesabına aktarılır. Bu, oyuncuların malları ürettiği veya tedarik ettiği, dükkanlarını doldurduğu, diğer işletmelerle rekabetçi fiyatlar belirlediği ve yatırımlarından pasif gelir elde ettiği eksiksiz bir perakende ekonomisi yaratır.

Performans Optimizasyonu ve Target Entegrasyonu

Her karede prop modellerini taramak sunucu performansını mahveder. Bunun yerine kademeli bir algılama yaklaşımı kullanın. Yakındaki otomat prop'larını bulmak için 15 metrelik yarıçapta her 2 saniyede bir geniş kapsamlı bir tarama çalıştırın. Bulunan makine konumlarını önbelleğe alın ve sonraki karelerde yalnızca önbelleğe karşı hassas mesafe kontrolleri yapın. Oyuncu önbelleğe alınan herhangi bir makineden 20 metreden fazla uzaklaştığında önbelleği temizleyin ve yeni bir tarama başlatın. ox_target veya qb-target gibi hedef sistemleri kullanan sunucularda, yakınlık bildirimleri kullanmak yerine bulunan prop'lar üzerinde hedef bölgeleri kaydedin. Hedef bölgeleri daha yüksek performanslıdır çünkü yalnızca oyuncu nesneye nişan aldığında etkinleşir ve sürekli mesafe kontrolü ihtiyacını tamamen ortadan kaldırır. Hedef yaklaşımı ayrıca havada asılı duran metin bildirimleri yerine doğrudan makine modeli üzerinde görünen bağlama duyarlı etkileşim seçenekleriyle daha temiz bir kullanıcı arayüzü deneyimi sunar.

-- client/target.lua (ox_target integration)
local registeredMachines = {}

CreateThread(function()
    for machineType, config in pairs(Config.Machines) do
        for _, model in ipairs(config.models) do
            exports.ox_target:addModel(model, {
                {
                    name     = 'vending_' .. machineType,
                    icon     = 'fas fa-shopping-cart',
                    label    = 'Use ' .. config.label,
                    onSelect = function(data)
                        OpenMachineMenu(machineType, data.entity)
                    end,
                    distance = Config.InteractDistance,
                },
            })
        end
    end
end)

Eşleşen script

Sunucunuz için hazır, güncellemeler dahil.

Başlamaya Hazır mısınız?

Scriptleri mağazamızdan edinin veya destek, güncellemeler ve gelecek yeniliklere göz atmak için Discord'a katılın.