Bloga Geri Dön
Tutorial8 dk. okuma

ox_target addSpherezone Örneği: QBCore ve ESX Lua Kodu

ox_target addSpherezone örneği: kullanıma hazır, kopyala, yapıştır Lua kodu. Ayrıca addBoxZone, addLocalEntity ve qb-target addGlobalPlayer konularını da kapsar. QBCore ve ESX.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Target System nedir ve neden kullanılmalıdır?

Bazen eye-target veya etkileşim sistemi olarak da adlandırılan bir target sistemi, bir nesnenin yanındayken bir tuşa basma şeklindeki geleneksel yaklaşımın yerini alır. Bir NPC'nin yanına gidip basmak yerine E yeterince yakın olmayı ummak yerine oyuncular hedefleme moduna girmek için bir tuşa (genellikle sol alt) basılı tutar, bu da ekranın ortasında küçük bir artı göstergesi görüntüler. Artı göstergesi hedeflenebilir bir entity, nesne veya bölgenin üzerine geldiğinde kullanılabilir eylemlerin bulunduğu bir menü belirir. Bu yaklaşım son derece daha sezgiseldir çünkü oyunculara neyle etkileşime girdikleri konusunda hassas kontrol sağlar. Birden fazla NPC, araç ve nesnenin bulunduğu kalabalık bir sahnede, target sistemi üst üste binen etkileşim bildirimleriyle uğraşmadan tam olarak istediğinizi seçmenizi sağlar. En popüler iki uygulama şunlardır: ox_target (Overextended ekibinden) ve qb-target (QBCore için oluşturulmuştur). Bu rehber, framework bağımsız olduğu ve daha aktif geliştirildiği için ox_target ağırlıklı olmak üzere her ikisini de kapsar.

ox_target vs qb-target: Hangisi Seçilmeli

Her iki sistem de aynı amaca ulaşır ancak API tasarımı ve performans açısından farklılık gösterir. ox_target standalone çalışır, her framework ile uyumludur, varlık tespiti için raycasting kullanır ve daha iyi TypeScript desteğine sahip daha temiz bir API sunar. qb-target QBCore ile sıkı bir şekilde entegredir, benzer bir raycast yaklaşımı kullanır ve daha uzun süredir mevcut olduğu için daha fazla mevcut script kutudan çıktığı gibi bunu destekler. Yeni bir sunucu başlatıyorsanız veya ESX/standalone kullanıyorsanız ox_target kullanın. QBCore kullanıyorsanız ve satın aldığınız script'lerin çoğu qb-target export'larını kullanıyorsa, qb-target ile devam etmek uyumluluk sorunlarını önler. İyi haber şu ki ox_target bir qb-target uyumluluk katmanı içerir, bu sayede şunu çağıran script'ler: exports['qb-target'] ox_target yüklüyken çalışacaktır. Ancak bunun tersi geçerli değildir, bu nedenle ox_target için yazılmış scriptler değişiklik yapılmadan qb-target ile çalışmaz.

Belirli Varlıklara Target Ekleme

Entity target'ları, etkileşim seçeneklerini ped, araç veya nesne gibi spawn edilmiş belirli bir entity'ye bağlar. Bu, bir meslek için NPC oluşturduğunuzda ve oyuncuların dünyadaki herhangi bir ped modeli yerine özellikle o NPC ile etkileşime girmesini istediğinizde kullanışlıdır. Target entity'yi takip eder, böylece NPC dolaşırsa etkileşim noktası da onunla birlikte hareket eder. Entity handle'ını, options dizisini ve nişangahın entity'yi ne kadar uzaktan algılayabileceğini kontrol eden isteğe bağlı bir mesafeyi belirtirsiniz. Sahipsiz target'ların bellekte kalmasını önlemek için entity silindiğinde veya kaynak durdurulduğunda entity target'larını her zaman temizleyin.

-- client.lua: Entity targeting with ox_target

