local h={}function h.Create(h,n)local i={Item=n;Equipped=false,Connections={}}local o={}local c=n.Parent.Parent local O=n:WaitForChild("\072\097\110\100\108\101")local l=O:WaitForChild("\077\117\122\122\108\101")local L=CONFIG:GetConfig(n)local E=true local s=false local x=false local R=false local b=0 local p=(n:WaitForChild("\065\109\109\111")).Value local M=false local function U()return i.Equipped and(E and p>0)end local function W()if not x and(i.Equipped and p<L.Magazine)then x=true R=false local h=c.Ammo[L.Size].Value if h>0 then MOUSE.Reticle="\082\101\108\111\097\100\105\110\103"REMOTES.Reload:FireServer(n)EFFECTS:Effect("\082\101\108\111\097\100",n)o.Reload:Play(.1,1,1/L.ReloadTime)local c=tick()local O=0 repeat O=tick()-c RunService.Stepped:wait()until O>=L.ReloadTime or R or not i.Equipped o.Reload:Stop()if i.Equipped then if O>=L.ReloadTime then local n=L.Magazine local i=n-p if h>=i then p=p+i else p=p+h end end MOUSE.Reticle=L.Reticle or"\071\117\110"EVENTS.Gun:Fire("\085\112\100\097\116\101",p)end end x=false end end local function N()p=p-1 local h=(MOUSE.WorldPosition-l.WorldPosition).Unit if L.AimCorrection then h=(h+Vector3.new(0,L.AimCorrection/100,0)).Unit end local i=EVENTS.GetProjectileID:Invoke()EVENTS.Projectile:Fire(PLAYER,n,i,l.WorldPosition,h)REMOTES.RocketLauncher:FireServer(n,"\070\105\114\101",i,l.WorldPosition,h)if M then o.AimShoot:Play(0,math.random(5,10)/10,1)else o.Shoot:Play(0,math.random(5,10)/10,1)end EFFECTS:Effect("\082\111\099\107\101\116\076\097\117\110\099\104\101\114",n,"\070\105\114\101",p>0)EVENTS.Gun:Fire("\085\112\100\097\116\101",p)EVENTS.Recoil:Fire(Vector3.new(math.random(-L.Recoil,L.Recoil)/4,0,math.random(L.Recoil/2,L.Recoil)))if p>0 then o.Reload:Play(.1,1,1/L.Cooldown)end end function i.Connect(h)local i=PLAYER.Character local c=i:WaitForChild("\072\117\109\097\110\111\105\100")for h,n in pairs((h.Item:WaitForChild("\065\110\105\109\097\116\105\111\110\115")):GetChildren())do o[n.Name]=c:LoadAnimation(n)end table.insert(h.Connections,INPUT.ActionBegan:connect(function(n,i)if h.Equipped and not i then if n=="\082\101\108\111\097\100"then W()end end end))table.insert(h.Connections,n.Attachments.ChildAdded:connect(function()L=CONFIG:GetConfig(n)if h.Equipped then EVENTS.Zoom:Fire(L.Zoom)EVENTS.Scope:Fire(L.Scope)end end))table.insert(h.Connections,n.Attachments.ChildRemoved:connect(function()L=CONFIG:GetConfig(n)if h.Equipped then EVENTS.Zoom:Fire(L.Zoom)EVENTS.Scope:Fire(L.Scope)end end))table.insert(h.Connections,EVENTS.Aim.Event:connect(function(n)M=n if h.Equipped then if M then o.Idle:Stop()o.Aim:Play()else o.Aim:Stop()o.Idle:Play()end end end))end function i.Disconnect(h)for h,n in pairs(h.Connections)do n:Disconnect()end h.Connections={}end function i.Equip(h)EVENTS.Zoom:Fire(L.Zoom)EVENTS.Scope:Fire(L.Scope)MOUSE.Reticle=L.Reticle or"\071\117\110"if M then o.Aim:Play()else o.Idle:Play()end o.Equip:Play(0,1,1)p=n.Ammo.Value EVENTS.Gun:Fire("\069\110\097\098\108\101",L.Size,p)h.Equipped=true b=tick()if p==0 then spawn(function()W()end)end end function i.Unequip(h)EVENTS.Zoom:Fire()EVENTS.Scope:Fire(false)MOUSE.Reticle="\068\101\102\097\117\108\116"for h,n in pairs(o)do n:Stop()end EVENTS.Gun:Fire("\068\105\115\097\098\108\101",L.Size,p)h.Equipped=false end function i.Activate(h)s=true if U()then R=true E=false N()wait(L.Cooldown)E=true end end function i.Deactivate(h)s=false end return i end return h
-- modules

local module = {}

