When a place already has lighting instances before the kit is ran, the LightingManager checks some of those instances and stores their values to use as the PlaceDefault. However, this is only ran on the lighting instances that have defaults different than what Roblox uses. This means that some lighting instances may have two of them. This ain't good, because tower lighting may be inaccurate due to these instances existing.
I've fixed these issues in the following code. The fixes are
--!strict
--!optimize 2
-- By @synnwave (09/12/24 DD/MM/YY)
--[[
--------------------------------------------------------------------------------
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
⚠️ WARNING - PLEASE READ! ⚠️
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
If you are submitting to EToH:
PLEASE, **DO NOT** make any script edits to this script.
This is a core script and any edits you make to this script will NOT work
elsewhere.
If you have any suggestions, please let us know.
Thank you
--------------------------------------------------------------------------------
]]
--[=[
@class LightingManager
@client
Manager module responsible for the functionality of Lighting Changers
and other things generally related to lighting.
]=]
--[[
---------------------------------------------------------------------------
Services, modules and other objects
---------------------------------------------------------------------------
]]
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Lighting = game:GetService("Lighting")
local TweenService = game:GetService("TweenService")
local Framework = ReplicatedStorage.Framework
local _TDefs = require(script.TypeDefs)
--[[
---------------------------------------------------------------------------
Constants
---------------------------------------------------------------------------
]]
local CONFIGURABLE_PROPERTIES = {
ColorCorrectionEffect = { "Brightness", "Contrast", "Saturation", "TintColor" },
BlurEffect = { "Size" },
Lighting = {
"Ambient",
"Brightness",
"ClockTime",
"ColorShift_Bottom",
"ColorShift_Top",
"EnvironmentDiffuseScale",
"EnvironmentSpecularScale",
"ExposureCompensation",
"FogColor",
"FogEnd",
"FogStart",
"GeographicLatitude",
"GlobalShadows",
"OutdoorAmbient",
"ShadowSoftness",
"TimeOfDay",
},
BloomEffect = { "Intensity", "Size", "Threshold" },
DepthOfFieldEffect = { "FarIntensity", "FocusDistance", "InFocusRadius", "NearIntensity" },
SunRaysEffect = { "Intensity", "Spread"},
ColorGradingEffect = { "TonemapperPreset" },
Atmosphere = { "Density", "Offset", "Color", "Decay", "Glare", "Haze" },
Sky = {
"MoonAngularSize",
"MoonTextureId",
"SkyboxBk",
"SkyboxDn",
"SkyboxFt",
"SkyboxLf",
"SkyboxRt",
"SkyboxUp",
"StarCount",
"SunAngularSize",
"SunTextureId",
"SkyboxOrientation", -- eyes 👀
},
} :: { [string]: { string } }
--[[
---------------------------------------------------------------------------
Lighting tables
---------------------------------------------------------------------------
]]
-- Default properties are set here since using Instance.new uses a different set
-- of default properties
local defaultProperties = {
BloomEffect = { Intensity = 1, Size = 24, Threshold = 2 },
BlurEffect = { Size = 0 },
DepthOfFieldEffect = { FarIntensity = 0, FocusDistance = 0, InFocusRadius = 0, NearIntensity = 0 },
SunRaysEffect = { Intensity = 0, Spread = 0 },
Atmosphere = { Density = 0, Offset = 0 },
} :: { [string]: { [string]: any } }
local lightingTemplates = {
PlaceDefault = defaultProperties,
}
local lightingInstances = {}
--[[
---------------------------------------------------------------------------
Main table
---------------------------------------------------------------------------
]]
local LightingManager = {
__initialized = false,
Templates = lightingTemplates,
} :: _TDefs.LightingManager
--[[
---------------------------------------------------------------------------
Functions
---------------------------------------------------------------------------
]]
--[=[
@within LightingManager
Changes the active lighting based on the given `config`.
You can create a lighting preset by using `SetDefault` as a `string` parameter in a
lighting changer's config module. These can then be reused by using `UseDefault`
as a `string` parameter with the same value.
]=]
function LightingManager:ChangeLighting(config: _TDefs.LightingConfiguration)
if CONFIGURABLE_PROPERTIES[config.Type] == nil then
return
end
if not config.TweenInfo then
config.TweenInfo = TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
end
local lightingInstance = lightingInstances[config.Type]
local propertyTable = {}
local thisConfig = if typeof(config.UseDefault) == "string"
then (
lightingTemplates[config.UseDefault] and lightingTemplates[config.UseDefault][config.Type]
or lightingTemplates.PlaceDefault[config.Type]
)
elseif config.Configuration == "Default" then lightingTemplates.PlaceDefault[config.Type]
else config.Configuration
local saveTo = nil
if typeof(config.SetDefault) == "string" then
saveTo = lightingTemplates[config.SetDefault]
if not saveTo then
saveTo = {}
lightingTemplates[config.SetDefault] = saveTo
end
end
if saveTo and saveTo[config.Type] == nil then
saveTo[config.Type] = {}
end
for property, value in thisConfig :: any do
if not table.find(CONFIGURABLE_PROPERTIES[config.Type],property) and property ~= "Enabled" then
continue
end
if saveTo then
saveTo[config.Type][property] = value
end
if property == "Enabled" then
if config.Type == "Atmosphere" then
-- For atmospheres we have to parent elsewhere because there is no
-- .Enabled property
lightingInstance.Parent = if value then Lighting else script
continue
elseif config.Type == "Lighting" then
continue -- There is no Enabled property in Lighting
end
end
if typeof(value) == "string" or typeof(value) == "boolean" or typeof(value) == "EnumItem" then
lightingInstance[property] = value
else
propertyTable[property] = value
end
end
TweenService:Create(lightingInstance, config.TweenInfo, propertyTable):Play()
end
--[=[
@within LightingManager
Resets all lighting properties back to their default state.
]=]
function LightingManager:ResetLighting()
for effectType in CONFIGURABLE_PROPERTIES do
LightingManager:ChangeLighting({
Type = effectType,
Configuration = "Default",
})
end
end
--[=[
@within LightingManager
Removes the registered `preset` from the lighting template list.
Used when the client object folder unloads.
]=]
function LightingManager:DeregisterPreset(preset: string)
if preset:lower() == "placedefault" then
return
end
for key in lightingTemplates do
if key:lower():sub(1, preset:len()) == preset:lower() then
lightingTemplates[key] = nil
end
end
end
function LightingManager:Init()
if self.__initialized then
return LightingManager
end
self.__initialized = true
--> Setup lighting defaults
for effect, properties in CONFIGURABLE_PROPERTIES do
if not defaultProperties[effect] then
defaultProperties[effect] = {}
end
local lightingEffect: Instance = nil
if effect == "Lighting" then
lightingEffect = Lighting
else
local lightingEffects = Lighting:QueryDescendants(`{effect}:not([Enabled = false])`)
if #lightingEffects < 1 then
lightingEffect = Instance.new(effect)
lightingEffect.Parent = Lighting
for name, value in defaultProperties[effect] do
(lightingEffect :: any)[name] = value
end
else
lightingEffect = table.remove(lightingEffects, 1) :: Instance
for _, unusedEffect in lightingEffects do
unusedEffect:Destroy()
end
end
lightingEffect.Name = `LC{effect}`
end
for i, property in properties do
defaultProperties[effect][property] = (lightingEffect :: any)[property]
end
lightingInstances[effect] = lightingEffect
end
return LightingManager
end
return LightingManager
btw if this is merged just remember to add the ColorGradingEffect stuff to the lighting changer repo
When a place already has lighting instances before the kit is ran, the LightingManager checks some of those instances and stores their values to use as the PlaceDefault. However, this is only ran on the lighting instances that have defaults different than what Roblox uses. This means that some lighting instances may have two of them. This ain't good, because tower lighting may be inaccurate due to these instances existing.
I've fixed these issues in the following code. The fixes are
local lightingInstance = if config.Type == "Lighting" then Lighting else lightingInstances[config.Type]tolocal lightingInstance = lightingInstances[config.Type]in the ChangeLighting function because of any lighting instance being added to the lightingInstances tablefor property, value in thisConfig :: any doto resolve You can change properties on lighting items that aren't actually in the CONFIGURABLE_PROPERTIES table of the LightingManager #84, disallows Enabled from being set to Lighting since that property doesn't exist, and preventsEnumItems from being tweened because i dont think you can tween them.btw if this is merged just remember to add the ColorGradingEffect stuff to the lighting changer repo