local v={}local X=game:GetService("\083\111\117\110\100\083\101\114\118\105\099\101")local C="\068\101\102\097\117\108\116\083\111\117\110\100\069\118\101\110\116\115"local p=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local h=nil local F=nil local D=p:FindFirstChild(C)local k=(UserSettings()):IsUserFeatureEnabled("\085\115\101\114\085\115\101\083\111\117\110\100\068\105\115\112\097\116\099\104\101\114")if k then if not D then D=Instance.new("\070\111\108\100\101\114",p)D.Name=C D.Archivable=false end F=D:FindFirstChild("\082\101\109\111\118\101\067\104\097\114\097\099\116\101\114\069\118\101\110\116")if F==nil then F=Instance.new("\082\101\109\111\116\101\069\118\101\110\116",D)F.Name="\082\101\109\111\118\101\067\104\097\114\097\099\116\101\114\069\118\101\110\116"end h=D:FindFirstChild("\065\100\100\067\104\097\114\097\099\116\101\114\076\111\097\100\101\100\069\118\101\110\116")if h==nil then h=Instance.new("\082\101\109\111\116\101\069\118\101\110\116",D)h.Name="\065\100\100\067\104\097\114\097\099\116\101\114\076\111\097\100\101\100\069\118\101\110\116"end h:FireServer()game.Players.LocalPlayer.CharacterRemoving:connect(function(v)F:FireServer(game.Players.LocalPlayer)end)end do local X=script.Parent.Parent Head=X:WaitForChild("\072\101\097\100")while not Humanoid do for v,X in pairs(X:GetChildren())do if X:IsA("\072\117\109\097\110\111\105\100")then Humanoid=X break end end if Humanoid then break end X.ChildAdded:wait()end v[SFX.Died]=Head:WaitForChild("\068\105\101\100")v[SFX.Running]=Head:WaitForChild("\082\117\110\110\105\110\103")v[SFX.Swimming]=Head:WaitForChild("\083\119\105\109\109\105\110\103")v[SFX.Climbing]=Head:WaitForChild("\067\108\105\109\098\105\110\103")v[SFX.Jumping]=Head:WaitForChild("\074\117\109\112\105\110\103")v[SFX.GettingUp]=Head:WaitForChild("\071\101\116\116\105\110\103\085\112")v[SFX.FreeFalling]=Head:WaitForChild("\070\114\101\101\070\097\108\108\105\110\103")v[SFX.Landing]=Head:WaitForChild("\076\097\110\100\105\110\103")v[SFX.Splash]=Head:WaitForChild("\083\112\108\097\115\104")local C=nil if k then C=D:FindFirstChild("\068\101\102\097\117\108\116\083\101\114\118\101\114\083\111\117\110\100\069\118\101\110\116")else C=(game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):FindFirstChild("\068\101\102\097\117\108\116\083\101\114\118\101\114\083\111\117\110\100\069\118\101\110\116")end if C then C.OnClientEvent:connect(function(v,X,C)if C and v.TimePosition~=0 then v.TimePosition=0 end if v.IsPlaying~=X then v.Playing=X end end)end end local O=function()return game.Workspace.FilteringEnabled and X.RespectFilteringEnabled end local d d={YForLineGivenXAndTwoPts=function(v,X,C,p,h)local F=(C-h)/(X-p)local D=C-F*X return F*v+D end;Clamp=function(v,X,C)return math.min(C,math.max(X,v))end,HorizontalSpeed=function(v)local X=v.Velocity+Vector3.new(0,-v.Velocity.Y,0)return X.magnitude end,VerticalSpeed=function(v)return math.abs(v.Velocity.Y)end;Play=function(v)if O()then v.CharacterSoundEvent:FireServer(true,true)end if v.TimePosition~=0 then v.TimePosition=0 end if not v.IsPlaying then v.Playing=true end end;Pause=function(v)if O()then v.CharacterSoundEvent:FireServer(false,false)end if v.IsPlaying then v.Playing=false end end,Resume=function(v)if O()then v.CharacterSoundEvent:FireServer(true,false)end if not v.IsPlaying then v.Playing=true end end;Stop=function(v)if O()then v.CharacterSoundEvent:FireServer(false,true)end if v.IsPlaying then v.Playing=false end if v.TimePosition~=0 then v.TimePosition=0 end end}do local X={}local C=nil local p=0 function setSoundInPlayingLoopedSounds(v)for C=1,#X,1 do if X[C]==v then return end end table.insert(X,v)end function stopPlayingLoopedSoundsExcept(v)for C=#X,1,-1 do if X[C]~=v then d.Pause(X[C])table.remove(X,C)end end end local h={[Enum.HumanoidStateType.Dead]=function()stopPlayingLoopedSoundsExcept()local X=v[SFX.Died]d.Play(X)end;[Enum.HumanoidStateType.RunningNoPhysics]=function(v)stateUpdated(Enum.HumanoidStateType.Running,v)end;[Enum.HumanoidStateType.Running]=function(X)local h=v[SFX.Running]stopPlayingLoopedSoundsExcept(h)if useUpdatedLocalSoundFlag and(C==Enum.HumanoidStateType.Freefall and p>.1)then local X=math.min(1.0,math.max(.0,(p-50)/110))local C=v[SFX.FreeFalling]C.Volume=X d.Play(C)p=0 end if useUpdatedLocalSoundFlag then if X~=nil and X>.5 then d.Resume(h)setSoundInPlayingLoopedSounds(h)elseif X~=nil then stopPlayingLoopedSoundsExcept()end else if d.HorizontalSpeed(Head)>.5 then d.Resume(h)setSoundInPlayingLoopedSounds(h)else stopPlayingLoopedSoundsExcept()end end end;[Enum.HumanoidStateType.Swimming]=function(X)local p if useUpdatedLocalSoundFlag then p=X else p=d.VerticalSpeed(Head)end if C~=Enum.HumanoidStateType.Swimming and p>.1 then local X=v[SFX.Splash]X.Volume=d.Clamp(d.YForLineGivenXAndTwoPts(d.VerticalSpeed(Head),100,.28,350,1),0,1)d.Play(X)end do local X=v[SFX.Swimming]stopPlayingLoopedSoundsExcept(X)d.Resume(X)setSoundInPlayingLoopedSounds(X)end end,[Enum.HumanoidStateType.Climbing]=function(X)local C=v[SFX.Climbing]if useUpdatedLocalSoundFlag then if X~=nil and math.abs(X)>.1 then d.Resume(C)stopPlayingLoopedSoundsExcept(C)else d.Pause(C)stopPlayingLoopedSoundsExcept(C)end else if d.VerticalSpeed(Head)>.1 then d.Resume(C)stopPlayingLoopedSoundsExcept(C)else stopPlayingLoopedSoundsExcept()end end setSoundInPlayingLoopedSounds(C)end,[Enum.HumanoidStateType.Jumping]=function()if C==Enum.HumanoidStateType.Jumping then return end stopPlayingLoopedSoundsExcept()local X=v[SFX.Jumping]d.Play(X)end;[Enum.HumanoidStateType.GettingUp]=function()stopPlayingLoopedSoundsExcept()local X=v[SFX.GettingUp]d.Play(X)end,[Enum.HumanoidStateType.Freefall]=function()if C==Enum.HumanoidStateType.Freefall then return end local X=v[SFX.FreeFalling]X.Volume=0 stopPlayingLoopedSoundsExcept()p=math.max(p,math.abs(Head.Velocity.y))end;[Enum.HumanoidStateType.FallingDown]=function()stopPlayingLoopedSoundsExcept()end,[Enum.HumanoidStateType.Landed]=function()stopPlayingLoopedSoundsExcept()if d.VerticalSpeed(Head)>75 then local X=v[SFX.Landing]X.Volume=d.Clamp(d.YForLineGivenXAndTwoPts(d.VerticalSpeed(Head),50,0,100,1),0,1)d.Play(X)end end,[Enum.HumanoidStateType.Seated]=function()stopPlayingLoopedSoundsExcept()end}function stateUpdated(v,X)if h[v]~=nil then if useUpdatedLocalSoundFlag and(v==Enum.HumanoidStateType.Running or v==Enum.HumanoidStateType.Climbing or v==Enum.HumanoidStateType.Swimming or v==Enum.HumanoidStateType.RunningNoPhysics)then h[v](X)else h[v]()end end C=v end Humanoid.Died:connect(function()stateUpdated(Enum.HumanoidStateType.Dead)end)Humanoid.Running:connect(function(v)stateUpdated(Enum.HumanoidStateType.Running,v)end)Humanoid.Swimming:connect(function(v)stateUpdated(Enum.HumanoidStateType.Swimming,v)end)Humanoid.Climbing:connect(function(v)stateUpdated(Enum.HumanoidStateType.Climbing,v)end)Humanoid.Jumping:connect(function()stateUpdated(Enum.HumanoidStateType.Jumping)end)Humanoid.GettingUp:connect(function()stateUpdated(Enum.HumanoidStateType.GettingUp)end)Humanoid.FreeFalling:connect(function()stateUpdated(Enum.HumanoidStateType.Freefall)end)Humanoid.FallingDown:connect(function()stateUpdated(Enum.HumanoidStateType.FallingDown)end)Humanoid.StateChanged:connect(function(v,X)stateUpdated(X)end)function onUpdate(X,p)local h=X/p do local X=v[SFX.FreeFalling]if C==Enum.HumanoidStateType.Freefall then if Head.Velocity.Y<0 and d.VerticalSpeed(Head)>75 then d.Resume(X)local v=1.1 local C=p/v X.Volume=d.Clamp(X.Volume+C*h,0,1)else X.Volume=0 end else d.Pause(X)end end do local X=v[SFX.Running]if C==Enum.HumanoidStateType.Running then if d.HorizontalSpeed(Head)<.5 then d.Pause(X)end end end end local F=tick()local D=.25 while true do onUpdate(tick()-F,D)F=tick()wait(D)end end

