--//The logic behind the Starlight Sword's Chain-reaction ability

local Properties = {
	Duration = 0, -- The current time the ability is active
	MaxDuration = 5, -- How long can the ability delay itself before it fully executes.
	LinkDamage = 10 -- The amount of damage multiplied per-person linked.
}

local FindFirstChild, FindFirstChildOfClass, WaitForChild = script.FindFirstChild, script.FindFirstChildOfClass, script.WaitForChild

local Clone, Destroy = script.Clone, script.Destroy

local Handle = WaitForChild(script, "HandleRef", 5)
local Creator = WaitForChild(script, "Creator", 5)
local InitialTarget = WaitForChild(script, "InitialTarget", 5)

if not InitialTarget or not InitialTarget.Value or not Handle or not Handle.Value or not Creator then script:Destroy() end

Handle = Handle.Value
Creator = Creator.Value
InitialTarget = InitialTarget.Value

local TargetTorso = (FindFirstChild(InitialTarget.Parent, "Torso") or FindFirstChild(InitialTarget.Parent, "UpperTorso"))

local Humanoid = FindFirstChildOfClass(Creator.Character, "Humanoid")

local Players = (game:FindService("Players") or game:GetService("Players"))
local Debris = (game:FindService("Debris") or game:GetService("Debris"))
local RunService = (game:FindService("RunService") or game:GetService("RunService"))

print("Starlight Link ability activated! Tag as much people as you can before " .. Properties.MaxDuration .. " seconds is up!")

local NewRay = Ray.new

local GetChildren, GetDescendants = script.GetChildren, script.GetDescendants

local IsA = script.IsA

function IsTeamMate(Player1, Player2)
	return (Player1 and Player2 and not Player1.Neutral and not Player2.Neutral and Player1.TeamColor == Player2.TeamColor)
end

function TagHumanoid(humanoid, player)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	Debris:AddItem(Creator_Tag, 2)
	Creator_Tag.Parent = humanoid
end

function UntagHumanoid(humanoid)
	for i, v in pairs(GetChildren(humanoid)) do
		if IsA(v,"ObjectValue") and v.Name == "creator" then
			Destroy(v)
		end
	end
end

local Deletables, Events = {}, {} --Put objects in the tables to discard when we're done.

local DurationValue = Instance.new("NumberValue")
DurationValue.Value = Properties.Duration
DurationValue.Name = "Duration"
DurationValue.Parent = script

