--Made by Luckymaxer

Seat = script.Parent
Model = Seat.Parent

Engine = Model:WaitForChild("Engine")
BeamPart = Model:WaitForChild("BeamPart")
Lights = Model:WaitForChild("Lights")
Seats = Model:WaitForChild("Seats")

Sounds = {
	Flying = Engine:WaitForChild("UFO_Flying"),
	Beam = Engine:WaitForChild("UFO_Beam"),
	Idle = Engine:WaitForChild("UFO_Idle"),
	TakingOff = Engine:WaitForChild("UFO_Taking_Off")
}

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

BeamSize = 50
CurrentBeamSize = 0

MaxVelocity = 40
MinVelocity = -40

MaxSideVelocity = 40
MinSideVelocity = -40

Acceleration = 2
Deceleration = 2
AutoDeceleration = 2

SideAcceleration = 2
SideDeceleration = 2
AutoSideDeceleration = 2

LiftOffSpeed = 5
LiftSpeed = 10
LowerSpeed = -10

Velocity = Vector3.new(0, 0, 0)
SideVelocity = 0

FlipForce = 1000000

InUse = false
PlayerUsing = nil
PlayerControlScript = nil
PlayerConnection = nil
BeamActive = false
TakingOff = false

LightsEnabled = false

Enabled = false

Controls = {
	Forward = {Key = "W", Byte = 17, Mode = false},
	Backward = {Key = "S", Byte = 18, Mode = false},
	Left = {Key = "A", Byte = 20, Mode = false},
	Right = {Key = "D", Byte = 19, Mode = false},
	Up = {Key = "Q", Byte = 113, Mode = false},
	Down = {Key = "E", Byte = 101, Mode = false},
}

ControlScript = script:WaitForChild("ControlScript")

Beam = Instance.new("Part")
Beam.Name = "Beam"
Beam.Transparency = 0.3
Beam.BrickColor = BrickColor.new("Pastel Blue")
Beam.Material = Enum.Material.Plastic
Beam.Shape = Enum.PartType.Block
Beam.TopSurface = Enum.SurfaceType.Smooth
Beam.BottomSurface = Enum.SurfaceType.Smooth
Beam.FormFactor = Enum.FormFactor.Custom
Beam.Size = Vector3.new(BeamPart.Size.X, 0.2, BeamPart.Size.Z)
Beam.Anchored = false
Beam.CanCollide = false
BeamMesh = Instance.new("CylinderMesh")
BeamMesh.Parent = Beam

for i, v in pairs(Sounds) do
	v:Stop()
end

RemoteConnection = script:FindFirstChild("RemoteConnection")
if not RemoteConnection then
	RemoteConnection = Instance.new("RemoteFunction")
	RemoteConnection.Name = "RemoteConnection"
	RemoteConnection.Parent = script
end

BodyGyro = Engine:FindFirstChild("BodyGyro")
if not BodyGyro then
	BodyGyro = Instance.new("BodyGyro")
	BodyGyro.Parent = Engine
end
BodyGyro.maxTorque = Vector3.new(0, 0, 0)
BodyGyro.D = 7500
BodyGyro.P = 10000

BodyPosition = Engine:FindFirstChild("BodyPosition")
if not BodyPosition then
	BodyPosition = Instance.new("BodyPosition")
	BodyPosition.Parent = Engine
end
BodyPosition.maxForce = Vector3.new(0, 0, 0)
BodyPosition.D = 10000
BodyPosition.P = 50000

BodyVelocity = Engine:FindFirstChild("BodyVelocity")
if not BodyVelocity then
	BodyVelocity = Instance.new("BodyVelocity")
	BodyVelocity.Parent = Engine
end
BodyVelocity.velocity = Vector3.new(0, 0, 0)
BodyVelocity.maxForce = Vector3.new(0, 0, 0)
BodyVelocity.P = 10000

FlipGyro = BeamPart:FindFirstChild("FlipGyro")
if not FlipGyro then
	FlipGyro = Instance.new("BodyGyro")
	FlipGyro.Name = "FlipGyro"
	FlipGyro.Parent = BeamPart
end
FlipGyro.maxTorque = Vector3.new(0, 0, 0)
FlipGyro.D = 500
FlipGyro.P = 3000

