function stopAllAnimations()local E=currentAnim if emoteNames[E]~=nil and emoteNames[E]==false then E="\105\100\108\101"end if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then E="\105\100\108\101"currentlyPlayingEmote=false end currentAnim=""currentAnimInstance=nil if currentAnimKeyframeHandler~=nil then currentAnimKeyframeHandler:Disconnect()end if currentAnimTrack~=nil then currentAnimTrack:Stop()currentAnimTrack:Destroy()currentAnimTrack=nil end if runAnimKeyframeHandler~=nil then runAnimKeyframeHandler:Disconnect()end if runAnimTrack~=nil then runAnimTrack:Stop()runAnimTrack:Destroy()runAnimTrack=nil end return E end function getHeightScale()if Humanoid then if not Humanoid.AutomaticScalingEnabled then return 1 end local E=Humanoid.HipHeight/HumanoidHipHeight if AnimationSpeedDampeningObject==nil then AnimationSpeedDampeningObject=script:FindFirstChild("\083\099\097\108\101\068\097\109\112\101\110\105\110\103\080\101\114\099\101\110\116")end if AnimationSpeedDampeningObject~=nil then E=1+((Humanoid.HipHeight-HumanoidHipHeight)*AnimationSpeedDampeningObject.Value)/HumanoidHipHeight end return E end return 1 end local function E(E)local e=E*1.25 local Z=getHeightScale()local B=e/Z return B end local e=.0001 local function Z(Z)local B=.5 local J=1 local T=E(Z)local H=e local s=e local D=T/B local w=T/J if T<=B then H=1 elseif T<J then local E=(T-B)/(J-B)H=1-E s=E D=1 w=1 else s=1 end currentAnimTrack:AdjustWeight(H)runAnimTrack:AdjustWeight(s)currentAnimTrack:AdjustSpeed(D)runAnimTrack:AdjustSpeed(w)end function setAnimationSpeed(E)if currentAnim=="\119\097\108\107"then Z(E)else if E~=currentAnimSpeed then currentAnimSpeed=E currentAnimTrack:AdjustSpeed(currentAnimSpeed)end end end function keyFrameReachedFunc(E)if E=="\069\110\100"then if currentAnim=="\119\097\108\107"then if userNoUpdateOnLoop==true then if runAnimTrack.Looped~=true then runAnimTrack.TimePosition=.0 end if currentAnimTrack.Looped~=true then currentAnimTrack.TimePosition=.0 end else runAnimTrack.TimePosition=.0 currentAnimTrack.TimePosition=.0 end else local E=currentAnim if emoteNames[E]~=nil and emoteNames[E]==false then E="\105\100\108\101"end if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then if currentAnimTrack.Looped then return end E="\105\100\108\101"currentlyPlayingEmote=false end local e=currentAnimSpeed playAnimation(E,.15,Humanoid)setAnimationSpeed(e)end end end function rollAnimation(E)local e=math.random(1,animTable[E].totalWeight)local Z=e local B=1 while e>animTable[E][B].weight do e=e-animTable[E][B].weight B=B+1 end return B end local function B(E,e,Z,B)if E~=currentAnimInstance then if currentAnimTrack~=nil then currentAnimTrack:Stop(Z)currentAnimTrack:Destroy()end if runAnimTrack~=nil then runAnimTrack:Stop(Z)runAnimTrack:Destroy()if userNoUpdateOnLoop==true then runAnimTrack=nil end end currentAnimSpeed=1.0 currentAnimTrack=B:LoadAnimation(E)currentAnimTrack.Priority=Enum.AnimationPriority.Core currentAnimTrack:Play(Z)currentAnim=e currentAnimInstance=E if currentAnimKeyframeHandler~=nil then currentAnimKeyframeHandler:Disconnect()end currentAnimKeyframeHandler=currentAnimTrack.KeyframeReached:Connect(keyFrameReachedFunc)if e=="\119\097\108\107"then local E="\114\117\110"local e=rollAnimation(E)runAnimTrack=B:LoadAnimation(animTable[E][e].anim)runAnimTrack.Priority=Enum.AnimationPriority.Core runAnimTrack:Play(Z)if runAnimKeyframeHandler~=nil then runAnimKeyframeHandler:Disconnect()end runAnimKeyframeHandler=runAnimTrack.KeyframeReached:Connect(keyFrameReachedFunc)end end end function playAnimation(E,e,Z)local J=rollAnimation(E)local T=animTable[E][J].anim B(T,E,e,Z)currentlyPlayingEmote=false end function playEmote(E,e,Z)B(E,E.Name,e,Z)currentlyPlayingEmote=true end
-- functions

