local q={}function q.Create(q,R)local Y={Item=R;Equipped=false,Connections={}}local h={}local X=R.Parent.Parent local P=R:WaitForChild("\072\097\110\100\108\101")local B=P:WaitForChild("\077\117\122\122\108\101")local U=CONFIG:GetConfig(R)local O=true local e=false local S=false local Z=false local k=0 local x=(R:WaitForChild("\065\109\109\111")).Value local n=false local function H()return Y.Equipped and(O and x>0)end local function I()if not S and(Y.Equipped and x<U.Magazine)then S=true Z=false local q=X.Ammo[U.Size].Value if q>0 then MOUSE.Reticle="\082\101\108\111\097\100\105\110\103"REMOTES.Reload:FireServer(R)EFFECTS:Effect("\082\101\108\111\097\100",R)h.Reload:Play(.1,1,1/U.ReloadTime)local X=tick()local P=0 repeat P=tick()-X RunService.Stepped:wait()until P>=U.ReloadTime or Z or not Y.Equipped h.Reload:Stop()if Y.Equipped then if P>=U.ReloadTime then local R=U.Magazine local Y=R-x if q>=Y then x=x+Y else x=x+q end end MOUSE.Reticle=U.Reticle or"\071\117\110"EVENTS.Gun:Fire("\085\112\100\097\116\101",x)end end S=false end end local function t()x=x-1 local q=B.WorldPosition local Y={}for h=1,U.ShotSize,1 do local P=U.Spread*10 local B=CFrame.new(q,MOUSE.WorldPosition)if U.SpreadPattern then local q,R=U.SpreadPattern[h][1],U.SpreadPattern[h][2]B=B*CFrame.Angles(math.rad((P*R)/50),math.rad((P*q)/50),0)else B=B*CFrame.Angles(math.rad(math.random(-P,P)/50),math.rad(math.random(-P,P)/50),0)end local O=B.lookVector table.insert(Y,O)local e,S,Z,k=Raycast(q,O*U.Range,{X})if e and k then if DAMAGE:PlayerCanDamage(PLAYER,k)then local Y=DAMAGE:Calculate(R,e,q)local X=k:FindFirstChild("\065\114\109\111\114")and k.Armor.Value>0 EVENTS.Hitmarker:Fire(S,Y,X,e.Name=="\072\101\097\100")REMOTES.Hit:FireServer(e,h)end end end if n then h.AimShoot:Play(0,math.random(5,10)/10,1)else h.Shoot:Play(0,math.random(5,10)/10,1)end EVENTS.Gun:Fire("\085\112\100\097\116\101",x)EFFECTS:Effect("\083\104\111\111\116",R,q,Y,x)REMOTES.Shoot:FireServer(R,q,Y)EVENTS.Recoil:Fire(Vector3.new(math.random(-U.Recoil,U.Recoil)/4,0,math.random(U.Recoil/2,U.Recoil)))end function Y.Connect(q)local Y=PLAYER.Character local X=Y:WaitForChild("\072\117\109\097\110\111\105\100")for q,R in pairs((q.Item:WaitForChild("\065\110\105\109\097\116\105\111\110\115")):GetChildren())do h[R.Name]=X:LoadAnimation(R)end table.insert(q.Connections,INPUT.ActionBegan:connect(function(R,Y)if q.Equipped and not Y then if R=="\082\101\108\111\097\100"then I()end end end))table.insert(q.Connections,R.Attachments.ChildAdded:connect(function()U=CONFIG:GetConfig(R)if q.Equipped then EVENTS.Zoom:Fire(U.Zoom)EVENTS.Scope:Fire(U.Scope)end end))table.insert(q.Connections,R.Attachments.ChildRemoved:connect(function()U=CONFIG:GetConfig(R)if q.Equipped then EVENTS.Zoom:Fire(U.Zoom)EVENTS.Scope:Fire(U.Scope)end end))table.insert(q.Connections,EVENTS.Aim.Event:connect(function(R)n=R if q.Equipped then if n then h.Idle:Stop()h.Aim:Play()else h.Aim:Stop()h.Idle:Play()end end end))end function Y.Disconnect(q)for q,R in pairs(q.Connections)do R:Disconnect()end q.Connections={}end function Y.Equip(q)EVENTS.Zoom:Fire(U.Zoom)EVENTS.Scope:Fire(U.Scope)MOUSE.Reticle=U.Reticle or"\071\117\110"if n then h.Aim:Play()else h.Idle:Play()end h.Equip:Play(0,1,1)x=R.Ammo.Value EVENTS.Gun:Fire("\069\110\097\098\108\101",U.Size,x)q.Equipped=true k=tick()if x==0 then spawn(function()I()end)end end function Y.Unequip(q)EVENTS.Zoom:Fire()EVENTS.Scope:Fire(false)MOUSE.Reticle="\068\101\102\097\117\108\116"for q,R in pairs(h)do R:Stop()end EVENTS.Gun:Fire("\068\105\115\097\098\108\101",U.Size,x)q.Equipped=false end function Y.Activate(q)e=true if tick()-k>=EQUIP_COOLDOWN then if U.FireMode=="\083\101\109\105"then if H()then Z=true O=false t()wait(1/U.FireRate)O=true end elseif U.FireMode=="\065\117\116\111"then while e and H()do Z=true O=false t()wait(1/U.FireRate)O=true end elseif U.FireMode=="\066\117\114\115\116"then while e and H()do O=false for q=1,U.BurstAmount,1 do if e and x>0 then Z=true t()wait(1/U.BurstRate)else break end end wait(1/U.FireRate)O=true end end if x==0 then I()end end end function Y.Deactivate(q)e=false end return Y end return q


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 position		= muzzle.WorldPosition
		local directions	= {}
		
		for i = 1, config.ShotSize do
			local spread	= config.Spread * 10
			local cframe	= CFrame.new(position, MOUSE.WorldPosition)
			
			if config.SpreadPattern then
				local x, y	= config.SpreadPattern[i][1], config.SpreadPattern[i][2]
				cframe		= cframe * CFrame.Angles(math.rad(spread * y / 50), math.rad(spread * x / 50), 0)
			else
				cframe		= cframe * CFrame.Angles(math.rad(math.random(-spread, spread) / 50), math.rad(math.random(-spread, spread) / 50), 0)
			end
			
			local direction	= cframe.lookVector
			table.insert(directions, direction)
			
			local hit, pos, normal, humanoid	= Raycast(position, direction * config.Range, {character})
			
			if hit and humanoid then
				if DAMAGE:PlayerCanDamage(PLAYER, humanoid) then
					local damage	= DAMAGE:Calculate(item, hit, position)
					local armor		= (humanoid:FindFirstChild("Armor") and humanoid.Armor.Value > 0)
					EVENTS.Hitmarker:Fire(pos, damage, armor, hit.Name == "Head")
					REMOTES.Hit:FireServer(hit, i)
				end
			end
		end
		
		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
		
		EVENTS.Gun:Fire("Update", ammo)
		EFFECTS:Effect("Shoot", item, position, directions, ammo)
		REMOTES.Shoot:FireServer(item, position, directions)
		
		EVENTS.Recoil:Fire(Vector3.new(math.random(-config.Recoil, config.Recoil) / 4, 0, math.random(config.Recoil / 2, config.Recoil)))
	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 tick() - equipTime >= EQUIP_COOLDOWN then
			if config.FireMode == "Semi" then
				if CanShoot() then
					rCancelled	= true
					canShoot	= false
					Shoot()
					wait(1 / config.FireRate)
					canShoot	= true
				end
			elseif config.FireMode == "Auto" then
				while clicking and CanShoot() do
					rCancelled	= true
					canShoot	= false
					Shoot()
					wait(1 / config.FireRate)
					canShoot	= true
				end
			elseif config.FireMode == "Burst" then
				while clicking and CanShoot() do
					canShoot	= false
					for i = 1, config.BurstAmount do
						if clicking and ammo > 0 then
							rCancelled	= true
							Shoot()
							wait(1 / config.BurstRate)
						else
							break
						end
					end
					wait(1 / config.FireRate)
					canShoot	= true
				end
			end
			if ammo == 0 then
				Reload()
			end
		end
	end
	
	function itemModule.Deactivate(self)
		clicking	= false
	end
	
	return itemModule
end

return module
