------------------------------------------------------------------------------
--------------------[ FUNCTIONS ]---------------------------------------------
------------------------------------------------------------------------------


local CreateShockwave = function(Center, Radius)
	local Shockwave = Instance.new("Part")
	Shockwave.BrickColor = S.ShockwaveColor
	Shockwave.Material = Enum.Material.SmoothPlastic
	Shockwave.Name = "Shockwave"
	Shockwave.Anchored = true
	Shockwave.CanCollide = false
	Shockwave.FormFactor = Enum.FormFactor.Symmetric
	Shockwave.Size = VEC3(1, 1, 1)
	Shockwave.BottomSurface = Enum.SurfaceType.Smooth
	Shockwave.TopSurface = Enum.SurfaceType.Smooth
	local Mesh = Instance.new("SpecialMesh")
	Mesh.MeshType = Enum.MeshType.Sphere
	Mesh.Scale = VEC3()
	Mesh.Parent = Shockwave
	Shockwave.Parent = Main.Parent
	Shockwave.CFrame = CF(Center)
	spawn(function()
		for i = 0, 1, 1 / (30 * S.ShockwaveDuration) do
			local Scale = 2 * Radius * i
			Mesh.Scale = VEC3(Scale, Scale, Scale)
			Shockwave.Transparency = i
			wait()
		end
		Shockwave:Destroy()
	end)
end

local AdvRayCast = function(Origin, Direction, Dist, CustomIgnore)
	local NewIgnore = (CustomIgnore and CustomIgnore or Ignore)
	local NewRay = Ray.new(Origin, Direction * (Dist > 999 and 999 or Dist))
	local HitObj, HitPos = game.Workspace:FindPartOnRayWithIgnoreList(NewRay, NewIgnore)
	local LastPos = HitPos
	local FinalHitObj, FinalHitPos = nil, nil
	local RepTimes = math.floor(Dist / 999)
	if (not HitObj) and (Dist > 999) then
		for i = 0, RepTimes do
			local NewDist = (i == RepTimes and  (Dist - (LastPos - Origin).magnitude) or 999)
			local Ray2 = Ray.new(LastPos, Direction * NewDist)
			local HitObj2, HitPos2 = game.Workspace:FindPartOnRayWithIgnoreList(Ray2, NewIgnore)
			if i ~= RepTimes then
				if HitObj2 then
					FinalHitObj, FinalHitPos = HitObj2, HitPos2
					break
				end
			elseif i == RepTimes then
				FinalHitObj, FinalHitPos = HitObj2, HitPos2
			end
			LastPos = HitPos2
		end
		return FinalHitObj, FinalHitPos
	elseif HitObj or (Dist <= 999) then
		return HitObj, HitPos
	end
end

local FindFirstClass = function(Object, Class)
	local FoundObject = nil
	for _, Obj in pairs(Object:GetChildren()) do
		if Obj.ClassName == Class then
			FoundObject = Obj
			break
		end
	end
	return FoundObject
end

local IsEnemy = function(Human)
	local HitPlyr = game.Players:GetPlayerFromCharacter(Human.Parent)
	if (not HitPlyr) then return S.CanDamageNPCs end
	return S.AllowFriendlyFire or (HitPlyr.TeamColor ~= Plyr.Value.TeamColor or HitPlyr.Neutral)
end

local IsIgnored = function(Obj)
	for _,v in pairs(Ignore) do
		if Obj == v or Obj:IsDescendantOf(v) then
			return true
		end
	end
	return false
end

local MarkHit = function()
	spawn(function()
		local Gui_Clone = Plyr.Value:WaitForChild("PlayerGui"):WaitForChild("Main_Gui")
		local HitMarker = Gui_Clone:WaitForChild("HitMarker")
		
		HitMarker.Visible = true
		local StartMark = tick()
		HitMarker.LastMark.Value = StartMark
		
		wait(0.5)
		
		if HitMarker.LastMark.Value <= StartMark then
			HitMarker.Visible = false
		end
	end)
end
