-- Other
local IsGettingOff = false
local IsOnSegway = false
local Vector3new, CFramenew, Mathrad, Mathpi, CFrameangles, Raynew = Vector3.new, CFrame.new, math.rad, math.pi, CFrame.Angles, Ray.new

local function Get_des(instance, func)
	func(instance)
	for _, child in next, instance:GetChildren() do
		Get_des(child, func)
	end
end

function Hopoff()
	if SegwayObject.Value ~= nil and IsGettingOff == false and SegwayObject.Value.PrimaryPart and SeaterObject.Value ~= nil then
	IsGettingOff = true
	IsOnSegway = false
	local PrimaryPart = SegwayObject.Value.PrimaryPart 
	local px,py,pz,xx,yx,zx,xy,yy,zy,xz,yz,zz=PrimaryPart.CFrame:components()
	
	ContextService:UnbindAction("segInputAction")
		
	-- Delete welds
	if SeaterObject.Value ~= nil then
		repeat wait() until DeleteWelds:InvokeServer(SeaterObject.Value.Parent) == true or SeaterObject.Value == nil
	end
	
	-- Resets camera's behavior
	Camera.CameraType = "Custom"
	
	-- Set gyro to have power
	if Thruster.Value then
		Thruster.Value.BodyGyro.MaxTorque = Vector3new(400000, 0, 400000)
	end
	
	-- Stops sounds
	if SeaterObject.Value and SeaterObject.Value.Parent:FindFirstChild("Run") then
		StopSound:FireServer(SeaterObject.Value.Parent.Run,0)
		PlaySound:FireServer(SeaterObject.Value.Parent.Off,SeaterObject.Value.Parent.Off.Pitch,SeaterObject.Value.Parent.Off.Volume)
	end
	
	-- Flips segway if fell over
	if SegwayObject.Value then
		SegwayObject.Value:SetPrimaryPartCFrame(CFramenew(px,py+0.1,pz,1,yx,zx,xy,1,zy,xz,yz,1))
	end	
	
	-- Turn off lights
	ConfigLights:FireServer(0.3,"Bright bluish green",false,"SmoothPlastic",Lights,Notifiers)
	
	-- Re-parents mobile gui and reshows mobile controls
	GuiControls.Parent = script.Parent
	UserInputService.ModalEnabled = false
	OffButton.ImageColor3 = LiftedColor
	
	-- Shows tool UI via use with VR
	if UserInputService.VREnabled then
		if PlayerGui and PlayerGui:FindFirstChild("DisplayGui") and PlayerGui:FindFirstChild("ColorGui") then
			PlayerGui:FindFirstChild("DisplayGui").Enabled = true
			PlayerGui:FindFirstChild("ColorGui").Enabled = true
		end
		
		UpdateCharTrans(0,0)
	end
	
	-- Disconnect events
	SitListener:disconnect()
	JumpListener:disconnect()
	
	-- Resets the tilt motor angle
	if TiltMotor.Value then
		TiltMotor.Value.DesiredAngle = 0
	end
	
	-- Makes the thruster's velocity still
	AnchorSegway:FireServer(PrimaryPart,true)
	
	-- Makes object values nil
	UndoTags:FireServer(SegwayObject,WeldObject,TiltMotor)
	
	-- Configures humanoid
	ConfigHumanoid:FireServer(Humanoid,false,true,true)
	
	-- Unanchors segway
	wait(1)
	AnchorSegway:FireServer(PrimaryPart,false)
	UndoHasWelded:FireServer(SeaterObject)
	
	-- Reset direction and steer tags
	Direction = 0
	Steer = 0
	IsGettingOff = false
	end
end

function UpdateCharTrans(BodyTrans,SegwayTrans)	
	-- Changes character's body while VR
	Get_des(Character,function(d)
		if d and d:IsA("BasePart") then
			if (d.Parent:FindFirstChild("Humanoid") or d.Parent:IsA("Accessory")) then
				d.LocalTransparencyModifier = BodyTrans
			else 
				d.LocalTransparencyModifier = SegwayTrans
			end
		elseif d and d:IsA("Decal") and d.Name == "face" then
			d.Transparency = BodyTrans
		end
	end)
end

function UpdateVRPos()
	if UserInputService.VREnabled and Character and Character.Parent and Character:FindFirstChild("Head") then
		local hpx,hpy,hpz,hxx,hxy,hxz,hyx,hyy,hyz,hzx,hzy,hzz = Character.Head.CFrame:components()
		
		Camera.CFrame = CFramenew(hpx,hpy,hpz,
			hxx,0,hxz,
			0,1,0,
			hzx,0,hzz
		) + (Vector3new(hxy,hyy,hzy)*2.5) --Height in studs above character's head
	end
end

function Accelerate()
	if IsOnSegway then
		local v = Direction*Thruster.Value.CFrame.lookVector*MaxSpeed.Value
		local NewVelocity = Thruster.Value.Velocity:Lerp(v, 0.05) -- Thrust
		local NewRotVelocity = Vector3new(0,-Steer*TurnSpeed.Value/10,0) -- Steering
		local px,py,pz,xx,xy,xz,yx,yy,yz,zx,zy,zz = Thruster.Value.CFrame:components()
		
		if yy > 0.7 then -- If segway is upsided
			Thruster.Value.BodyGyro.MaxTorque = Vector3new(400000, 0, 400000)
			Thruster.Value.Velocity = NewVelocity
			Thruster.Value.RotVelocity = NewRotVelocity
		else
			Thruster.Value.BodyGyro.MaxTorque = Vector3new(0,0,0)
		end
			
	end
