Why is the original working while it's now failing after splitting it into a module script?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Make the sign, weather, and day/night update correctly again.

  2. What is the issue? My original script worked but when I split into a module and a main, it now is failing to do the stuff from 1 above.

  3. What solutions have you tried so far? I’'ve tried asking Gemini (and since I asked her to help me set up a moudle script, something I’d never done before, she likely introduced the error.) I believe it’s happening in the heartbeat and apply weather effects, but can’t seem to figure out what’s causing it.

Original Working script:

=================================================================================================

-- || WEATHER & REAL-TIME SYNC SCRIPT (FINAL, STABLE VERSION) ||

-- =================================================================================================



-- Services

local Lighting = game:GetService("Lighting")

local RunService = game:GetService("RunService")

local HttpService = game:GetService("HttpService")

local Http = game:GetService("HttpService") 

local Players = game:GetService("Players")

local InsertService = game:GetService("InsertService")



-- Configuration Variables

local LATITUDE = 41.36      -- Oglesby, IL

local LONGITUDE = -89.04    -- Oglesby, IL

local TIMEZONE = "America/Chicago"

local API_ENDPOINT = "https://api.open-meteo.com/v1/forecast"



-- Weather Check Interval (How often to fetch new data, e.g., every 5 minutes)

local WEATHER_CHECK_INTERVAL = 5 * 60 



-- Umbrella Configuration

local UMBRELLA_ASSET_ID = 13710882876 

local UMBRELLA_HANDLE = nil -- Cache the Handle once it's loaded



-- Asset Definitions (Place these objects in Workspace/WeatherSource)

local WEATHER_SOURCE = workspace:WaitForChild("WeatherSource", 10)

local RAIN_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainEmitter")

local SNOW_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("SnowEmitter")

local HAIL_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("HailEmitter")



local RAIN_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainSound")

local WIND_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("WindSound")

local THUNDER_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("ThunderSound")



local Terrain = game:GetService("Terrain")

local CLOUDS = workspace.Terrain:FindFirstChild("Clouds") -- Don't wait, just check



-- || FIXED SIGN CONFIGURATION FOR NEW STRUCTURE ||

-- ====================================================================



-- 1. Get the main container object (Model or Folder)

local WEATHER_SIGN_CONTAINER = workspace:FindFirstChild("WeatherSign") 



-- 2. The SurfaceGui is now a DIRECT CHILD of the container, so we find it here.

local SIGN_GUI = WEATHER_SIGN_CONTAINER and WEATHER_SIGN_CONTAINER:FindFirstChildOfClass("SurfaceGui")



-- 3. Get the TextLabel object (which is a direct child of the SurfaceGui)

local WEATHER_TEXT_LABEL = SIGN_GUI and SIGN_GUI:FindFirstChildOfClass("TextLabel")



-- ====================================================================



-- Script State Trackers

local lastAppliedWeather = ""

local currentWeather = ""



-- =================================================================================================

-- || API INTERFACE & CORE WEATHER LOGIC ||

-- =================================================================================================



local function fetchWeatherCondition()

local url = string.format(

"%s?latitude=%f&longitude=%f&timezone=%s&current=weather_code",

API_ENDPOINT, LATITUDE, LONGITUDE, TIMEZONE

)



local rawData = nil

local success, result = pcall(function()

rawData = Http:GetAsync(url)

return HttpService:JSONDecode(rawData)

end)



if not success or not rawData or not result or not result.current then

warn("API ERROR: Failed to fetch weather data. Defaulting to No Input.")

return "No Input" 

end



local weatherCode = result.current.weather_code



local function getWeatherCondition(code)

-- ** UPDATED: Expanded logic based on WMO codes **



-- WMO Code 0: Clear Sky

if code == 0 then return "Clear"

elseif code == 3 then 

return "Overcast"

elseif code == 2 then 

return "Mostly Cloudy"

elseif code == 1 then 

return "Partly Cloudy"

elseif code >= 45 and code <= 48 then return "Fog"

elseif code >= 50 and code <= 69 then return "Rain"

elseif code >= 70 and code <= 89 then return "Snow"

elseif code >= 90 then return "Thunderstorm"

else

return "Unknown"

end

end



return getWeatherCondition(weatherCode)

end



-- ** NEW: Function to update the sign's text **

local function updateWeatherSign(condition)

local textToShow = condition or "No Input"

if WEATHER_TEXT_LABEL then

WEATHER_TEXT_LABEL.Text = textToShow

warn("SIGN UPDATED: Showing '" .. textToShow .. "'")

else

warn("WARNING: Weather Text Label not found or configured incorrectly.")

end

end



local function applyWeatherEffects(weatherCondition)

-- Always update sign, even if weather didn't change

updateWeatherSign(weatherCondition)



-- Always update clouds, even if weather didn't change

if CLOUDS == nil then

warn("WARNING: Clouds object not found in Terrain!")

