local function a(a,n)n=n or{}local t,H,O local z=false repeat t,H,O=Workspace:FindPartOnRayWithIgnoreList(a,n)if t then if t.Parent:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")then z=true elseif t.CanCollide and t.Transparency~=1 then z=true else table.insert(n,t)end else z=true end until z return t,H,O end local function n(a)if a.Splash then REMOTES.Effect:FireAllClients(a.SplashEffect,a.Position,a.SplashRadius)end REMOTES.Projectile:FireAllClients("\075\105\108\108",a.ID)for n,t in pairs(projectiles)do if t==a then table.remove(projectiles,n)break end end if a.Splash then local n=Region3.new(a.Position+Vector3.new(-1,-1,-1)*a.SplashRadius,a.Position+Vector3.new(1,1,1)*a.SplashRadius)local t=Workspace:FindPartsInRegion3WithIgnoreList(n,{Workspace.Effects},100)for n,t in pairs(t)do if t.Name=="\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116"then local n=t.Parent:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if n then local H=Players:GetPlayerFromCharacter(n.Parent)if H==a.Owner or DAMAGE:PlayerCanDamage(a.Owner,n)then if n.Health>0 then local H=(t.Position-a.Position).Magnitude if H<a.SplashRadius then local O=n:FindFirstChild("\068\111\119\110")local z=false if O then z=O.Value end local L=math.cos((H/a.SplashRadius)^2*(math.pi/2))local N=math.ceil(L*a.Damage)local r=Players:GetPlayerFromCharacter(n.Parent)local A=(t.Position-a.Position).Unit if r then REMOTES.HitIndicator:FireClient(r,A,N)end if a.Owner then REMOTES.Hitmarker:FireClient(a.Owner,t.Position,N,n:FindFirstChild("\065\114\109\111\114")and n.Armor.Value>0,false)end DAMAGE:Damage(n,N,a.Owner)if n.Health<=0 then for a,n in pairs(n.Parent:GetChildren())do if n:IsA("\066\097\115\101\080\097\114\116")then n.Velocity=(A*N)*2 end end local H=math.floor((a.StartPosition-t.Position).Magnitude+.5)STAT_SCRIPT.FurthestKill:Fire(a.Owner,H)REMOTES.Killfeed:FireAllClients(a.Owner.Name,n.Parent.Name,a.Model,H)end end end end end end end end end local function t(n,t)n.Velocity=n.Velocity+Vector3.new(0,-n.Gravity*t,0)local H=Ray.new(n.Position,n.Velocity*t)local O,z=a(H,n.Ignore)n.Position=z if O then return false end return true end local function H(a,H,O,z,L)local N=pings[a]and pings[a].Average or 0 local r=CONFIG:GetConfig(H)local A=PROJECTILE:Create(r.Projectile,O)A.Position=z A.Velocity=L.Unit*A.Speed A.Damage=r.Damage A.Owner=a A.StartPosition=z if a.Character then table.insert(A.Ignore,a.Character)end table.insert(projectiles,A)local i=t(A,N)if i then for n,t in pairs(Players:GetPlayers())do if t~=a then REMOTES.Projectile:FireClient(t,"\067\114\101\097\116\101",a,H,O,z,L)end end else n(A)end end
-- functions

local function Raycast(ray, ignore)
	ignore = ignore or {}

	local hit, position, normal

	local success = false
	repeat
		hit, position, normal = Workspace:FindPartOnRayWithIgnoreList(ray, ignore)

		if hit then
			if hit.Parent:FindFirstChildOfClass("Humanoid") then
				success = true
			elseif hit.CanCollide and hit.Transparency ~= 1 then
				success = true
			else
				table.insert(ignore, hit)
			end
		else
			success = true
		end
	until success

	return hit, position, normal
end

