Tool=script.Parent Handle=Tool:WaitForChild("\072\097\110\100\108\101")Players=game:GetService("\080\108\097\121\101\114\115")Debris=game:GetService("\068\101\098\114\105\115")RunService=game:GetService("\082\117\110\083\101\114\118\105\099\101")Camera=(game:GetService("\087\111\114\107\115\112\097\099\101")).CurrentCamera Animations={}LocalObjects={}Speed={CurrentSpeed=5;MaxSpeed=100}Jumping={JumpTick=0;Jumps=0;JumpTime=.25,JumpsRequired=1}Controls={Forward={Number=0,Numbers={On=-1;Off=0};Keys={"\087",17}};Backward={Number=0,Numbers={On=1;Off=0};Keys={"\083",18}};Left={Number=0;Numbers={On=-1,Off=0},Keys={"\065";20}};Right={Number=0;Numbers={On=1,Off=0};Keys={"\068",19}}}UsableAnimations={Pose={Animation=Tool:WaitForChild("\080\111\115\101"),FadeTime=nil;Weight=nil;Speed=nil}}Sounds={Wind=Handle:WaitForChild("\087\105\110\100")}FlyRate=.016666666666667 Debounce=false Flying=false ToolEquipped=false ServerControl=Tool:WaitForChild("\083\101\114\118\101\114\067\111\110\116\114\111\108")ClientControl=Tool:WaitForChild("\067\108\105\101\110\116\067\111\110\116\114\111\108")function SetAnimation(J,H)if J=="\080\108\097\121\065\110\105\109\097\116\105\111\110"and(H and(ToolEquipped and Humanoid))then for J,u in pairs(Animations)do if u.Animation==H.Animation then u.AnimationTrack:Stop()table.remove(Animations,J)end end local J=Humanoid:LoadAnimation(H.Animation)table.insert(Animations,{Animation=H.Animation;AnimationTrack=J})J:Play(H.FadeTime,H.Weight,H.Speed)elseif J=="\083\116\111\112\065\110\105\109\097\116\105\111\110"and H then for J,u in pairs(Animations)do if u.Animation==H.Animation then u.AnimationTrack:Stop()table.remove(Animations,J)end end end end function DisableJump(J)if PreventJump then PreventJump:disconnect()end if J then PreventJump=Humanoid.Changed:connect(function(J)if J=="\074\117\109\112"then Humanoid.Jump=false end end)end end function Clamp(J,H,u)return math.max(math.min(u,J),H)end function Fly()if Flying and(Player and(Torso and(Humanoid and Humanoid.Health>0)))then local J=Vector3.new(0,0,0)local H=Vector3.new(0,0,0)local u=0 local G=0 local y=Speed.MaxSpeed local V=1-Speed.CurrentSpeed/y J=(Torso.Velocity+Torso.CFrame.lookVector*3)+Vector3.new(0,10,0)J=Vector3.new(Clamp(J.X,-15,15),Clamp(J.Y,-15,15),Clamp(J.Z,-15,15))BodyVelocity.maxForce=Vector3.new(1,1,1)*1000000.0 BodyGyro.maxTorque=Vector3.new(BodyGyro.P,BodyGyro.P,BodyGyro.P)BodyGyro.cframe=Torso.CFrame Spawn(function()InvokeServer("\070\108\121\105\110\103",{Flying=true})end)SetAnimation("\080\108\097\121\065\110\105\109\097\116\105\111\110",UsableAnimations.Pose)Humanoid.AutoRotate=false while Flying and(Torso and(Humanoid and Humanoid.Health>0))do if y~=Speed.MaxSpeed then y=Speed.MaxSpeed V=1-Speed.CurrentSpeed/y end local f=Camera.CoordinateFrame:vectorToWorldSpace(Vector3.new(Controls.Left.Number+Controls.Right.Number,math.abs(Controls.Forward.Number)*.2,Controls.Forward.Number+Controls.Backward.Number))local S=f*Speed.CurrentSpeed J=J*V+S local R=J.magnitude if R>y then R=y end local K=((J*Vector3.new(1,0,1)).unit:Cross((H*Vector3.new(1,0,1)).unit)).y local M=tostring(K)if M=="-\049\046\035\073\078\068"or M=="\049\046\035\073\078\068"or K==math.huge or K==-math.huge or M==tostring(0/0)then K=0 end local F=math.abs(K)if F>.06 or F<.0001 then if math.abs(u)>.0001 then K=u*.9 else K=0 end else K=u*.77+K*.25 end u=K if R<.5 then J=Vector3.new(0,0,0)R=0 BodyGyro.cframe=Camera.CoordinateFrame else BodyGyro.cframe=(CFrame.new(Vector3.new(0,0,0),J)*CFrame.Angles(0,0,K*-20))*CFrame.Angles((math.pi*-0.5)*(R/y),0,0)end local g=((J*Vector3.new(0,1,0)-Vector3.new(0,-Speed.MaxSpeed,0)).magnitude/Speed.MaxSpeed)*.5 if g>.45 and tick()>G then G=tick()+.5 Spawn(function()if not Flying then return end if not Sounds.Wind.IsPlaying then Sounds.Wind:Play()end Spawn(function()InvokeServer("\083\101\116\087\105\110\103\083\112\097\110",{Angle=0,MaxVelocity=.05})end)wait(.25)if not Flying then return end Spawn(function()InvokeServer("\083\101\116\087\105\110\103\083\112\097\110",{Angle=.5;MaxVelocity=.05})end)wait(.25)end)elseif g<=.45 then Sounds.Wind:Stop()end BodyVelocity.velocity=J H=J wait(FlyRate)end Sounds.Wind:Stop()Spawn(function()InvokeServer("\083\101\116\087\105\110\103\083\112\097\110",{Angle=0;MaxVelocity=.01})end)Spawn(function()InvokeServer("\070\108\121\105\110\103",{Flying=false})end)SetAnimation("\083\116\111\112\065\110\105\109\097\116\105\111\110",UsableAnimations.Pose)BodyVelocity.maxForce=Vector3.new(0,0,0)BodyGyro.maxTorque=Vector3.new(0,0,0)if CheckIfAlive()then Humanoid.AutoRotate=true Humanoid:ChangeState(Enum.HumanoidStateType.Freefall)end end end function StopFlying()Flying=false BodyVelocity.maxForce=Vector3.new(0,0,0)BodyGyro.maxTorque=Vector3.new(0,0,0)end function CheckIfAlive()return(Character and(Character.Parent and(Humanoid and(Humanoid.Parent and(Humanoid.Health>0 and(Torso and(Torso.Parent and(Player and Player.Parent))))))))and true or false end function Equipped(J)Character=Tool.Parent Humanoid=Character:FindFirstChild("\072\117\109\097\110\111\105\100")Torso=Character:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")Player=Players:GetPlayerFromCharacter(Character)if not CheckIfAlive()then return end PlayerMouse=Player:GetMouse()J.Button1Down:connect(function()InvokeServer("\077\111\117\115\101\067\108\105\099\107",{Down=true})end)J.Button1Up:connect(function()InvokeServer("\077\111\117\115\101\067\108\105\099\107",{Down=false})end)J.KeyDown:connect(function(J)local H=string.lower(J)local u=string.byte(H)if u==string.byte(" ")and not Debounce then if Flying then StopFlying()elseif not Flying then if tick()-Jumping.JumpTick<=Jumping.JumpTime or Jumping.JumpTick==0 then Jumping.JumpTick=tick()Jumping.Jumps=Jumping.Jumps+1 if Jumping.Jumps>=Jumping.JumpsRequired then Debounce=true Jumping.JumpTick=0 Jumping.Jumps=0 Flying=true Spawn(Fly)Debounce=false end else Jumping.JumpTick=tick()Jumping.Jumps=1 end end end for J,G in pairs(Controls)do for J,y in pairs(G.Keys)do G.Number=(string.lower(type(y))==string.lower("\083\116\114\105\110\103")and H==string.lower(y)or string.lower(type(y))==string.lower("\078\117\109\098\101\114")and u==y)and G.Numbers.On or G.Number end end end)J.KeyUp:connect(function(J)local H=string.lower(J)local u=string.byte(H)for J,G in pairs(Controls)do for J,y in pairs(G.Keys)do G.Number=(string.lower(type(y))==string.lower("\083\116\114\105\110\103")and H==string.lower(y)or string.lower(type(y))==string.lower("\078\117\109\098\101\114")and u==y)and G.Numbers.Off or G.Number end end end)ToolEquipped=true while not BodyVelocity or not BodyVelocity.Parent or not BodyGyro or not BodyGyro.Parent and(CheckIfAlive()and ToolEquipped)do BodyVelocity=Torso:FindFirstChild("\066\111\100\121\086\101\108\111\099\105\116\121")BodyGyro=Torso:FindFirstChild("\066\111\100\121\071\121\114\111")RunService.Stepped:wait()end end function Unequipped()LocalObjects={}for J,H in pairs(Animations)do if H and H.AnimationTrack then H.AnimationTrack:Stop()end end for J,H in pairs({PreventJump})do if H then H:disconnect()end end Sounds.Wind:Stop()Animations={}Flying=false ToolEquipped=false end function InvokeServer(J,H)pcall(function()local u=ServerControl:InvokeServer(J,H)return u end)end function OnClientInvoke(J,H)if J=="\080\108\097\121\065\110\105\109\097\116\105\111\110"and(H and(ToolEquipped and Humanoid))then SetAnimation("\080\108\097\121\065\110\105\109\097\116\105\111\110",H)elseif J=="\083\116\111\112\065\110\105\109\097\116\105\111\110"and H then SetAnimation("\083\116\111\112\065\110\105\109\097\116\105\111\110",H)elseif J=="\080\108\097\121\083\111\117\110\100"and H then H:Play()elseif J=="\083\116\111\112\083\111\117\110\100"and H then H:Stop()elseif J=="\077\111\117\115\101\080\111\115\105\116\105\111\110"then return PlayerMouse.Hit.p elseif J=="\068\105\115\097\098\108\101\074\117\109\112"then DisableJump(H)elseif J=="\070\108\121"and not Flying then Flying=true Spawn(function()Fly()end)end end Tool.Equipped:connect(Equipped)Tool.Unequipped:connect(Unequipped)ClientControl.OnClientInvoke=OnClientInvoke