RiseVelocity = BeamPart:FindFirstChild("RiseVelocity")
if not RiseVelocity then
	RiseVelocity = Instance.new("BodyVelocity")
	RiseVelocity.Name = "RiseVelocity"
	RiseVelocity.Parent = BeamPart
end
RiseVelocity.velocity = Vector3.new(0, 0, 0)
RiseVelocity.maxForce = Vector3.new(0, 0, 0)
RiseVelocity.P = 10000

function RayCast(Position, Direction, MaxDistance, IgnoreList)
	return game:GetService("Workspace"):FindPartOnRayWithIgnoreList(Ray.new(Position, Direction.unit * (MaxDistance or 999.999)), IgnoreList) 
end

function ToggleLights()
	for i, v in pairs(Lights:GetChildren()) do
		if v:IsA("BasePart") then
			for ii, vv in pairs(v:GetChildren()) do
				if vv:IsA("Light") then
					vv.Enabled = LightsEnabled
				end
			end
		end
	end
end

ToggleLights()

function CheckTable(Table, Instance)
	for i, v in pairs(Table) do
		if v == Instance then
			return true
		end
	end
	return false
end

function RandomizeTable(Table)
	local TableCopy = {}
	for i = 1, #Table do
		local Index = math.random(1, #Table)
		table.insert(TableCopy, Table[Index])
		table.remove(Table, Index)
	end
	return TableCopy
end

for i, v in pairs(Model:GetChildren()) do
	if v:IsA("BasePart") and v.Name == "Beam" then
		v:Destroy()
	end
end

function GetPartsInBeam(beam)
	local IgnoreObjects = {(((PlayerUsing and PlayerUsing.Character) and PlayerUsing.Character) or nil), Model}
	local NegativePartRadius = Vector3.new((beam.Size.X / 2), ((CurrentBeamSize / 5) / 2), (beam.Size.Z / 2))
	local PositivePartRadius = Vector3.new((beam.Size.X / 2), ((CurrentBeamSize / 5) / 2), (beam.Size.Z / 2))
	local Parts = game:GetService("Workspace"):FindPartsInRegion3WithIgnoreList(Region3.new(beam.Position - NegativePartRadius, beam.Position + PositivePartRadius), IgnoreObjects, 100)
	local Humanoids = {}
	local Torsos = {}
	for i, v in pairs(Parts) do
		if v and v.Parent then
			local humanoid = v.Parent:FindFirstChild("Humanoid")
			local torso = v.Parent:FindFirstChild("Torso")
			local player = Players:GetPlayerFromCharacter(v.Parent)
			if player and humanoid and humanoid.Health > 0 and torso and not CheckTable(Humanoids, humanoid) then
				table.insert(Humanoids, humanoid)
				table.insert(Torsos, {Humanoid = humanoid, Torso = torso})
			end
		end
	end
	return Torsos
end

RemoteConnection.OnServerInvoke = (function(Player, Script, Action, Value)
	if Script and Script ~= PlayerControlScript then
		Script.Disabled = true
		Script:Destroy()
	else
		if Action == "KeyDown" then
			if Value == "l" then
				LightsEnabled = not LightsEnabled
				ToggleLights()
			elseif Value == "t" then
				if TemporaryBeam and TemporaryBeam.Parent then
					local Torsos = GetPartsInBeam(TemporaryBeam)
					local TorsosUsed = {}
					Torsos = RandomizeTable(Torsos)
					for i, v in pairs(Seats:GetChildren()) do
						if v:IsA("Seat") and not v:FindFirstChild("SeatWeld") then
							for ii, vv in pairs(Torsos) do
								if vv.Humanoid and vv.Humanoid.Parent and vv.Humanoid.Health > 0 and not vv.Humanoid.Sit and vv.Torso and vv.Torso.Parent and not CheckTable(TorsosUsed, vv.Torso) then
									table.insert(TorsosUsed, vv.Torso)
									vv.Torso.CFrame = v.CFrame
									break
								end
							end
						end
					end
				end
			end
			if not TakingOff then
				for i, v in pairs(Controls) do
					if string.lower(v.Key) == string.lower(Value) or v.Byte == string.byte(Value) then
						v.Mode = true
					end
				end
				if Controls.Up.Mode or Controls.Down.Mode then
					RiseVelocity.maxForce = Vector3.new(0, 1000000, 0)
				end
				if Controls.Forward.Mode or Controls.Backward.Mode or Controls.Left.Mode or Controls.Right.Mode or Controls.Up.Mode or Controls.Down.Mode then
					Sounds.Idle:Stop()
					Sounds.Flying:Play()
				end
			end
		elseif Action == "KeyUp" then
			if not TakingOff then
				for i, v in pairs(Controls) do
					if string.lower(v.Key) == string.lower(Value) or v.Byte == string.byte(Value) then
						v.Mode = false
					end
				end
				if not Controls.Up.Mode and not Controls.Down.Mode then
					BodyPosition.position = Engine.Position
					BodyPosition.maxForce = Vector3.new(0, 100000000, 0)
					RiseVelocity.maxForce = Vector3.new(0, 0, 0)
					RiseVelocity.velocity = Vector3.new(0, 0, 0)
				end
				if not Controls.Forward.Mode and not Controls.Backward.Mode and not Controls.Left.Mode and not Controls.Right.Mode and not Controls.Up.Mode and not Controls.Down.Mode then
					Sounds.Flying:Stop()
					Sounds.Idle:Play()
				end
			end
		elseif Action == "Button1Down" then
			if not BeamActive and not TakingOff then
				BeamActive = true
				if TemporaryBeam and TemporaryBeam.Parent then
					TemporaryBeam:Destroy()
				end
				TemporaryBeam = Beam:Clone()
				TemporaryBeam.Parent = Model
				Spawn(function()
					while TemporaryBeam and TemporaryBeam.Parent do
						local Torsos = GetPartsInBeam(TemporaryBeam)
						for i, v in pairs(Torsos) do
							if v.Humanoid and v.Humanoid.Parent and v.Humanoid.Health > 0 and v.Torso and v.Torso.Parent and not v.Torso:FindFirstChild("UFOPullForce") and not v.Torso:FindFirstChild("UFOBalanceForce") then
								local UFOPullForce = Instance.new("BodyVelocity")
								UFOPullForce.Name = "UFOPullForce"
								UFOPullForce.maxForce = Vector3.new(0, 1000000, 0)
								UFOPullForce.velocity = CFrame.new(v.Torso.Position, BeamPart.Position).lookVector * 25
								Debris:AddItem(UFOPullForce, 0.25)
								UFOPullForce.Parent = v.Torso
								local UFOBalanceForce = Instance.new("BodyGyro")
								UFOBalanceForce.Name = "UFOBalanceForce"
								UFOBalanceForce.maxTorque = Vector3.new(1000000, 0, 1000000)
								Debris:AddItem(UFOBalanceForce, 0.25)
								UFOBalanceForce.Parent = v.Torso
							end
						end
						wait()
					end
				end)
				local BeamWeld = Instance.new("Weld")
				BeamWeld.Part0 = BeamPart
				BeamWeld.Part1 = TemporaryBeam
				Spawn(function()
					Sounds.Beam:Play()
					while Enabled and BeamActive and TemporaryBeam and TemporaryBeam.Parent do
						local IgnoreTable = {Model}
						for i, v in pairs(Players:GetChildren()) do
							if v:IsA("Player") and v.Character then
								table.insert(IgnoreTable, v.Character)
							end
						end
						local BeamPartClone = BeamPart:Clone()
						local BeamPartCloneY = BeamPartClone:Clone()
						BeamPartCloneY.CFrame = BeamPartCloneY.CFrame * CFrame.Angles(-math.rad(90), 0, 0)		
						BeamPartCloneY.CFrame = BeamPartCloneY.CFrame - BeamPartCloneY.CFrame.lookVector * ((BeamPart.Size.Y / 2))
						local Hit, Position = RayCast(BeamPart.Position, BeamPartCloneY.CFrame.lookVector, BeamSize, IgnoreTable)
						CurrentBeamSize = ((BeamPart.Position - Position).magnitude * 5)
						TemporaryBeam.Mesh.Scale = Vector3.new(1, CurrentBeamSize, 1)
						BeamWeld.Parent = TemporaryBeam
						BeamWeld.C0 = CFrame.new(0, 0, 0) - Vector3.new(0, ((CurrentBeamSize / 2) + (BeamPart.Size.Y / 2)) / 5 , 0)
						wait()
					end
					BeamActive = false
					Sounds.Beam:Stop()
					if TemporaryBeam and TemporaryBeam.Parent then
						TemporaryBeam:Destroy()
					end
				end)
			end
		elseif Action == "Button1Up" then
			BeamActive = false
		end
	end
end)

function ManageMotionStep(ForceLift, CoordinateFrame)
	
	local CameraForwards = -CoordinateFrame:vectorToWorldSpace(Vector3.new(0, 0, 1))
	local CameraSideways = -CoordinateFrame:vectorToWorldSpace(Vector3.new(1, 0, 0))
	local CameraRotation = -CoordinateFrame:vectorToWorldSpace(Vector3.new(0, 1, 0))

	CameraForwards = CameraForwards * Vector3.new(1, 0, 1)
	CameraSideways = CameraSideways * Vector3.new(1, 0, 1)

	if CameraForwards:Dot(CameraForwards) < 0.1 or CameraSideways:Dot(CameraSideways) < 0.1 then
		return
	end
	
	CameraForwards = CameraForwards.unit
	CameraSideways = CameraSideways.unit

	if math.abs(Velocity.X) < 2 and math.abs(Velocity.Z) < 2 then
		BodyVelocity.velocity = Vector3.new(0, 0, 0)
	else
		BodyVelocity.velocity = Velocity
	end
	BodyGyro.cframe = CFrame.new(0, 0, 0) * CFrame.Angles(Velocity:Dot(Vector3.new(0, 0, 1)) * (math.pi / 320), 0, math.pi - Velocity:Dot(Vector3.new(1, 0, 0)) * (math.pi / 320))
	if Controls.Forward.Mode and (not Controls.Backward.Mode) and Velocity:Dot(CameraForwards) < MaxVelocity then
		Velocity = Velocity + Acceleration * CameraForwards
	elseif Controls.Backward.Mode and (not Controls.Forward.Mode) and Velocity:Dot(CameraForwards) > MinVelocity then
		Velocity = Velocity - Deceleration * CameraForwards
	elseif (not Controls.Backward.Mode) and (not Controls.Forward.Mode) and Velocity:Dot(CameraForwards) > 0 then
		Velocity = Velocity - AutoDeceleration * CameraForwards
	elseif (not Controls.Backward.Mode) and (not Controls.Forward.Mode) and Velocity:Dot(CameraForwards) < 0 then
		Velocity = Velocity + AutoDeceleration * CameraForwards
	end

	if Controls.Left.Mode and (not Controls.Right.Mode) and Velocity:Dot(CameraSideways) < MaxSideVelocity then
		Velocity = Velocity + SideAcceleration * CameraSideways
	elseif Controls.Right.Mode and (not Controls.Left.Mode) and Velocity:Dot(CameraSideways) > MinSideVelocity then
		Velocity = Velocity - SideDeceleration * CameraSideways
	elseif (not Controls.Right.Mode) and (not Controls.Left.Mode) and Velocity:Dot(CameraSideways) > 0 then
		Velocity = Velocity - AutoSideDeceleration * CameraSideways
	elseif (not Controls.Right.Mode) and (not Controls.Left.Mode) and Velocity:Dot(CameraSideways) < 0 then
		Velocity = Velocity + AutoSideDeceleration * CameraSideways
	end

	if ForceLift then
		RiseVelocity.velocity = Vector3.new(0, LiftOffSpeed, 0)
	else
		if Controls.Up.Mode and (not Controls.Down.Mode) then
			RiseVelocity.velocity = Vector3.new(0, LiftSpeed, 0)
			BodyPosition.maxForce = Vector3.new(0, 0, 0)
		elseif Controls.Down.Mode and (not Controls.Up.Mode) then
			RiseVelocity.velocity = Vector3.new(0, LowerSpeed, 0)
			BodyPosition.maxForce = Vector3.new(0, 0, 0)
		end
	end
	
end

function MotionManager()
	Spawn(function()
		TakingOff = true
		RiseVelocity.maxForce = Vector3.new(0, 1000000, 0)
		local StartTime = tick()
		Sounds.TakingOff:Play()
		while Enabled and PlayerConnection and (tick() - StartTime) < 3 do
			local CoordinateFrame = PlayerConnection:InvokeClient(PlayerUsing, "CoordinateFrame")
			ManageMotionStep(true, CoordinateFrame)
			wait()
		end
		TakingOff = false
		Sounds.TakingOff:Stop()
		while PlayerConnection and (Enabled or Velocity:Dot(Velocity) > 0.5) do
			local CoordinateFrame = PlayerConnection:InvokeClient(PlayerUsing, "CoordinateFrame")
			ManageMotionStep(false, CoordinateFrame)
			wait()
		end
	end)
end

function LiftOff()
	
	BodyGyro.maxTorque = Vector3.new(1000000, 1000000, 1000000)
	BodyVelocity.maxForce = Vector3.new(1000000, 0, 1000000)
	
	Velocity = Vector3.new(0, 0, 0)

	Enabled = true
	
	MotionManager()

end

function Equipped(Player)
	local Backpack = Player:FindFirstChild("Backpack")
	if Backpack then
		InUse = true
		PlayerUsing = Player
		PlayerControlScript = ControlScript:Clone()
		local RemoteController = Instance.new("ObjectValue")
		RemoteController.Name = "RemoteController"
		RemoteController.Value = RemoteConnection
		RemoteController.Parent = PlayerControlScript
		local VehicleSeat = Instance.new("ObjectValue")
		VehicleSeat.Name = "VehicleSeat"
		VehicleSeat.Value = Seat
		VehicleSeat.Parent = PlayerControlScript
		PlayerConnection = Instance.new("RemoteFunction")
		PlayerConnection.Name = "PlayerConnection"
		PlayerConnection.Parent = PlayerControlScript
		PlayerControlScript.Disabled = false
		PlayerControlScript.Parent = Backpack
		LiftOff()
	end
end

function Unequipped()
	if PlayerControlScript and PlayerControlScript.Parent then
		PlayerControlScript:Destroy()
	end
	Enabled = false
	PlayerControlScript = nil
	PlayerUsing = nil
	PlayerConnection = nil
	BeamActive = false
	TakingOff = false
	InUse = false
	BodyGyro.maxTorque = Vector3.new(0, 0, 0)
	BodyPosition.maxForce = Vector3.new(0, 0, 0)
	BodyVelocity.maxForce = Vector3.new(0, 0, 0)
	BodyVelocity.velocity = Vector3.new(0, 0, 0)
	RiseVelocity.maxForce = Vector3.new(0, 0, 0)
	RiseVelocity.velocity = Vector3.new(0, 0, 0)
	for i, v in pairs(Controls) do
		v.Mode = false
	end
end

function Flip()
	local EngineCloneY = Engine:Clone()
	EngineCloneY.CFrame = EngineCloneY.CFrame * CFrame.Angles(-math.rad(90), 0, 0)
	if EngineCloneY.CFrame.lookVector.Y < 0.707 then
		FlipGyro.cframe = CFrame.new(Vector3.new(0, 0, 0), Vector3.new(0, 1, 0)) * CFrame.Angles((-math.pi / 2), 0, 0)
		FlipGyro.maxTorque = Vector3.new(FlipForce, FlipForce, FlipForce)
		wait(2)
		FlipGyro.maxTorque = Vector3.new(0,0,0)
	end
end

Seat.ChildAdded:connect(function(Child)
	if Child:IsA("Weld") and Child.Name == "SeatWeld" then
		if Child.Part0 and Child.Part0 == Seat and Child.Part1 and Child.Part1.Parent then
			local Player = Players:GetPlayerFromCharacter(Child.Part1.Parent)
			if Player then
				Equipped(Player)
			end
		end
	end
end)

Seat.ChildRemoved:connect(function(Child)
	if Child:IsA("Weld") and Child.Name == "SeatWeld" then
		if Child.Part0 and Child.Part0 == Seat and Child.Part1 and Child.Part1.Parent then
			local Player = Players:GetPlayerFromCharacter(Child.Part1.Parent)
			if Player and Player == PlayerUsing then
				Unequipped(Player)
			end
		end
	end
end)

Spawn(function()
	while true do
		Flip()
		wait(5)
	end
end)