end

function CastToGround()
	if Thruster.Value and Thruster.Value.Parent then
		
		-- Raycast to face segway towards ground
		local px,py,pz,xx,xy,xz,yx,yy,yz,zx,zy,zz = Thruster.Value.CFrame:components()
		local SegDnVect = -Vector3new(xy,yy,zy)
		local Ray = Raynew(Thruster.Value.CFrame.p, SegDnVect*50)
		local hit, position, normal = workspace:FindPartOnRayWithIgnoreList(Ray,{SegwayObject.Value,RayTest})
		local HitDepth = (Thruster.Value.Position-position).magnitude
		local NextRayAngle = (normal-SegDnVect).magnitude
		
		if hit and hit.CanCollide and NextRayAngle > 1.7 then
			Thruster.Value.BodyGyro.MaxTorque = Vector3new(400000, 0, 400000)
			Thruster.Value.BodyGyro.CFrame = CFramenew(position, position + normal) * CFrameangles(-Mathpi/2, 0, 0)
		end
	end
end

function Sound()
	if Thruster.Value and 0.85+Mathrad(Thruster.Value.Velocity.Magnitude/1.8) <= RunSoundPitchLimit then
		SeaterObject.Value.Parent.Run.Pitch = 0.85+Mathrad(Thruster.Value.Velocity.Magnitude/1.8)
	end
end

function Tilt()
	if Direction ~= 0 then
		TiltMotor.Value.DesiredAngle = Direction/10
		SeaterObject.Value.Parent.Run.Volume = RunSoundVol
		
	else 
		TiltMotor.Value.DesiredAngle = 0
		
		-- Change sound based on current status
		if Steer == 0 then
			SeaterObject.Value.Parent.Run.Volume = 0
		else --Adjusts the run sound when still and just turning
			SeaterObject.Value.Parent.Run.Volume = RunSoundVol
			SeaterObject.Value.Parent.Run.Pitch = 0.85+Mathrad(Thruster.Value.RotVelocity.Magnitude/1.8)				
		end
		
	end
end

function SetGuiButtons()
	--Exit button
	OffButton.MouseButton1Down:connect(function() OffButton.ImageColor3 = PressedColor end)
	OffButton.MouseButton1Up:connect(function() OffButton.ImageColor3 = LiftedColor Hopoff(Character)end)
	OffButton.MouseLeave:connect(function()OffButton.ImageColor3 = LiftedColor end)
	
	--Left button pressed/lifted
	LeftButton.MouseButton1Down:connect(function()Steer = -1 LeftButton.ImageColor3 = PressedColor end)
	LeftButton.MouseButton1Up:connect(function()Steer = 0 LeftButton.ImageColor3 = LiftedColor end)
	LeftButton.MouseLeave:connect(function()LeftButton.ImageColor3 = LiftedColor end)
	
	--Right button pressed/lifted
	RightButton.MouseButton1Down:connect(function()Steer = 1 RightButton.ImageColor3 = PressedColor end)
	RightButton.MouseButton1Up:connect(function()Steer = 0 RightButton.ImageColor3 = LiftedColor end)
	RightButton.MouseLeave:connect(function()RightButton.ImageColor3 = LiftedColor end)
	
	--Backward button pressed/lifted
	DownButton.MouseButton1Down:connect(function()Direction = -1 DownButton.ImageColor3 = PressedColor end)
	DownButton.MouseButton1Up:connect(function()Direction = 0 DownButton.ImageColor3 = LiftedColor end)
	DownButton.MouseLeave:connect(function()DownButton.ImageColor3 = LiftedColor end)
	
	--Forward button pressed/lifted
	UpButton.MouseButton1Down:connect(function()Direction = 1 UpButton.ImageColor3 = PressedColor end)
	UpButton.MouseButton1Up:connect(function()Direction = 0 UpButton.ImageColor3 = LiftedColor end)
	UpButton.MouseLeave:connect(function()UpButton.ImageColor3 = LiftedColor end)
end

function onGENInput(actionName,inputState,inputObj)
	if WeldObject.Value ~= nil then
		local Key=inputObj.KeyCode
		
		-- Hop off segway if press Spacebar, Backspace or controller A button
		if (Key == Enum.KeyCode.Space or Key == Enum.KeyCode.Backspace or Key == Enum.KeyCode.ButtonA) and inputState == Enum.UserInputState.Begin then	
			Hopoff()
		end
		
		--Forward
		if Key == Enum.KeyCode.W or Key == Enum.KeyCode.Up or Key == Enum.KeyCode.ButtonR2 then
			Direction = (inputState == Enum.UserInputState.Begin and 1) or (Direction == 1 and 0) or Direction
		end
		
		--Backward
		if Key == Enum.KeyCode.S or Key == Enum.KeyCode.Down or Key == Enum.KeyCode.ButtonL2 then
			Direction = (inputState == Enum.UserInputState.Begin and -1) or (Direction == -1 and 0) or Direction
		end
		
		--Left
		if Key == Enum.KeyCode.D or Key == Enum.KeyCode.Right then
			Steer = (inputState == Enum.UserInputState.Begin and 1) or (Steer == 1 and 0) or Steer
		end
		
		--Right
		if Key == Enum.KeyCode.A or Key == Enum.KeyCode.Left then
			Steer = (inputState == Enum.UserInputState.Begin and -1) or (Steer == -1 and 0) or Steer
		end
	end
end