function module.Create(self, item)
	local itemModule = {
		Item = item,
		Equipped = false,
		Connections = {},
	}

	-- variables

	local animations = {}

	local character = item.Parent.Parent
	local handle = item:WaitForChild("Handle")
	local muzzle = handle:WaitForChild("Muzzle")

	local config = CONFIG:GetConfig(item)
	local canShoot = true
	local clicking = false
	local reloading = false
	local rCancelled = false
	local equipTime = 0

	local ammo = item:WaitForChild("Ammo").Value

	local aiming = false

	-- functions

	local function CanShoot()
		return itemModule.Equipped and canShoot and ammo > 0
	end

	local function Reload()
		if (not reloading) and itemModule.Equipped and ammo < config.Magazine then
			reloading = true
			rCancelled = false

			local storedAmmo = character.Ammo[config.Size].Value
			if storedAmmo > 0 then
				MOUSE.Reticle = "Reloading"
				REMOTES.Reload:FireServer(item)
				EFFECTS:Effect("Reload", item)
				animations.Reload:Play(0.1, 1, 1 / config.ReloadTime)

				local start = tick()
				local elapsed = 0
				repeat
					elapsed = tick() - start
					RunService.Stepped:wait()
				until elapsed >= config.ReloadTime or rCancelled or not itemModule.Equipped

				animations.Reload:Stop()

				if itemModule.Equipped then
					if elapsed >= config.ReloadTime then
						local magazine = config.Magazine
						local needed = magazine - ammo

						if storedAmmo >= needed then
							ammo = ammo + needed
						else
							ammo = ammo + storedAmmo
						end
					end

					MOUSE.Reticle = config.Reticle or "Gun"
					EVENTS.Gun:Fire("Update", ammo)
				end
			end
			reloading = false
		end
	end

	local function Shoot()
		ammo = ammo - 1

		local direction = (MOUSE.WorldPosition - muzzle.WorldPosition).Unit

		if config.AimCorrection then
			direction = (direction + Vector3.new(0, config.AimCorrection / 100, 0)).Unit
		end

		local projectileID = EVENTS.GetProjectileID:Invoke()

		EVENTS.Projectile:Fire(PLAYER, item, projectileID, muzzle.WorldPosition, direction)
		REMOTES.RocketLauncher:FireServer(item, "Fire", projectileID, muzzle.WorldPosition, direction)

		if aiming then
			animations.AimShoot:Play(0, math.random(5, 10) / 10, 1)
		else
			animations.Shoot:Play(0, math.random(5, 10) / 10, 1)
		end

		EFFECTS:Effect("RocketLauncher", item, "Fire", ammo > 0)
		EVENTS.Gun:Fire("Update", ammo)
		EVENTS.Recoil:Fire(
			Vector3.new(
				math.random(-config.Recoil, config.Recoil) / 4,
				0,
				math.random(config.Recoil / 2, config.Recoil)
			)
		)

		if ammo > 0 then
			animations.Reload:Play(0.1, 1, 1 / config.Cooldown)
		end
	end

	-- module functions

	function itemModule.Connect(self)
		local character = PLAYER.Character
		local humanoid = character:WaitForChild("Humanoid")

		for _, animation in pairs(self.Item:WaitForChild("Animations"):GetChildren()) do
			animations[animation.Name] = humanoid:LoadAnimation(animation)
		end

		table.insert(
			self.Connections,
			INPUT.ActionBegan:connect(function(action, processed)
				if self.Equipped and not processed then
					if action == "Reload" then
						Reload()
					end
				end
			end)
		)

		table.insert(
			self.Connections,
			item.Attachments.ChildAdded:connect(function()
				config = CONFIG:GetConfig(item)
				if self.Equipped then
					EVENTS.Zoom:Fire(config.Zoom)
					EVENTS.Scope:Fire(config.Scope)
				end
			end)
		)

		table.insert(
			self.Connections,
			item.Attachments.ChildRemoved:connect(function()
				config = CONFIG:GetConfig(item)
				if self.Equipped then
					EVENTS.Zoom:Fire(config.Zoom)
					EVENTS.Scope:Fire(config.Scope)
				end
			end)
		)

		table.insert(
			self.Connections,
			EVENTS.Aim.Event:connect(function(a)
				aiming = a

				if self.Equipped then
					if aiming then
						animations.Idle:Stop()
						animations.Aim:Play()
					else
						animations.Aim:Stop()
						animations.Idle:Play()
					end
				end
			end)
		)
	end

	function itemModule.Disconnect(self)
		for _, connection in pairs(self.Connections) do
			connection:Disconnect()
		end
		self.Connections = {}
	end

	function itemModule.Equip(self)
		EVENTS.Zoom:Fire(config.Zoom)
		EVENTS.Scope:Fire(config.Scope)
		MOUSE.Reticle = config.Reticle or "Gun"
		if aiming then
			animations.Aim:Play()
		else
			animations.Idle:Play()
		end
		animations.Equip:Play(0, 1, 1)

		ammo = item.Ammo.Value

		EVENTS.Gun:Fire("Enable", config.Size, ammo)

		self.Equipped = true
		equipTime = tick()

		if ammo == 0 then
			spawn(function()
				Reload()
			end)
		end
	end

	function itemModule.Unequip(self)
		EVENTS.Zoom:Fire()
		EVENTS.Scope:Fire(false)
		MOUSE.Reticle = "Default"

		for _, animation in pairs(animations) do
			animation:Stop()
		end

		EVENTS.Gun:Fire("Disable", config.Size, ammo)

		self.Equipped = false
	end

	function itemModule.Activate(self)
		clicking = true

		if CanShoot() then
			rCancelled = true
			canShoot = false
			Shoot()
			wait(config.Cooldown)
			canShoot = true
		end
	end

	function itemModule.Deactivate(self)
		clicking = false
	end

	return itemModule
end

return module
