I’ve sort of recoded a free model script to fit my style, this model is a rain script.
The issue I’m getting is on line 149: attempt to perform arithmetic (mul) on Vector3 and table, and have no idea why.

This is the server script.
local rain = require(script.Rain)
rain:setColor(Color3.fromRGB(script.Color.Value.x, script.Color.Value.y, script.Color.Value.z))
rain:setTransparency(script.Transparency.Value)
rain:setSpeedRatio(script.SpeedRatio.Value)
rain:setIntensityRatio(script.IntensityRatio.Value)
rain:setLightInfluence(script.LightInfluence.Value)
rain:setLightEmission(script.LightEmission.Value)
rain:setVolume(script.Volume.Value)
rain:setDirection(script.Direction.Value)
rain:setStraightTexture(script.StraightTexture.Value)
rain:setTopDownTexture(script.TopDownTexture.Value)
rain:setSplashTexture(script.SplashTexture.Value)
rain:setSoundId(script.SoundId.Value)
local threshold = script.TransparencyThreshold.Value
if script.TransparencyConstraint.Value and script.CanCollideConstraint.Value then
rain:setCollisionMode(rain.CollisionMode.Function, function(p)
return p.Transparency <= threshold and p.CanCollide
end)
elseif script.TransparencyConstraint.Value then
rain:setCollisionMode(rain.CollisionMode.Function, function(p)
return p.Transparency <= threshold
end)
elseif script.CanCollideConstraint.Value then
rain:setCollisionMode(rain.CollisionMode.Function, function(p)
return p.CanCollide
end)
end
rain:Enable()
This is the module script that handles the main events.
local min_Size = Vector3.new(.1, .1, .1)
local rain_Default_Color = Color3.new(255, 255, 255)
local rain_Default_Transparency = 0
local rain_Default_Speedratio = 1
local rain_Default_Intensityratio = 1
local rain_Default_Lightemission = .05
local rain_Default_Lightinfluence = .9
local rain_Default_Direction = Vector3.new(0, -1, 0)
local rain_Transparency_T1 = .25
local rain_Transparency_T2 = .75
local rain_Scanheight = 1000
local rain_Emitter_Dim_Default = 40
local rain_Emitter_Dim_Maxforward = 100
local rain_Emitter_Up_Modifier = 20
local rain_Sound_Asset = "rbxassetid://1516791621"
local rain_Sound_Basevolume = .2
local rain_Sound_Fadein_Time = 10
local rain_Sound_Fadeout_Time = 10
local rain_Straight_Asset = "rbxassetid://1822883048"
local rain_Straight_Alpha_Low = .7
local rain_Straight_Size = NumberSequence.new(15)
local rain_Straight_Lifetime = NumberRange.new(.8)
local rain_Straight_Max_Rate = 750
local rain_Straight_Max_Speed = 75
local rain_Topdown_Asset = "rbxassetid://1822856633"
local rain_Topdown_Alpha_Low = .85
local rain_Topdown_Size = NumberSequence.new{
NumberSequenceKeypoint.new(0, 5.33, 2.75);
NumberSequenceKeypoint.new(1, 5.33, 2.75);
}
local rain_Topdown_Lifetime = NumberRange.new(.8)
local rain_Topdown_Rotation = NumberRange.new(0, 360)
local rain_Topdown_Max_Rate = 750
local rain_Topdown_Max_Speed = 75
local rain_Splash_Asset = "rbxassetid://1822856633"
local rain_Splash_Alpha_Low = .6
local rain_Splash_Size = NumberSequence.new{
NumberSequenceKeypoint.new(0, 0);
NumberSequenceKeypoint.new(.4, 3);
NumberSequenceKeypoint.new(1, 0);
}
local rain_Splash_Lifetime = NumberRange.new(.1, .15)
local rain_Splash_Rotation = NumberRange.new(0, 360)
local rain_Splash_Number = 20
local rain_Splash_Correction_Y = .5
local rain_Splash_Straight_Offset_Y = 50
local rain_Nosplash_Straight_Offset_Y_Min = 20
local rain_Nosplash_Straight_Offset_Y_Max = 100
local rain_Occluded_Minspeed = 70
local rain_Occluded_Maxspeed = 100
local rain_Occluded_Spread = Vector2.new(10, 10)
local rain_Occluded_Maxintensity = 2
local rain_Occludecheck_Offset_Y = 500
local rain_Occludecheck_Offset_XZ_Min = -100
local rain_Occludecheck_Offset_XZ_Max = 100
local rain_Occludecheck_Scan_Y = 550
local rain_Update_Period = 6
local rain_Volume_Scan_Radius = 50
local rain_Volume_Scan_Grid = {
Vector3.new(0.141421363, 0, 0.141421363);
Vector3.new(-0.141421363, 0, 0.141421363);
Vector3.new(-0.141421363, 0, -0.141421363);
Vector3.new(0.141421363, 0, -0.141421363);
Vector3.new(0.400000006, 0, 0);
Vector3.new(0.282842726, 0, 0.282842726);
Vector3.new(2.44929371e-17, 0, 0.400000006);
Vector3.new(-0.282842726, 0, 0.282842726);
Vector3.new(-0.400000006, 0, 4.89858741e-17);
Vector3.new(-0.282842726, 0, -0.282842726);
Vector3.new(-7.34788045e-17, 0, -0.400000006);
Vector3.new(0.282842726, 0, -0.282842726);
Vector3.new(0.600000024, 0, 0);
Vector3.new(0.485410213, 0, 0.352671146);
Vector3.new(0.185410202, 0, 0.570633948);
Vector3.new(-0.185410202, 0, 0.570633948);
Vector3.new(-0.485410213, 0, 0.352671146);
Vector3.new(-0.600000024, 0, 7.34788112e-17);
Vector3.new(-0.485410213, 0, -0.352671146);
Vector3.new(-0.185410202, 0, -0.570633948);
Vector3.new(0.185410202, 0, -0.570633948);
Vector3.new(0.485410213, 0, -0.352671146);
Vector3.new(0.772740662, 0, 0.207055241);
Vector3.new(0.565685451, 0, 0.565685451);
Vector3.new(0.207055241, 0, 0.772740662);
Vector3.new(-0.207055241, 0, 0.772740662);
Vector3.new(-0.565685451, 0, 0.565685451);
Vector3.new(-0.772740662, 0, 0.207055241);
Vector3.new(-0.772740662, 0, -0.207055241);
Vector3.new(-0.565685451, 0, -0.565685451);
Vector3.new(-0.207055241, 0, -0.772740662);
Vector3.new(0.207055241, 0, -0.772740662);
Vector3.new(0.565685451, 0, -0.565685451);
Vector3.new(0.772740662, 0, -0.207055241);
}
local collisionMode = {
None = 0;
Whitelist = 1;
Blacklist = 2;
Function = 3;
}
local players = game:GetService("Players")
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")
local globalModifier = Instance.new("NumberValue")
globalModifier.Value = 1
local connections = {}
local disabled = true
local rainDirection = rain_Default_Direction
local currentCeiling = nil
local collisionMode = collisionMode.None
local collisionList = nil
local collisionFunc = nil
local straightLowAlpha = 1
local topdownLowAlpha = 1
local intensityOccludedRain = 0
local numberSplashes = 0
local volumeTarget = 0
local v3 = Vector3.new
local numberSequenceKeypoint1 = NumberSequenceKeypoint.new(0, 1, 0)
local numberSequenceKeypoint2 = NumberSequenceKeypoint.new(1, 1, 0)
local volumeScanGrid = {}
for _, v in pairs(rain_Volume_Scan_Grid) do
table.insert(volumeScanGrid, v * rain_Volume_Scan_Grid)
end
table.sort(volumeScanGrid, function(a, b)
return a.magnitude < b.magnitude
end)
local soundGroup = Instance.new("SoundGroup")
soundGroup.Name = "__RainSoundGroup"
soundGroup.Volume = rain_Sound_Basevolume
soundGroup.Archivable = false
local sound = Instance.new("Sound")
sound.Name = "RainSound"
sound.Volume = volumeTarget
sound.SoundId = rain_Sound_Asset
sound.Looped = true
sound.SoundGroup = soundGroup
sound.Parent = soundGroup
sound.Archivable = false
local emitter do
emitter = Instance.new("Part")
emitter.Transparency = 1
emitter.Anchored = true
emitter.CanCollide = false
emitter.Locked = false
emitter.Archivable = false
emitter.TopSurface = Enum.SurfaceType.Smooth
emitter.BottomSurface = Enum.SurfaceType.Smooth
emitter.Name = "__RainEmitter"
emitter.Size = min_Size
emitter.Archivable = false
local straight = Instance.new("ParticleEmitter")
straight.Name = "RainStraight"
straight.LightEmission = rain_Default_Lightemission
straight.LightInfluence = rain_Default_Lightinfluence
straight.Size = rain_Straight_Size
straight.Texture = rain_Straight_Asset
straight.LockedToPart = false
straight.Enabled = false
straight.Lifetime = rain_Straight_Lifetime
straight.Rate = rain_Straight_Max_Rate
straight.Speed = NumberRange.new(rain_Straight_Max_Speed)
straight.EmissionDirection = Enum.NormalId.Bottom
straight.Parent = emitter
straight.Orientation = Enum.ParticleOrientation.FacingCameraWorldUp
local topdown = Instance.new("ParticleEmitter")
topdown.Name = "RainTopDown"
topdown.LightEmission = rain_Default_Lightemission
topdown.LightInfluence = rain_Default_Lightinfluence
topdown.Size = rain_Topdown_Size
topdown.Texture = rain_Topdown_Asset
topdown.LockedToPart = false
topdown.Enabled = false
topdown.Rotation = rain_Topdown_Rotation
topdown.Lifetime = rain_Topdown_Lifetime
topdown.Rate = rain_Topdown_Max_Rate
topdown.Speed = NumberRange.new(rain_Topdown_Max_Speed)
topdown.EmissionDirection = Enum.NormalId.Bottom
topdown.Parent = emitter
end
local splashAttachments, rainAttachments do
splashAttachments = {}
rainAttachments = {}
for i = 1, rain_Splash_Number do
local splashAttachment = Instance.new("Attachment")
splashAttachment.Name = "__RainSplashAttachment"
local splash = Instance.new("ParticleEmitter")
splash.LightEmission = rain_Default_Lightemission
splash.LightInfluence = rain_Default_Lightinfluence
splash.Size = rain_Splash_Size
splash.Texture = rain_Splash_Asset
splash.Rotation = rain_Splash_Rotation
splash.Lifetime = rain_Splash_Lifetime
splash.Transparency = NumberSequence.new{
numberSequenceKeypoint1;
NumberSequenceKeypoint.new(rain_Transparency_T1, rain_Splash_Alpha_Low, 0);
NumberSequenceKeypoint.new(rain_Transparency_T2, rain_Splash_Alpha_Low, 0);
numberSequenceKeypoint2;
}
splash.Enabled = false
splash.Rate = 0
splash.Speed = NumberRange.new(0)
splash.Name = "RainSplash"
splash.Parent = splashAttachment
splashAttachment.Archivable = false
table.insert(splashAttachments, splashAttachment)
local rainAttachment = Instance.new("Attachment")
rainAttachment.Name = "__RainOccludedAttachment"
local straightOccluded = emitter.RainStraight:Clone()
straightOccluded.Speed = NumberRange.new(rain_Occluded_Minspeed, rain_Occluded_Maxspeed)
straightOccluded.SpreadAngle = rain_Occluded_Spread
straightOccluded.LockedToPart = false
straightOccluded.Enabled = false
straightOccluded.Parent = rainAttachment
local topdownOccluded = emitter.RainTopDown:Clone()
topdownOccluded.Speed = NumberRange.new(rain_Occluded_Minspeed, rain_Occluded_Maxspeed)
topdownOccluded.SpreadAngle = rain_Occluded_Spread
topdownOccluded.LockedToPart = false
topdownOccluded.Enabled = false
topdownOccluded.Parent = rainAttachment
rainAttachment.Archivable = false
table.insert(rainAttachments, rainAttachment)
end
end
local ignoreEmitterList = {emitter}
local raycastFunctions = {
[collisionMode.None] = function(ray, ignoreCharacter)
return workspace:FindPartOnRayWithIgnoreList(ray, ignoreCharacter and {emitter, players.LocalPlayer and players.LocalPlayer.Character} or ignoreEmitterList)
end;
[collisionMode.Blacklist] = function(ray)
return workspace:FindPartOnRayWithIgnoreList(ray, collisionList)
end;
[collisionMode.Whitelist] = function(ray)
return workspace:FindPartOnRayWithWhitelist(ray, collisionList)
end;
[collisionMode.Function] = function(ray)
local destination = ray.Origin + ray.Direction
while ray.Direction.magnitude > .001 do
local part, pos, norm, mat = workspace:FindPartOnRayWithIgnoreList(ray, ignoreEmitterList)
if not part or collisionFunc(part) then
return part, pos, norm, mat
end
local start = pos + ray.Direction.Unit * 0.001
ray = Ray.new(start, destination - start)
end
end;
}
local raycast = raycastFunctions[collisionMode]
local function connectLoop()
local rand = Random.new()
local inside = true
local frame = rain_Update_Period
table.insert(connections, runService.RenderStepped:connect(function()
local part, position = raycast(Ray.new(workspace.CurrentCamera.CFrame.p, -rainDirection * rain_Scanheight), true)
if (not currentCeiling or workspace.CurrentCamera.CFrame.p.y <= currentCeiling) and not part then
if volumeTarget < 1 and not disabled then
volumeTarget = 1
tweenService:Create(sound, TweenInfo.new(.5), {Volume = 1}):Play()
end
frame = rain_Update_Period
local t = math.abs(workspace.CurrentCamera.CFrame.lookVector:Dot(rainDirection))
local center = workspace.CurrentCamera.CFrame.p
local right = workspace.CurrentCamera.CFrame.lookVector:Cross(-rainDirection)
right = right.magnitude > .001 and right.unit or -rainDirection
local forward = rainDirection:Cross(right).unit
emitter.Size = v3(
rain_Emitter_Dim_Default,
rain_Emitter_Dim_Default,
rain_Emitter_Dim_Default + (1 - t)*(rain_Emitter_Dim_Maxforward - rain_Emitter_Dim_Default))
emitter.CFrame = CFrame.new(
center.x, center.y, center.z,
right.x, -rainDirection.x, forward.x,
right.y, -rainDirection.y, forward.y,
right.z, -rainDirection.z, forward.z
)
+ (1 - t) * workspace.CurrentCamera.CFrame.lookVector * emitter.Size.Z/3
- t * rainDirection * rain_Emitter_Up_Modifier
emitter.RainStraight.Enabled = true
emitter.RainTopDown.Enabled = true
inside = false
else
emitter.RainStraight.Enabled = false
emitter.RainTopDown.Enabled = false
inside = true
end
end))
local signal = runService:IsRunning() and runService.Stepped or runService.RenderStepped
table.insert(connections, signal:connect(function()
frame = frame + 1
if frame >= rain_Update_Period then
local t = math.abs(workspace.CurrentCamera.CFrame.lookVector:Dot(rainDirection))
local straightSequence = NumberSequence.new{
numberSequenceKeypoint1;
NumberSequenceKeypoint.new(rain_Transparency_T1, (1 - t)*straightLowAlpha + t, 0);
NumberSequenceKeypoint.new(rain_Transparency_T2, (1 - t)*straightLowAlpha + t, 0);
numberSequenceKeypoint2;
}
local topdownSequence = NumberSequence.new{
numberSequenceKeypoint1;
NumberSequenceKeypoint.new(rain_Transparency_T1, t*topdownLowAlpha + (1 - t), 0);
NumberSequenceKeypoint.new(rain_Transparency_T2, t*topdownLowAlpha + (1 - t), 0);
numberSequenceKeypoint2;
}
local mapped = workspace.Camera.CFrame:inverse() * (workspace.Camera.CFrame.p - rainDirection)
local straightRotation = NumberRange.new(math.deg(math.atan2(-mapped.x, mapped.y)))
if inside then
for _,v in pairs(rainAttachments) do
v.RainStraight.Transparency = straightSequence
v.RainStraight.Rotation = straightRotation
v.RainTopDown.Transparency = topdownSequence
end
if not disabled then
local volume = 0
if (not currentCeiling or workspace.CurrentCamera.CFrame.p.y <= currentCeiling) then
local minDistance = rain_Volume_Scan_Radius
local rayDirection = -rainDirection * rain_Scanheight
for i = 1, #volumeScanGrid do
if not raycast(Ray.new(workspace.CurrentCamera.CFrame * volumeScanGrid[i], rayDirection), true) then
minDistance = volumeScanGrid[i].magnitude
break
end
end
volume = 1 - minDistance / rain_Volume_Scan_Radius
end
if math.abs(volume - volumeTarget) > .01 then
volumeTarget = volume
tweenService:Create(sound, TweenInfo.new(1), {Volume = volumeTarget}):Play()
end
end
else
emitter.RainStraight.Transparency = straightSequence
emitter.RainStraight.Rotation = straightRotation
emitter.RainTopDown.Transparency = topdownSequence
end
frame = 0
end
local center = workspace.CurrentCamera.CFrame.p
local right = workspace.CurrentCamera.CFrame.lookVector:Cross(-rainDirection)
right = right.magnitude > .001 and right.unit or -rainDirection
local forward = rainDirection:Cross(right).unit
local transform = CFrame.new(
center.x, center.y, center.z,
right.x, -rainDirection.x, forward.x,
right.y, -rainDirection.y, forward.y,
right.z, -rainDirection.z, forward.z
)
local rayDirection = rainDirection * rain_Occludecheck_Scan_Y
for i = 1, numSplashes do
local splashAttachment = splashAttachments[i]
local rainAttachment = rainAttachments[i]
local x = rand:NextNumber(rain_Occludecheck_Offset_XZ_Min, rain_Occludecheck_Offset_XZ_Max)
local z = rand:NextNumber(rain_Occludecheck_Offset_XZ_Min, rain_Occludecheck_Offset_XZ_Max)
local part, position, normal = raycast(Ray.new(transform * v3(x, rain_Occludecheck_Offset_Y, z), rayDirection))
if part then
splashAttachment.Position = position + normal * rain_Splash_Correction_Y
splashAttachment.RainSplash:Emit(1)
if inside then
local corrected = position - rainDirection * rain_Splash_Straight_Offset_Y
if currentCeiling and corrected.Y > currentCeiling and rainDirection.Y < 0 then
corrected = corrected + rainDirection * (currentCeiling - corrected.Y) / rainDirection.Y
end
rainAttachment.CFrame = transform - transform.p + corrected
rainAttachment.RainStraight:Emit(intensityOccludedRain)
rainAttachment.RainTopDown:Emit(intensityOccludedRain)
end
elseif inside then
local corrected = transform * v3(x, rand:NextNumber(rain_Nosplash_Straight_Offset_Y_Min, rain_Nosplash_Straight_Offset_Y_Max), z)
if currentCeiling and corrected.Y > currentCeiling and rainDirection.Y < 0 then
corrected = corrected + rainDirection * (currentCeiling - corrected.Y) / rainDirection.Y
end
rainAttachment.CFrame = transform - transform.p + corrected
rainAttachment.RainStraight:Emit(intensityOccludedRain)
rainAttachment.RainTopDown:Emit(intensityOccludedRain)
end
end
end))
end
local function disconnectLoop()
if #connections > 0 then
for _,v in pairs(connections) do
v:disconnect()
end
connections = {}
end
end
local function disableSound(tweenInfo)
volumeTarget = 0
local tween = tweenService:Create(sound, tweenInfo, {Volume = 0})
tween.Completed:connect(function(state)
if state == Enum.PlaybackState.Completed then
sound:Stop()
end
tween:Destroy()
end)
tween:Play()
end
local function disable()
disconnectLoop()
emitter.RainStraight.Enabled = false
emitter.RainTopDown.Enabled = false
emitter.Size = min_Size
if not disabled then
disableSound(TweenInfo.new(rain_Sound_Fadeout_Time))
end
end
local function makeProperty(valueObjectClass, defaultValue, setter)
local valueObject = Instance.new(valueObjectClass)
if defaultValue then
valueObject.Value = defaultValue
end
valueObject.Changed:connect(setter)
setter(valueObject.Value)
return valueObject
end
local Color = makeProperty("Color3Value", rain_Default_Color, function(value)
local value = ColorSequence.new(value)
emitter.RainStraight.Color = value
emitter.RainTopDown.Color = value
for _,v in pairs(splashAttachments) do
v.RainSplash.Color = value
end
for _,v in pairs(rainAttachments) do
v.RainStraight.Color = value
v.RainTopDown.Color = value
end
end)
local function updateTransparency(value)
local opacity = (1 - value) * (1 - globalModifier.Value)
local transparency = 1 - opacity
straightLowAlpha = rain_Straight_Alpha_Low * opacity + transparency
topdownLowAlpha = rain_Topdown_Alpha_Low * opacity + transparency
local splashSequence = NumberSequence.new {
numberSequenceKeypoint1;
NumberSequenceKeypoint.new(rain_Transparency_T1, opacity*rain_Splash_Alpha_Low + transparency, 0);
NumberSequenceKeypoint.new(rain_Transparency_T2, opacity*rain_Splash_Alpha_Low + transparency, 0);
numberSequenceKeypoint2;
}
for _,v in pairs(splashAttachments) do
v.RainSplash.Transparency = splashSequence
end
end
local Transparency = makeProperty("NumberValue", rain_Default_Transparency, updateTransparency)
globalModifier.Changed:connect(updateTransparency)
local SpeedRatio = makeProperty("NumberValue", rain_Default_Speedratio, function(value)
emitter.RainStraight.Speed = NumberRange.new(value * rain_Straight_Max_Speed)
emitter.RainTopDown.Speed = NumberRange.new(value * rain_Topdown_Max_Speed)
end)
local IntensityRatio = makeProperty("NumberValue", rain_Default_Intensityratio, function(value)
emitter.RainStraight.Rate = rain_Straight_Max_Rate * value
emitter.RainTopDown.Rate = rain_Topdown_Size * value
intensityOccludedRain = math.ceil(rain_Occluded_Maxintensity * value)
numSplashes = rain_Splash_Number * value
end)
local LightEmission = makeProperty("NumberValue", rain_Default_Lightemission, function(value)
emitter.RainStraight.LightEmission = value
emitter.RainTopDown.LightEmission = value
for _,v in pairs(rainAttachments) do
v.RainStraight.LightEmission = value
v.RainTopDown.LightEmission = value
end
for _,v in pairs(splashAttachments) do
v.RainSplash.LightEmission = value
end
end)
local LightInfluence = makeProperty("NumberValue", rain_Default_Lightinfluence, function(value)
emitter.RainStraight.LightInfluence = value
emitter.RainTopDown.LightInfluence = value
for _,v in pairs(rainAttachments) do
v.RainStraight.LightInfluence = value
v.RainTopDown.LightInfluence = value
end
for _,v in pairs(splashAttachments) do
v.RainSplash.LightInfluence = value
end
end)
local RainDirection = makeProperty("Vector3Value", rain_Default_Direction, function(value)
if value.magnitude > 0.001 then
rainDirection = value.unit
end
end)
local Rain = {}
Rain.CollisionMode = collisionMode
function Rain:Enable(tweenInfo)
if tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #1 to 'Enable' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
disconnectLoop()
emitter.RainStraight.Enabled = true
emitter.RainTopDown.Enabled = true
emitter.Parent = workspace.CurrentCamera
for i = 1, rain_Splash_Number do
splashAttachments[i].Parent = workspace.Terrain
rainAttachments[i].Parent = workspace.Terrain
end
if runService:IsRunning() then
soundGroup.Parent = game:GetService("SoundService")
end
connectLoop()
if tweenInfo then
tweenService:Create(globalModifier, tweenInfo, {Value = 0}):Play()
else
globalModifier.Value = 0
end
if not sound.Playing then
sound:Play()
sound.TimePosition = math.random()*sound.TimeLength
end
disabled = false
end
function Rain:Disable(tweenInfo)
if tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #1 to 'Disable' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
if tweenInfo then
local tween = tweenService:Create(globalModifier, tweenInfo, {Value = 1})
tween.Completed:connect(function(state)
if state == Enum.PlaybackState.Completed then
disable()
end
tween:Destroy()
end)
tween:Play()
disableSound(tweenInfo)
else
globalModifier.Value = 1
disable()
end
disabled = true
end
function Rain:setColor(value, tweenInfo)
if typeof(value) ~= "Color3" then
error("bad argument #1 to 'SetColor' (Color3 expected, got " .. typeof(value) .. ")", 2)
elseif tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #2 to 'SetColor' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
if tweenInfo then
tweenService:Create(Color, tweenInfo, {Value = value}):Play()
else
Color.Value = value
end
end
local function makeRatioSetter(methodName, valueObject)
return function(_, value, tweenInfo)
if typeof(value) ~= "number" then
error("bad argument #1 to '" .. methodName .. "' (number expected, got " .. typeof(value) .. ")", 2)
elseif tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #2 to '" .. methodName .. "' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
value = math.clamp(value, 0, 1)
if tweenInfo then
tweenService:Create(valueObject, tweenInfo, {Value = value}):Play()
else
valueObject.Value = value
end
end
end
Rain.setTransparency = makeRatioSetter("setTransparency", Transparency)
Rain.setSpeedRatio = makeRatioSetter("setSpeedRatio", SpeedRatio)
Rain.setIntensityRatio = makeRatioSetter("setIntensityRatio", IntensityRatio)
Rain.setLightEmission = makeRatioSetter("setLightEmission", LightEmission)
Rain.setLightInfluence = makeRatioSetter("setLightInfluence", LightInfluence)
function Rain:setVolume(volume, tweenInfo)
if typeof(volume) ~= "number" then
error("bad argument #1 to 'SetVolume' (number expected, got " .. typeof(volume) .. ")", 2)
elseif tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #2 to 'SetVolume' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
if tweenInfo then
tweenService:Create(soundGroup, tweenInfo, {Volume = volume}):Play()
else
soundGroup.Volume = volume
end
end
function Rain:setDirection(direction, tweenInfo)
if typeof(direction) ~= "Vector3" then
error("bad argument #1 to 'SetDirection' (Vector3 expected, got " .. typeof(direction) .. ")", 2)
elseif tweenInfo ~= nil and typeof(tweenInfo) ~= "TweenInfo" then
error("bad argument #2 to 'SetDirection' (TweenInfo expected, got " .. typeof(tweenInfo) .. ")", 2)
end
if not (direction.unit.magnitude > 0) then -- intentional statement formatting since NaN comparison
warn("Attempt to set rain direction to a zero-length vector, falling back on default direction = (" .. tostring(rain_Default_Direction) .. ")")
direction = rain_Default_Direction
end
if tweenInfo then
tweenService:Create(RainDirection, tweenInfo, {Value = direction}):Play()
else
RainDirection.Value = direction
end
end
function Rain:setCeiling(ceiling)
if ceiling ~= nil and typeof(ceiling) ~= "number" then
error("bad argument #1 to 'SetCeiling' (number expected, got " .. typeof(ceiling) .. ")", 2)
end
currentCeiling = ceiling
end
function Rain:setStraightTexture(asset)
if typeof(asset) ~= "string" then
error("bad argument #1 to 'SetStraightTexture' (string expected, got " .. typeof(asset) .. ")", 2)
end
emitter.RainStraight.Texture = asset
for _,v in pairs(rainAttachments) do
v.RainStraight.Texture = asset
end
end
function Rain:setTopDownTexture(asset)
if typeof(asset) ~= "string" then
error("bad argument #1 to 'SetStraightTexture' (string expected, got " .. typeof(asset) .. ")", 2)
end
emitter.RainTopDown.Texture = asset
for _,v in pairs(rainAttachments) do
v.RainTopDown.Texture = asset
end
end
function Rain:setSplashTexture(asset)
if typeof(asset) ~= "string" then
error("bad argument #1 to 'SetStraightTexture' (string expected, got " .. typeof(asset) .. ")", 2)
end
for _,v in pairs(splashAttachments) do
v.RainSplash.Texture = asset
end
end
function Rain:setSoundId(asset)
if typeof(asset) ~= "string" then
error("bad argument #1 to 'SetSoundId' (string expected, got " .. typeof(asset) .. ")", 2)
end
sound.SoundId = asset
end
function Rain:setCollisionMode(mode, param)
if mode == collisionMode.None then
collisionList = nil
collisionFunc = nil
elseif mode == collisionMode.Blacklist then
if typeof(param) == "Instance" then
collisionList = {param, emitter}
elseif typeof(param) == "table" then
for i = 1, #param do
if typeof(param[i]) ~= "Instance" then
error("bad argument #2 to 'SetCollisionMode' (blacklist contained a " .. typeof(param[i]) .. " on index " .. tostring(i) .. " which is not an Instance)", 2)
end
end
collisionList = {emitter}
for i = 1, #param do
table.insert(collisionList, param[i])
end
else
error("bad argument #2 to 'SetCollisionMode (Instance or array of Instance expected, got " .. typeof(param) .. ")'", 2)
end
collisionFunc = nil
elseif mode == collisionMode.Whitelist then
if typeof(param) == "Instance" then
collisionList = {param}
elseif typeof(param) == "table" then
for i = 1, #param do
if typeof(param[i]) ~= "Instance" then
error("bad argument #2 to 'SetCollisionMode' (whitelist contained a " .. typeof(param[i]) .. " on index " .. tostring(i) .. " which is not an Instance)", 2)
end
end
collisionList = {}
for i = 1, #param do
table.insert(collisionList, param[i])
end
else
error("bad argument #2 to 'SetCollisionMode (Instance or array of Instance expected, got " .. typeof(param) .. ")'", 2)
end
collisionFunc = nil
elseif mode == collisionMode.Function then
if typeof(param) ~= "function" then
error("bad argument #2 to 'SetCollisionMode' (function expected, got " .. typeof(param) .. ")", 2)
end
collisionList = nil
collisionFunc = param
else
error("bad argument #1 to 'SetCollisionMode (Rain.CollisionMode expected, got " .. typeof(param) .. ")'", 2)
end
collisionMode = mode
raycast = raycastFunctions[mode]
end
return Rain
Also some extra values ect needed for this to work.

This is maintained within the server script.
I’ve looked on other devforums for a hint at what might be the problem but can’t get it, possibly missing something out.
Any help is appreciated, thank you!