function Invisicam.Update(O)if not Torso then local O=Character:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if O and O.Torso then Torso=O.Torso else Torso=Character:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")if not Torso then return end end local w w=Torso.AncestryChanged:connect(function(O,h)if O==Torso and not h then Torso=nil if w and w.Connected then w:Disconnect()w=nil end end end)end local w={}BehaviorFunction(w)local h={}local M={Character}local function j(O)h[O]=true if not SavedHits[O]then SavedHits[O]=O.LocalTransparencyModifier end end local i=Camera:GetPartsObscuringTarget(w,M)for O=1,#i,1 do local w=i[O]j(w)for O,w in pairs(w:GetChildren())do if w:IsA("\068\101\099\097\108")or w:IsA("\084\101\120\116\117\114\101")then j(w)end end end for O,w in pairs(SavedHits)do local M=O.LocalTransparencyModifier if h[O]then if M<FADE_TARGET then O.LocalTransparencyModifier=math_min(M+FADE_RATE,FADE_TARGET)end else if M>w then O.LocalTransparencyModifier=math_max(w,M-FADE_RATE)else SavedHits[O]=nil end end end end function Invisicam.SetMode(w,O)AssertTypes(O,"\110\117\109\098\101\114")for w,h in pairs(MODE)do if h==O then Mode=O BehaviorFunction=Behaviors[Mode]return end end error("\073\110\118\097\108\105\100 \109\111\100\101 \110\117\109\098\101\114")end function Invisicam.SetCustomBehavior(w,O)AssertTypes(O,"\102\117\110\099\116\105\111\110")Behaviors[MODE.CUSTOM]=O if Mode==MODE.CUSTOM then BehaviorFunction=O end end

function Invisicam:Update()
	-- Make sure we still have a Torso
	if not Torso then
		local humanoid = Character:FindFirstChildOfClass("Humanoid")
		if humanoid and humanoid.Torso then
			Torso = humanoid.Torso
		else
			-- Not set up with Humanoid? Try and see if there's one in the Character at all:
			Torso = Character:FindFirstChild("HumanoidRootPart")
			if not Torso then
				-- Bail out, since we're relying on Torso existing
				return
			end
		end
		local ancestryChangedConn;
		ancestryChangedConn = Torso.AncestryChanged:connect(function(child, parent)
			if child == Torso and not parent then 
				Torso = nil
				if ancestryChangedConn and ancestryChangedConn.Connected then
					ancestryChangedConn:Disconnect()
					ancestryChangedConn = nil
				end
			end
		end)
	end

	-- Make a list of world points to raycast to
	local castPoints = {}
	BehaviorFunction(castPoints)
	
	-- Cast to get a list of objects between the camera and the cast points
	local currentHits = {}
	local ignoreList = {Character}
	local function add(hit)
		currentHits[hit] = true
		if not SavedHits[hit] then
			SavedHits[hit] = hit.LocalTransparencyModifier
		end
	end

	local hitParts = Camera:GetPartsObscuringTarget(castPoints, ignoreList)
	for i = 1, #hitParts do
		local hitPart = hitParts[i]
		add(hitPart)
		for _, child in pairs(hitPart:GetChildren()) do
			if child:IsA('Decal') or child:IsA('Texture') then
				add(child)
			end
		end
	end
	
	-- Fade out objects that are in the way, restore those that aren't anymore
	for hit, originalFade in pairs(SavedHits) do
		local currentFade = hit.LocalTransparencyModifier
		if currentHits[hit] then -- Fade
			if currentFade < FADE_TARGET then
				hit.LocalTransparencyModifier = math_min(currentFade + FADE_RATE, FADE_TARGET)
			end
		else -- Restore
			if currentFade > originalFade then
				hit.LocalTransparencyModifier = math_max(originalFade, currentFade - FADE_RATE)
			else
				SavedHits[hit] = nil
			end
		end
	end
end

function Invisicam:SetMode(newMode)
	AssertTypes(newMode, 'number')
	for modeName, modeNum in pairs(MODE) do
		if modeNum == newMode then
			Mode = newMode
			BehaviorFunction = Behaviors[Mode]
			return
		end
	end
	error("Invalid mode number")
end

function Invisicam:SetCustomBehavior(func)
	AssertTypes(func, 'function')
	Behaviors[MODE.CUSTOM] = func
	if Mode == MODE.CUSTOM then
		BehaviorFunction = func
	end
end