local function KillProjectile(projectile)
	if projectile.Splash then
		REMOTES.Effect:FireAllClients(projectile.SplashEffect, projectile.Position, projectile.SplashRadius)
	end

	REMOTES.Projectile:FireAllClients("Kill", projectile.ID)
	for i, p in pairs(projectiles) do
		if p == projectile then
			table.remove(projectiles, i)
			break
		end
	end

	if projectile.Splash then
		local region = Region3.new(
			projectile.Position + Vector3.new(-1, -1, -1) * projectile.SplashRadius,
			projectile.Position + Vector3.new(1, 1, 1) * projectile.SplashRadius
		)
		local parts = Workspace:FindPartsInRegion3WithIgnoreList(region, { Workspace.Effects }, 100)

		for _, part in pairs(parts) do
			if part.Name == "HumanoidRootPart" then
				local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")

				if humanoid then
					local hitPlayer = Players:GetPlayerFromCharacter(humanoid.Parent)

					if hitPlayer == projectile.Owner or DAMAGE:PlayerCanDamage(projectile.Owner, humanoid) then
						if humanoid.Health > 0 then
							local distance = (part.Position - projectile.Position).Magnitude
							if distance < projectile.SplashRadius then
								local down = humanoid:FindFirstChild("Down")
								local alreadyDowned = false

								if down then
									alreadyDowned = down.Value
								end

								local amount = math.cos((distance / projectile.SplashRadius) ^ 2 * (math.pi / 2))
								local damage = math.ceil(amount * projectile.Damage)
								local player = Players:GetPlayerFromCharacter(humanoid.Parent)

								local direction = (part.Position - projectile.Position).Unit

								if player then
									REMOTES.HitIndicator:FireClient(player, direction, damage)
								end

								if projectile.Owner then
									REMOTES.Hitmarker:FireClient(
										projectile.Owner,
										part.Position,
										damage,
										humanoid:FindFirstChild("Armor") and humanoid.Armor.Value > 0,
										false
									)
								end

								DAMAGE:Damage(humanoid, damage, projectile.Owner)

								if humanoid.Health <= 0 then
									for _, part in pairs(humanoid.Parent:GetChildren()) do
										if part:IsA("BasePart") then
											part.Velocity = direction * damage * 2
										end
									end
									local killDist =
										math.floor((projectile.StartPosition - part.Position).Magnitude + 0.5)
									STAT_SCRIPT.FurthestKill:Fire(projectile.Owner, killDist)
									REMOTES.Killfeed:FireAllClients(
										projectile.Owner.Name,
										humanoid.Parent.Name,
										projectile.Model,
										killDist
									)
								end
							end
						end
					end
				end
			end
		end
	end
end

local function UpdateProjectile(projectile, deltaTime)
	projectile.Velocity = projectile.Velocity + Vector3.new(0, -projectile.Gravity * deltaTime, 0)

	local ray = Ray.new(projectile.Position, projectile.Velocity * deltaTime)
	local hit, position = Raycast(ray, projectile.Ignore)

	projectile.Position = position
	--projectile.Debug.CFrame	= CFrame.new(projectile.Position)

	if hit then
		return false
	end

	return true
end

local function Projectile(player, item, id, position, direction)
	local ping = pings[player] and pings[player].Average or 0
	local config = CONFIG:GetConfig(item)

	local projectile = PROJECTILE:Create(config.Projectile, id)
	projectile.Position = position
	projectile.Velocity = direction.Unit * projectile.Speed
	projectile.Damage = config.Damage
	projectile.Owner = player
	projectile.StartPosition = position

	if player.Character then
		table.insert(projectile.Ignore, player.Character)
	end

	--[[local de	= Instance.new("Part")
		de.Anchored		= true
		de.CanCollide	= false
		de.Size			= Vector3.new(1, 1, 1)
		de.Material		= Enum.Material.Neon
		de.Parent		= workspace
		
	projectile.Debug	= de]]

	table.insert(projectiles, projectile)

	local alive = UpdateProjectile(projectile, ping)

	if alive then
		for _, p in pairs(Players:GetPlayers()) do
			if p ~= player then
				REMOTES.Projectile:FireClient(p, "Create", player, item, id, position, direction)
			end
		end
	else
		KillProjectile(projectile)
	end
end