function stopAllAnimations()
	local oldAnim = currentAnim

	-- return to idle if finishing an emote
	if emoteNames[oldAnim] ~= nil and emoteNames[oldAnim] == false then
		oldAnim = "idle"
	end

	if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then
		oldAnim = "idle"
		currentlyPlayingEmote = false
	end

	currentAnim = ""
	currentAnimInstance = nil
	if currentAnimKeyframeHandler ~= nil then
		currentAnimKeyframeHandler:Disconnect()
	end

	if currentAnimTrack ~= nil then
		currentAnimTrack:Stop()
		currentAnimTrack:Destroy()
		currentAnimTrack = nil
	end

	-- clean up walk if there is one
	if runAnimKeyframeHandler ~= nil then
		runAnimKeyframeHandler:Disconnect()
	end

	if runAnimTrack ~= nil then
		runAnimTrack:Stop()
		runAnimTrack:Destroy()
		runAnimTrack = nil
	end

	return oldAnim
end

function getHeightScale()
	if Humanoid then
		if not Humanoid.AutomaticScalingEnabled then
			return 1
		end

		local scale = Humanoid.HipHeight / HumanoidHipHeight
		if AnimationSpeedDampeningObject == nil then
			AnimationSpeedDampeningObject = script:FindFirstChild("ScaleDampeningPercent")
		end
		if AnimationSpeedDampeningObject ~= nil then
			scale = 1
				+ (Humanoid.HipHeight - HumanoidHipHeight) * AnimationSpeedDampeningObject.Value / HumanoidHipHeight
		end
		return scale
	end
	return 1
end

local function rootMotionCompensation(speed)
	local speedScaled = speed * 1.25
	local heightScale = getHeightScale()
	local runSpeed = speedScaled / heightScale
	return runSpeed
end

local smallButNotZero = 0.0001
local function setRunSpeed(speed)
	local normalizedWalkSpeed = 0.5 -- established empirically using current `913402848` walk animation
	local normalizedRunSpeed = 1
	local runSpeed = rootMotionCompensation(speed)

	local walkAnimationWeight = smallButNotZero
	local runAnimationWeight = smallButNotZero
	local walkAnimationTimewarp = runSpeed / normalizedWalkSpeed
	local runAnimationTimerwarp = runSpeed / normalizedRunSpeed

	if runSpeed <= normalizedWalkSpeed then
		walkAnimationWeight = 1
	elseif runSpeed < normalizedRunSpeed then
		local fadeInRun = (runSpeed - normalizedWalkSpeed) / (normalizedRunSpeed - normalizedWalkSpeed)
		walkAnimationWeight = 1 - fadeInRun
		runAnimationWeight = fadeInRun
		walkAnimationTimewarp = 1
		runAnimationTimerwarp = 1
	else
		runAnimationWeight = 1
	end
	currentAnimTrack:AdjustWeight(walkAnimationWeight)
	runAnimTrack:AdjustWeight(runAnimationWeight)
	currentAnimTrack:AdjustSpeed(walkAnimationTimewarp)
	runAnimTrack:AdjustSpeed(runAnimationTimerwarp)
end

