--[[ m-banking — client/animations.lua Loads, plays and (importantly) cleans up the teller / ATM animations. Each entry in Config.Animations is either a scenario or an anim dictionary: { type = 'scenario', scenario = 'PROP_HUMAN_ATM' } { type = 'anim', dict = '...', name = '...', flag = 49 } ]] Anim = Anim or {} local current = nil --- @param dict string --- @param timeout number|nil ms --- @return boolean loaded local function loadDict(dict, timeout) if HasAnimDictLoaded(dict) then return true end RequestAnimDict(dict) local deadline = GetGameTimer() + (timeout or 3000) while not HasAnimDictLoaded(dict) do if GetGameTimer() > deadline then print(('[m-banking] anim dict "%s" failed to load'):format(dict)) return false end Wait(10) end return true end --- Scenario or anim? `type` wins, otherwise infer from the fields present. --- @param anim table --- @return string local function kindOf(anim) if anim.type then return anim.type end return anim.scenario and 'scenario' or 'anim' end local function ped() return cache and cache.ped or PlayerPedId() end --- Play the animation configured for a context. --- @param context string 'bank' | 'atm' function Anim.Play(context) local anim = Config.Animations[context] if not anim then return end Anim.Stop() if kindOf(anim) == 'scenario' then -- Scenarios need no dictionary and clean up with ClearPedTasks. TaskStartScenarioInPlace(ped(), anim.scenario, 0, true) current = anim return end if not loadDict(anim.dict) then return end TaskPlayAnim(ped(), anim.dict, anim.name, 8.0, -8.0, -1, anim.flag or 49, 0.0, false, false, false) current = anim end --- Stop whatever we started and release the dictionary. function Anim.Stop() if not current then return end local playerPed = ped() if kindOf(current) == 'scenario' then ClearPedTasks(playerPed) else StopAnimTask(playerPed, current.dict, current.name, 1.0) RemoveAnimDict(current.dict) end current = nil end --- Safety net: never leave a player stuck in an animation on resource restart. AddEventHandler('onResourceStop', function(resource) if resource ~= GetCurrentResourceName() then return end Anim.Stop() end)