else

if weatherCondition == "Partly Cloudy" then

CLOUDS.Enabled = true

CLOUDS.Density = 0.2

CLOUDS.Cover = 0.4

CLOUDS.Color = Color3.fromRGB(220, 220, 220)

--Lighting.OutdoorAmbient = Color3.fromRGB(150, 150, 160)

--Lighting.GlobalShadows = true

elseif weatherCondition == "Mostly Cloudy" then

CLOUDS.Enabled = true

CLOUDS.Density = 0.5

CLOUDS.Cover = 0.7

CLOUDS.Color = Color3.fromRGB(180, 180, 190)

-- Lighting.OutdoorAmbient = Color3.fromRGB(120, 120, 130)

-- Lighting.GlobalShadows = false

elseif weatherCondition == "Overcast" then

CLOUDS.Enabled = true

CLOUDS.Density = 1.0

CLOUDS.Cover = 1.0

local currentTime = Lighting.ClockTime

local isNight = (currentTime >= 18.0) or (currentTime < 6.0)

if isNight then

CLOUDS.Color = Color3.fromRGB(50, 50, 60)

--Lighting.OutdoorAmbient = Color3.fromRGB(30, 30, 40)

--Lighting.Ambient = Color3.fromRGB(20, 20, 25)

--Lighting.ExposureCompensation = -2.0

--Lighting.Brightness = 0.1

else

CLOUDS.Color = Color3.fromRGB(150, 150, 160)

--Lighting.OutdoorAmbient = Color3.fromRGB(90, 90, 100)

--Lighting.Ambient = Color3.fromRGB(120, 120, 120)

--Lighting.ExposureCompensation = 0.0

end

Lighting.GlobalShadows = false

if Lighting:FindFirstChild("Sky") then

Lighting.Sky.CelestialBodiesShown = false

end

else

-- Not cloudy, reset clouds

CLOUDS.Enabled = false

-- Lighting.OutdoorAmbient = Color3.fromRGB(192, 192, 192)

-- Lighting.Ambient = Color3.fromRGB(128, 128, 128)

Lighting.GlobalShadows = true

if Lighting:FindFirstChild("Sky") then

Lighting.Sky.CelestialBodiesShown = true

end

end

end



-- Only reset emitters/sounds and log when weather changes

if weatherCondition ~= lastAppliedWeather and weatherCondition ~= "No Input" then

lastAppliedWeather = weatherCondition

warn("WEATHER CHANGE: New Condition: " .. weatherCondition)

if RAIN_EMITTER then RAIN_EMITTER.Enabled = false end

if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end

if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end

if RAIN_SOUND then RAIN_SOUND.Playing = false end

if WIND_SOUND then WIND_SOUND.Playing = false end

if THUNDER_SOUND then THUNDER_SOUND.Playing = false end

end

end



-- =================================================================================================

-- || MAIN CONTROL LOGIC (Instant Execution) ||

-- =================================================================================================



local function updateLightingTime()

local currentTimeUnix = os.time()

local hour = tonumber(os.date("%H", currentTimeUnix))

local minute = tonumber(os.date("%M", currentTimeUnix))

local second = tonumber(os.date("%S", currentTimeUnix))

Lighting.ClockTime = hour + (minute / 60) + (second / 3600)

end



-- 1. Initial Data Fetch (Run once immediately)

currentWeather = fetchWeatherCondition()

applyWeatherEffects(currentWeather)

warn("WEATHER INITIALIZED: Condition: " .. currentWeather)



-- 2. Polling loop for Time Sync and Weather Check

local lastCheckTime = 0



RunService.Heartbeat:Connect(function()

updateLightingTime() 



local currentTime = os.time()

if currentTime - lastCheckTime >= WEATHER_CHECK_INTERVAL then

local newCondition = fetchWeatherCondition()

if newCondition then

currentWeather = newCondition

end

lastCheckTime = currentTime

warn("WEATHER CHECK: Refreshed data.")

end



applyWeatherEffects(currentWeather)

end) 



print("Weather and Real-Time Sync script is now running.")

WeatherService (new one as a modulescript)

-- =================================================================================================
-- || WEATHER & REAL-TIME SYNC MODULESCRIPT (Complete) ||
-- =================================================================================================

-- 1. Define the module table that will be returned.
local WeatherService = {}

-- Services
local Lighting = game:GetService("Lighting")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local InsertService = game:GetService("InsertService")
local Terrain = game:GetService("Terrain")

-- ====================================================================
-- || CONFIGURATION (Publicly accessible) ||
-- ====================================================================

WeatherService.LATITUDE = 41.36   -- Oglesby, IL
WeatherService.LONGITUDE = -89.04 -- Oglesby, IL
WeatherService.TIMEZONE = "America/Chicago"

local API_ENDPOINT = "https://api.open-meteo.com/v1/forecast"
local WEATHER_CHECK_INTERVAL = 5 * 60 -- How often to fetch new data