Tool = script.Parent
Handle = Tool:WaitForChild("Handle")

Players = game:GetService("Players")
Debris = game:GetService("Debris")
RunService = game:GetService("RunService")

Camera = game:GetService("Workspace").CurrentCamera

Animations = {}
LocalObjects = {}

Speed = {
	CurrentSpeed = 5,
	MaxSpeed = 100
}

Jumping = {
	JumpTick = 0,
	Jumps = 0,
	JumpTime = 0.25,
	JumpsRequired = 1
}

Controls = {
	Forward = {Number = 0, Numbers = {On = -1, Off = 0}, Keys = {"W", 17}},
	Backward = {Number = 0, Numbers = { On = 1, Off = 0}, Keys = {"S", 18}},
	Left = {Number = 0, Numbers = {On = -1, Off = 0}, Keys = {"A", 20}},
	Right = {Number = 0, Numbers = {On = 1, Off = 0}, Keys = {"D", 19}}
}

UsableAnimations = {
	Pose = {Animation = Tool:WaitForChild("Pose"), FadeTime = nil, Weight = nil, Speed = nil},
}

Sounds = {
	Wind = Handle:WaitForChild("Wind"),
}

FlyRate = (1 / 60)

Debounce = false
Flying = false
ToolEquipped = false

ServerControl = Tool:WaitForChild("ServerControl")
ClientControl = Tool:WaitForChild("ClientControl")

