Script do detect if player is illuminated

I tried to find a script to steal utilize in one of my games that would detect if the player is in a light source or not, well I didn’t find any good ones, so I made my own. It’s not perfect but it works for me and it might work for you, attached are the script, which is in StarterCharacterScripts and a demo video

video

(that link expires in a week so if it doesn’t work you know why)

local LLT = 0.1 -- Set this to 0 if you want it to detect all light even if its very faint

local RS = game:GetService("RunService")

local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local RP = char:WaitForChild("HumanoidRootPart")

local Lights = {}

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {char}

for i, v in pairs(workspace:GetDescendants()) do
	if v:IsA("SpotLight") or v:IsA("PointLight") then
		table.insert(Lights, v)
	end
end

function getRangeBrightnessWeight(range, brighteness)
	local value = brighteness/range
	return value > LLT
end

function LineOfSight(target)
	local rayDirection = target.Position - RP.Position  
	
	local RayResult = workspace:Raycast(RP.Position, rayDirection, rayParams)
	
	return RayResult.Instance == target

end

function getPointLightIlluminated(light)
	
	if not light or not light.Parent or not light:IsA("PointLight") then
		return false
	end
	
	if LineOfSight(light.Parent) then
		local distanceFromPointLight = (light.Parent.Position - RP.Position).Magnitude
		
		if not getRangeBrightnessWeight(distanceFromPointLight, light.Brightness) then return false end
		
		if distanceFromPointLight <= light.Range - light.Range/20 then
			return true
		end
	end
	return false
end

function getAllSpotLight(target)
	for i, playerPart in pairs(char:GetDescendants()) do
		if playerPart:IsA("Part") or playerPart:IsA("MeshPart") then

			local partToRP = (playerPart.Position - target.Parent.Position).Unit
			local partLook = target.Parent.CFrame.LookVector
			local dotProduct = partToRP:Dot(partLook)

			local lightAngleRad = math.rad(target.Angle / 2) 
			local minDotProduct = math.cos(lightAngleRad) 
			
			if not getRangeBrightnessWeight((target.Parent.Position - RP.Position).Magnitude, target.Brightness) then continue end
			
			
			if dotProduct > minDotProduct then
				return true
			end
		end
	end
	
	return false
end


function getSpotLightIlluminated(light)
	if not light or not light.Parent or not light:IsA("SpotLight") then
		return false
	end

	if not LineOfSight(light.Parent, RP.Position) then
		return false
	end

	local distanceFromPointLight = (light.Parent.Position - RP.Position).Magnitude
	if distanceFromPointLight > light.Range then
		return false
	end

	return getAllSpotLight(light)
	
end

game["Run Service"].Heartbeat:Connect(function()
	
	local illuminated = false
	
	for i, light in pairs(Lights) do
		if light:IsA("PointLight") then
			if getPointLightIlluminated(light) then
				illuminated = true
			end
		elseif light:IsA("SpotLight") then
			if getSpotLightIlluminated(light) then
				illuminated = true
			end
		end
	end
	if illuminated == true then
		char.Head.BrickColor = BrickColor.new("Sea green")
	else
		char.Head.BrickColor = BrickColor.new("Really red")
	end
end)