-- Umbrella Configuration (Private)
local UMBRELLA_ASSET_ID = 13710882876
local UMBRELLA_HANDLE = nil

-- ====================================================================
-- || INITIALIZATION (Finding Assets) ||
-- ====================================================================

-- Note: Using WaitForChild ensures assets exist before module initializes
local WEATHER_SOURCE = workspace:WaitForChild("WeatherSource", 10)
local RAIN_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainEmitter")
local SNOW_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("SnowEmitter")
local HAIL_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("HailEmitter")

local RAIN_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainSound")
local WIND_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("WindSound")
local THUNDER_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("ThunderSound")

local CLOUDS = Terrain:FindFirstChild("Clouds")

local WEATHER_SIGN_CONTAINER = workspace:FindFirstChild("WeatherSign")
local SIGN_GUI = WEATHER_SIGN_CONTAINER and WEATHER_SIGN_CONTAINER:FindFirstChildOfClass("SurfaceGui")
local WEATHER_TEXT_LABEL = SIGN_GUI and SIGN_GUI:FindFirstChildOfClass("TextLabel")

-- Script State Trackers (Private)
local lastAppliedWeather = ""
WeatherSerivce.currentWeather = ""

-- =================================================================================================
-- || PUBLIC FUNCTION: Fetch Weather (Can be called externally) ||
-- =================================================================================================

function WeatherService.fetchWeatherCondition()
	-- 🟢 Inner Function (Helper: remains local/private)
	local function getWeatherCondition(code)
		-- WMO Code 0: Clear Sky
		if code == 0 then return "Clear"
		elseif code == 3 then return "Overcast"
		elseif code == 2 then return "Mostly Cloudy"
		elseif code == 1 then return "Partly Cloudy"
		elseif code >= 45 and code <= 48 then return "Fog"
		elseif code >= 50 and code <= 69 then return "Rain"
		elseif code >= 70 and code <= 89 then return "Snow"
		elseif code >= 90 then return "Thunderstorm"
		else
			return "Unknown"
		end
	end

	-- API fetching logic
	local url = string.format(
		"%s?latitude=%f&longitude=%f&timezone=%s&current=weather_code",
		API_ENDPOINT, WeatherService.LATITUDE, WeatherService.LONGITUDE, WeatherService.TIMEZONE
	)

	local rawData = nil
	local success, result = pcall(function()
		rawData = HttpService:GetAsync(url)
		return HttpService:JSONDecode(rawData)
	end)

	if not success or not rawData or not result or not result.current then
		warn("API ERROR: Failed to fetch weather data. Defaulting to No Input.")
		return "No Input"
	end

	local weatherCode = result.current.weather_code

	-- Returns the result of the local helper function
	return getWeatherCondition(weatherCode) 
end

-- =================================================================================================
-- || PRIVATE HELPER: Update Sign ||
-- =================================================================================================

local function updateWeatherSign(condition)
	local textToShow = condition or "No Input"
	if WEATHER_TEXT_LABEL then
		WEATHER_TEXT_LABEL.Text = textToShow
	else
		warn("WARNING: Weather Text Label not found or configured incorrectly.")
	end
end

-- =================================================================================================
-- || PUBLIC FUNCTION: Apply Effects (Can be called externally) ||
-- =================================================================================================

function WeatherService.applyWeatherEffects(weatherCondition)
	-- Update the module's private state tracker
	WeatherService.currentWeather = weatherCondition

	-- Always update sign
	updateWeatherSign(weatherCondition)

	-- Update clouds
	if CLOUDS == nil then
		warn("WARNING: Clouds object not found in Terrain!")
	else
		if weatherCondition == "Partly Cloudy" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 0.2
			CLOUDS.Cover = 0.4
			CLOUDS.Color = Color3.fromRGB(220, 220, 220)
		elseif weatherCondition == "Mostly Cloudy" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 0.5
			CLOUDS.Cover = 0.7
			CLOUDS.Color = Color3.fromRGB(180, 180, 190)
		elseif weatherCondition == "Overcast" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 1.0
			CLOUDS.Cover = 1.0
			local currentTime = Lighting.ClockTime
			local isNight = (currentTime >= 18.0) or (currentTime < 6.0)
			if isNight then
				CLOUDS.Color = Color3.fromRGB(50, 50, 60)
			else
				CLOUDS.Color = Color3.fromRGB(150, 150, 160)
			end
			Lighting.GlobalShadows = false
			if Lighting:FindFirstChild("Sky") then
				Lighting.Sky.CelestialBodiesShown = false
			end
		else
			-- Not cloudy, reset clouds
			CLOUDS.Enabled = false
			Lighting.GlobalShadows = true
			if Lighting:FindFirstChild("Sky") then
				Lighting.Sky.CelestialBodiesShown = true
			end
		end
	end

	-- Only reset emitters/sounds and log when weather changes
	if weatherCondition ~= lastAppliedWeather and weatherCondition ~= "No Input" then
		lastAppliedWeather = weatherCondition
		warn("WEATHER CHANGE: New Condition: " .. weatherCondition)

		-- Turn everything OFF first
		if RAIN_EMITTER then RAIN_EMITTER.Enabled = false end
		if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end
		if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end
		if RAIN_SOUND then RAIN_SOUND.Playing = false end
		if WIND_SOUND then WIND_SOUND.Playing = false end
		if THUNDER_SOUND then THUNDER_SOUND.Playing = false end

		-- Re-enable specific effects for the new weather
		if weatherCondition == "Rain" then
			if RAIN_EMITTER then RAIN_EMITTER.Enabled = true end
			if RAIN_SOUND then RAIN_SOUND.Playing = true end
		elseif weatherCondition == "Snow" then
			if SNOW_EMITTER then SNOW_EMITTER.Enabled = true end
			if WIND_SOUND then WIND_SOUND.Playing = true end
		elseif weatherCondition == "Thunderstorm" then
			if RAIN_EMITTER then RAIN_EMITTER.Enabled = true end
			if THUNDER_SOUND then THUNDER_SOUND.Playing = true end
		end
	end