local Sounds = {}
local SoundService = game:GetService("SoundService")
local soundEventFolderName = "DefaultSoundEvents"
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AddCharacterLoadedEvent = nil
local RemoveCharacterEvent = nil
local soundEventFolder = ReplicatedStorage:FindFirstChild(soundEventFolderName)
local useSoundDispatcher = UserSettings():IsUserFeatureEnabled("UserUseSoundDispatcher")

if useSoundDispatcher then
	if not soundEventFolder then
		soundEventFolder = Instance.new("Folder", ReplicatedStorage)
		soundEventFolder.Name = soundEventFolderName
		soundEventFolder.Archivable = false
	end
	
	-- Load the RemoveCharacterEvent
	RemoveCharacterEvent = soundEventFolder:FindFirstChild("RemoveCharacterEvent")
	if RemoveCharacterEvent == nil then
		RemoveCharacterEvent = Instance.new("RemoteEvent", soundEventFolder)
		RemoveCharacterEvent.Name = "RemoveCharacterEvent"
	end

	AddCharacterLoadedEvent = soundEventFolder:FindFirstChild("AddCharacterLoadedEvent")
	if AddCharacterLoadedEvent == nil then
		AddCharacterLoadedEvent = Instance.new("RemoteEvent", soundEventFolder)
		AddCharacterLoadedEvent.Name = "AddCharacterLoadedEvent"
	end

	-- Notify the server a new character has been loaded
	AddCharacterLoadedEvent:FireServer()

	-- Notify the sound dispatcher this character has left.
	game.Players.LocalPlayer.CharacterRemoving:connect(function(character)
		RemoveCharacterEvent:FireServer(game.Players.LocalPlayer)
	end)
