Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

I Modified PopperCam, Is There a Better Way of Doing it?

Asked by 5 years ago

So I modified CameraScript.PopperCam to make it so the Camera ignores "Models" in workspace. Is there a better way of doing this? Everything in this script is kept the same, except I added lines 136 to 142, which ignores the "Models" I want. The script is doing what I want, but is there a better way of doing this because I don't know if it's slowing down the game, etc.? Thanks!

-- 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',
}

local portraitPopperFixFlagExists, portraitPopperFixFlagEnabled = pcall(function()
    return UserSettings():IsUserFeatureEnabled("UserPortraitPopperFix")
end)
local FFlagUserPortraitPopperFix = portraitPopperFixFlagExists and portraitPopperFixFlagEnabled

-----------------
--| Variables |--
-----------------

local PlayersService = 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 = false

local CFrame_new = CFrame.new

-----------------------
--| Local Functions |--
-----------------------

local math_abs = math.abs

local function OnCameraSubjectChanged()
    VehicleParts = {}

    local newSubject = Camera.CameraSubject
    if newSubject then
        -- Determine if we should be popping at all
        PopperEnabled = false
        for _, subjectType in pairs(VALID_SUBJECTS) do
            if newSubject:IsA(subjectType) then
                PopperEnabled = true
                break
            end
        end

        -- Get all parts of the vehicle the player is controlling
        if newSubject:IsA('VehicleSeat') then
            VehicleParts = newSubject:GetConnectedParts(true)
        end

        if FFlagUserPortraitPopperFix then
            if newSubject:IsA("BasePart") then
                SubjectPart = newSubject
            elseif newSubject:IsA("Model") then
                SubjectPart = newSubject.PrimaryPart
            elseif newSubject:IsA("Humanoid") then
                SubjectPart = newSubject.Torso
            end
        end
    end
end

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

 local function OnWorkspaceChanged(property)
    if property == 'CurrentCamera' then
        local newCamera = workspace.CurrentCamera
        if newCamera then
            Camera = newCamera

            if CameraSubjectChangeConn then
                CameraSubjectChangeConn:disconnect()
            end

            CameraSubjectChangeConn = Camera:GetPropertyChangedSignal("CameraSubject"):connect(OnCameraSubjectChanged)
            OnCameraSubjectChanged()
        end
    end
end

-------------------------
--| Exposed Functions |--
-------------------------

function PopperCam:Update(EnabledCamera)
    if PopperEnabled then
        -- First, prep some intermediate vars
        local cameraCFrame = Camera.CFrame
        local focusPoint = Camera.Focus.p

        if FFlagUserPortraitPopperFix and SubjectPart then
            focusPoint = SubjectPart.CFrame.p
        end

        local ignoreList = {}
        for _, character in pairs(PlayerCharacters) do
            ignoreList[#ignoreList + 1] = character
        end
        -- I added this v
        for _, Children in next, workspace:GetChildren() do
            if Children.Name == "Model" then
                ignoreList[#ignoreList + 1] = Children
            end
        end
        -- I added this ^
        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

        -- Stop shift lock being able to see through walls by manipulating Camera focus inside the wall
        if EnabledCamera and EnabledCamera:GetShiftLock() and not EnabledCamera:IsInFirstPerson() then
            if EnabledCamera:GetCameraActualZoom() < 1 then
                local subjectPosition = EnabledCamera.lastSubjectPosition 
                if subjectPosition then
                    Camera.Focus = CFrame_new(subjectPosition)
                    Camera.CFrame = CFrame_new(subjectPosition - MIN_CAMERA_ZOOM*EnabledCamera:GetCameraLook(), subjectPosition)
                end
            end
        end
    end
end

--------------------
--| Script Logic |--
--------------------

-- Connect to the current and all future cameras
workspace.Changed:connect(OnWorkspaceChanged)
OnWorkspaceChanged('CurrentCamera')

-- Connect to all Players so we can ignore their Characters
PlayersService.ChildRemoved:connect(OnPlayersChildRemoved)
PlayersService.ChildAdded:connect(OnPlayersChildAdded)
for _, player in pairs(PlayersService:GetPlayers()) do
    OnPlayersChildAdded(player)
end

return PopperCam

Answer this question