local a=.1 local Q=5 local d=.8 local B=4 local c=10 local i=20 local G=Instance.new("\070\111\108\100\101\114")G.Name="\082\097\105\110"G.Parent=game.Workspace.CurrentCamera local y=Instance.new("\080\097\114\116")y.Transparency=1 y.Size=Vector3.new(.2,.2,.2)y.Anchored=true y.CanCollide=false y.TopSurface="\083\109\111\111\116\104"y.BottomSurface="\083\109\111\111\116\104"local function r()local B,G=math.random(-c,c),math.random(-c,c)local r=math.random(0,i)local W=Instance.new("\065\116\116\097\099\104\109\101\110\116")W.Position=Vector3.new(B-a/2,r,G)W.Parent=y local z=Instance.new("\065\116\116\097\099\104\109\101\110\116")z.Position=Vector3.new(B+a/2,r,G)z.Parent=y local h=Instance.new("\084\114\097\105\108")h.Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,d,0),NumberSequenceKeypoint.new(1,1)})h.Attachment0=W h.Attachment1=z h.Lifetime=Q/RainFallSpeed h.Parent=y end for a=1,B,1 do r()end local W=game.Workspace.CurrentCamera local z=(game:GetService("\082\117\110\083\101\114\118\105\099\101")).RenderStepped local h=RainRadius/2 local L=y.Clone local J,H=CFrame.new,CFrame.Angles local b=math.random local E=z.Connect local e={}local w={}local f=0 local q local function K(a,Q,d,B,c,i,r)local W,h=J(a,Q,d)*r,J(B,c,i)*r local H=W.lerp local function b(a)return H(W,h,a)end local e=L(y)e.CFrame=W e.Parent=G local w=(Q-c)/RainFallSpeed local f=tick()local q q=E(z,function()local a=(tick()-f)/w if a>1 then e:Destroy()q:disconnect()else e.CFrame=b(a)end end)end local function g(a,Q)local d,B=a+b(-h,h),Q+b(-h,h)local c,i=StartY,DefaultEndY for a=1,#w,1 do local Q=w[a]if d>Q[1]and(B>Q[2]and(d<Q[3]and B<Q[4]))then i=Q[5]break end end local G=(c-i)/RainFallSpeed local y,r=(G*WindSpeedX)/2,(G*WindSpeedZ)/2 K(d-y,c,B-r,d+y,i,B+r,H(0,b(),0))end local function V()if q then q:Disconnect()end end local function o()V()q=E(z,function(a)local Q=W.CFrame.p local d,B=Q.X,Q.Z for a=1,RainGroupsPerSecond*a,1 do g(d,B)end end)end function e.AddOverrideRegion(G,a,Q,d,B,i)f=f+1 local y=f table.insert(w,{a-c;Q-c;d+c;B+c,i;y})return y end function e.RemoveOverrideRegion(Q,a)for a,Q in pairs(w)do if Q[6]==a then table.remove(w,a)end end end function e.StartRain(a)o()end function e.StopRain(a)V()end function e.SetWindSpeed(d,a,Q)WindSpeedX=a WindSpeedZ=Q end function e.GetWindSpeed(a)return WindSpeedX,WindSpeedZ end function e.SetRainGroupsPerSecond(Q,a)RainGroupsPerSecond=a end function e.GetRainGroupsPerSecond(a)return RainGroupsPerSecond end return e
--APPEARANCE
local RainThickness = 0.1 --Thickness of the rain drops in studs
local RainLength = 5 --Length of the rain drop in studs
local RainTransparency = 0.8 --Transparency of the rain
local TrailPerPart = 4 --Amount of trails adorned to one part
local TrailPartRadius = 10 --Max radius from the part a trail can be adorned
local TrailYOffset = 20 --Max Y offset a trail can have

local RainParent = Instance.new("Folder")
RainParent.Name = "Rain"
RainParent.Parent = game.Workspace.CurrentCamera

local RainPart = Instance.new("Part")
RainPart.Transparency = 1
RainPart.Size = Vector3.new(0.2, 0.2, 0.2)
RainPart.Anchored = true
RainPart.CanCollide = false
RainPart.TopSurface = "Smooth"
RainPart.BottomSurface = "Smooth"

local function AdornRandomTrailToPart()
	local RandomCenterX, RandomCenterZ =
		math.random(-TrailPartRadius, TrailPartRadius), math.random(-TrailPartRadius, TrailPartRadius)
	local YOffset = math.random(0, TrailYOffset)
	local Attahcment1 = Instance.new("Attachment")
	Attahcment1.Position = Vector3.new(RandomCenterX - RainThickness / 2, YOffset, RandomCenterZ)
	Attahcment1.Parent = RainPart

	local Attahcment2 = Instance.new("Attachment")
	Attahcment2.Position = Vector3.new(RandomCenterX + RainThickness / 2, YOffset, RandomCenterZ)
	Attahcment2.Parent = RainPart

	local Trail = Instance.new("Trail")
	Trail.Transparency =
		NumberSequence.new({ NumberSequenceKeypoint.new(0, RainTransparency, 0), NumberSequenceKeypoint.new(1, 1) })
	Trail.Attachment0 = Attahcment1
	Trail.Attachment1 = Attahcment2
	Trail.Lifetime = RainLength / RainFallSpeed
	Trail.Parent = RainPart