end

-- =================================================================================================
-- || PUBLIC FUNCTION: Start System (The main entry point) ||
-- =================================================================================================


-- =================================================================================================
-- || OTHER PUBLIC GETTERS ||
-- =================================================================================================



-- =================================================================================================
-- || MODULE RETURN STATEMENT ||
-- =================================================================================================

-- 2. Return the table, making all assigned functions and data public.
return WeatherService

New main


-- =================================================================================================
-- || MAIN CONTROL LOGIC (Instant Execution) ||
-- =================================================================================================

local WEATHER_CHECK_INTERVAL = 5 * 60
-- Services
local RunService = game:GetService("RunService")
local Lighting = game:GetService("Lighting")

-- Load the ModuleScript
local WeatherService = require(workspace.ServerScriptService.WeatherService)

local function updateLightingTime()
	local currentTimeUnix = os.time()
	local hour = tonumber(os.date("%H", currentTimeUnix))
	local minute = tonumber(os.date("%M", currentTimeUnix))
	local second = tonumber(os.date("%S", currentTimeUnix))
	Lighting.ClockTime = hour + (minute / 60) + (second / 3600)
end

-- 1. Initial Data Fetch (Run once immediately)
currentWeather = WeatherService.fetchWeatherCondition()
WeatherService.applyWeatherEffects(currentWeather)
warn("WEATHER INITIALIZED: Condition: " .. currentWeather)

-- 2. Polling loop for Time Sync and Weather Check
local lastCheckTime = 0

RunService.Heartbeat:Connect(function()
	updateLightingTime() 

	local currentTime = os.time()
	if currentTime - lastCheckTime >= WEATHER_CHECK_INTERVAL then
		local newCondition = WeatherService.fetchWeatherCondition()
		if newCondition then
			currentWeather = newCondition
		end
		lastCheckTime = currentTime
		warn("WEATHER CHECK: Refreshed data.")
	end

	WeatherService.applyWeatherEffects(currentWeather)
end) 

print("Weather and Real-Time Sync script is now running.")


I had a getCurrentWeather() function in the module but Gemini suggested that that was causing the problem and to change it to public and that that would fix it, but it didn’t.

I don’t believe that the error is anywhere outside the applyWeatherEffects() in the module or inside the Heartbeat in the main (though I could be wrong.)

Again, the top code, the longest one, IS working, but the two split ones (a module and a main) seem to be goofing up somewhre with applyweathereffects() and the Heartbeat.

My sign should be showing something like “Snow” or “Overcast” but it’s showing “Put Text Here” or whatever it said. The time should be a little after midnight but it’s about noon (the default).

So somthing is going wrong either in the heartbeat or apply weather effects. I don’t see how it could be anything else.

UPDATE----

Maybe this line is the cause. It’s the only thing that, if going wrong, could mess with everything:

local WeatherService = require(workspace.ServerScriptService.WeatherService)

UPDATE----

Fixed a typo in the module script and it’s still not working.

UPDATE—

Now checking into loading (i.e. it may be being operated upon before it’s loaded. Since part of it is now in a module, that could be the problem.)

4 Likes

Huh? Why is it looking at WORKSPACE for ServerScriptService? Should be “game.ServerScriptService” or even “game.ServerStorage”.
Parent the module to one of those and the main script to ServerScriptService and fix the reference (and please stop using AI, it won’t help you learn, always value learning over just “making things fast”).

Take a look a this Video about Module Scripts, I like the channel and it taught me a lot when I started.

1 Like

Do you get any errors? Have you placed any prints along the way to see where it’s failing? What warnings do show up and which don’t?

The problem is, when I was using

