local F=require(script.Parent)local u=require(script.Parent.LightningSparks)local A=Random.new()local l=os.clock function RandomVectorOffsetBetween(F,u,l)return((CFrame.lookAt(Vector3.new(),F)*CFrame.Angles(0,0,A:NextNumber(0,2*math.pi)))*CFrame.Angles(math.acos(A:NextNumber(math.cos(l),math.cos(u))),0,0)).LookVector end local I={}local H={}H.__index=H function H.new(i,o,Y,D,y,q)local n=setmetatable({},H)n.Size=o or 1 n.NumBolts=Y or 14 n.Color=D or ColorSequence.new(Color3.new(1,0,0),Color3.new(0,0,1))n.BoltColor=y or Color3.new(.3,.3,1)n.UpVector=q or Vector3.new(0,1,0)local e=workspace.CurrentCamera local w=Instance.new("\080\097\114\116")w.Name="\076\105\103\104\116\110\105\110\103\069\120\112\108\111\115\105\111\110"w.Anchored=true w.CanCollide=false w.Locked=true w.CastShadow=false w.Transparency=1 w.Size=Vector3.new(.05,.05,.05)w.CFrame=CFrame.lookAt(i+Vector3.new(0,.5,0),(i+Vector3.new(0,.5,0))+n.UpVector)*(CFrame.lookAt(Vector3.new(),Vector3.new(0,1,0))):inverse()w.Parent=e local b=Instance.new("\065\116\116\097\099\104\109\101\110\116")b.Parent=w b.CFrame=CFrame.new()local C=script.ExplosionBrightspot:Clone()local v=script.GlareEmitter:Clone()local G=script.PlasmaEmitter:Clone()local g=math.clamp(n.Size,0,1)v.Size=NumberSequence.new(30*g)G.Size=NumberSequence.new(18*g)G.Speed=NumberRange.new(100*g)C.Parent=b v.Parent=b G.Parent=b local R=n.Color if typeof(R)=="\067\111\108\111\114\051"then v.Color,G.Color=ColorSequence.new(R),ColorSequence.new(R)local F,u,A=Color3.toHSV(R)C.Color=ColorSequence.new(Color3.fromHSV(F,.5,A))else v.Color,G.Color=R,R local F=R.Keypoints for u=1,#F,1 do local A,l,I=Color3.toHSV(F[u].Value)F[u]=ColorSequenceKeypoint.new(F[u].Time,Color3.fromHSV(A,.5,I))end C.Color=ColorSequence.new(F)end C.Enabled,v.Enabled,G.Enabled=false,false,false local M={}for l=1,n.NumBolts,1 do local I,H={},{}I.WorldPosition,I.WorldAxis=b.WorldPosition,RandomVectorOffsetBetween(n.UpVector,math.rad(65),math.rad(80))H.WorldPosition,H.WorldAxis=b.WorldPosition+((I.WorldAxis*A:NextNumber(20,40))*1.4)*g,RandomVectorOffsetBetween(-n.UpVector,math.rad(70),math.rad(110))local i=F.new(I,H,10)i.AnimationSpeed=0 i.Thickness=1 i.Color=n.BoltColor i.PulseLength=.8 i.ColorOffsetSpeed=20 i.Frequency=2 i.MinRadius,i.MaxRadius=0,4*g i.FadeLength=.4 i.PulseSpeed=5 i.MinThicknessMultiplier,i.MaxThicknessMultiplier=.7,1 local o=u.new(i,5)o.MinDistance,o.MaxDistance=7.5,10 i.Velocity=((H.WorldPosition-I.WorldPosition).Unit*.1)*g M[#M+1]=i end n.Bolts=M n.Attachment=b n.Part=w n.StartT=l()n.RefIndex=#I+1 I[n.RefIndex]=n return n end function H.Destroy(F)I[F.RefIndex]=nil F.Part:Destroy()for u=1,#F.Bolts,1 do F.Bolts[u]=nil end F=nil end;(game:GetService("\082\117\110\083\101\114\118\105\099\101")).Heartbeat:Connect(function()for F,u in pairs(I)do local A=l()-u.StartT local I=u.Attachment if A<.7 then if A>.2 then I.ExplosionBrightspot.Enabled,I.GlareEmitter.Enabled,I.PlasmaEmitter.Enabled=false,false,false end for F=1,#u.Bolts,1 do local A=u.Bolts[F]A.Attachment1.WorldPosition=A.Attachment1.WorldPosition+A.Velocity end else u:Destroy()end end end)return H
--Properties do not update in realtime here
--i.e. You can't change explosion properties at any time beyond the initial function execution
local LightningBolt = require(script.Parent)
local LightningSparks = require(script.Parent.LightningSparks)

local rng_v = Random.new()
local clock = os.clock

function RandomVectorOffsetBetween(v, minAngle, maxAngle) --returns uniformly-distributed random unit vector no more than maxAngle radians away from v and no less than minAngle radians
	return (CFrame.lookAt(Vector3.new(), v) * CFrame.Angles(0, 0, rng_v:NextNumber(0, 2 * math.pi)) * CFrame.Angles(
		math.acos(rng_v:NextNumber(math.cos(maxAngle), math.cos(minAngle))),
		0,
		0
	)).LookVector
end

local ActiveExplosions = {}

local LightningExplosion = {}
LightningExplosion.__index = LightningExplosion

