Super-Nostalgia-Zone/Client/Camera/Popper.lua

135 lines
3.0 KiB
Lua

-- PopperCam Version 16
-- OnlyTwentyCharacters
local PopperCam = {} -- Guarantees your players won't see outside the bounds of your map!
-----------------
--| Constants |--
-----------------
local POP_RESTORE_RATE = 0.3
local MIN_CAMERA_ZOOM = 0.5
local VALID_SUBJECTS =
{
'Humanoid',
'VehicleSeat',
'SkateboardPlatform',
}
-----------------
--| Variables |--
-----------------
local Players = game:GetService('Players')
local Camera = nil
local CameraSubjectChangeConn = nil
local SubjectPart = nil
local PlayerCharacters = {} -- For ignoring in raycasts
local VehicleParts = {} -- Also just for ignoring
local LastPopAmount = 0
local LastZoomLevel = 0
local PopperEnabled = true
local CFrame_new = CFrame.new
-----------------------
--| Local Functions |--
-----------------------
local math_abs = math.abs
local function OnCharacterAdded(player, character)
PlayerCharacters[player] = character
end
local function OnPlayersChildAdded(child)
if child:IsA('Player') then
child.CharacterAdded:connect(function(character)
OnCharacterAdded(child, character)
end)
if child.Character then
OnCharacterAdded(child, child.Character)
end
end
end
local function OnPlayersChildRemoved(child)
if child:IsA('Player') then
PlayerCharacters[child] = nil
end
end
-------------------------
--| Exposed Functions |--
-------------------------
function PopperCam:Update()
if PopperEnabled then
-- First, prep some intermediate vars
local Camera = workspace.CurrentCamera
if Camera.CameraType.Name == "Fixed" then
return
end
local cameraCFrame = Camera.CFrame
local focusPoint = Camera.Focus.p
if SubjectPart then
focusPoint = SubjectPart.CFrame.p
end
local ignoreList = {}
for _, character in pairs(PlayerCharacters) do
ignoreList[#ignoreList + 1] = character
end
for i = 1, #VehicleParts do
ignoreList[#ignoreList + 1] = VehicleParts[i]
end
-- Get largest cutoff distance
local largest = Camera:GetLargestCutoffDistance(ignoreList)
-- Then check if the player zoomed since the last frame,
-- and if so, reset our pop history so we stop tweening
local zoomLevel = (cameraCFrame.p - focusPoint).Magnitude
if math_abs(zoomLevel - LastZoomLevel) > 0.001 then
LastPopAmount = 0
end
-- Finally, zoom the camera in (pop) by that most-cut-off amount, or the last pop amount if that's more
local popAmount = largest
if LastPopAmount > popAmount then
popAmount = LastPopAmount
end
if popAmount > 0 then
Camera.CFrame = cameraCFrame + (cameraCFrame.lookVector * popAmount)
LastPopAmount = popAmount - POP_RESTORE_RATE -- Shrink it for the next frame
if LastPopAmount < 0 then
LastPopAmount = 0
end
end
LastZoomLevel = zoomLevel
end
end
--------------------
--| Script Logic |--
--------------------
-- Connect to all Players so we can ignore their Characters
Players.ChildRemoved:connect(OnPlayersChildRemoved)
Players.ChildAdded:connect(OnPlayersChildAdded)
for _, player in pairs(Players:GetPlayers()) do
OnPlayersChildAdded(player)
end
return PopperCam