local WeatherService = require(game.ServerScriptService.WeatherService)

It kept complaining that I wasn’t using a module script.

When I used

workspace.ServerScriptService.WeatherService

That error went away.

UPDATE: One issue was that I was using a script rather than a module script, but even fixing that, and no matter how I format the call to the require.

I don’t have time to fiddle with this for hours on end wehn I already have a working copy and nothing can seem to find the error for me in the new ones.

I also seem to be running into this error after many updates I’ve made, and it takes me hours to fix it each time. That’s why I’m ready just to call it quits on using the module script if I can’t find the issue. Waiitng to load the game before require isn’t fixing it, making it a module script instead of a regular script isn’t fixing it. Changing it to game.ServerScriptService.WeatherService isn’t fixing it.

I’d eventually like to figure out why this works by these don’t:


=================================================================================================

-- || WEATHER & REAL-TIME SYNC SCRIPT (FINAL, STABLE VERSION) ||

-- =================================================================================================



-- Services

local Lighting = game:GetService("Lighting")

local RunService = game:GetService("RunService")

local HttpService = game:GetService("HttpService")

local Http = game:GetService("HttpService") 

local Players = game:GetService("Players")

local InsertService = game:GetService("InsertService")



-- Configuration Variables

local LATITUDE = 41.36      -- Oglesby, IL

local LONGITUDE = -89.04    -- Oglesby, IL

local TIMEZONE = "America/Chicago"

local API_ENDPOINT = "https://api.open-meteo.com/v1/forecast"



-- Weather Check Interval (How often to fetch new data, e.g., every 5 minutes)

local WEATHER_CHECK_INTERVAL = 5 * 60 



-- Umbrella Configuration

local UMBRELLA_ASSET_ID = 13710882876 

local UMBRELLA_HANDLE = nil -- Cache the Handle once it's loaded



-- Asset Definitions (Place these objects in Workspace/WeatherSource)

local WEATHER_SOURCE = workspace:WaitForChild("WeatherSource", 10)

local RAIN_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainEmitter")

local SNOW_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("SnowEmitter")

local HAIL_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("HailEmitter")



local RAIN_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainSound")

local WIND_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("WindSound")

local THUNDER_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("ThunderSound")



local Terrain = game:GetService("Terrain")

local CLOUDS = workspace.Terrain:FindFirstChild("Clouds") -- Don't wait, just check



-- || FIXED SIGN CONFIGURATION FOR NEW STRUCTURE ||

-- ====================================================================



-- 1. Get the main container object (Model or Folder)

local WEATHER_SIGN_CONTAINER = workspace:FindFirstChild("WeatherSign") 



-- 2. The SurfaceGui is now a DIRECT CHILD of the container, so we find it here.

local SIGN_GUI = WEATHER_SIGN_CONTAINER and WEATHER_SIGN_CONTAINER:FindFirstChildOfClass("SurfaceGui")



-- 3. Get the TextLabel object (which is a direct child of the SurfaceGui)

local WEATHER_TEXT_LABEL = SIGN_GUI and SIGN_GUI:FindFirstChildOfClass("TextLabel")



-- ====================================================================



-- Script State Trackers

local lastAppliedWeather = ""

local currentWeather = ""



-- =================================================================================================

-- || API INTERFACE & CORE WEATHER LOGIC ||

-- =================================================================================================



local function fetchWeatherCondition()

local url = string.format(

"%s?latitude=%f&longitude=%f&timezone=%s&current=weather_code",

API_ENDPOINT, LATITUDE, LONGITUDE, TIMEZONE

)



local rawData = nil

local success, result = pcall(function()

rawData = Http:GetAsync(url)

return HttpService:JSONDecode(rawData)

end)



if not success or not rawData or not result or not result.current then

warn("API ERROR: Failed to fetch weather data. Defaulting to No Input.")

return "No Input" 

end



local weatherCode = result.current.weather_code



local function getWeatherCondition(code)

-- ** UPDATED: Expanded logic based on WMO codes **



-- WMO Code 0: Clear Sky

if code == 0 then return "Clear"

elseif code == 3 then 

return "Overcast"

elseif code == 2 then 

return "Mostly Cloudy"

elseif code == 1 then 

return "Partly Cloudy"

elseif code >= 45 and code <= 48 then return "Fog"

elseif code >= 50 and code <= 69 then return "Rain"

elseif code >= 70 and code <= 89 then return "Snow"

elseif code >= 90 then return "Thunderstorm"

else

return "Unknown"

end

end



return getWeatherCondition(weatherCode)

end



-- ** NEW: Function to update the sign's text **

local function updateWeatherSign(condition)

local textToShow = condition or "No Input"

if WEATHER_TEXT_LABEL then

WEATHER_TEXT_LABEL.Text = textToShow

warn("SIGN UPDATED: Showing '" .. textToShow .. "'")

else