local Attach = Instance.new("Attachment")
Deletables[#Deletables+1] = Attach
	
Attach.Name = "Constellation_Link"
Attach.Position = Vector3.new(0,0,0)

Attach.Parent = TargetTorso

local NewColorSequence = ColorSequence.new
local Color_1, Color_2 = Color3.fromRGB(0,170,255), Color3.new(1,1,1)

local Queue, AttachQueue, SparkleQueue = {}, {}, {}
local Sounds = {}
pcall(function()
		
	local Sparkles = Clone(script["Sparkle_Large_Blue"])
	SparkleQueue[#SparkleQueue+1] = Sparkles
	Deletables[#Deletables+1] = Sparkles
		
	Sparkles.Parent = TargetTorso
		
	Sparkles.Enabled = true
	
	Events[#Events+1] = DurationValue:GetPropertyChangedSignal("Value"):Connect(function()
		Sparkles.Color = NewColorSequence(Color_1:Lerp(Color_2, Properties.Duration/Properties.MaxDuration), Color_2)
	end)
	
end)

pcall(function()
	local ExplodeSound = Clone(script.ExplodeSound)
	Sounds[#Sounds+1] = ExplodeSound
	ExplodeSound.Parent = Attach
end)
	
local LastAttachment = Attach --Reference the last attachment point we made.

local Hit_WhiteList, TaggedHumanoids = {}, {}
TaggedHumanoids[InitialTarget] = InitialTarget
local Total = 1





Queue[#Queue+1] = InitialTarget
AttachQueue[#AttachQueue+1] = Attach

function Link(hit)
	
	if not hit or not hit.Parent then return end
	
	Hit_WhiteList[1] = hit --Replace the Whitelisted entry (Also helps reduce lag)
	
	--Do a Server-sided check to make sure the sword is in reasonable distance to the part hit (To prevent exploits)
	
	local DistanceRay = NewRay( Handle.Position , (hit.Position - Handle.Position).Unit * math.max(Handle.Size.X,Handle.Size.Y,Handle.Size.Z) * 2 )
	
	local part = workspace:FindPartOnRayWithWhitelist(DistanceRay, Hit_WhiteList , true)	
	
	--warn((part and "Part in range") or "Part not in range")
	--assert(part, "Part not in range: Potential exploit")
	if part ~= hit then return end -- Potential exploiter may be abusing the touched events
	
	local FF, Hum, Torso = FindFirstChildOfClass(hit.Parent, "ForceField"), FindFirstChildOfClass(hit.Parent, "Humanoid"), (FindFirstChild(hit.Parent, "Torso") or FindFirstChild(hit.Parent, "UpperTorso"))
	
	if FF or not Hum or not Torso or Hum == Humanoid or Hum.Health <= 0 or TaggedHumanoids[Hum] then return end --Don't hit yourself or anyone with a ForceField now..
	
	if IsTeamMate(Creator, Players:GetPlayerFromCharacter(Hum.Parent)) then return end
	
	TaggedHumanoids[Hum] = Hum --We got one!
	
	Queue[#Queue+1] = Hum
	
	Attach = Instance.new("Attachment")
	AttachQueue[#AttachQueue+1] = Attach
	
	pcall(function()
		local ExplodeSound = Clone(script.ExplodeSound)
		Sounds[#Sounds+1] = ExplodeSound
		ExplodeSound.Parent = Attach
	end)
	
	
	Deletables[#Deletables+1] = Attach
	
	Attach.Name = "Constellation_Link"
	Attach.Position = Vector3.new(0,0,0)
	
	--warn(LastAttachment)
	
	if LastAttachment then
		--Create a Constellation Beam from one target to another
		pcall(function()
			
			local Constellation_Beam = Clone(script["Constellation_Beam"])
			Deletables[#Deletables+1] = Constellation_Beam
			
			Constellation_Beam.Attachment0 = LastAttachment
			Constellation_Beam.Attachment1 = Attach
			Constellation_Beam.Enabled = true
			
			Constellation_Beam.Parent = Attach
			
			Events[#Events+1] = DurationValue:GetPropertyChangedSignal("Value"):Connect(function()
				Constellation_Beam.Color = NewColorSequence(Color_1:Lerp(Color_2, Properties.Duration/Properties.MaxDuration))
			end)
					
			--print("Linked Targets!")
			
		end)
		
	end
	
	pcall(function()
		
		local Sparkles = Clone(script["Sparkle_Large_Blue"])
		Deletables[#Deletables+1] = Sparkles
		SparkleQueue[#SparkleQueue+1] = Sparkles
		
		Sparkles.Parent = Torso
		
		Sparkles.Enabled = true
		
		Events[#Events+1] = DurationValue:GetPropertyChangedSignal("Value"):Connect(function()
			Sparkles.Color = NewColorSequence(Color_1:Lerp(Color_2, Properties.Duration/Properties.MaxDuration), Color_2)
		end)
		
	end)
	
	Attach.Parent = Torso
	
	LastAttachment = Attach --Reference the last attachment point we made.
	
	Total = Total + 1
	
	--warn("Tagged " .. Hum.Parent.Name .. "!", "\n Pending damage: " .. Properties.LinkDamage * Total)
	
	Properties.Duration = 0 --Reset the duration for every time you've tagged a person.
	
end

Handle.Touched:Connect(Link)
local Canceled = false

while Properties.Duration < Properties.MaxDuration and not Canceled do
	local delta = RunService.Heartbeat:Wait()
	Properties.Duration = Properties.Duration + delta
	DurationValue.Value = Properties.Duration
	--print(Properties.Duration)
end