Scripts/resources/[custom_script]/keep-companion/client/animator.lua

494 lines
18 KiB
Lua
Raw Permalink Normal View History

2024-12-29 19:48:41 +00:00
-- sequential animations are only supported for up to 3 animations
-- they need to be in the order of Start=>Loop=>Exit
local animationList = {
['rottweiler'] = {
['standing'] = {
['normal_bark'] = {
animDictionary = 'creatures@retriever@amb@world_dog_barking@idle_a',
animationName = 'idle_a'
},
['standing_bark'] = {
animDictionary = 'creatures@retriever@amb@world_dog_barking@idle_a',
animationName = 'idle_b'
},
['rotate_bark'] = {
animDictionary = 'creatures@retriever@amb@world_dog_barking@idle_a',
animationName = 'idle_c'
}
},
['siting'] = {
['self_itch'] = {
animDictionary = 'creatures@retriever@amb@world_dog_sitting@idle_a',
animationName = 'idle_a'
},
['look_around'] = {
animDictionary = 'creatures@retriever@amb@world_dog_sitting@idle_a',
animationName = 'idle_b',
skip = { 'A_C_Westy', 'A_C_Pug', 'A_C_Poodle', 'A_C_Cat_01', 'A_C_MtLion', 'A_C_Panther' }
},
['sit_Up'] = {
animDictionary = 'creatures@retriever@amb@world_dog_sitting@idle_a',
animationName = 'idle_c'
},
['sit'] = {
animDictionary = 'creatures@retriever@amb@world_dog_sitting@base',
animationName = 'base'
}
},
['misc'] = {
['indicate_ahead'] = {
animDictionary = 'creatures@rottweiler@indication@',
animationName = 'indicate_ahead'
},
['indicate_high'] = {
animDictionary = 'creatures@rottweiler@indication@',
animationName = 'indicate_high'
},
['indicate_low'] = {
animDictionary = 'creatures@rottweiler@indication@',
animationName = 'indicate_low'
},
['play_dead'] = {
animDictionary = 'creatures@rottweiler@move',
animationName = 'dying'
}
},
['tricks'] = {
['beg'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'beg_enter'
},
[2] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'beg_loop'
},
[3] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'beg_exit'
}
}
},
['paw'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'paw_right_enter'
},
[2] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'paw_right_loop'
},
[3] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'paw_right_exit'
}
}
},
['petting_chop'] = {
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'petting_chop'
},
['petting_franklin'] = { -- this is for human that is petting dog!
animDictionary = 'creatures@rottweiler@tricks@',
animationName = 'petting_franklin'
}
},
['hump'] = {
['hump_chop'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_enter_chop'
},
[2] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_loop_chop'
},
[3] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_exit_chop'
}
}
},
['hump_ladydog'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_enter_ladydog'
},
[2] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_loop_ladydog'
},
[3] = {
animDictionary = 'creatures@rottweiler@amb@',
animationName = 'hump_exit_ladydog'
}
}
}
},
['sleep'] = {
['exit_kennel'] = {
animDictionary = 'creatures@rottweiler@amb@sleep_in_kennel@',
animationName = 'exit_kennel'
},
['sleep_in_kennel'] = {
animDictionary = 'creatures@rottweiler@amb@sleep_in_kennel@',
animationName = 'sleep_in_kennel'
}
},
['pickup'] = {
['fetch_drop'] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'fetch_drop'
},
['fetch_pickup'] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'fetch_pickup'
}
},
['dump'] = {
['dumpi'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'dump_enter'
},
[2] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'dump_loop'
},
[3] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'dump_exit'
}
}
}
},
['pee'] = {
['pee'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'pee_left_enter'
},
[2] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'pee_left_idle'
},
[3] = {
animDictionary = 'CREATURES@ROTTWEILER@MOVE',
animationName = 'pee_left_exit'
}
}
}
}
},
['cat'] = {
['standing'] = {
['idle'] = {
animDictionary = 'creatures@cat@move',
animationName = 'idle'
},
['idle_dwn'] = {
animDictionary = 'creatures@cat@move',
animationName = 'idle_dwn'
},
['idle_upp'] = {
animDictionary = 'creatures@cat@move',
animationName = 'idle_upp'
}
},
['siting'] = {
['sitting'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ledge@idle_a',
animationName = 'idle_a'
}
},
['misc'] = {},
['sleep'] = {
['enter_sleep'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ground@enter',
animationName = 'enter'
},
['sleep'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ground@base',
animationName = 'base'
},
['idle_sleep'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ground@idle_a',
animationName = 'idle_a'
},
['exit_sleep'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ground@exit',
animationName = 'base'
},
['exit2_sleep'] = {
animDictionary = 'creatures@cat@amb@peyote@enter',
animationName = 'enter'
},
['exit_panic_sleep'] = {
animDictionary = 'creatures@cat@amb@world_cat_sleeping_ground@exit',
animationName = 'idle_a'
}
}
},
['cougar'] = {
['standing'] = {
['idle'] = {
animDictionary = 'creatures@cat@move',
animationName = 'idle'
}
},
['siting'] = {
['sitting'] = {
animDictionary = 'creatures@cougar@amb@world_cougar_rest@idle_a',
animationName = 'idle_c'
}
},
['misc'] = {},
['sleep'] = {
['enter_sleep'] = {
animDictionary = 'creatures@cougar@amb@world_cougar_rest@idle_a',
animationName = 'idle_a'
}
}
},
['small'] = {
['standing'] = {
['barking'] = {
animDictionary = 'creatures@pug@amb@world_dog_barking@idle_a',
animationName = 'idle_a'
},
['barking_idle'] = {
animDictionary = 'creatures@pug@amb@world_dog_barking@idle_a',
animationName = 'idle_b'
},
['self_clean'] = {
animDictionary = 'creatures@pug@amb@world_dog_barking@idle_a',
animationName = 'idle_c'
}
},
['siting'] = {
['siting_1'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@enter',
animationName = 'enter'
},
[2] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@base',
animationName = 'base'
},
[3] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@exit',
animationName = 'exit'
}
}
},
['sitting_idle_a'] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@idle_a',
animationName = 'idle_a'
},
['look_around'] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@idle_a',
animationName = 'idle_b'
},
['sitting_idle_c'] = {
animDictionary = 'creatures@pug@amb@world_dog_sitting@idle_a',
animationName = 'idle_c'
}
},
['sleep'] = {}
},
['PLAYER'] = {
['revive'] = {
['tendtodead'] = {
sequential = true,
list = {
[1] = {
animDictionary = 'amb@medic@standing@tendtodead@enter',
animationName = 'enter'
},
[2] = {
animDictionary = 'amb@medic@standing@tendtodead@idle_a',
animationName = 'idle_c'
},
[3] = {
animDictionary = 'amb@medic@standing@tendtodead@exit',
animationName = 'exit'
}
}
}
}
}
}
-- sort animations by ped model
local correctionList = {
['A_C_Husky'] = animationList.rottweiler,
['A_C_shepherd'] = animationList.rottweiler,
['A_C_Rottweiler'] = animationList.rottweiler,
['A_C_Retriever'] = animationList.rottweiler,
['A_C_Westy'] = animationList.small,
['A_C_Pug'] = animationList.small,
['A_C_Poodle'] = animationList.small,
['A_C_Panther'] = animationList.cougar,
['A_C_MtLion'] = animationList.cougar,
['A_C_Cat_01'] = animationList.cat,
['PLAYER'] = animationList.PLAYER
}
function Animator(pedHandle, pedModel, state, options)
if type(pedHandle) ~= 'number' then assert(pedHandle, 'pedhandle is not a number') return false end
if type(options) ~= 'table' then assert(table, 'Failed to load options table') return false end
-- find a random animaiton if animation is not defined by request
if options.animation == nil then
local tmp = {}
for key, value in pairs(correctionList[pedModel][state]) do
tmp[#tmp + 1] = key
end
options.animation = tmp[math.random(1, #tmp)]
while correctionList[pedModel][state][options.animation].sequential ~= nil do
options.animation = tmp[math.random(1, #tmp)]
end
end
if correctionList[pedModel] == nil or correctionList[pedModel][state] == nil or
correctionList[pedModel][state][options.animation] == nil then
return false
end
-- sequential animation logic
if correctionList[pedModel][state][options.animation].sequential ~= nil and
correctionList[pedModel][state][options.animation].sequential == true then
CreateThread(function()
local finish = false
local count = 1
local size = #correctionList[pedModel][state][options.animation].list
while finish == false do
local currentAnimation = options.animation
if count <= size then
currentAnimation = correctionList[pedModel][state][options.animation].list[count]
end
local c_animDictionary = currentAnimation.animDictionary
local c_animationName = currentAnimation.animationName
local timeout = 0
if options == nil then
options = {}
end
if options.sequentialTimings == nil then
options.sequentialTimings = {}
end
local tmpsequentialTimings = {
[1] = options.sequentialTimings[1] or 0, -- start animation Timeout ==> 1sec(6s-5s) to loop
[2] = options.sequentialTimings[2] or 0, -- loop animation Timeout ==> 6sec(6s-0s) to exit
[3] = options.sequentialTimings[3] or 0, -- exit animation Timeout ==> 4sec(6s-2s) to end
step = options.sequentialTimings['step'] or 1,
Timeout = options.sequentialTimings['Timeout'] or 5
}
if count == 1 then
timeout = timeout + tmpsequentialTimings[1]
excuteAnimation(pedHandle, c_animDictionary, c_animationName, 'STOP_LAST_FRAME')
elseif count == 2 then
timeout = timeout + tmpsequentialTimings[2]
excuteAnimation(pedHandle, c_animDictionary, c_animationName, 'REPEAT')
elseif count == 3 then
timeout = timeout + tmpsequentialTimings[3]
excuteAnimation(pedHandle, c_animDictionary, c_animationName)
end
local skip = false
Wait(75)
while IsEntityPlayingAnim(pedHandle, c_animDictionary, c_animationName, 3) == 1 and skip == false do
if tmpsequentialTimings['Timeout'] ~= 5 then
timeout = timeout + tmpsequentialTimings['step']
if timeout > tmpsequentialTimings['Timeout'] then
skip = true
end
else
timeout = timeout + 1
if timeout > 6 then
skip = true
end
end
Wait(1000)
end
count = count + 1
if count > size then
finish = true
end
end
end)
-- skip rest of functions when we have to play sequential
return
end
-- QBCore.Functions.Notify(Lang:t('menu.action_menu.error.pet_unable_to_do_that'), 'error', 1500)
-- QBCore.Functions.Notify(Lang:t('menu.general_menu_items.success'), 'success', 1500)
local c_animDictionary = correctionList[pedModel][state][options.animation].animDictionary
local c_animationName = correctionList[pedModel][state][options.animation].animationName
excuteAnimation(pedHandle, c_animDictionary, c_animationName, options.c_timings)
end
function excuteAnimation(pedHandle, c_animDictionary, c_animationName, c_timings)
local flag = 0
local slow = -1
if c_timings ~= nil then
if c_timings == 'REPEAT' then
flag = 1
elseif c_timings == 'STOP_LAST_FRAME' then
flag = 2
elseif c_timings == 'UPPERBODY' then
flag = 16
elseif c_timings == 'ENABLE_PLAYER_CONTROL' then
flag = 32
elseif c_timings == 'CANCELABLE' then
flag = 120
else
flag = -1
end
end
waitForAnimation(c_animDictionary)
TaskPlayAnim(pedHandle, c_animDictionary, c_animationName, 8.0, -8, slow, flag, 0, false, false, false)
end
-- missexile2 fra0_ig_14_chop_sniff_fwds
-- missexile2 taunt_01 taunt_02
-- missfra0_chop_find chop_bark_at_ballas
-- missfra0_chop_find fra0_ig_14_chop_sniff_fwds
-- 014704 random@nigel@1c take_collar_cam 3966
-- 014705 random@nigel@1c take_collar_dog 3966
-- 014706 random@nigel@1c take_collar_dogfacial 3966
-- 014707 random@nigel@1c take_collar_trevor 3966
--- missfra1leadinoutfra_1_int_trevor _trevor_leadin_loop_chop <<<< sleep with feared face!
--- misschop_vehicle@back_of_van chop_sit_loop chop_lean_back_loop chop_growl_to_sit chop_growl chop_bark
-- fix_agy_int1-1 a_c_chop_02_dual-1 <<<< sleep
-- options = {
-- animation = ?, -- if not icluded sciprt will pick one random animation inside list
-- c_timings = ?,
-- }