end

for _ = 1, TrailPerPart do
	AdornRandomTrailToPart()
end

local Camera = game.Workspace.CurrentCamera
local RenderStepped = game:GetService("RunService").RenderStepped

local RainRadiusDiv2 = RainRadius / 2
local RainPartClone = RainPart.Clone
local CFramenew, CFrameAngles = CFrame.new, CFrame.Angles
local random = math.random
local RenderSteppedConnect = RenderStepped.Connect

local RainAPI = {}
local OverridenRegions = {}
local CurrentOverrideId = 0
local CurrentCreateEvent

local function CreateRainDrop(StartX, StartY, StartZ, EndX, EndY, EndZ, Rotation)
	local StartCF, EndCF = CFramenew(StartX, StartY, StartZ) * Rotation, CFramenew(EndX, EndY, EndZ) * Rotation
	local LerpFunction = StartCF.lerp

	local function GetCFrame(Alpha)
		return LerpFunction(StartCF, EndCF, Alpha)
	end

	local NewDrop = RainPartClone(RainPart)
	NewDrop.CFrame = StartCF
	NewDrop.Parent = RainParent

	local FallTime = (StartY - EndY) / RainFallSpeed
	local StartTime = tick()
	local RenderSteppedEvent
	RenderSteppedEvent = RenderSteppedConnect(RenderStepped, function()
		local Alpha = (tick() - StartTime) / FallTime
		if Alpha > 1 then
			NewDrop:Destroy()
			RenderSteppedEvent:disconnect()
		else
			NewDrop.CFrame = GetCFrame(Alpha)
		end
	end)
end

local function SpawnRainDrop(CenterX, CenterZ)
	local X, Z = CenterX + random(-RainRadiusDiv2, RainRadiusDiv2), CenterZ + random(-RainRadiusDiv2, RainRadiusDiv2)
	local StartY, EndY = StartY, DefaultEndY

	for i = 1, #OverridenRegions do
		local RegionData = OverridenRegions[i]
		if X > RegionData[1] and Z > RegionData[2] and X < RegionData[3] and Z < RegionData[4] then
			EndY = RegionData[5]
			break
		end
	end

	local FallTime = (StartY - EndY) / RainFallSpeed
	local WindOffsetX, WindOffsetZ = (FallTime * WindSpeedX) / 2, (FallTime * WindSpeedZ) / 2
	CreateRainDrop(
		X - WindOffsetX,
		StartY,
		Z - WindOffsetZ,
		X + WindOffsetX,
		EndY,
		Z + WindOffsetZ,
		CFrameAngles(0, random(), 0)
	)
end

local function StopRain()
	if CurrentCreateEvent then
		CurrentCreateEvent:Disconnect()
	end
end

local function StartRain()
	StopRain()
	CurrentCreateEvent = RenderSteppedConnect(RenderStepped, function(Delta)
		local CameraPosition = Camera.CFrame.p
		local X, Z = CameraPosition.X, CameraPosition.Z
		for _ = 1, RainGroupsPerSecond * Delta do
			SpawnRainDrop(X, Z)
		end
	end)
end

function RainAPI:AddOverrideRegion(X1, Z1, X2, Z2, OverrideY)
	CurrentOverrideId = CurrentOverrideId + 1
	local Id = CurrentOverrideId

	table.insert(
		OverridenRegions,
		{ X1 - TrailPartRadius, Z1 - TrailPartRadius, X2 + TrailPartRadius, Z2 + TrailPartRadius, OverrideY, Id }
	)
	return Id
end

function RainAPI:RemoveOverrideRegion(Id)
	for i, RegionData in pairs(OverridenRegions) do
		if RegionData[6] == i then
			table.remove(OverridenRegions, i)
		end
	end
end

function RainAPI:StartRain()
	StartRain()
end

function RainAPI:StopRain()
	StopRain()
end

function RainAPI:SetWindSpeed(X, Z)
	WindSpeedX = X
	WindSpeedZ = Z
end

function RainAPI:GetWindSpeed()
	return WindSpeedX, WindSpeedZ
end

function RainAPI:SetRainGroupsPerSecond(NewRainGroupsPerSecond)
	RainGroupsPerSecond = NewRainGroupsPerSecond
end

function RainAPI:GetRainGroupsPerSecond()
	return RainGroupsPerSecond
end

return RainAPI