function SetAnimation(Mode, Value)
	if Mode == "PlayAnimation" and Value and ToolEquipped and Humanoid then
		for i, v in pairs(Animations) do
			if v.Animation == Value.Animation then
				v.AnimationTrack:Stop()
				table.remove(Animations, i)
			end
		end
		local AnimationTrack = Humanoid:LoadAnimation(Value.Animation)
		table.insert(Animations, {Animation = Value.Animation, AnimationTrack = AnimationTrack})
		AnimationTrack:Play(Value.FadeTime, Value.Weight, Value.Speed)
	elseif Mode == "StopAnimation" and Value then
		for i, v in pairs(Animations) do
			if v.Animation == Value.Animation then
				v.AnimationTrack:Stop()
				table.remove(Animations, i)
			end
		end
	end
end

function DisableJump(Boolean)
	if PreventJump then
		PreventJump:disconnect()
	end
	if Boolean then
		PreventJump = Humanoid.Changed:connect(function(Property)
			if Property ==  "Jump" then
				Humanoid.Jump = false
			end
		end)
	end
end

function Clamp(Number, Min, Max)
	return math.max(math.min(Max, Number), Min)
end

function Fly()
	if Flying and Player and Torso and Humanoid and Humanoid.Health > 0 then
		local Momentum = Vector3.new(0, 0, 0)
		local LastMomentum = Vector3.new(0, 0, 0)
		local LastTilt = 0
		local LastFlap = 0
		local CurrentSpeed = Speed.MaxSpeed
		local Inertia = (1 - (Speed.CurrentSpeed / CurrentSpeed))
		
		Momentum = (Torso.Velocity + (Torso.CFrame.lookVector * 3) + Vector3.new(0, 10, 0))
		Momentum = Vector3.new(Clamp(Momentum.X, -15, 15), Clamp(Momentum.Y, -15, 15), Clamp(Momentum.Z, -15, 15))		
		
		BodyVelocity.maxForce = Vector3.new(1, 1, 1) * (10 ^ 6)	
		
		BodyGyro.maxTorque = Vector3.new(BodyGyro.P, BodyGyro.P, BodyGyro.P)
		BodyGyro.cframe = Torso.CFrame
		
		Spawn(function()
			InvokeServer("Flying", {Flying = true})
		end)
		
		SetAnimation("PlayAnimation", UsableAnimations.Pose)
		
		Humanoid.AutoRotate = false
				
		while Flying and Torso and Humanoid and Humanoid.Health > 0 do
			
			if CurrentSpeed ~= Speed.MaxSpeed then
				CurrentSpeed = Speed.MaxSpeed
				Inertia = (1 - (Speed.CurrentSpeed / CurrentSpeed))
			end
			
			local Direction = Camera.CoordinateFrame:vectorToWorldSpace(Vector3.new(Controls.Left.Number + Controls.Right.Number, math.abs(Controls.Forward.Number) * 0.2, Controls.Forward.Number + Controls.Backward.Number))
			local Movement = Direction * Speed.CurrentSpeed
			
			Momentum = (Momentum * Inertia) + Movement
			
			local TotalMomentum = Momentum.magnitude
			
			if TotalMomentum > CurrentSpeed then
				TotalMomentum = CurrentSpeed
			end
			
			local Tilt = ((Momentum * Vector3.new(1, 0, 1)).unit:Cross(((LastMomentum * Vector3.new(1, 0, 1)).unit))).y
			local StringTilt = tostring(Tilt)
			
			if StringTilt == "-1.#IND" or StringTilt == "1.#IND" or Tilt == math.huge or Tilt == -math.huge or StringTilt == tostring(0 / 0) then
				Tilt = 0
			end
			
			local AbsoluteTilt = math.abs(Tilt)
			
			if AbsoluteTilt > 0.06 or AbsoluteTilt < 0.0001 then
				if math.abs(LastTilt) > 0.0001 then
					Tilt = (LastTilt * 0.9)
				else
					Tilt = 0
				end
			else
				Tilt = ((LastTilt * 0.77) + (Tilt * 0.25))
			end
			
			LastTilt = Tilt

			if TotalMomentum < 0.5 then
				Momentum = Vector3.new(0, 0, 0)
				TotalMomentum = 0
				BodyGyro.cframe = Camera.CoordinateFrame
			else
				BodyGyro.cframe = CFrame.new(Vector3.new(0, 0, 0), Momentum) * CFrame.Angles(0, 0, (Tilt * -20)) * CFrame.Angles((math.pi * -0.5 * (TotalMomentum / CurrentSpeed)), 0, 0)
			end
			
			local GravityDelta = ((((Momentum * Vector3.new(0, 1, 0)) - Vector3.new(0, -Speed.MaxSpeed, 0)).magnitude / Speed.MaxSpeed) * 0.5)
			if GravityDelta > 0.45 and tick() > LastFlap then
				LastFlap = (tick() + 0.5)
				Spawn(function()
					if not Flying then
						return
					end
					if not Sounds.Wind.IsPlaying then
						Sounds.Wind:Play()
					end
					Spawn(function()
						InvokeServer("SetWingSpan", {Angle = 0, MaxVelocity = 0.05})
					end)
					wait(0.25)
					if not Flying then
						return
					end
					Spawn(function()
						InvokeServer("SetWingSpan", {Angle = 0.5, MaxVelocity = 0.05})
					end)
					wait(0.25)
				end)
			elseif GravityDelta <= 0.45 then
				Sounds.Wind:Stop()
			end
			
			BodyVelocity.velocity = Momentum
			LastMomentum = Momentum
			
			wait(FlyRate)
			
		end
		
		Sounds.Wind:Stop()
		
		Spawn(function()
			InvokeServer("SetWingSpan", {Angle = 0, MaxVelocity = 0.01})
		end)
		
		Spawn(function()
			InvokeServer("Flying", {Flying = false})
		end)
		
		SetAnimation("StopAnimation", UsableAnimations.Pose)		
		
		BodyVelocity.maxForce = Vector3.new(0, 0, 0)
		BodyGyro.maxTorque = Vector3.new(0, 0, 0)
		
		if CheckIfAlive() then
			Humanoid.AutoRotate = true
			Humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
		end
		
	end