warn("WARNING: Weather Text Label not found or configured incorrectly.")

end

end



local function applyWeatherEffects(weatherCondition)

-- Always update sign, even if weather didn't change

updateWeatherSign(weatherCondition)



-- Always update clouds, even if weather didn't change

if CLOUDS == nil then

warn("WARNING: Clouds object not found in Terrain!")

else

if weatherCondition == "Partly Cloudy" then

CLOUDS.Enabled = true

CLOUDS.Density = 0.2

CLOUDS.Cover = 0.4

CLOUDS.Color = Color3.fromRGB(220, 220, 220)

--Lighting.OutdoorAmbient = Color3.fromRGB(150, 150, 160)

--Lighting.GlobalShadows = true

elseif weatherCondition == "Mostly Cloudy" then

CLOUDS.Enabled = true

CLOUDS.Density = 0.5

CLOUDS.Cover = 0.7

CLOUDS.Color = Color3.fromRGB(180, 180, 190)

-- Lighting.OutdoorAmbient = Color3.fromRGB(120, 120, 130)

-- Lighting.GlobalShadows = false

elseif weatherCondition == "Overcast" then

CLOUDS.Enabled = true

CLOUDS.Density = 1.0

CLOUDS.Cover = 1.0

local currentTime = Lighting.ClockTime

local isNight = (currentTime >= 18.0) or (currentTime < 6.0)

if isNight then

CLOUDS.Color = Color3.fromRGB(50, 50, 60)

--Lighting.OutdoorAmbient = Color3.fromRGB(30, 30, 40)

--Lighting.Ambient = Color3.fromRGB(20, 20, 25)

--Lighting.ExposureCompensation = -2.0

--Lighting.Brightness = 0.1

else

CLOUDS.Color = Color3.fromRGB(150, 150, 160)

--Lighting.OutdoorAmbient = Color3.fromRGB(90, 90, 100)

--Lighting.Ambient = Color3.fromRGB(120, 120, 120)

--Lighting.ExposureCompensation = 0.0

end

Lighting.GlobalShadows = false

if Lighting:FindFirstChild("Sky") then

Lighting.Sky.CelestialBodiesShown = false

end

else

-- Not cloudy, reset clouds

CLOUDS.Enabled = false

-- Lighting.OutdoorAmbient = Color3.fromRGB(192, 192, 192)

-- Lighting.Ambient = Color3.fromRGB(128, 128, 128)

Lighting.GlobalShadows = true

if Lighting:FindFirstChild("Sky") then

Lighting.Sky.CelestialBodiesShown = true

end

end

end



-- Only reset emitters/sounds and log when weather changes

if weatherCondition ~= lastAppliedWeather and weatherCondition ~= "No Input" then

lastAppliedWeather = weatherCondition

warn("WEATHER CHANGE: New Condition: " .. weatherCondition)

if RAIN_EMITTER then RAIN_EMITTER.Enabled = false end

if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end

if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end

if RAIN_SOUND then RAIN_SOUND.Playing = false end

if WIND_SOUND then WIND_SOUND.Playing = false end

if THUNDER_SOUND then THUNDER_SOUND.Playing = false end

end

end



-- =================================================================================================

-- || MAIN CONTROL LOGIC (Instant Execution) ||

-- =================================================================================================



local function updateLightingTime()

local currentTimeUnix = os.time()

local hour = tonumber(os.date("%H", currentTimeUnix))

local minute = tonumber(os.date("%M", currentTimeUnix))

local second = tonumber(os.date("%S", currentTimeUnix))

Lighting.ClockTime = hour + (minute / 60) + (second / 3600)

end



-- 1. Initial Data Fetch (Run once immediately)

currentWeather = fetchWeatherCondition()

applyWeatherEffects(currentWeather)

warn("WEATHER INITIALIZED: Condition: " .. currentWeather)



-- 2. Polling loop for Time Sync and Weather Check

local lastCheckTime = 0



RunService.Heartbeat:Connect(function()

updateLightingTime() 



local currentTime = os.time()

if currentTime - lastCheckTime >= WEATHER_CHECK_INTERVAL then

local newCondition = fetchWeatherCondition()

if newCondition then

currentWeather = newCondition

end

lastCheckTime = currentTime

warn("WEATHER CHECK: Refreshed data.")

end



applyWeatherEffects(currentWeather)

end) 



print("Weather and Real-Time Sync script is now running.")

<------ This works!

These two are creating an error that is making it never reach the lighting and sign update part.
Script Main:

local WEATHER_CHECK_INTERVAL = 5 * 60
local RunService = game:GetService("RunService")
local Lighting = game:GetService("Lighting")

-- Due to some checking, the error is being introduced in the very next line.   But, Assistant isn't spotting any syntax errors or anything and neither, so far, am I.   
local ServerScriptService = game:GetService("ServerScriptService")   


game.Loaded:Wait()
local WeatherService = require(workspace.ServerScriptService.WeatherService)