end

do
	local Figure = script.Parent.Parent
	Head = Figure:WaitForChild("Head")
	while not Humanoid do
		for _,NewHumanoid in pairs(Figure:GetChildren()) do
			if NewHumanoid:IsA("Humanoid") then
				Humanoid = NewHumanoid
				break
			end
		end
		if Humanoid then break end
		Figure.ChildAdded:wait()
	end
	Sounds[SFX.Died] = 			Head:WaitForChild("Died")
	Sounds[SFX.Running] = 		Head:WaitForChild("Running")
	Sounds[SFX.Swimming] = 	Head:WaitForChild("Swimming")
	Sounds[SFX.Climbing] = 	Head:WaitForChild("Climbing")
	Sounds[SFX.Jumping] = 		Head:WaitForChild("Jumping")
	Sounds[SFX.GettingUp] = 	Head:WaitForChild("GettingUp")
	Sounds[SFX.FreeFalling] = 	Head:WaitForChild("FreeFalling")
	Sounds[SFX.Landing] = 		Head:WaitForChild("Landing")
	Sounds[SFX.Splash] = 		Head:WaitForChild("Splash")

	local DefaultServerSoundEvent = nil
	if useSoundDispatcher then
		DefaultServerSoundEvent = soundEventFolder:FindFirstChild("DefaultServerSoundEvent")
	else
		DefaultServerSoundEvent = game:GetService("ReplicatedStorage"):FindFirstChild("DefaultServerSoundEvent")
	end

	if DefaultServerSoundEvent then
		DefaultServerSoundEvent.OnClientEvent:connect(function(sound, playing, resetPosition)
			if resetPosition and sound.TimePosition ~= 0 then
				sound.TimePosition = 0
			end
			if sound.IsPlaying ~= playing then
				sound.Playing = playing
			end
		end)
	end
