Passing updated variable from server to client sided modulescript

I want the wind speed/direction to be updated in my server script (which is being run correctly in a coroutine wrap, see below) to also update the wind speed/direction in this script called RainAPI (largely not scripted by me). I am using methods to do this. There’s also RainGroupsPerSecond being updated as well by a local script (client-side), however, that is working as intended unlike my wind updating. I want help in getting the wind part of my server script:

RainAPI:SetWindSpeed(xwind.X, zwind.Z) 

to pass the same values and update it as frequently as possible to the RainAPI:

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

to make the wind effect happen just like the RainGroupsPerSecond.

Here is the full RainAPI module script (client-side, mostly not my written work):

local RainFallSpeed = 150 --Studs the rain falls per second
local RainGroupsPerSecond = 200 --Amount of rain drops per second
local RainRadius = 200 --Radius from the camera in studs where rain drops will spawn
local StartY = 100 --Start height of the rain
local DefaultEndY = -10 --Default end height of the rain. Can be overriden for certain zones
local WindSpeedX = 0 --Wind speed in studs on X axis
local WindSpeedZ = 0 --Wind speed in studs on Z axis



local TimePeriod = 30 -- Time period (in seconds) for wind and rain variation 

--APPEARANCE
local RainThickness = 0.1 --Thickness of the rain drops in studs
local RainLength = 4 --Length of the rain drop in studs
local RainTransparency = 0.3 --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, FallSpeed, DropSize)
	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.Size = NewDrop.Size * DropSize -- Adjusting the size
	NewDrop.CFrame = StartCF
	NewDrop.Parent = RainParent

	local FallTime = (StartY - EndY)/FallSpeed -- Adjusting the speed
	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

	local DropSpeed = random(100, 400) -- Randomizing speed
	local DropSize = random(50, 1000)/100 -- Randomizing size (ranges from 0.8 to 1.2)
	CreateRainDrop(X - WindOffsetX,StartY,Z - WindOffsetZ,X + WindOffsetX,EndY,Z + WindOffsetZ,CFrameAngles(0,random(),0), DropSpeed, DropSize)
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

Here is the relevant part of my ServerScript called CloudScript (not working):

-- this coroutine runs inefinetely
coroutine.wrap(function()
	while true do
		for i=1,gustIntervals do
			local f = math.sin(math.pi * dgf * i)
			workspace.GlobalWind = baseWind + f * gust
			xwind = baseWind + f * gust
			zwind = baseWind + f * gust
			RainAPI:SetWindSpeed(xwind.X, zwind.Z) -- Not Working
			print(xwind.X .. " " .. zwind.Z)
			wait(dg)
		end
		workspace.GlobalWind = baseWind 
		xwind = baseWind
		zwind = baseWind
		RainAPI:SetWindSpeed(xwind.X, zwind.Z) -- Not Working
		wait(math.random()*gustCycleDelay)
		gustCycleDelay = math.random(4, 10) 
		gust = Vector3.new(math.random(0, 50) - 25, 0, -math.random(0, 40))
		gustCycleDuration = math.random(3, 10)
		dg = gustCycleDuration / gustIntervals
		dgf = dg / gustCycleDuration
	end
end)()

Here is the LocalScript part of the RainGroupsPerSecond (this works):

RunService.RenderStepped:Connect(function()
	local RayOrigin = HumanoidRootPart.Position
	local RayDirection = Vector3.new(0, 1, 0)
	local MaxDistance = 2000 
	local totalVvv, cloudCount = RecursiveRaycast(RayOrigin, RayDirection, 0, 0, MaxDistance)
	--print(totalVvv .. " " .. cloudCount)
	if cloudCount > 0 then
		if rainebounce == true then
			RainAPI:StartRain()
			rainebounce = false
		end
		local rainDensity = math.floor((totalVvv)^(3/4))*20
		RainAPI:SetRainGroupsPerSecond(rainDensity) -- this works!
	else 
		if rainebounce == false then
			print("stoprain")
			RainAPI:StopRain()
			rainebounce = true
		end
	end
end)

Any help to make it work would be appreciated!

Figured it out, had to pass that as a RemoteEvent, as methods don’t automatically work across the client/server wall

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.