FiveM анимации и предметы: флаги TaskPlayAnim, присоединение к кости, удаление

Воспроизведение анимаций и присоединение предметов в FiveM Lua: RequestAnimDict, флаги TaskPlayAnim 1, 16, 32 и 49, ClearPedTasks, AttachEntityToEntity к кости, сценарии и очистка.

Вы хотите, чтобы игрок пил кофе, держал телефон или использовал инструмент: анимацию, часто с предметом в руке. Если сделано неправильно, анимация ничего не делает, предмет плывет в ногах игрока или остается в мире навсегда. Это руководство показывает рабочую последовательность и очистку.

Загрузите, воспроизведите, очистите

Анимация живет в словаре. Словарь должен быть загружен перед воспроизведением из него:

lua
local function playAnim(ped, dict, anim, flag, duration)
    RequestAnimDict(dict)
    while not HasAnimDictLoaded(dict) do
        Wait(0)
    end
    TaskPlayAnim(ped, dict, anim, 8.0, -8.0, duration or -1, flag or 0, 0.0, false, false, false)
end

Если HasAnimDictLoaded никогда не true, имя словаря неправильно и этот цикл зависает, поэтому добавьте таймаут, когда имя приходит из конфига. С ox_lib одна строка заменяет цикл:

lua
lib.requestAnimDict('mp_player_inteat@burger')

TaskPlayAnim принимает педа, словарь, анимацию, смешивание в, смешивание из, продолжительность в мс (-1 = до остановки), флаг и скорость воспроизведения. Освободите словарь, когда закончите с RemoveAnimDict(dict).

Флаги анимации

Флаг — это битовая маска, поэтому значения складываются. Те, которые вы будете использовать:

Флаг Эффект
0 Воспроизвести один раз, игрок не может двигаться
1 Цикл
16 Только верхняя часть тела, ноги продолжают ходить
32 Игрок сохраняет контроль
49 1 + 16 + 32: цикл, верхняя часть, контролируемая

Для анимации, держащейся в руке (телефон, напиток, сигарета), 49 — обычный выбор: она зацикливается, только верхняя часть тела анимирована, и игрок все еще может ходить. Для одноразового действия, при котором игрок должен стоять неподвижно, используйте 0, или 1, если оно должно зацикливаться.

Остановка анимации

lua
local ped = PlayerPedId()
ClearPedTasks(ped)                 -- stop and let the ped blend out
-- or, if it is stuck:
ClearPedTasksImmediately(ped)      -- cut instantly, can look abrupt
StopAnimTask(ped, dict, anim, 1.0) -- stop only that animation

Используйте StopAnimTask, когда несколько вещей работают на педе, так как ClearPedTasks также отменяет ходьбу или сценарий внизу. ClearPedTasksImmediately исправляет застрявшего педа, но также выбивает его из транспортных средств, поэтому сохраняйте это для восстановления.

Предмет в руке

Предмет — это объект, который вы создаете и присоединяете к кости педа. Последовательность: загрузите модель, создайте объект, присоедините его, воспроизведите анимацию.

lua
local prop

local function attachProp(ped, model, bone, x, y, z, rx, ry, rz)
    local hash = joaat(model)
    RequestModel(hash)
    while not HasModelLoaded(hash) do Wait(0) end

    local coords = GetEntityCoords(ped)
    prop = CreateObject(hash, coords.x, coords.y, coords.z + 0.2, true, true, false)

    AttachEntityToEntity(
        prop, ped, GetPedBoneIndex(ped, bone),
        x, y, z, rx, ry, rz,
        true, true, false, true, 1, true
    )
    SetModelAsNoLongerNeeded(hash)
    return prop
end

Куски:

  • CreateObject(model, x, y, z, isNetwork, netMissionEntity, doorFlag): передайте isNetwork = true, если другие игроки должны видеть предмет, что обычно то, что вы хотите для чего-то в руке.
  • GetPedBoneIndex(ped, boneId) преобразует id кости, такой как 28422 (размещение правой руки) или 18905 (левая рука) в индекс. Ищите список id костей для других.
  • x, y, z и rx, ry, rz — смещения и вращение относительно кости. Это нужно настраивать за предмет; нет ярлыка, поэтому измените значение и протестируйте.
  • Логические операции после вращения — мягкая прокладка, коллизия и похожие флаги. Коллизия false предотвращает толкание предмета педой вокруг.