end

local IsSoundFilteringEnabled = function()
	return game.Workspace.FilteringEnabled and SoundService.RespectFilteringEnabled
end

local Util
Util = {

	--Define linear relationship between (pt1x,pt2x) and (pt2x,pt2y). Evaluate this at x.
	YForLineGivenXAndTwoPts = function(x,pt1x,pt1y,pt2x,pt2y)
		--(y - y1)/(x - x1) = m
		local m = (pt1y - pt2y) / (pt1x - pt2x)
		--float b = pt1.y - m * pt1.x;
		local b = (pt1y - m * pt1x)
		return m * x + b
	end;

	--Clamps the value of "val" between the "min" and "max"
	Clamp = function(val,min,max)
		return math.min(max,math.max(min,val))	
	end;

	--Gets the horizontal (x,z) velocity magnitude of the given part
	HorizontalSpeed = function(Head)
		local hVel = Head.Velocity + Vector3.new(0,-Head.Velocity.Y,0)
		return hVel.magnitude	
	end;

	--Gets the vertical (y) velocity magnitude of the given part
	VerticalSpeed = function(Head)
		return math.abs(Head.Velocity.Y)
	end;

	--Setting Playing/TimePosition values directly result in less network traffic than Play/Pause/Resume/Stop
	--If these properties are enabled, use them.
	Play = function(sound)	
		if IsSoundFilteringEnabled() then
			sound.CharacterSoundEvent:FireServer(true, true)
		end
		if sound.TimePosition ~= 0 then
			sound.TimePosition = 0
		end
		if not sound.IsPlaying then
			sound.Playing = true
		end
	end;

	Pause = function(sound)
		if IsSoundFilteringEnabled() then
			sound.CharacterSoundEvent:FireServer(false, false)
		end
		if sound.IsPlaying then
			sound.Playing = false
		end
	end;

	Resume = function(sound)
		if IsSoundFilteringEnabled() then
			sound.CharacterSoundEvent:FireServer(true, false)
		end
		if not sound.IsPlaying then
			sound.Playing = true
		end
	end;

	Stop = function(sound)
		if IsSoundFilteringEnabled() then
			sound.CharacterSoundEvent:FireServer(false, true)
		end
		if sound.IsPlaying then
			sound.Playing = false
		end
		if sound.TimePosition ~= 0 then
			sound.TimePosition = 0
		end
	end;
}