-- Create a shop NPC and add target
local model = joaat('a_m_m_business_01')
lib.requestModel(model)

local ped = CreatePed(0, model, 25.7, -1347.3, 29.5, 270.0, false, false)
FreezeEntityPosition(ped, true)
SetEntityInvincible(ped, true)
SetBlockingOfNonTemporaryEvents(ped, true)

-- Add target to this specific ped
exports.ox_target:addLocalEntity(ped, {
    {
        name = 'open_shop',
        icon = 'fas fa-store',
        label = 'Open General Store',
        distance = 2.5,
        onSelect = function(data)
            -- data.entity contains the entity handle
            TriggerEvent('shop:open', 'general')
        end,
    },
    {
        name = 'talk_to_clerk',
        icon = 'fas fa-comment',
        label = 'Talk to Clerk',
        distance = 2.0,
        canInteract = function(entity, distance, coords, name)
            -- Only show if player has completed a quest
            return PlayerData.questComplete == true
        end,
        onSelect = function()
            TriggerEvent('dialogue:start', 'clerk_01')
        end,
    },
})

-- Clean up on resource stop
AddEventHandler('onResourceStop', function(resource)
    if resource == GetCurrentResourceName() then
        exports.ox_target:removeLocalEntity(ped)
        DeleteEntity(ped)
    end
end)

Model Tabanlı Hedefler: Tüm Örnekleri Hedefleme

Model hedefleri, oyun dünyasındaki belirli bir modelin her bir örneğine etkileşim seçenekleri uygular. Bu: ATM'ler, otomatlar, çöp konteynerleri, çöp kutuları veya harita genelinde birden fazla konumda bulunan herhangi bir prop için son derece güçlüdür. Yüzlerce koordinatta hedefleri manuel olarak kaydetmek yerine model adına göre bir kez kaydedersiniz ve eşleşen her nesne etkileşimli hale gelir. Performans etkisi minimum düzeydedir çünkü hedef sistemi tüm dünyadaki her nesneyi değil, yalnızca raycast menzili içindeki modelleri kontrol eder. Yine de yaygın modeller konusunda dikkatli olun. Her birini hedeflemek prop_bin_01a haritada bulunması oyunculara yüzlerce etkileşim noktası sağlar, bu nedenle eylemin o modelin tüm örnekleri için mantıklı olduğundan emin olun.

-- client.lua: Model-based targeting

-- ox_target: Target all ATM models
exports.ox_target:addModel({'prop_atm_01', 'prop_atm_02', 'prop_atm_03', 'prop_fleeca_atm'}, {
    {
        name = 'use_atm',
        icon = 'fas fa-credit-card',
        label = 'Use ATM',
        distance = 1.5,
        onSelect = function(data)
            TriggerEvent('banking:openATM')
        end,
    },
})

-- Target all vending machines
exports.ox_target:addModel({
    'prop_vend_coffe_01',
    'prop_vend_soda_01',
    'prop_vend_soda_02',
    'prop_vend_water_01',
}, {
    {
        name = 'buy_drink',
        icon = 'fas fa-mug-hot',
        label = 'Buy Drink ($5)',
        distance = 1.5,
        onSelect = function(data)
            local model = GetEntityModel(data.entity)
            TriggerServerEvent('vending:buy', model)
        end,
    },
})

-- qb-target equivalent for comparison
exports['qb-target']:AddTargetModel({'prop_atm_01', 'prop_atm_02'}, {
    options = {
        {
            type = 'client',
            event = 'banking:openATM',
            icon = 'fas fa-credit-card',
            label = 'Use ATM',
        },
    },
    distance = 1.5,
})

Zone Tabanlı Hedefler: Görünmez Etkileşim Alanları