end

function StopFlying()
	Flying = false
	BodyVelocity.maxForce = Vector3.new(0, 0, 0)
	BodyGyro.maxTorque = Vector3.new(0, 0, 0)
end

function CheckIfAlive()
	return (((Character and Character.Parent and Humanoid and Humanoid.Parent and Humanoid.Health > 0 and Torso and Torso.Parent and Player and Player.Parent) and true) or false)
end

function Equipped(Mouse)
	Character = Tool.Parent
	Humanoid = Character:FindFirstChild("Humanoid")
	Torso = Character:FindFirstChild("UpperTorso")
	Player = Players:GetPlayerFromCharacter(Character)
	if not CheckIfAlive() then
		return
	end
	PlayerMouse = Player:GetMouse()
	Mouse.Button1Down:connect(function()
		InvokeServer("MouseClick", {Down = true})
	end)
	Mouse.Button1Up:connect(function()
		InvokeServer("MouseClick", {Down = false})
	end)
	Mouse.KeyDown:connect(function(Key)
		local Key = string.lower(Key)
		local ByteKey = string.byte(Key)
		if ByteKey == string.byte(" ") and not Debounce then
			if Flying then
				StopFlying()
			elseif not Flying then
				if (tick() - Jumping.JumpTick) <= Jumping.JumpTime or Jumping.JumpTick == 0 then
					Jumping.JumpTick = tick()
					Jumping.Jumps = Jumping.Jumps + 1
					if Jumping.Jumps >= Jumping.JumpsRequired then
						Debounce = true
						Jumping.JumpTick = 0
						Jumping.Jumps = 0
						Flying = true
						Spawn(Fly)
						Debounce = false
					end
				else
					Jumping.JumpTick = tick()
					Jumping.Jumps = 1
				end
			end
		end
		for i, v in pairs(Controls) do
			for ii, vv in pairs(v.Keys) do
				v.Number = ((((string.lower(type(vv)) == string.lower("String") and Key == string.lower(vv)) or (string.lower(type(vv)) == string.lower("Number") and ByteKey == vv)) and v.Numbers.On) or v.Number)
			end
		end
	end)
	Mouse.KeyUp:connect(function(Key)
		local Key = string.lower(Key)
		local ByteKey = string.byte(Key)
		for i, v in pairs(Controls) do
			for ii, vv in pairs(v.Keys) do
				v.Number = ((((string.lower(type(vv)) == string.lower("String") and Key == string.lower(vv)) or (string.lower(type(vv)) == string.lower("Number") and ByteKey == vv)) and v.Numbers.Off) or v.Number)
			end
		end
	end)
	ToolEquipped = true
	while not BodyVelocity or not BodyVelocity.Parent or not BodyGyro or not BodyGyro.Parent and CheckIfAlive() and ToolEquipped do
		BodyVelocity = Torso:FindFirstChild("BodyVelocity")
		BodyGyro = Torso:FindFirstChild("BodyGyro")
		RunService.Stepped:wait()
	end
