local F=game:GetService("\082\117\110\083\101\114\118\105\099\101")local G=script.Parent local h={}local l=G:WaitForChild("\067\111\110\102\105\103\117\114\097\116\105\111\110")local d=(l:WaitForChild("\083\116\111\114\097\103\101\070\111\108\100\101\114")).Value local o=game.Players.LocalPlayer local O=require(script:WaitForChild("\082\111\099\107\101\116\077\097\110\097\103\101\114"))local y=G.Handle local M,e,t,L local n local s=o:GetMouse()local S=false local X=true for F,G in ipairs(d:GetChildren())do table.insert(h,G)end local function f()if o.Character.Humanoid:GetState()==Enum.HumanoidStateType.Swimming then return end if X then X=false local F=table.remove(h,1)F.Rocket.Transparency=0 G.FireRocket:FireServer(F)local d=(s.Hit.p-y.Position).unit local o=d*5 F.PrimaryPart.CFrame=CFrame.new(y.Position,y.Position+o)+o F.PrimaryPart.Velocity=o*40 O:BindRocketEvents(F)wait(l.ReloadTimeSeconds.Value)X=true end end local function u(F)table.insert(h,F)end local function E()if o.Character.Humanoid.RigType==Enum.HumanoidRigType.R15 then return end local F=o.Character:FindFirstChild("\084\111\114\115\111")M=F.Neck t=M.C0 e=F["\082\105\103\104\116 \083\104\111\117\108\100\101\114"]L=e.C0 end local function j(F)if o.Character.Humanoid:GetState()==Enum.HumanoidStateType.Swimming then return end local G=o.Character.HumanoidRootPart local h=o.Character.Head local l=(F-h.Position).unit local d=math.acos(l:Dot(Vector3.new(0,1,0)))local O=d if math.deg(O)>110 then O=math.rad(110)end M.C0=CFrame.new(0,1,0)*CFrame.Angles(math.pi-O,math.pi,0)local y=o.Character["\082\105\103\104\116 \065\114\109"]local t=G.Position+G.CFrame:vectorToWorldSpace(Vector3.new(G.Size.X/2+y.Size.X/2,G.Size.Y/2-y.Size.Z/2,0))local L=((F-t)*Vector3.new(1,0,1)).unit local n=(G.CFrame.lookVector*Vector3.new(1,0,1)).unit local s=math.acos(L:Dot(n))if tostring(s)=="-\049\046\035\073\078\068"then s=0 end if o.Character.Humanoid:GetState()==Enum.HumanoidStateType.Seated then local F=G.CFrame.lookVector:Cross(L)if s>math.pi/2 then s=math.pi/2 end if F.Y<0 then s=-s end end e.C0=CFrame.new(1,.5,0)*CFrame.Angles(math.pi/2-d,math.pi/2+s,0)if o.Character.Humanoid:GetState()~=Enum.HumanoidStateType.Seated then G.CFrame=CFrame.new(G.Position,G.Position+(Vector3.new(F.X,G.Position.Y,F.Z)-G.Position).unit)end end local function V()j(s.Hit.p)end local function K()E()n=s.Icon s.Icon="\114\098\120\097\115\115\101\116\105\100\058\047\047\055\057\054\053\056\052\052\057"s.TargetFilter=o.Character if o.Character.Humanoid.RigType==Enum.HumanoidRigType.R6 then S=o.Character.Humanoid.AutoRotate o.Character.Humanoid.AutoRotate=false F:BindToRenderStep("\082\111\116\097\116\101\067\104\097\114\097\099\116\101\114",Enum.RenderPriority.Input.Value,V)end end local function R()s.Icon=n if o.Character.Humanoid.RigType==Enum.HumanoidRigType.R6 then M.C0=t e.C0=L o.Character.Humanoid.AutoRotate=S F:UnbindFromRenderStep("\082\111\116\097\116\101\067\104\097\114\097\099\116\101\114")end end G.Activated:connect(f)d.ChildAdded:connect(u)G.Equipped:connect(K)G.Unequipped:connect(R)
local RunService = game:GetService('RunService')

-- Local Variables
local Tool = script.Parent
local Buffer = {}
local Configurations = Tool:WaitForChild('Configuration')
local Storage = Configurations:WaitForChild('StorageFolder').Value
local Player = game.Players.LocalPlayer
local RocketManager = require(script:WaitForChild('RocketManager'))
local Handle = Tool.Handle
local Neck, Shoulder, OldNeckC0, OldShoulderC0
local OldMouseIcon
local Mouse = Player:GetMouse()
local AutoRotate = false
local CanFire = true

-- Initialization
for _, child in ipairs(Storage:GetChildren()) do
	table.insert(Buffer, child)
end