local currentWeather = "No Input"
local lastWeatherCheck = 0

local function updateLightingTime()
	local currentTimeUnix = os.time()
	local hour = tonumber(os.date("%H", currentTimeUnix))
	local minute = tonumber(os.date("%M", currentTimeUnix))
	local second = tonumber(os.date("%S", currentTimeUnix))
	Lighting.ClockTime = hour + (minute / 60) + (second / 3600)
end

-- Function to update weather and apply effects
local function updateWeather()
	local weatherCondition = WeatherService.fetchWeatherCondition()
	currentWeather = weatherCondition
	WeatherService.applyWeatherEffects(weatherCondition)
end

-- Initial fetch and apply
updateWeather()

-- Heartbeat loop for time and weather
RunService.Heartbeat:Connect(function(step)
	updateLightingTime()
	
	-- Always apply weather effects using latest condition (for sign/cloud color updates)
	WeatherService.applyWeatherEffects(currentWeather)

	-- Check if it's time to update weather
	if tick() - lastWeatherCheck > WEATHER_CHECK_INTERVAL then
		updateWeather()
		lastWeatherCheck = tick()
	end
end)

WeatherService:

-- =================================================================================================
-- || WEATHER & REAL-TIME SYNC MODULESCRIPT (Complete) ||
-- =================================================================================================

local WeatherService = {}

local Lighting = game:GetService("Lighting")
local RunService = game:GetService("RunService")
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local InsertService = game:GetService("InsertService")
local Terrain = game:GetService("Terrain")

WeatherService.LATITUDE = 41.36
WeatherService.LONGITUDE = -89.04
WeatherService.TIMEZONE = "America/Chicago"

local API_ENDPOINT = "https://api.open-meteo.com/v1/forecast"
local WEATHER_CHECK_INTERVAL = 5 * 60

local UMBRELLA_ASSET_ID = 13710882876
local UMBRELLA_HANDLE = nil

local WEATHER_SOURCE = workspace:WaitForChild("WeatherSource", 10)
local RAIN_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainEmitter")
local SNOW_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("SnowEmitter")
local HAIL_EMITTER = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("HailEmitter")

local RAIN_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("RainSound")
local WIND_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("WindSound")
local THUNDER_SOUND = WEATHER_SOURCE and WEATHER_SOURCE:FindFirstChild("ThunderSound")

local CLOUDS = Terrain:FindFirstChild("Clouds")

local WEATHER_SIGN_CONTAINER = workspace:FindFirstChild("WeatherSign")
local SIGN_GUI = WEATHER_SIGN_CONTAINER and WEATHER_SIGN_CONTAINER:FindFirstChildOfClass("SurfaceGui")
local WEATHER_TEXT_LABEL = SIGN_GUI and SIGN_GUI:FindFirstChildOfClass("TextLabel")

local lastAppliedWeather = ""
WeatherService.currentWeather = ""

function WeatherService.fetchWeatherCondition()
	local function getWeatherCondition(code)
		if code == 0 then return "Clear"
		elseif code == 3 then return "Overcast"
		elseif code == 2 then return "Mostly Cloudy"
		elseif code == 1 then return "Partly Cloudy"
		elseif code >= 45 and code <= 48 then return "Fog"
		elseif code >= 50 and code <= 69 then return "Rain"
		elseif code >= 70 and code <= 89 then return "Snow"
		elseif code >= 90 then return "Thunderstorm"
		else
			return "Unknown"
		end
	end

	local url = string.format(
		"%s?latitude=%f&longitude=%f&timezone=%s&current=weather_code",
		API_ENDPOINT, WeatherService.LATITUDE, WeatherService.LONGITUDE, WeatherService.TIMEZONE
	)

	local rawData = nil
	local success, result = pcall(function()
		rawData = HttpService:GetAsync(url)
		return HttpService:JSONDecode(rawData)
	end)

	if not success or not rawData or not result or not result.current then
		warn("API ERROR: Failed to fetch weather data. Defaulting to No Input.")
		return "No Input"
	end

	local weatherCode = result.current.weather_code
	return getWeatherCondition(weatherCode) 
end

local function updateWeatherSign(condition)
	local textToShow = condition or "No Input"
	if WEATHER_TEXT_LABEL then
		WEATHER_TEXT_LABEL.Text = textToShow
	else
		warn("WARNING: Weather Text Label not found or configured incorrectly.")
		if SIGN_GUI then
			warn("SurfaceGui found, but no TextLabel child.")
		elseif WEATHER_SIGN_CONTAINER then
			warn("WeatherSign model found, but no SurfaceGui child.")
		else
			warn("WeatherSign model not found in workspace.")
		end
	end
end

