-- 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 = ?, -- }