ox_target addSpherezone Пример - QBCore & ESX Lua код
Пример addSpherezone для ox_target: код на Lua, готовый к использованию. Также охватывает addBoxZone, addLocalEntity и qb-target addGlobalPlayer. QBCore и ESX.
Agency Scripts
Основатель и ведущий разработчик Agency Scripts
Что такое Target System и зачем его использовать?
Система таргетинга, иногда называемая eye-target или системой взаимодействия, заменяет традиционный подход с нажатием клавиши рядом с объектом. Вместо того чтобы подходить к NPC и нажимать E надеясь, что вы достаточно близко, игроки удерживают клавишу (обычно левый alt), чтобы войти в режим прицеливания, который отображает небольшой прицел в центре экрана. Когда прицел наведен на целевой объект, предмет или зону, появляется меню доступных действий. Такой подход значительно интуитивнее, так как дает игрокам точный контроль над тем, с чем они взаимодействуют. В переполненной сцене с множеством NPC, транспортных средств и объектов система прицеливания позволяет выбрать именно тот объект, который вы хотите, без борьбы с перекрывающимися подсказками взаимодействия. Две самые популярные реализации , ox_target (от команды Overextended) и qb-target (создан для QBCore). Это руководство охватывает оба варианта, с акцентом на ox_target, так как он не зависит от фреймворка и более активно развивается.
ox_target против qb-target: что выбрать
Обе системы достигают одной цели, но отличаются дизайном API и производительностью. ox_target является standalone, работает с любым фреймворком, использует raycasting для обнаружения сущностей и имеет более чистый API с лучшей поддержкой TypeScript. qb-target плотно интегрирован с QBCore, использует похожий подход raycast и существует дольше, поэтому больше существующих скриптов поддерживают его из коробки. Если вы начинаете новый сервер или используете ESX/standalone, используйте ox_target. Если вы на QBCore и большинство ваших купленных скриптов используют экспорты qb-target, использование qb-target избегает проблем совместимости. Хорошая новость в том, что ox_target включает слой совместимости с qb-target, так что скрипты, вызывающие exports['qb-target'] будет работать с установленным ox_target. Обратное неверно, поэтому скрипты, написанные для ox_target, не будут работать с qb-target без модификаций.
Добавление целей к определённым сущностям
Entity targets прикрепляют опции взаимодействия к конкретной созданной сущности, такой как пэд, транспортное средство или объект. Это полезно, когда вы создаёте NPC для работы и хотите, чтобы игроки взаимодействовали именно с этим NPC, а не с любой моделью пэда в мире. Цель следует за сущностью, поэтому если NPC перемещается, точка взаимодействия движется вместе с ним. Вы предоставляете дескриптор сущности, массив опций и необязательное расстояние, которое контролирует, как далеко прицел может обнаруживать сущность. Всегда очищайте entity targets при удалении сущности или остановке ресурса, чтобы предотвратить зависание «осиротевших» целей в памяти.
-- 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)
Цели на основе модели: нацеливание на все экземпляры
Цели по модели применяют опции взаимодействия ко всем экземплярам конкретной модели в игровом мире. Это чрезвычайно мощно для таких объектов, как банкоматы, торговые автоматы, мусорные контейнеры или любой проп, который существует в нескольких местах на карте. Вместо ручной регистрации целей по сотням координат вы регистрируете один раз по названию модели, и каждый совпадающий объект становится интерактивным. Влияние на производительность минимально, потому что система целей проверяет только модели в пределах диапазона лучевого кастинга, а не каждый объект во всем мире. Однако будьте осторожны с распространёнными моделями. Целевые объекты для каждой prop_bin_01a на карте даёт игрокам сотни точек взаимодействия, поэтому убедитесь, что действие имеет смысл для всех экземпляров этой модели.
-- 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,
})
Зональные цели: невидимые области взаимодействия
Зональные цели создают невидимые области взаимодействия в определённых координатах. Они идеальны для мест, где нет физического объекта, но вы всё равно хотите, чтобы игроки взаимодействовали, например, прилавок внутри здания, конкретное место на земле для тайника или зона перед дверью для опции взлома замка. Вы определяете зоны как коробки или сферы с координатами, размером и вращением. Зона активна только тогда, когда прицел направлен на область зоны, что делает взаимодействие точным и предотвращает случайные действия. Зональные цели также являются основным решением для добавления взаимодействий к частям MLO карты, где объекты встроены в карту и не могут быть нацелены по модели.
-- 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
Параметр canInteract функция делает системы таргетинга действительно мощными. Она запускается каждый раз, когда прицел наведен на цель, и определяет, должна ли каждая опция отображаться или скрываться. Это позволяет создавать контекстно-зависимые взаимодействия, где полицейский видит одни опции, а гражданский , другие, где опция отмычки появляется только если у игрока есть отмычка, или опция ремонта автомобиля показывается только при повреждении транспортного средства. Функция получает параметры: дескриптор сущности, расстояние, координаты и имя опции. Логику держите в canInteract легковесный, так как работает на каждом кадре, пока игрок наводит курсор на цель. Избегайте запросов к базе данных или тяжелых вычислений внутри него. Вместо этого кэшируйте необходимые данные в локальной переменной, которая обновляется через события.
-- 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,
},
})
Глобальные цели: взаимодействия с игроками и транспортными средствами
Глобальные цели применяются ко всем игрокам-педам или всем транспортным средствам в мире без необходимости регистрировать каждое отдельно. addGlobalPlayer добавляет опции, которые появляются при наведении на любого другого игрока, что идеально подходит для взаимодействий, таких как передача предметов, проверка удостоверений, наручники подозреваемым или лечение других игроков. addGlobalVehicle добавляет опции для каждого транспортного средства, полезные для механиков, полицейских обысков или систем заправки. Используйте canInteract щедро используйте глобальные цели, чтобы избежать перегрузки опциями. Гражданский не должен видеть опцию наручников, а механик должен видеть только опции ремонта, когда он на дежурстве. Глобальные цели , самый удобный способ добавить универсальные взаимодействия, но и самый простой для неправильного использования, поэтому тщательно продумывайте, когда каждая опция должна быть видна.
-- 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,
},
})
Советы по производительности и распространённые ошибки
Целевые системы хорошо оптимизированы, но могут влиять на производительность при неправильном использовании. Самая распространённая ошибка , регистрация слишком большого количества зон с включённым режимом отладки в продакшене. Отрисовка отладки рисует каркасные фигуры для каждой зоны, что дорого при наличии десятков зон. Всегда устанавливайте debug = false до развертывания. Еще одна ошибка , помещать дорогую логику внутрь canInteract функции. Поскольку это запускается каждый кадр при наведении, даже один exports.ox_inventory:Search вызов может накапливаться, если у вас десять опций, все одновременно запускающие проверки инвентаря. Кэшируйте эти значения и обновляйте их при изменении инвентаря. Наконец, всегда очищайте цели при остановке вашего ресурса. Используйте onResourceStop обработчик события для удаления всех целей зон, моделей и сущностей. Утечки целей остаются в памяти и могут вызывать ошибки или дублирование опций при перезапуске ресурса. ox_target автоматически очищает некоторые локальные сущности, но явная очистка всегда безопаснее.