Zone hedefleri, belirli koordinatlarda görünmez etkileşim alanları oluşturur. Bunlar, bir bina içindeki tezgah, zula için zemindeki belirli bir nokta veya maymuncuk seçeneği için bir kapının önündeki alan gibi fiziksel bir nesnenin bulunmadığı ancak oyuncuların yine de etkileşime girmesini istediğiniz yerler için idealdir. Zone'ları koordinatlar, boyut ve rotasyon içeren kutular veya küreler olarak tanımlarsınız. Zone yalnızca nişangah bölgenin alanını gösterdiğinde aktifleşir; bu da onu hassas kılar ve kazara etkileşimleri önler. Zone hedefleri, prop'ların haritaya gömülü olduğu ve modele göre hedeflenemediği harita MLO'larının parçalarına etkileşim eklemek için de en uygun çözümdür.

-- client.lua: Zone-based targeting

-- ox_target: Box zone for a reception desk
exports.ox_target:addBoxZone({
    coords = vec3(441.8, -981.0, 30.7),
    size = vec3(2.0, 1.0, 1.5),
    rotation = 0,
    debug = true,  -- Shows the box in-game, set false for production
    options = {
        {
            name = 'check_in',
            icon = 'fas fa-clipboard-check',
            label = 'Check In at Reception',
            onSelect = function()
                TriggerEvent('police:checkIn')
            end,
            canInteract = function()
                return PlayerData.job == 'police'
            end,
        },
    },
})

-- Sphere zone for a ground stash
local stashZone = exports.ox_target:addSphereZone({
    coords = vec3(128.4, -1280.5, 29.0),
    radius = 0.5,
    debug = false,
    options = {
        {
            name = 'open_stash',
            icon = 'fas fa-box-open',
            label = 'Open Stash',
            distance = 1.5,
            onSelect = function()
                TriggerServerEvent('stash:open', 'ground_stash_01')
            end,
        },
    },
})

-- Remove zone later if needed
exports.ox_target:removeZone(stashZone)

canInteract ile Koşullu Görünürlük

The canInteract function, target sistemlerini gerçekten güçlü kılan unsurdur. Artı göstergesi bir hedefin üzerine her geldiğinde çalışır ve her bir seçeneğin gösterilip gösterilmeyeceğini belirler. Bu sayede bir polis memurunun sivilden farklı seçenekler gördüğü, maymuncuk seçeneğinin yalnızca oyuncuda maymuncuk eşyası varsa göründüğü veya araç tamir seçeneğinin yalnızca araç hasarlı olduğunda çıktığı bağlama duyarlı etkileşimler oluşturabilirsiniz. Function; entity handle, mesafe, koordinatlar ve seçenek adını parametre olarak alır. Mantığı şurada tutun: canInteract hafif olmalıdır çünkü oyuncu hedefin üzerindeyken her karede (frame) çalışır. İçinde veritabanı sorgularından veya ağır hesaplamalardan kaçının. Bunun yerine, gerekli verileri event'ler aracılığıyla güncellenen yerel bir değişkende önbelleğe alın.

-- client.lua: Advanced canInteract examples

-- Vehicle interaction with multiple conditional options
exports.ox_target:addGlobalVehicle({
    {
        name = 'repair_vehicle',
        icon = 'fas fa-wrench',
        label = 'Repair Vehicle',
        distance = 3.0,
        bones = {'engine'},  -- Only when targeting the engine area
        canInteract = function(entity)
            local health = GetVehicleEngineHealth(entity)
            return health < 900.0  -- Only show if damaged
        end,
        onSelect = function(data)
            TriggerEvent('mechanic:repair', data.entity)
        end,
    },
    {
        name = 'lockpick_vehicle',
        icon = 'fas fa-key',
        label = 'Lockpick Door',
        distance = 2.0,
        bones = {'door_dside_f', 'door_pside_f'},
        canInteract = function(entity)
            local locked = GetVehicleDoorLockStatus(entity)
            local hasItem = exports.ox_inventory:Search('count', 'lockpick') > 0
            return locked == 2 and hasItem
        end,
        onSelect = function(data)
            TriggerEvent('lockpick:start', data.entity)
        end,
    },
    {
        name = 'open_trunk',
        icon = 'fas fa-box',
        label = 'Open Trunk',
        distance = 2.5,
        bones = {'boot'},
        canInteract = function(entity)
            return not IsVehicleDoorFullyOpen(entity, 5)
        end,
        onSelect = function(data)
            SetVehicleDoorOpen(data.entity, 5, false, false)
            TriggerEvent('inventory:openTrunk', data.entity)
        end,
    },
})