Соберите это

lua
local function eatBurger()
    local ped = PlayerPedId()
    attachProp(ped, 'prop_cs_burger_01', 28422, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
    lib.requestAnimDict('mp_player_inteat@burger')
    TaskPlayAnim(ped, 'mp_player_inteat@burger', 'mp_player_int_eat_burger', 8.0, -8.0, 3000, 49, 0.0, false, false, false)
    Wait(3000)
    ClearPedTasks(ped)
    deleteProp()
end

Если предмет выглядит неправильно в руке, сначала исправьте смещения, затем кость. Если другое имя анимации не существует в словаре, TaskPlayAnim молча ничего не делает, поэтому дважды проверьте пару (точные имена словаря и анимации, в нижнем регистре, как написано).

Удалите предмет

Всегда очищайте. Предмет, который не удален, остается в мире, все еще присоединен к педу, который его больше не держит:

lua
function deleteProp()
    if prop and DoesEntityExist(prop) then
        DetachEntity(prop, true, true)
        DeleteEntity(prop)
    end
    prop = nil
end

AddEventHandler('onResourceStop', function(resource)
    if resource ~= GetCurrentResourceName() then return end
    deleteProp()
    ClearPedTasks(PlayerPedId())
end)

Также удалите предмет при смерти и когда игрок оставляет анимацию, не только по счастливому пути. Утекшие предметы — это классический источник "объектов везде" и медленного сервера; смотрите resmon high ms.

Сценарии

Для стоящих анимаций, которые включают свои собственные предметы, такие как наклон, курение или написание на доске, используйте сценарий вместо этого:

lua
local ped = PlayerPedId()
TaskStartScenarioInPlace(ped, 'WORLD_HUMAN_CLIPBOARD', 0, true)

-- later
ClearPedTasks(ped)

Аргументы — это пед, имя сценария, задержка в мс (0 для отсутствия) и воспроизведение ли анимации входа. Сценарии присоединяют и очищают свой предмет для вас, и они — самый простой вариант, когда анимация не должна быть, удерживая при ходьбе.

Для готовой версии анимация плюс предмет плюс полоса прогресса используйте lib.progressBar ox_lib, который принимает опции anim и prop; смотрите notifications and progress bars и Wait and threads для привычек ожидания за циклами выше.

Контрольный список

Симптом Исправление
Анимация ничего не делает Запросите словарь и сначала дождитесь HasAnimDictLoaded
Цикл зависает при загрузке Имя словаря неправильно; добавьте таймаут
Игрок заморожен на месте Флаг 0 или 1 блокирует движение; используйте 49 для сохранения контроля
Предмет у ног, а не в руке Неправильная кость или нет AttachEntityToEntity; проверьте GetPedBoneIndex
Предмет перекос в руке Настройте смещения x, y, z и поворота
Предметы, оставленные в мире DeleteEntity(prop) при окончании, смерти и остановке ресурса
Пед застрял в позе ClearPedTasks или, в крайнем случае, ClearPedTasksImmediately

Короткие ответы

Почему моя анимация не воспроизводится?

Словарь анимации еще не был загружен. Вызовите RequestAnimDict, дождитесь, пока HasAnimDictLoaded будет true, и только потом вызовите TaskPlayAnim. С ox_lib lib.requestAnimDict(dict) делает это для вас.

Какой флаг TaskPlayAnim мне использовать?

Используйте 1 для цикла, 16 для воспроизведения только верхней части тела, 32 для того, чтобы позволить игроку сохранить контроль, и 49 для цикла плюс верхняя часть плюс контролируемая. Это обычные комбинации для анимаций, которые вы держите во время ходьбы.

Как мне удалить предмет после анимации?

Вызовите DeleteEntity(prop), когда анимация заканчивается или скрипт останавливается, и освободите модель с помощью SetModelAsNoLongerNeeded. Предметы, оставленные позади, накапливаются в мире.

Скрипты без этой проблемы

Hookah SystemУстанавливаемые кальяны и лаунж-мебель: более 50 вкусов и эффектов.Смотреть скрипт →Vape SystemБолее 50 вейпов со вкусами, дымом и эффектами — от манго до суперскорости.Смотреть скрипт →Super Leaf BlowerВоздуходувка, которая сдувает игроков, машины, NPC и пропы. Работает на любом фреймворке.Смотреть скрипт →

Читайте также