function LightningExplosion.new(Position, Size, NumBolts, Color, BoltColor, UpVector)
	local self = setmetatable({}, LightningExplosion)

	--Main (default) Properties--

	self.Size = Size or 1 --Value between 0 and 1 (1 for largest)
	self.NumBolts = NumBolts or 14 --Number of lightning bolts shot out from explosion
	self.Color = Color or ColorSequence.new(Color3.new(1, 0, 0), Color3.new(0, 0, 1)) --Can be a Color3 or ColorSequence
	self.BoltColor = BoltColor or Color3.new(0.3, 0.3, 1) --Can be a Color3 or ColorSequence
	self.UpVector = UpVector or Vector3.new(0, 1, 0) --Can be used to "rotate" the explosion

	--

	local parent = workspace.CurrentCamera

	local part = Instance.new("Part")
	part.Name = "LightningExplosion"
	part.Anchored = true
	part.CanCollide = false
	part.Locked = true
	part.CastShadow = false
	part.Transparency = 1
	part.Size = Vector3.new(0.05, 0.05, 0.05)
	part.CFrame = CFrame.lookAt(Position + Vector3.new(0, 0.5, 0), Position + Vector3.new(0, 0.5, 0) + self.UpVector)
		* CFrame.lookAt(Vector3.new(), Vector3.new(0, 1, 0)):inverse()
	part.Parent = parent

	local attach = Instance.new("Attachment")
	attach.Parent = part
	attach.CFrame = CFrame.new()

	local partEmit1 = script.ExplosionBrightspot:Clone()
	local partEmit2 = script.GlareEmitter:Clone()
	local partEmit3 = script.PlasmaEmitter:Clone()

	local size = math.clamp(self.Size, 0, 1)

	partEmit2.Size = NumberSequence.new(30 * size)
	partEmit3.Size = NumberSequence.new(18 * size)
	partEmit3.Speed = NumberRange.new(100 * size)

	partEmit1.Parent = attach
	partEmit2.Parent = attach
	partEmit3.Parent = attach

	local color = self.Color

	if typeof(color) == "Color3" then
		partEmit2.Color, partEmit3.Color = ColorSequence.new(color), ColorSequence.new(color)
		local cH, cS, cV = Color3.toHSV(color)
		partEmit1.Color = ColorSequence.new(Color3.fromHSV(cH, 0.5, cV))
	else --ColorSequence
		partEmit2.Color, partEmit3.Color = color, color
		local keypoints = color.Keypoints
		for i = 1, #keypoints do
			local cH, cS, cV = Color3.toHSV(keypoints[i].Value)
			keypoints[i] = ColorSequenceKeypoint.new(keypoints[i].Time, Color3.fromHSV(cH, 0.5, cV))
		end
		partEmit1.Color = ColorSequence.new(keypoints)
	end

	partEmit1.Enabled, partEmit2.Enabled, partEmit3.Enabled = false, false, false

	local bolts = {}

	for i = 1, self.NumBolts do
		local A1, A2 = {}, {}

		A1.WorldPosition, A1.WorldAxis =
			attach.WorldPosition, RandomVectorOffsetBetween(self.UpVector, math.rad(65), math.rad(80))
		A2.WorldPosition, A2.WorldAxis =
			attach.WorldPosition + A1.WorldAxis * rng_v:NextNumber(20, 40) * 1.4 * size,
			RandomVectorOffsetBetween(-self.UpVector, math.rad(70), math.rad(110))
		--local curve0, curve1 = rng_v:NextNumber(0, 10)*size, rng_v:NextNumber(0, 10)*size
		local NewBolt = LightningBolt.new(A1, A2, 10)
		NewBolt.AnimationSpeed = 0
		NewBolt.Thickness = 1 --*size
		NewBolt.Color = self.BoltColor
		NewBolt.PulseLength = 0.8
		NewBolt.ColorOffsetSpeed = 20
		NewBolt.Frequency = 2
		NewBolt.MinRadius, NewBolt.MaxRadius = 0, 4 * size
		NewBolt.FadeLength = 0.4
		NewBolt.PulseSpeed = 5
		NewBolt.MinThicknessMultiplier, NewBolt.MaxThicknessMultiplier = 0.7, 1

		local NewSparks = LightningSparks.new(NewBolt, 5)
		NewSparks.MinDistance, NewSparks.MaxDistance = 7.5, 10

		NewBolt.Velocity = (A2.WorldPosition - A1.WorldPosition).Unit * 0.1 * size
		--NewBolt.v0, NewBolt.v1 = rng_v:NextNumber(0, 5)*size, rng_v:NextNumber(0, 5)*size

		bolts[#bolts + 1] = NewBolt
	end

	self.Bolts = bolts
	self.Attachment = attach
	self.Part = part
	self.StartT = clock()
	self.RefIndex = #ActiveExplosions + 1

	ActiveExplosions[self.RefIndex] = self

	return self
end

function LightningExplosion:Destroy()
	ActiveExplosions[self.RefIndex] = nil
	self.Part:Destroy()

	for i = 1, #self.Bolts do
		self.Bolts[i] = nil
	end

	self = nil
end

game:GetService("RunService").Heartbeat:Connect(function()
	for _, ThisExplosion in pairs(ActiveExplosions) do
		local timePassed = clock() - ThisExplosion.StartT
		local attach = ThisExplosion.Attachment

		if timePassed < 0.7 then
			if timePassed > 0.2 then
				attach.ExplosionBrightspot.Enabled, attach.GlareEmitter.Enabled, attach.PlasmaEmitter.Enabled =
					false, false, false
			end

			for i = 1, #ThisExplosion.Bolts do
				local currBolt = ThisExplosion.Bolts[i]
				currBolt.Attachment1.WorldPosition = currBolt.Attachment1.WorldPosition + currBolt.Velocity
				--currBolt.CurveSize0, currBolt.CurveSize1 = currBolt.CurveSize0 + currBolt.v0, currBolt.CurveSize1 + currBolt.v1
			end
		else
			ThisExplosion:Destroy()
		end
	end
end)

return LightningExplosion