Global Targets: Oyuncu ve Araç Etkileşimleri

Global targets, her birini ayrı ayrı kaydetmeye gerek kalmadan dünyadaki her oyuncu ped'ine veya her araca uygulanır. addGlobalPlayer başka bir oyuncuyu hedeflerken görünen seçenekler ekler; eşya verme, kimlik kontrolü, şüphelileri kelepçeleme veya diğer oyuncuları iyileştirme gibi etkileşimler için idealdir. addGlobalVehicle her araç için seçenekler ekler, tamirciler, polis aramaları veya yakıt sistemleri için kullanışlıdır. Şunu kullanın: canInteract seçenek karmaşasını önlemek adına global target'lar konusunda dikkatli olun. Bir sivil kelepçeleme seçeneğini görmemeli, bir tamirci ise tamir seçeneklerini yalnızca görevdeyken görmelidir. Global target'lar evrensel etkileşimler eklemenin en pratik yoludur ancak kötüye kullanılması da en kolay olanıdır, bu yüzden her seçeneğin tam olarak ne zaman görünür olması gerektiğini iyi düşünün.

-- client.lua: Global player and vehicle targets

-- Target any player for EMS interactions
exports.ox_target:addGlobalPlayer({
    {
        name = 'revive_player',
        icon = 'fas fa-heartbeat',
        label = 'Revive Player',
        distance = 2.0,
        canInteract = function(entity)
            -- Only show if player is EMS and target is downed
            local isEms = PlayerData.job == 'ambulance'
            local targetState = Entity(entity).state.isDead
            return isEms and targetState == true
        end,
        onSelect = function(data)
            local targetServerId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))
            TriggerServerEvent('ems:revive', targetServerId)
        end,
    },
    {
        name = 'give_item',
        icon = 'fas fa-hand-holding',
        label = 'Give Item',
        distance = 2.0,
        onSelect = function(data)
            local targetServerId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))
            TriggerEvent('inventory:giveItem', targetServerId)
        end,
    },
})

Performans İpuçları ve Sık Yapılan Hatalar

Target sistemleri iyi optimize edilmiştir ancak yanlış kullanıldığında performansı yine de etkileyebilir. En yaygın hata, canlı sunucuda hata ayıklama modu etkinken çok fazla alan hedefi kaydetmektir. Hata ayıklama çizimi, her bölge için tel kafes şekilleri çizer ve bunlardan onlarca olduğunda yüksek kaynak tüketir. Her zaman şunu ayarlayın: debug = false dağıtımdan önce. Diğer bir hata ise maliyetli mantığı şunun içine yerleştirmektir: canInteract functions. İmleç üzerindeyken bu işlem her karede çalıştığı için tek bir exports.ox_inventory:Search çağrısı, aynı anda envanter kontrolü yapan on seçeneğiniz varsa birikerek yük oluşturabilir. Bunun yerine bu değerleri önbelleğe alın ve envanter değiştiğinde güncelleyin. Son olarak, resource durduğunda hedefleri her zaman temizleyin. Şunu kullanın: onResourceStop tüm zone, model ve entity hedeflerini kaldırmak için event handler. Sızan hedefler bellekte kalır ve resource yeniden başlatıldığında hatalara veya yinelenen seçeneklere neden olabilir. ox_target yerel entity'ler için bazı temizlikleri otomatik olarak halleder, ancak açık temizleme her zaman en güvenli yaklaşımdır.

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.