function setAnimationSpeed(speed)
	if currentAnim == "walk" then
		setRunSpeed(speed)
	else
		if speed ~= currentAnimSpeed then
			currentAnimSpeed = speed
			currentAnimTrack:AdjustSpeed(currentAnimSpeed)
		end
	end
end

function keyFrameReachedFunc(frameName)
	if frameName == "End" then
		if currentAnim == "walk" then
			if userNoUpdateOnLoop == true then
				if runAnimTrack.Looped ~= true then
					runAnimTrack.TimePosition = 0.0
				end
				if currentAnimTrack.Looped ~= true then
					currentAnimTrack.TimePosition = 0.0
				end
			else
				runAnimTrack.TimePosition = 0.0
				currentAnimTrack.TimePosition = 0.0
			end
		else
			local repeatAnim = currentAnim
			-- return to idle if finishing an emote
			if emoteNames[repeatAnim] ~= nil and emoteNames[repeatAnim] == false then
				repeatAnim = "idle"
			end

			if FFlagAnimateScriptEmoteHook and currentlyPlayingEmote then
				if currentAnimTrack.Looped then
					-- Allow the emote to loop
					return
				end

				repeatAnim = "idle"
				currentlyPlayingEmote = false
			end

			local animSpeed = currentAnimSpeed
			playAnimation(repeatAnim, 0.15, Humanoid)
			setAnimationSpeed(animSpeed)
		end
	end
end

function rollAnimation(animName)
	local roll = math.random(1, animTable[animName].totalWeight)
	local origRoll = roll
	local idx = 1
	while roll > animTable[animName][idx].weight do
		roll = roll - animTable[animName][idx].weight
		idx = idx + 1
	end
	return idx
end

local function switchToAnim(anim, animName, transitionTime, humanoid)
	-- switch animation
	if anim ~= currentAnimInstance then
		if currentAnimTrack ~= nil then
			currentAnimTrack:Stop(transitionTime)
			currentAnimTrack:Destroy()
		end

		if runAnimTrack ~= nil then
			runAnimTrack:Stop(transitionTime)
			runAnimTrack:Destroy()
			if userNoUpdateOnLoop == true then
				runAnimTrack = nil
			end
		end

		currentAnimSpeed = 1.0

		-- load it to the humanoid; get AnimationTrack
		currentAnimTrack = humanoid:LoadAnimation(anim)
		currentAnimTrack.Priority = Enum.AnimationPriority.Core

		-- play the animation
		currentAnimTrack:Play(transitionTime)
		currentAnim = animName
		currentAnimInstance = anim

		-- set up keyframe name triggers
		if currentAnimKeyframeHandler ~= nil then
			currentAnimKeyframeHandler:Disconnect()
		end
		currentAnimKeyframeHandler = currentAnimTrack.KeyframeReached:Connect(keyFrameReachedFunc)

		-- check to see if we need to blend a walk/run animation
		if animName == "walk" then
			local runAnimName = "run"
			local runIdx = rollAnimation(runAnimName)

			runAnimTrack = humanoid:LoadAnimation(animTable[runAnimName][runIdx].anim)
			runAnimTrack.Priority = Enum.AnimationPriority.Core
			runAnimTrack:Play(transitionTime)

			if runAnimKeyframeHandler ~= nil then
				runAnimKeyframeHandler:Disconnect()
			end
			runAnimKeyframeHandler = runAnimTrack.KeyframeReached:Connect(keyFrameReachedFunc)
		end
	end
end

function playAnimation(animName, transitionTime, humanoid)
	local idx = rollAnimation(animName)
	local anim = animTable[animName][idx].anim

	switchToAnim(anim, animName, transitionTime, humanoid)
	currentlyPlayingEmote = false
end

function playEmote(emoteAnim, transitionTime, humanoid)
	switchToAnim(emoteAnim, emoteAnim.Name, transitionTime, humanoid)
	currentlyPlayingEmote = true
end
