--// services used in this script local Players = game:GetService("Players") -- service for players local UIS = game:GetService("UserInputService") -- service for input local RS = game:GetService("RunService") -- service for heartbeat/renderstep local TweenService = game:GetService("TweenService") -- service for tweens local ReplicatedStorage = game:GetService("ReplicatedStorage") -- service for replicated data local StarterGui = game:GetService("StarterGui") -- service for ui local Debris = game:GetService("Debris") -- service for cleanup --// player references local player = Players.LocalPlayer -- variable for local player repeat task.wait() until player.Character -- wait for character to exist local character = player.Character -- variable for character local humanoid = character:WaitForChild("Humanoid") -- variable for humanoid local HRP = character:WaitForChild("HumanoidRootPart") -- variable for root part if character.PrimaryPart.Name ~= "HumanoidRootPart" then -- check if primary part is not hrp character.PrimaryPart = HRP -- set hrp as primary part end local primaryP = character.PrimaryPart -- variable for primary part local animator = humanoid:WaitForChild("Animator") -- variable for animator --// required modules local controlModule = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"):WaitForChild("ControlModule")) -- module for movement local PlayerStats = require(ReplicatedStorage:WaitForChild("PlayerStats")) -- module for player stats --// animations local FlyIdle = script:WaitForChild("FlyIdle") -- idle animation asset local FlyForward = script:WaitForChild("FlyForward") -- forward animation asset local FlyLeft = script:WaitForChild("FlyLeft") -- left animation asset local FlyRight = script:WaitForChild("FlyRight") -- right animation asset local FlyBackward = script:WaitForChild("FlyBackward") -- backward animation asset --// animation tracks local IdleTrack = animator:LoadAnimation(FlyIdle) -- track for idle local ForwardTrack = animator:LoadAnimation(FlyForward) -- track for forward --// trails local trailL = script:WaitForChild("leftTrail") -- left trail local trailR = script:WaitForChild("rightTrail") -- right trail --// constraints local vector = script:WaitForChild("VectorForce") -- vector force local align = script:WaitForChild("AlignOrientation") -- align orientation vector.Attachment0 = primaryP.RootAttachment -- set attachment for vector align.Attachment0 = primaryP.RootAttachment -- set attachment for align --// camera local camera = workspace.CurrentCamera -- variable for camera --// ui local UI = StarterGui:WaitForChild("Stamina") -- variable for stamina ui --// fx + event local FX = ReplicatedStorage.Effects:WaitForChild("FlightEffects") -- variable for flight effects local event = ReplicatedStorage:WaitForChild("FlightEvent") -- variable for remote event --// flight variables local gravity = Vector3.new(0, workspace.Gravity, 0) -- vector for gravity local IsFlying = false -- bool for flying state local IsHyper = false -- bool for hyper state local Flight = nil -- connection for heartbeat local FOV = 120 -- target fov local momentum = 5 -- momentum value local drag = 0.7 -- drag constant local force = PlayerStats.DefaultFlySpeed -- current fly speed local stamina = 100 -- starting stamina local maxStamina = PlayerStats.MaxStamina -- max stamina local hyperSpeed = PlayerStats.MaxFlySpeed -- boosted fly speed local canBoost = true -- bool for boost state local IsADown = false -- bool for A key local IsDDown = false -- bool for D key local IsSDown = false -- bool for S key local sidetrack -- variable for side animation track local backtrack -- variable for back animation track --// helper function: tween camera fov local function tweenFOV(targetFOV, duration) local info = TweenInfo.new(duration or 0.4, Enum.EasingStyle.Back, Enum.EasingDirection.Out) -- tween info local goals = { FieldOfView = targetFOV } -- goal for fov local tween = TweenService:Create(camera, info, goals) -- create tween tween:Play() -- play tween end --// helper function: stop all flight animations local function stopAllFlightAnimations() if IdleTrack then IdleTrack:Stop() end -- stop idle if ForwardTrack then ForwardTrack:Stop() end -- stop forward if sidetrack then sidetrack:Stop() end -- stop side if backtrack then backtrack:Stop() end -- stop back end --// helper function: reset boost local function resetBoost() IsHyper = false -- set hyper to false force = 3000 -- reset force trailL.Enabled = false -- disable left trail trailR.Enabled = false -- disable right trail end --// helper function: play idle animation local function playIdle() for _,v in pairs(animator:GetPlayingAnimationTracks()) do -- loop all tracks v:Stop() -- stop track end IdleTrack:Play() -- play idle end --// helper function: update stamina values local function updateStamina() if IsHyper and canBoost and stamina > 0 then -- if boosting and has stamina stamina -= 0.25 -- drain stamina humanoid:SetAttribute("Stamina", stamina) -- update attribute elseif stamina < maxStamina and not IsHyper then -- if not boosting and not full stamina += 0.25 -- regen stamina humanoid:SetAttribute("Stamina", stamina) -- update attribute end if stamina == 0 then -- if stamina empty tweenFOV(70) -- reset fov resetBoost() -- reset boost state canBoost = false -- disable boosting end if not canBoost and stamina > 10 then -- if regen over threshold canBoost = true -- enable boost again end end --// helper function: calculate force vectors local function calculateFlightForce() align.CFrame = camera.CFrame -- align with camera vector.Force = gravity * primaryP.AssemblyMass -- apply gravity local movevector = controlModule:GetMoveVector() -- get movement input local direction = camera.CFrame.RightVector * movevector.X + camera.CFrame.LookVector * (movevector.Z * -1) -- calculate direction if direction:Dot(direction) > 0 then -- if not zero direction = direction.Unit -- normalize direction end vector.Force += direction * force * primaryP.AssemblyMass -- apply directional force if primaryP.AssemblyLinearVelocity.Magnitude > 0 then -- if moving local dragVector = -primaryP.AssemblyLinearVelocity.Unit -- drag opposite velocity local v2 = primaryP.AssemblyLinearVelocity.Magnitude ^ 1.6 -- drag power vector.Force += dragVector * drag * primaryP.AssemblyMass * v2 -- apply drag end end --// helper function: handle animation switching local function handleAnimationState() if humanoid.MoveDirection ~= Vector3.new() then -- if moving momentum = 5 -- reset momentum if not ForwardTrack.IsPlaying then -- if forward not playing IdleTrack:Stop() -- stop idle ForwardTrack:Play() -- play forward end else -- if idle momentum = 0 -- reset momentum if ForwardTrack.IsPlaying then -- if forward is playing ForwardTrack:Stop() -- stop forward IdleTrack:Play() -- play idle end end end --// helper function: start flying local function startFlight() humanoid:SetAttribute("IsFlying", true) -- set attribute if humanoid.FloorMaterial ~= Enum.Material.Air then -- if grounded humanoid:ChangeState("Jumping") -- jump state event:FireServer("Jump") -- fire event task.wait(0.09) -- small delay end IsFlying = true -- set flying align.Enabled = true -- enable align vector.Enabled = true -- enable vector playIdle() -- play idle animation humanoid:ChangeState("Physics") -- physics state UI.Background.Visible = true -- show stamina ui Flight = RS.Heartbeat:Connect(function() -- connect heartbeat updateStamina() -- update stamina calculateFlightForce() -- calculate force handleAnimationState() -- handle animations end) end --// helper function: stop flying local function stopFlight() humanoid:SetAttribute("IsFlying", false) -- set attribute vector.Enabled = false -- disable vector align.Enabled = false -- disable align humanoid:ChangeState("Freefall") -- set freefall if Flight then -- if connection exists Flight:Disconnect() -- disconnect Flight = nil -- reset connection end IsFlying = false -- set flying false stopAllFlightAnimations() -- stop animations if camera.FieldOfView == FOV then -- if boosted fov tweenFOV(70) -- reset fov end end --// input: toggle flight UIS.InputBegan:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.Q then -- q pressed if IsFlying then -- if already flying stopFlight() -- stop else -- else not flying startFlight() -- start end end end) --// input: boost UIS.InputBegan:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.Space and IsFlying and canBoost and stamina > 0 then -- space pressed if humanoid.MoveDirection ~= Vector3.new() then -- if moving event:FireServer("Boost") -- fire boost event tweenFOV(FOV) -- tween fov trailL.Enabled = true -- enable left trail trailR.Enabled = true -- enable right trail else -- if not moving tweenFOV(70) -- reset fov trailL.Enabled = false -- disable left trail trailR.Enabled = false -- disable right trail end IsHyper = true -- set hyper force = hyperSpeed -- set hyper speed end end) --// input: stop boost UIS.InputEnded:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.Space and IsFlying then -- space released tweenFOV(70) -- reset fov resetBoost() -- reset boost end end) --// input: left / right animations UIS.InputBegan:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.A and IsFlying then -- a pressed IsADown = true -- set a down if sidetrack then sidetrack:Stop() end -- stop current side if ForwardTrack.IsPlaying then ForwardTrack:Stop() end -- stop forward if IsSDown and backtrack then backtrack:Stop() end -- stop back if s pressed sidetrack = animator:LoadAnimation(FlyLeft) -- load left sidetrack:Play() -- play left elseif input.KeyCode == Enum.KeyCode.D and IsFlying then -- d pressed IsDDown = true -- set d down if sidetrack then sidetrack:Stop() end -- stop current side if ForwardTrack.IsPlaying then ForwardTrack:Stop() end -- stop forward if IsSDown and backtrack then backtrack:Stop() end -- stop back if s pressed sidetrack = animator:LoadAnimation(FlyRight) -- load right sidetrack:Play() -- play right end end) UIS.InputEnded:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.A and IsFlying then -- a released IsADown = false -- set a false if sidetrack then sidetrack:Stop() end -- stop side if IsDDown then -- if d down sidetrack = animator:LoadAnimation(FlyRight) -- load right sidetrack:Play() -- play right end end if input.KeyCode == Enum.KeyCode.D and IsFlying then -- d released IsDDown = false -- set d false if sidetrack then sidetrack:Stop() end -- stop side if IsADown then -- if a down sidetrack = animator:LoadAnimation(FlyLeft) -- load left sidetrack:Play() -- play left end end end) --// input: backward animation UIS.InputBegan:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.S and IsFlying then -- s pressed IsSDown = true -- set s down backtrack = animator:LoadAnimation(FlyBackward) -- load backward backtrack:Play() -- play backward end end) UIS.InputEnded:Connect(function(input, typing) if typing then return end -- ignore typing if input.KeyCode == Enum.KeyCode.S and IsFlying then -- s released IsSDown = false -- set s false if backtrack then backtrack:Stop() end -- stop back backtrack = nil -- clear backtrack end end) --// event: effects event.OnClientEvent:Connect(function(character, effect) if effect == "Jump" then -- if jump effect local jump = FX:WaitForChild("Jump"):Clone() -- clone jump fx jump.Parent = workspace.Effects -- parent to workspace jump.Position = HRP.Position - Vector3.new(0,3.75,0) -- set position local info = TweenInfo.new(0.4, Enum.EasingStyle.Quart, Enum.EasingDirection.Out) -- tween info local goals = { Size = jump.Size + Vector3.new(25,0,25), Transparency = 1 } -- tween goals local tween = TweenService:Create(jump, info, goals) -- create tween tween:Play() -- play tween Debris:AddItem(jump, 0.4) -- cleanup end end)