local A=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local x=game:GetService("\084\119\101\101\110\083\101\114\118\105\099\101")local X=game:GetService("\082\117\110\083\101\114\118\105\099\101")local o=game:GetService("\080\108\097\121\101\114\115")local F=o.LocalPlayer local H=script:WaitForChild("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110\071\117\105")local Y=H:WaitForChild("\086\105\101\119\112\111\114\116\070\114\097\109\101")local w=Y:WaitForChild("\084\111\107\101\110")local e=Y:WaitForChild("\071\108\111\119\080\097\114\116")local Q=e:WaitForChild("\071\108\111\119\068\101\099\097\108")local y=H:WaitForChild("\066\097\099\107\103\114\111\117\110\100")local K=H:WaitForChild("\070\108\121\083\111\117\110\100")local W=Instance.new("\067\097\109\101\114\097")W.CameraType=Enum.CameraType.Scriptable W.CFrame=CFrame.new(0,0,0)W.FieldOfView=40 W.Parent=Y Y.CurrentCamera=W local k=3 local E=-0.25 local G=.3 local D=.15 local J=1.5 local g=2 local m=3 local f=Random.new()local T=math.pi*.5 local L=math.pi*2 local U=false local p=0 local h=false local q=nil local r=false local B=w.PrimaryPart.CFrame local O={}for A,x in pairs(w:GetDescendants())do if x:IsA("\066\097\115\101\080\097\114\116")and x~=w.PrimaryPart then O[x]=x.CFrame:ToObjectSpace(w.PrimaryPart.CFrame)end end local Z=0 local N=0 function spinToken(A)Z=(Z+(A*L)*(E+N))%L if math.abs(N)<A*D then N=0 else N=N-(A*D)*math.sign(N)end local x=B*CFrame.Angles(0,Z,0)w.PrimaryPart.CFrame=x for A,X in pairs(O)do A.CFrame=x*X end local X=math.sin(Z*2+T)*.5+.5 Q.Transparency=.75+.1*(1-X)local o=7.5+1*X e.Size=Vector3.new(o,.01,o)end function requestBadge()if not r then r=true end end function spinAction(A)N=math.clamp(N+G*A,-J,J)requestBadge()end local i={[Enum.KeyCode.DPadLeft]=true,[Enum.KeyCode.ButtonL1]=true,[Enum.KeyCode.A]=true,[Enum.KeyCode.Left]=true}local v={[Enum.KeyCode.DPadRight]=true,[Enum.KeyCode.ButtonR1]=true,[Enum.KeyCode.D]=true,[Enum.KeyCode.Right]=true}function handleInput(A,x)if A and A.UserInputState==Enum.UserInputState.Begin then if A.UserInputType==Enum.UserInputType.Touch or A.UserInputType==Enum.UserInputType.MouseButton1 then local x=math.sign(A.Position.X-Y.AbsoluteSize.X*.5)spinAction(x)elseif A.UserInputType==Enum.UserInputType.Gamepad1 or A.UserInputType==Enum.UserInputType.Keyboard then if i[A.KeyCode]then spinAction(-1)elseif v[A.KeyCode]then spinAction(1)end end end end function enable(o)local w=F:FindFirstChild("\080\108\097\121\101\114\071\117\105")if not U and w then U=true p=p+1 local F=p if not H.Enabled then Z=L*.9 N=0 y.BackgroundTransparency=1 W.CFrame=CFrame.new(-7,0,-10)end Y.ImageTransparency=0 Y.Visible=true H.Parent=w H.Enabled=true K.PlaybackSpeed=.5 K.Volume=.5 K:Play()if not h then h=true X:BindToRenderStep("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110",Enum.RenderPriority.Camera.Value-1,spinToken)end;(x:Create(K,TweenInfo.new(k,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{Volume=.5})):Play();(x:Create(Y,TweenInfo.new(.1,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{ImageTransparency=0})):Play();(x:Create(W,TweenInfo.new(1.5,Enum.EasingStyle.Quad,Enum.EasingDirection.Out),{CFrame=CFrame.new(0,0,-10)})):Play()task.delay(1.5,function()if F==p then if q then q:Disconnect()q=nil end if o then q=A.InputBegan:connect(handleInput)end;(x:Create(y,TweenInfo.new(.5,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{BackgroundTransparency=0})):Play();(x:Create(W,TweenInfo.new(4,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{CFrame=CFrame.new(0,0,0)})):Play()end end)end end function disable()local A=F:FindFirstChild("\080\108\097\121\101\114\071\117\105")if U and A then U=false p=p+1 local A=p if q then q:Disconnect()q=nil end K.PlaybackSpeed=.5 K:Play();(x:Create(K,TweenInfo.new(k,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{Volume=0})):Play();(x:Create(W,TweenInfo.new(k,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{CFrame=CFrame.new(0,0,300)})):Play();(x:Create(y,TweenInfo.new(k,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{BackgroundTransparency=1})):Play();(x:Create(Y,TweenInfo.new(k,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{ImageTransparency=1})):Play()task.delay(k,function()if A==p then for A,x in pairs(H:GetChildren())do if x and(x.Parent and x.Name=="\067\108\101\097\110\105\110\103\085\112\073\099\111\110")or x.Name=="\073\099\111\110"then x:Destroy()end end H.Enabled=false H.ViewportFrame.Visible=false H.Parent=script if not h then h=false X:UnbindFromRenderStep("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110")end end end)end end local P={Enable=enable;Disable=disable}return P



local uis = game:GetService('UserInputService')
local tweenService = game:GetService('TweenService')
local runService = game:GetService('RunService')
local playersService = game:GetService('Players')
local localPlayer = playersService.LocalPlayer
local gui = script:WaitForChild('TokenTransitionGui')
local viewportFrame = gui:WaitForChild('ViewportFrame')
local tokenModel = viewportFrame:WaitForChild('Token')
local glowPart = viewportFrame:WaitForChild('GlowPart')
local glowDecal = glowPart:WaitForChild('GlowDecal')
local background = gui:WaitForChild('Background')
local sound = gui:WaitForChild('FlySound')

local camera = Instance.new('Camera')
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(0,0,0)
camera.FieldOfView = 40
camera.Parent = viewportFrame
viewportFrame.CurrentCamera = camera

local DISABLE_TIME = 3

local TOKEN_SPIN_RATE = -.25
local CLICK_VELOCITY = .3
local SPIN_DAMPER = .15
local MAX_SPEED = 1.5

local ICON_FADE_IN_TIME = 2
local ICON_FADE_OUT_TIME = 3


local rng = Random.new()
local qpi = math.pi*.5
local tau = math.pi*2


local enabled = false
local changeIndex = 0
local renderstepBound = false
local inputConnection = nil
local requestedBadge = false


local tokenOriginalCF = tokenModel.PrimaryPart.CFrame
local tokenPartCFrames = {}
for _,child in pairs(tokenModel:GetDescendants()) do
	if child:IsA("BasePart") and child ~= tokenModel.PrimaryPart then
		tokenPartCFrames[child] = child.CFrame:ToObjectSpace(tokenModel.PrimaryPart.CFrame)
	end
end

local spin = 0
local spinVelocity = 0
function spinToken(delta)
	--local spin = os.clock()*tau*TOKEN_SPIN_RATE
	spin = (spin + delta*tau*(TOKEN_SPIN_RATE+spinVelocity))%tau
	if math.abs(spinVelocity) < delta*SPIN_DAMPER then
		spinVelocity = 0
	else
		spinVelocity = spinVelocity - delta * SPIN_DAMPER * math.sign(spinVelocity)
	end
	
	local newCFrame = tokenOriginalCF * CFrame.Angles(0, spin, 0)
	tokenModel.PrimaryPart.CFrame = newCFrame
	for tokenModelPart, cframeOffset in pairs(tokenPartCFrames) do
		tokenModelPart.CFrame = newCFrame * cframeOffset
	end
	
	local glownessPercent = math.sin(spin*2+qpi)*.5+.5
	glowDecal.Transparency = .75+.1*(1-glownessPercent)
	local width = 7.5+1*glownessPercent
	glowPart.Size = Vector3.new(width, .01, width)
end


function requestBadge()
	if not requestedBadge then	--TODO: replace with a debounce timer
		requestedBadge = true
		--TODO: request badge
	end
end

function spinAction(direction)
	spinVelocity = math.clamp(spinVelocity + CLICK_VELOCITY*direction, -MAX_SPEED, MAX_SPEED)
	requestBadge()
end

local leftControls = {
	[Enum.KeyCode.DPadLeft] = true,
	[Enum.KeyCode.ButtonL1] = true,
	[Enum.KeyCode.A] = true,
	[Enum.KeyCode.Left] = true,
}
local rightControls = {
	[Enum.KeyCode.DPadRight] = true,
	[Enum.KeyCode.ButtonR1] = true,
	[Enum.KeyCode.D] = true,
	[Enum.KeyCode.Right] = true,
}
function handleInput(input, processed)
	if input and input.UserInputState == Enum.UserInputState.Begin then
		if input.UserInputType == Enum.UserInputType.Touch or input.UserInputType == Enum.UserInputType.MouseButton1 then
			local direction = math.sign(input.Position.X - viewportFrame.AbsoluteSize.X*.5)
			spinAction(direction)
		elseif input.UserInputType == Enum.UserInputType.Gamepad1 or input.UserInputType == Enum.UserInputType.Keyboard then
			if leftControls[input.KeyCode] then
				spinAction(-1)
			elseif rightControls[input.KeyCode] then
				spinAction(1)
			end
		end
	end
end


function enable(spinControl)
	local playerGui = localPlayer:FindFirstChild('PlayerGui')
	if not enabled and playerGui then
		enabled = true
		changeIndex = changeIndex + 1
		local thisChangeIndex = changeIndex
		if not gui.Enabled then
			spin = tau*.9	-- Initial rotation
			spinVelocity = 0
			background.BackgroundTransparency = 1
			camera.CFrame = CFrame.new(-7,0,-10)
		end
		viewportFrame.ImageTransparency = 0
		viewportFrame.Visible = true
		gui.Parent = playerGui
		gui.Enabled = true
		sound.PlaybackSpeed = .5
		sound.Volume = .5
		sound:Play()
		
		if not renderstepBound then
			renderstepBound = true
			runService:BindToRenderStep('TokenTransition', Enum.RenderPriority.Camera.Value-1, spinToken)
		end
		
		tweenService:Create(sound,
			TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['Volume'] = .5,}
		):Play()
		tweenService:Create(viewportFrame,
			TweenInfo.new(.1, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['ImageTransparency'] = 0,}
		):Play()
		tweenService:Create(camera,
			TweenInfo.new(1.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
			{['CFrame'] = CFrame.new(0,0,-10),}
		):Play()
		task.delay(1.5, function()
			if thisChangeIndex == changeIndex then
				if inputConnection then
					inputConnection:Disconnect()
					inputConnection = nil
				end
				if spinControl then
					inputConnection = uis.InputBegan:connect(handleInput)
				end
				tweenService:Create(background,
					TweenInfo.new(.5, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
					{['BackgroundTransparency'] = 0,}
				):Play()
				tweenService:Create(camera,
					TweenInfo.new(4, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
					{['CFrame'] = CFrame.new(0,0,0),}
				):Play()
			end
		end)
	end
end

function disable()
	local playerGui = localPlayer:FindFirstChild('PlayerGui')
	if enabled and playerGui then
		enabled = false
		changeIndex = changeIndex + 1
		local thisChangeIndex = changeIndex
		if inputConnection then
			inputConnection:Disconnect()
			inputConnection = nil
		end

		sound.PlaybackSpeed = .5
		sound:Play()
		tweenService:Create(sound,
			TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['Volume'] = 0,}
		):Play()
		tweenService:Create(camera,
			TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['CFrame'] = CFrame.new(0,0,300),}
		):Play()
		tweenService:Create(background,
			TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['BackgroundTransparency'] = 1,}
		):Play()
		tweenService:Create(viewportFrame,
			TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
			{['ImageTransparency'] = 1,}
		):Play()
		task.delay(DISABLE_TIME, function()
			if thisChangeIndex == changeIndex then
				for _,iconLabel in pairs(gui:GetChildren()) do
					if iconLabel and iconLabel.Parent and iconLabel.Name == 'CleaningUpIcon' or iconLabel.Name == 'Icon' then
						iconLabel:Destroy()
					end
				end
				gui.Enabled = false
				gui.ViewportFrame.Visible = false
				gui.Parent = script
				if not renderstepBound then
					renderstepBound = false
					runService:UnbindFromRenderStep('TokenTransition')
				end
			end
		end)
	end
end


local module = {
	Enable = enable,
	Disable = disable,
}

return module
