Untitled
unknown
lua
a year ago
19 kB
6
Indexable
--------------------------- -- author: maksgame19 -- -- version: 1.0 -- --------------------------- local Players = game.Players or game:GetService("Players") local playersData = {} local legacyChat = (game.TextChatService or game:GetService("TextChatService")).ChatVersion == Enum.ChatVersion.LegacyChatService local allowCustomAnims = (game.StarterPlayer or game:GetService("StarterPlayer")).AllowCustomAnimations local localPlrID = Players.localPlayer.UserId local freefall, idle1, idle2, jumping, running, seated, walk, swimmingIdle, swimming, defaultTool, climbing, emotes--animations local customState, localPlayerTable, oldAnim local function startSound(playerTable, sound) local oldSound = playerTable.oldSound if oldSound ~= sound then if oldSound then oldSound:Pause()--can't do "oldSound.Playing = false" because it will privent from fireing Paused event end if sound then sound.Playing = true end playerTable.oldSound = sound end end local function startSoundAndAnim(sound, anim, transitionTime, state) startSound(localPlayerTable, sound) if oldAnim ~= anim then if oldAnim then oldAnim:Stop(transitionTime) end if anim then anim:Play(transitionTime) end customState = state oldAnim = anim end end local function startEmote(emote) if emote then startSoundAndAnim(nil, emote, 0.5, "Idle") emote.Stopped:Wait() task.wait() if customState == "Idle" and emote == oldAnim then startSoundAndAnim(nil, idle1, 0.1, "Idle") end end end local function adjustWalkAndRunProperties(walkWaight, runWaight, speed) walk:AdjustWeight(walkWaight) running:AdjustWeight(runWaight) walk:AdjustSpeed(speed) running:AdjustSpeed(speed) end local localStateFunctions = { [Enum.HumanoidStateType.Jumping] = function() local sounds = localPlayerTable.sounds startSoundAndAnim(sounds.freefall, jumping, 0.1, "jump") local jumpingSound = sounds.jumping jumpingSound.TimePosition = 0 jumpingSound.Playing = true end, [Enum.HumanoidStateType.Freefall] = function(rootPart) local freefallSound = localPlayerTable.sounds.freefall freefallSound.Volume = 0 if customState == "jump" then task.wait(0.3)--jump duration if not freefallSound.IsPlaying then return end end startSoundAndAnim(freefallSound, freefall, 0.2) local thread = task.spawn(function() while rootPart.assemblyLinearVelocity.Y > -75 do task.wait(0.05) end for i = 0, 1, 0.05 do freefallSound.Volume = i task.wait(0.05) end end) freefallSound.Paused:Wait() task.cancel(thread) end, [Enum.HumanoidStateType.Seated] = function() startSoundAndAnim(nil, seated, 0.5) end, } local stateFunctions = { [Enum.HumanoidStateType.Jumping] = function(playerTable) local jump = playerTable.sounds.jumping jump.TimePosition = 0 jump.Playing = true end, [Enum.HumanoidStateType.Freefall] = function(playerTable, rootPart) local freefall = playerTable.sounds.freefall freefall.Volume = 0 startSound(playerTable) task.wait(0.3) if freefall.IsPlaying then local thread = task.spawn(function() repeat freefall.Volume = 0 while rootPart.assemblyLinearVelocity.Y > -75 do task.wait(0.1) end for i = 0, 1, 0.1 do freefall.Volume = i task.wait(0.1) end until rootPart.assemblyLinearVelocity.Y < -75 end) freefall.Paused:Wait() task.cancel(thread) end end, [Enum.HumanoidStateType.Swimming] = function(playerTable, rootPart) local sounds = playerTable.sounds startSound(playerTable, sounds.swimming) rootPart = math.abs(rootPart.assemblyLinearVelocity.Y) if rootPart > 0.1 then local splash = sounds.splash splash.Volume = rootPart * 0.00288 - 0.008 --map a value from one range to another (velY - 100)*(1 - 0.28)/(350 - 100) + 0.28 splash:Play() end end, [Enum.HumanoidStateType.GettingUp] = function(playerTable) playerTable.sounds.gettingUp.Playing = true end, [Enum.HumanoidStateType.Landed] = function(playerTable, rootPart) rootPart = -rootPart.assemblyLinearVelocity.Y if rootPart > 75 then local landing = playerTable.sounds.landing landing.Volume = rootPart/50 - 1--map a value from one range to another (velY - 50)*(1 - 0)/(100 - 50) + 0 landing.Playing = true end end, [Enum.HumanoidStateType.Dead] = function(playerTable) startSound(playerTable) playerTable.sounds.died.Playing = true if playerTable.garbage then--for some reason running event in R15 code doesn't get disconnected so we need to do that manualy localPlayerTable.garbage:Disconnect() end playersData[playerTable.plrID] = nil end, [Enum.HumanoidStateType.Climbing] = function() end, [Enum.HumanoidStateType.Running] = function() end, } local function createSystem(roots, char, plrID, localplr) local humanoid, rootPart = roots.Humanoid, roots.HumanoidRootPart local _, activeState = pcall(function() return humanoid:GetState() end) playersData[plrID] = {} local playerTable = playersData[plrID] playerTable.plrID = plrID playerTable.sounds = {} local sounds = playerTable.sounds local soundsRes = script.Sounds:Clone() for _, sound in soundsRes:GetChildren() do sound.Parent = rootPart sounds[sound.Name] = sound end soundsRes.Parent = nil if not localplr then --connections humanoid.StateChanged:Connect(function(_, state)--state tracker activeState = state local func = stateFunctions[activeState] if func then func(playerTable, rootPart) else startSound(playerTable) end end) humanoid.running:Connect(function(vel) if humanoid.MoveDirection.Magnitude > 0 then local runSound = sounds.running startSound(playerTable, runSound) runSound.PlaybackSpeed = 1.85 else startSound(playerTable) end end) humanoid.climbing:Connect(function(vel) if vel ~= 0 then local runSound = sounds.running startSound(playerTable, runSound) sounds.running.PlaybackSpeed = 1 else startSound(playerTable) end end) --initialize first sound local func = stateFunctions[activeState] if func then func(playerTable, rootPart) end else --local player handler local animate = roots.Animate local rig = humanoid.RigType.Name local animsPack = script[rig] local animator = roots.Animator localPlayerTable = playerTable emotes = {} local function loadNewAnim(anim, priority) anim = animator:LoadAnimation(anim) anim.Priority = priority return anim end --load animations for _, emote in animsPack.emotes:GetChildren() do local name = emote.Name emotes[name] = loadNewAnim(emote, Enum.AnimationPriority.Core) if string.sub(name, 1, 5) ~= "dance" then--roblox set looped to true in every emote animation but only dance's should be looped emotes[name].Looped = false end end defaultTool, seated = loadNewAnim(animsPack.defaultTool, Enum.AnimationPriority.Idle), loadNewAnim(animsPack.seated, Enum.AnimationPriority.Core) if legacyChat and rig == "R15" or not legacyChat then roots.PlayEmote.OnInvoke = function(emote)--custom emote if customState == "Idle" then local loadedEmote = emotes[emote] if loadedEmote then startEmote(loadedEmote) return true elseif emote:IsA("Instance") then local name = emote.Name emotes[name] = loadNewAnim(emote, Enum.AnimationPriority.Core) loadedEmote = emotes[name] loadedEmote.Looped = false startEmote(loadedEmote) return true end end end end humanoid.StateChanged:Connect(function(_, state)--state tracker activeState = state local localFunc = localStateFunctions[activeState] if localFunc then localFunc(rootPart) return end local func = stateFunctions[activeState] if func then func(localPlayerTable, rootPart) else startSoundAndAnim() end end) char.ChildAdded:Connect(function(child) if child:IsA("Tool") and child:FindFirstChild("Handle") then defaultTool:Play() end end) char.ChildRemoved:Connect(function(child) if child:IsA("Tool") and child:FindFirstChild("Handle") then defaultTool:Stop() end end) if rig == "R15" then local humanoidDescription = roots.HumanoidDescription local oldHipHeight = humanoid.HipHeight local scale = 6.4 * oldHipHeight--16 / 1.25 * 2 / (1 + (oldHipHeight - 2) * 1 / 2) local walkIsPlaying localStateFunctions[Enum.HumanoidStateType.Swimming] = nil local function Connections() localPlayerTable.garbage = humanoid.running:Connect(function(vel) if humanoid.MoveDirection.Magnitude > 0 then local runSound = sounds.running startSoundAndAnim(runSound, running, 0.1) runSound.PlaybackSpeed = 1.85 if not walkIsPlaying then walkIsPlaying = true walk:Play() end if humanoid.HipHeight ~= oldHipHeight then oldHipHeight = humanoid.HipHeight scale = 6.4 * oldHipHeight --16 / 1.25 / (1 + (oldHipHeight - 2) * 1 / 2) end vel /= scale if vel <= 0.5 then adjustWalkAndRunProperties(1, 0.0001, vel / 0.5) elseif vel < 1 then vel = vel/0.5 - 1 --(vel-0.5)/0.5 adjustWalkAndRunProperties(1 - vel, vel , 1) else adjustWalkAndRunProperties(0.0001, 1, vel) end if walkIsPlaying == true then running.Stopped:Wait() walk:Stop() walkIsPlaying = nil end else startSoundAndAnim(nil, idle1, 0.2, "Idle") end end) humanoid.climbing:Connect(function(vel) if vel ~= 0 then local runSound = sounds.running startSoundAndAnim(runSound, climbing, 0.1) climbing:AdjustSpeed(vel / 5) runSound.PlaybackSpeed = 1 else startSound(localPlayerTable) climbing:AdjustSpeed(0) end end) humanoid.swimming:Connect(function(vel) if vel > 1 then startSoundAndAnim(sounds.swimming, swimming, 0.3) swimming:AdjustSpeed(vel / 10) else startSoundAndAnim(sounds.swimming, swimmingIdle, 0.5) end end) idle1.DidLoop:Connect(function() if math.random(1, 10) == 1 then idle1:Stop() idle2:Play() oldAnim = idle2 end end) idle2.DidLoop:Connect(function() idle2:Stop() idle1:Play() oldAnim = idle1 end) end --load the rest needed animations if allowCustomAnims and humanoidDescription then local descriptionAnims = {["ClimbAnimation"] = false, ["FallAnimation"] = false, ["IdleAnimation"] = true, ["JumpAnimation"] = false, ["RunAnimation"] = false, ["WalkAnimation"] = false, ["SwimAnimation"] = true} local connections, foundAnims = {}, {} local requiredAnims, count = 0, 0 for idx,anim in descriptionAnims do if humanoidDescription[idx] ~= 0 then if anim then requiredAnims += 2 else requiredAnims += 1 end end end if requiredAnims == 0 then climbing, freefall, idle1, idle2, jumping, running, walk, swimming, swimmingIdle = loadNewAnim(animsPack.climbing, Enum.AnimationPriority.Core), loadNewAnim(animsPack.freefall, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle1, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle2, Enum.AnimationPriority.Core), loadNewAnim(animsPack.jumping, Enum.AnimationPriority.Core), loadNewAnim(animsPack.running, Enum.AnimationPriority.Core), loadNewAnim(animsPack.walk, Enum.AnimationPriority.Core), loadNewAnim(animsPack.swimming, Enum.AnimationPriority.Core), loadNewAnim(animsPack.swimmingIdle, Enum.AnimationPriority.Core) Connections() return end local function checkChild(parent) if not parent:IsA("Animation") then for _,child in parent:GetChildren() do checkChild(child) end table.insert(connections, parent.ChildAdded:Connect(function(child) checkChild(child) end)) return elseif parent.Parent.Name == "pose" or parent.Parent.Name == "mood" then return end foundAnims[parent.Name] = parent count += 1 if count == requiredAnims then-- all Animations found for _,conn in connections do conn:Disconnect() end climbing, freefall, idle1, idle2, jumping, running, walk, swimming, swimmingIdle = loadNewAnim(foundAnims.ClimbAnim or animsPack.climbing, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.FallAnim or animsPack.freefall, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.Animation1 or animsPack.idle1, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.Animation2 or animsPack.idle2, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.JumpAnim or animsPack.jumping, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.RunAnim or animsPack.running, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.WalkAnim or animsPack.walk, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.Swim or animsPack.swimming, Enum.AnimationPriority.Core), loadNewAnim(foundAnims.SwimIdle or animsPack.swimmingIdle, Enum.AnimationPriority.Core) Connections() end end checkChild(animate) else climbing, freefall, idle1, idle2, jumping, running, walk, swimming, swimmingIdle = loadNewAnim(animsPack.climbing, Enum.AnimationPriority.Core), loadNewAnim(animsPack.freefall, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle1, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle2, Enum.AnimationPriority.Core), loadNewAnim(animsPack.jumping, Enum.AnimationPriority.Core), loadNewAnim(animsPack.running, Enum.AnimationPriority.Core), loadNewAnim(animsPack.walk, Enum.AnimationPriority.Core), loadNewAnim(animsPack.swimming, Enum.AnimationPriority.Core), loadNewAnim(animsPack.swimmingIdle, Enum.AnimationPriority.Core) Connections() end else--R6 localStateFunctions[Enum.HumanoidStateType.Swimming] = function(velY) startSoundAndAnim(sounds.swimming, running, 0.4) velY = math.abs(velY.assemblyLinearVelocity.Y) if velY > 0.1 then local splash = sounds.splash splash.Volume = velY * 0.00288 - 0.008 --map a value from one range to another (velY - 100)*(1 - 0.28)/(350 - 100) + 0.28 splash:Play() end end --load the rest needed animations climbing, freefall, idle1, idle2, jumping, running = loadNewAnim(animsPack.climbing, Enum.AnimationPriority.Core), loadNewAnim(animsPack.freefall, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle1, Enum.AnimationPriority.Core), loadNewAnim(animsPack.idle2, Enum.AnimationPriority.Core), loadNewAnim(animsPack.jumping, Enum.AnimationPriority.Core), loadNewAnim(animsPack.running, Enum.AnimationPriority.Core) --connections humanoid.running:Connect(function(vel) if humanoid.MoveDirection.Magnitude > 0 then print(1) local runSound = sounds.running startSoundAndAnim(runSound, running, 0.1) running:AdjustSpeed(vel / 14.5) runSound.PlaybackSpeed = 1.85 else startSoundAndAnim(nil, idle1, 0.1, "Idle") end end) humanoid.climbing:Connect(function(vel) if vel ~= 0 then local runSound = sounds.running startSoundAndAnim(runSound, climbing, 0.1) climbing:AdjustSpeed(vel / 12) runSound.PlaybackSpeed = 1 else startSound(localPlayerTable) climbing:AdjustSpeed(0) end end) idle1.DidLoop:Connect(function() if math.random(1, 10) == 1 then idle1:Stop() idle2:Play() oldAnim = idle2 end end) idle2.DidLoop:Connect(function() idle2:Stop() idle1:Play() oldAnim = idle1 end) end --initialize first animation and/or sound local func = localStateFunctions[activeState] if func then func(rootPart) else startSoundAndAnim(nil, idle1, nil, "Idle") end end end local function WaitForInstances(char, plrId)-- instantly get instances that just loaded local requiredInstances, instancesToFind, localplr, allInstancesFound local foundInstances, connections = {}, {} local count = 0 if plrId ~= localPlrID then localplr = false requiredInstances = 2 instancesToFind = { ["Humanoid"] = true, ["HumanoidRootPart"] = true } else localplr = true requiredInstances = 6 instancesToFind = { ["Animate"] = "PlayEmote", ["Humanoid"] = { ["Animator"] = true, ["HumanoidDescription"] = true }, ["HumanoidRootPart"] = true } end local function checkChild(parent, instancesToFind) local name = parent.Name local nextInstancesToFind = instancesToFind[name] or name == instancesToFind if not nextInstancesToFind then return end foundInstances[name] = parent count += 1 if count == requiredInstances then -- all instances found allInstancesFound = true for _,conn in connections do conn:Disconnect() end createSystem(foundInstances, char, plrId, localplr) elseif nextInstancesToFind ~= true then for _,child in parent:GetChildren() do checkChild(child, nextInstancesToFind) end table.insert(connections, parent.ChildAdded:Connect(function(child) checkChild(child, nextInstancesToFind) end)) end end for _,child in char:GetChildren() do checkChild(child, instancesToFind) end table.insert(connections, char.ChildAdded:Connect(function(child) checkChild(child, instancesToFind) end)) --timeout task.wait(0.1) if not allInstancesFound then if count == 5 and not foundInstances.HumanoidDescription then -- there is a possibility that player will load without custom animation for _,conn in connections do conn:Disconnect() end createSystem(foundInstances, char, plrId, localplr) else for _,conn in connections do conn:Disconnect() end warn("needed instances doesn't exist") end end end local function setup(plr) local char = plr.Character if char then WaitForInstances(char, plr.UserId) end plr.CharacterAdded:Connect(function(char) WaitForInstances(char, plr.UserId) end) end for _, plr in Players:GetChildren() do -- a bit faster from GetPlayers setup(plr) end Players.PlayerAdded:Connect(setup) Players.PlayerRemoving:Connect(function(plr) playersData[plr.UserId] = nil end) --emote executor if legacyChat then Players.localPlayer.Chatted:connect(function(msg) if string.sub(msg, 1, 1) == "/" and customState == "Idle" then msg = string.lower(msg) if string.sub(msg, 2, 3) == "e " then startEmote(emotes[string.sub(msg, 4)]) elseif string.sub(msg, 2, 7) == "emote " then startEmote(emotes[string.sub(msg, 8)]) end end end) end
Editor is loading...
Leave a Comment