SyntaxGameServer/RCCService2021/ExtraContent/scripts/PlayerScripts/StarterPlayerScripts/CameraScript/TransparencyController.lua

191 lines
5.2 KiB
Lua

-- SolarCrane
local MAX_TWEEN_RATE = 2.8 -- per second
local function clamp(low, high, num)
return (num > high and high or num < low and low or num)
end
local math_floor = math.floor
local function Round(num, places)
local decimalPivot = 10^places
return math_floor(num * decimalPivot + 0.5) / decimalPivot
end
local function CreateTransparencyController()
local module = {}
local LastUpdate = tick()
local TransparencyDirty = false
local Enabled = false
local LastTransparency = nil
local DescendantAddedConn, DescendantRemovingConn = nil, nil
local ToolDescendantAddedConns = {}
local ToolDescendantRemovingConns = {}
local CachedParts = {}
local function HasToolAncestor(object)
if object.Parent == nil then return false end
return object.Parent:IsA('Tool') or HasToolAncestor(object.Parent)
end
local function IsValidPartToModify(part)
if part:IsA('BasePart') or part:IsA('Decal') then
return not HasToolAncestor(part)
end
return false
end
local function CachePartsRecursive(object)
if object then
if IsValidPartToModify(object) then
CachedParts[object] = true
TransparencyDirty = true
end
for _, child in pairs(object:GetChildren()) do
CachePartsRecursive(child)
end
end
end
local function TeardownTransparency()
for child, _ in pairs(CachedParts) do
child.LocalTransparencyModifier = 0
end
CachedParts = {}
TransparencyDirty = true
LastTransparency = nil
if DescendantAddedConn then
DescendantAddedConn:disconnect()
DescendantAddedConn = nil
end
if DescendantRemovingConn then
DescendantRemovingConn:disconnect()
DescendantRemovingConn = nil
end
for object, conn in pairs(ToolDescendantAddedConns) do
conn:disconnect()
ToolDescendantAddedConns[object] = nil
end
for object, conn in pairs(ToolDescendantRemovingConns) do
conn:disconnect()
ToolDescendantRemovingConns[object] = nil
end
end
local function SetupTransparency(character)
TeardownTransparency()
if DescendantAddedConn then DescendantAddedConn:disconnect() end
DescendantAddedConn = character.DescendantAdded:connect(function(object)
-- This is a part we want to invisify
if IsValidPartToModify(object) then
CachedParts[object] = true
TransparencyDirty = true
-- There is now a tool under the character
elseif object:IsA('Tool') then
if ToolDescendantAddedConns[object] then ToolDescendantAddedConns[object]:disconnect() end
ToolDescendantAddedConns[object] = object.DescendantAdded:connect(function(toolChild)
CachedParts[toolChild] = nil
if toolChild:IsA('BasePart') or toolChild:IsA('Decal') then
-- Reset the transparency
toolChild.LocalTransparencyModifier = 0
end
end)
if ToolDescendantRemovingConns[object] then ToolDescendantRemovingConns[object]:disconnect() end
ToolDescendantRemovingConns[object] = object.DescendantRemoving:connect(function(formerToolChild)
wait() -- wait for new parent
if character and formerToolChild and formerToolChild:IsDescendantOf(character) then
if IsValidPartToModify(formerToolChild) then
CachedParts[formerToolChild] = true
TransparencyDirty = true
end
end
end)
end
end)
if DescendantRemovingConn then DescendantRemovingConn:disconnect() end
DescendantRemovingConn = character.DescendantRemoving:connect(function(object)
if CachedParts[object] then
CachedParts[object] = nil
-- Reset the transparency
object.LocalTransparencyModifier = 0
end
end)
CachePartsRecursive(character)
end
function module:SetEnabled(newState)
if Enabled ~= newState then
Enabled = newState
self:Update()
end
end
function module:SetSubject(subject)
local character = nil
if subject and subject:IsA("Humanoid") then
character = subject.Parent
end
if subject and subject:IsA("VehicleSeat") and subject.Occupant then
character = subject.Occupant.Parent
end
if character then
SetupTransparency(character)
else
TeardownTransparency()
end
end
function module:Update()
local instant = false
local now = tick()
local currentCamera = workspace.CurrentCamera
if currentCamera then
local transparency = 0
if not Enabled then
instant = true
else
local distance = (currentCamera.Focus.p - currentCamera.CoordinateFrame.p).magnitude
transparency = (7 - distance) / 5
if transparency < 0.5 then
transparency = 0
end
if LastTransparency then
local deltaTransparency = transparency - LastTransparency
-- Don't tween transparency if it is instant or your character was fully invisible last frame
if not instant and transparency < 1 and LastTransparency < 0.95 then
local maxDelta = MAX_TWEEN_RATE * (now - LastUpdate)
deltaTransparency = clamp(-maxDelta, maxDelta, deltaTransparency)
end
transparency = LastTransparency + deltaTransparency
else
TransparencyDirty = true
end
transparency = clamp(0, 1, Round(transparency, 2))
end
if TransparencyDirty or LastTransparency ~= transparency then
for child, _ in pairs(CachedParts) do
child.LocalTransparencyModifier = transparency
end
TransparencyDirty = false
LastTransparency = transparency
end
end
LastUpdate = now
end
return module
end
return CreateTransparencyController