do
	-- List of all active Looped sounds
	local playingLoopedSounds = {}

	-- Last seen Enum.HumanoidStateType
	local activeState = nil

	local fallSpeed = 0

	-- Verify and set that "sound" is in "playingLoopedSounds".
	function setSoundInPlayingLoopedSounds(sound)
		for i=1, #playingLoopedSounds do
			if playingLoopedSounds[i] == sound then
				return
			end
		end	
		table.insert(playingLoopedSounds,sound)
	end

	-- Stop all active looped sounds except parameter "except". If "except" is not passed, all looped sounds will be stopped.
	function stopPlayingLoopedSoundsExcept(except)
		for i=#playingLoopedSounds,1,-1 do
			if playingLoopedSounds[i] ~= except then
				Util.Pause(playingLoopedSounds[i])			
				table.remove(playingLoopedSounds,i)	
			end
		end
	end

	-- Table of Enum.HumanoidStateType to handling function
	local stateUpdateHandler = {
		[Enum.HumanoidStateType.Dead] = function()
			stopPlayingLoopedSoundsExcept()
			local sound = Sounds[SFX.Died]
			Util.Play(sound)
		end;

		[Enum.HumanoidStateType.RunningNoPhysics] = function(speed)
			stateUpdated(Enum.HumanoidStateType.Running, speed)
		end;

		[Enum.HumanoidStateType.Running] = function(speed)	
			local sound = Sounds[SFX.Running]
			stopPlayingLoopedSoundsExcept(sound)

			if(useUpdatedLocalSoundFlag and activeState == Enum.HumanoidStateType.Freefall and fallSpeed > 0.1) then
				-- Play a landing sound if the character dropped from a large distance
				local vol = math.min(1.0, math.max(0.0, (fallSpeed - 50) / 110))
				local freeFallSound = Sounds[SFX.FreeFalling]
				freeFallSound.Volume = vol
				Util.Play(freeFallSound)
				fallSpeed = 0
			end
			if useUpdatedLocalSoundFlag then
				if speed ~= nil and speed > 0.5 then
					Util.Resume(sound)
					setSoundInPlayingLoopedSounds(sound)
				elseif speed ~= nil then
					stopPlayingLoopedSoundsExcept()
				end
			else
				if Util.HorizontalSpeed(Head) > 0.5 then
					Util.Resume(sound)
					setSoundInPlayingLoopedSounds(sound)
				else
					stopPlayingLoopedSoundsExcept()
				end
			end
		end;

		[Enum.HumanoidStateType.Swimming] = function(speed)
		local threshold
		if useUpdatedLocalSoundFlag then threshold = speed else threshold = Util.VerticalSpeed(Head) end
			if activeState ~= Enum.HumanoidStateType.Swimming and threshold > 0.1 then
				local splashSound = Sounds[SFX.Splash]
				splashSound.Volume = Util.Clamp(
					Util.YForLineGivenXAndTwoPts(
						Util.VerticalSpeed(Head), 
						100, 0.28, 
						350, 1),
					0,1)
				Util.Play(splashSound)
			end

			do
				local sound = Sounds[SFX.Swimming]
				stopPlayingLoopedSoundsExcept(sound)
				Util.Resume(sound)
				setSoundInPlayingLoopedSounds(sound)
			end
		end;

		[Enum.HumanoidStateType.Climbing] = function(speed)
			local sound = Sounds[SFX.Climbing]
			if useUpdatedLocalSoundFlag then
				if speed ~= nil and math.abs(speed) > 0.1 then
					Util.Resume(sound)
					stopPlayingLoopedSoundsExcept(sound)
				else
					Util.Pause(sound)
					stopPlayingLoopedSoundsExcept(sound)
				end		
			else
				if Util.VerticalSpeed(Head) > 0.1 then
					Util.Resume(sound)
					stopPlayingLoopedSoundsExcept(sound)
				else
					stopPlayingLoopedSoundsExcept()
				end
			end

			setSoundInPlayingLoopedSounds(sound)
		end;

		[Enum.HumanoidStateType.Jumping] = function()
			if activeState == Enum.HumanoidStateType.Jumping then
				return
			end		
			stopPlayingLoopedSoundsExcept()
			local sound = Sounds[SFX.Jumping]
			Util.Play(sound)
		end;

		[Enum.HumanoidStateType.GettingUp] = function()
			stopPlayingLoopedSoundsExcept()
			local sound = Sounds[SFX.GettingUp]
			Util.Play(sound)
		end;

		[Enum.HumanoidStateType.Freefall] = function()
			if activeState == Enum.HumanoidStateType.Freefall then
				return
			end
			local sound = Sounds[SFX.FreeFalling]
			sound.Volume = 0
			stopPlayingLoopedSoundsExcept()

			fallSpeed = math.max(fallSpeed, math.abs(Head.Velocity.y))
		end;

		[Enum.HumanoidStateType.FallingDown] = function()
			stopPlayingLoopedSoundsExcept()
		end;

		[Enum.HumanoidStateType.Landed] = function()
			stopPlayingLoopedSoundsExcept()
			if Util.VerticalSpeed(Head) > 75 then
				local landingSound = Sounds[SFX.Landing]
				landingSound.Volume = Util.Clamp(
					Util.YForLineGivenXAndTwoPts(
						Util.VerticalSpeed(Head), 
						50, 0, 
						100, 1),
					0,1)
				Util.Play(landingSound)			
			end
		end;

		[Enum.HumanoidStateType.Seated] = function()
			stopPlayingLoopedSoundsExcept()
		end;	
	}

	

	-- Handle state event fired or OnChange fired
	function stateUpdated(state, speed)
		if stateUpdateHandler[state] ~= nil then
			if useUpdatedLocalSoundFlag and (state == Enum.HumanoidStateType.Running 
				or state == Enum.HumanoidStateType.Climbing
				or state == Enum.HumanoidStateType.Swimming
				or state == Enum.HumanoidStateType.RunningNoPhysics) then
				stateUpdateHandler[state](speed)
			else
				stateUpdateHandler[state]()
			end
		end
		activeState = state
	end

	Humanoid.Died:connect(			function() stateUpdated(Enum.HumanoidStateType.Dead) 			end)
	Humanoid.Running:connect(		function(speed) stateUpdated(Enum.HumanoidStateType.Running, speed) end)
	Humanoid.Swimming:connect(		function(speed) stateUpdated(Enum.HumanoidStateType.Swimming, speed) end)
	Humanoid.Climbing:connect(		function(speed) stateUpdated(Enum.HumanoidStateType.Climbing, speed) end)
	Humanoid.Jumping:connect(		function() stateUpdated(Enum.HumanoidStateType.Jumping) 		end)
	Humanoid.GettingUp:connect(		function() stateUpdated(Enum.HumanoidStateType.GettingUp) 		end)
	Humanoid.FreeFalling:connect(	function() stateUpdated(Enum.HumanoidStateType.Freefall) 		end)
	Humanoid.FallingDown:connect(	function() stateUpdated(Enum.HumanoidStateType.FallingDown) 	end)

	

	-- required for proper handling of Landed event

	Humanoid.StateChanged:connect(function(old, new)
		stateUpdated(new)
	end)

	

	function onUpdate(stepDeltaSeconds, tickSpeedSeconds)
		local stepScale = stepDeltaSeconds / tickSpeedSeconds
		do
			local sound = Sounds[SFX.FreeFalling]
			if activeState == Enum.HumanoidStateType.Freefall then
				if Head.Velocity.Y < 0 and Util.VerticalSpeed(Head) > 75 then
					Util.Resume(sound)

					--Volume takes 1.1 seconds to go from volume 0 to 1
					local ANIMATION_LENGTH_SECONDS = 1.1

					local normalizedIncrement = tickSpeedSeconds / ANIMATION_LENGTH_SECONDS									
					sound.Volume = Util.Clamp(sound.Volume + normalizedIncrement * stepScale, 0, 1)
				else
					sound.Volume = 0
				end			
			else
				Util.Pause(sound)
			end
		end

		do
			local sound = Sounds[SFX.Running]
			if activeState == Enum.HumanoidStateType.Running then
				if Util.HorizontalSpeed(Head) < 0.5 then
					Util.Pause(sound)
				end
			end
		end		
	end

	
	local lastTick = tick()
	local TICK_SPEED_SECONDS = 0.25
	while true do
		onUpdate(tick() - lastTick,TICK_SPEED_SECONDS)
		lastTick = tick()
		wait(TICK_SPEED_SECONDS)
	end

end