-- Local Functions
local function OnActivation()
	if Player.Character.Humanoid:GetState() == Enum.HumanoidStateType.Swimming then return end
	if CanFire then
		CanFire = false
		
		local rocket = table.remove(Buffer, 1)
		rocket.Rocket.Transparency = 0
		Tool.FireRocket:FireServer(rocket)		
		
		local toMouse = (Mouse.Hit.p - Handle.Position).unit
		local direction = toMouse * 5
		
		rocket.PrimaryPart.CFrame = CFrame.new(Handle.Position, Handle.Position + direction) + direction
		rocket.PrimaryPart.Velocity = direction * 40
		RocketManager:BindRocketEvents(rocket)
		
		wait(Configurations.ReloadTimeSeconds.Value)
		CanFire = true	
	end
end

local function OnStorageAdded(child)
	table.insert(Buffer, child)
end

local function SetupJoints()
	if Player.Character.Humanoid.RigType == Enum.HumanoidRigType.R15 then
		return -- TODO: Make tracking compatible with R15
	end
	local torso = Player.Character:FindFirstChild("Torso")
	
	Neck = torso.Neck
	OldNeckC0 = Neck.C0
	Shoulder = torso['Right Shoulder']
	OldShoulderC0 = Shoulder.C0
end

local function Frame(mousePosition)
	if Player.Character.Humanoid:GetState() == Enum.HumanoidStateType.Swimming then return end
	local torso = Player.Character.HumanoidRootPart
	local head = Player.Character.Head
	
	local toMouse = (mousePosition - head.Position).unit
	local angle = math.acos(toMouse:Dot(Vector3.new(0,1,0)))
	
	local neckAngle = angle
	
	-- Limit how much the head can tilt down. Too far and the head looks unnatural
	if math.deg(neckAngle) > 110 then
		neckAngle = math.rad(110)
	end
	Neck.C0 = CFrame.new(0,1,0) * CFrame.Angles(math.pi - neckAngle,math.pi,0)
	
	-- Calculate horizontal rotation
	local arm = Player.Character['Right Arm']
	local fromArmPos = torso.Position + torso.CFrame:vectorToWorldSpace(Vector3.new(
		torso.Size.X/2 + arm.Size.X/2, torso.Size.Y/2 - arm.Size.Z/2, 0))
	local toMouseArm = ((mousePosition - fromArmPos) * Vector3.new(1,0,1)).unit
	local look = (torso.CFrame.lookVector * Vector3.new(1,0,1)).unit
	local lateralAngle = math.acos(toMouseArm:Dot(look))
	
	-- Check for rogue math
	if tostring(lateralAngle) == "-1.#IND" then
		lateralAngle = 0
	end		
	
	-- Handle case where character is sitting down
	if Player.Character.Humanoid:GetState() == Enum.HumanoidStateType.Seated then			
		local cross = torso.CFrame.lookVector:Cross(toMouseArm)
		if lateralAngle > math.pi/2 then
			lateralAngle = math.pi/2
		end
		if cross.Y < 0 then
			lateralAngle = -lateralAngle
		end
	end	
	
	-- Turn shoulder to point to mouse
	Shoulder.C0 = CFrame.new(1,0.5,0) * CFrame.Angles(math.pi/2 - angle,math.pi/2 + lateralAngle,0)	
	
	-- If not sitting then aim torso laterally towards mouse
	if Player.Character.Humanoid:GetState() ~= Enum.HumanoidStateType.Seated then
		torso.CFrame = CFrame.new(torso.Position, torso.Position + (Vector3.new(
			mousePosition.X, torso.Position.Y, mousePosition.Z)-torso.Position).unit)
	end	
end

local function MouseFrame()
	Frame(Mouse.Hit.p)
end

local function OnEquip()
	-- Setup joint variables
	SetupJoints()
	
	-- Replace mouse icon and store old
	OldMouseIcon = Mouse.Icon
	Mouse.Icon = 'rbxassetid://79658449'
	
	Mouse.TargetFilter = Player.Character
	
	if Player.Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
		AutoRotate = Player.Character.Humanoid.AutoRotate
		Player.Character.Humanoid.AutoRotate = false
	
		RunService:BindToRenderStep('RotateCharacter', Enum.RenderPriority.Input.Value, MouseFrame)
	end
end

local function OnUnequip()
	Mouse.Icon = OldMouseIcon
	
	if Player.Character.Humanoid.RigType == Enum.HumanoidRigType.R6 then
		Neck.C0 = OldNeckC0
		Shoulder.C0 = OldShoulderC0
		
		Player.Character.Humanoid.AutoRotate = AutoRotate
		RunService:UnbindFromRenderStep('RotateCharacter')
	end
end

-- Event Binding
Tool.Activated:connect(OnActivation)
Storage.ChildAdded:connect(OnStorageAdded)
Tool.Equipped:connect(OnEquip)
Tool.Unequipped:connect(OnUnequip)