function WeatherService.applyWeatherEffects(weatherCondition)
	WeatherService.currentWeather = weatherCondition

	-- Always update sign
	updateWeatherSign(weatherCondition)

	-- Update clouds
	if CLOUDS == nil then
		warn("WARNING: Clouds object not found in Terrain!")
	else
		if weatherCondition == "Partly Cloudy" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 0.2
			CLOUDS.Cover = 0.4
			CLOUDS.Color = Color3.fromRGB(220, 220, 220)
		elseif weatherCondition == "Mostly Cloudy" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 0.5
			CLOUDS.Cover = 0.7
			CLOUDS.Color = Color3.fromRGB(180, 180, 190)
		elseif weatherCondition == "Overcast" then
			CLOUDS.Enabled = true
			CLOUDS.Density = 1.0
			CLOUDS.Cover = 1.0
			local currentTime = Lighting.ClockTime
			local isNight = (currentTime >= 18.0) or (currentTime < 6.0)
			if isNight then
				CLOUDS.Color = Color3.fromRGB(50, 50, 60)
			else
				CLOUDS.Color = Color3.fromRGB(150, 150, 160)
			end
			Lighting.GlobalShadows = false
			if Lighting:FindFirstChild("Sky") then
				Lighting.Sky.CelestialBodiesShown = false
			end
		else
			CLOUDS.Enabled = false
			Lighting.GlobalShadows = true
			if Lighting:FindFirstChild("Sky") then
				Lighting.Sky.CelestialBodiesShown = true
			end
		end
	end

	-- Always update emitters/sounds, not just on weather change
	if weatherCondition == "Rain" then
		if RAIN_EMITTER then RAIN_EMITTER.Enabled = true else warn("RainEmitter not found") end
		if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end
		if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end
		if RAIN_SOUND then RAIN_SOUND.Playing = true else warn("RainSound not found") end
		if WIND_SOUND then WIND_SOUND.Playing = false end
		if THUNDER_SOUND then THUNDER_SOUND.Playing = false end
	elseif weatherCondition == "Snow" then
		if RAIN_EMITTER then RAIN_EMITTER.Enabled = false end
		if SNOW_EMITTER then SNOW_EMITTER.Enabled = true else warn("SnowEmitter not found") end
		if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end
		if RAIN_SOUND then RAIN_SOUND.Playing = false end
		if WIND_SOUND then WIND_SOUND.Playing = true else warn("WindSound not found") end
		if THUNDER_SOUND then THUNDER_SOUND.Playing = false end
	elseif weatherCondition == "Thunderstorm" then
		if RAIN_EMITTER then RAIN_EMITTER.Enabled = true else warn("RainEmitter not found") end
		if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end
		if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end
		if RAIN_SOUND then RAIN_SOUND.Playing = false end
		if WIND_SOUND then WIND_SOUND.Playing = false end
		if THUNDER_SOUND then THUNDER_SOUND.Playing = true else warn("ThunderSound not found") end
	else
		-- Clear or unknown: turn everything off
		if RAIN_EMITTER then RAIN_EMITTER.Enabled = false end
		if SNOW_EMITTER then SNOW_EMITTER.Enabled = false end
		if HAIL_EMITTER then HAIL_EMITTER.Enabled = false end
		if RAIN_SOUND then RAIN_SOUND.Playing = false end
		if WIND_SOUND then WIND_SOUND.Playing = false end
		if THUNDER_SOUND then THUNDER_SOUND.Playing = false end
	end

	-- Log every update for debugging
	if weatherCondition ~= lastAppliedWeather then
		lastAppliedWeather = weatherCondition
		warn("WEATHER CHANGE: New Condition: " .. weatherCondition)
	else
		print("WeatherService: Weather condition applied: " .. weatherCondition)
	end
end

return WeatherService

Can you provide a screenshot with the location of both so I can take a look later? It might help me figure things out.

And I agree, if you’re not gonna share state between scripts there’s no problem in keeping it as a single script instead of using modules.

BUT, you should learn about module scripts as they’re the key to writing good, expandable, and maintainable code.

I believe it’s likely a typo in the Module Scrirpt somewhere, likely when something is being called for a service or something. That’s why it’s not catching it for a syntax error or anything.

It’d be helpful if you gave information about the specific errors you’re getting and showing what is getting outputted to the console.

Haven’t seen any specific errors yet, but, just on a hunch, I removed all the text of the module script and it still is having the error happen at the line to call require:

local WeatherService = require(game:GetService(“ServerScriptService”).WeatherService)

It has to be this line and only this line, as the other sources of error have been removed and it’s still continuing.

UPDATE –

I see what I was doing wrong earlier when I tested it with an empty module script. I needed at least a table and a return, and that had niehter. Once I just had that, now the lighting is working. That means that the error is solely in the module script.

I dd see one error, that I was missing local Http = game:GetService(“HttpService”) in the Module but had it in the original. However, even after fixing that, the problem isn’t going away.

I’m going to go back to the old script. I just hope I don’t have thsi issue for every module script and that it was just a typo or something for this one time.