end

function Unequipped()
	LocalObjects = {}
	for i, v in pairs(Animations) do
		if v and v.AnimationTrack then
			v.AnimationTrack:Stop()
		end
	end
	for i, v in pairs({PreventJump}) do
		if v then
			v:disconnect()
		end
	end
	Sounds.Wind:Stop()
	Animations = {}
	Flying = false
	ToolEquipped = false
end

function InvokeServer(Mode, Value)
	pcall(function()
		local ServerReturn = ServerControl:InvokeServer(Mode, Value)
		return ServerReturn
	end)
end

function OnClientInvoke(Mode, Value)
	if Mode == "PlayAnimation" and Value and ToolEquipped and Humanoid then
		SetAnimation("PlayAnimation", Value)
	elseif Mode == "StopAnimation" and Value then
		SetAnimation("StopAnimation", Value)
	elseif Mode == "PlaySound" and Value then
		Value:Play()
	elseif Mode == "StopSound" and Value then
		Value:Stop()
	elseif Mode == "MousePosition" then
		return PlayerMouse.Hit.p
	elseif Mode == "DisableJump" then
		DisableJump(Value)
	elseif Mode == "Fly" and not Flying then
		Flying = true
		Spawn(function()
			Fly()
		end)
	end
end

Tool.Equipped:connect(Equipped)
Tool.Unequipped:connect(Unequipped)
ClientControl.OnClientInvoke = OnClientInvoke
