1ForeverHD / ZonePlus

Construct dynamic zones that utilise region checking, raycasting and the new BasePart.CanTouch property to effectively determine players and parts within their boundaries.
https://devforum.roblox.com/t/zone/1017701
MIT License
74 stars 115 forks source link

Fully account for Streaming #56

Open 1ForeverHD opened 2 years ago

1ForeverHD commented 2 years ago
  1. Ensure :getRandomPoint() returns nil instead of recurring infinitely if zone parts are 0, e.g. if all streamed all:

    function Zone:getRandomPoint()
    local region = self.exactRegion
    local size = region.Size
    local cframe = region.CFrame
    local random = Random.new()
    local randomCFrame
    local success, touchingZoneParts
    local pointIsWithinZone
    local totalPartsInZone = #self.overlapParams.zonePartsWhitelist.FilterDescendantsInstances
    if totalPartsInZone <= 0 then
        -- Its important we return if there are no parts within the zone otherwise the checks below will recur infinitely.
        -- This could occur for example if streaming is enabled and the zone's parts disappear on the client
        return nil
    end
    repeat
        randomCFrame = cframe * CFrame.new(random:NextNumber(-size.X/2,size.X/2), random:NextNumber(-size.Y/2,size.Y/2), random:NextNumber(-size.Z/2,size.Z/2))
        success, touchingZoneParts = self:findPoint(randomCFrame)
        if success then
            pointIsWithinZone = true
        end
    until pointIsWithinZone
    local randomVector = randomCFrame.Position
    return randomVector, touchingZoneParts
    end
  2. line 87 of tracker so that it accounts for parts being streamed in:

    local function playerAdded(player)
    local function charAdded(character)
        local function trackChar()
            local hrp = character:WaitForChild("HumanoidRootPart", 0.1)
            local humanoid = character:WaitForChild("Humanoid", 0.1)
            local head = character:WaitForChild("Head", 0.1)
            if hrp == nil or humanoid == nil or head == nil then
                return
            end
            updatePlayerCharacters()
            self:update()
            for _, valueInstance in pairs(humanoid:GetChildren()) do
                if valueInstance:IsA("NumberValue") then
                    valueInstance.Changed:Connect(function()
                        self:update()
                    end)
                end
            end
        end
        local hrp = character:FindFirstChild("HumanoidRootPart")
        if hrp then
            task.delay(0.1, trackChar)
        else
            character.ChildAdded:Connect(function(child)
                if child.Name == "HumanoidRootPart" and child:IsA("BasePart") then
                    task.delay(0.1, trackChar)
                end
            end)
        end
    end
    if player.Character then
        charAdded(player.Character)
    end
    player.CharacterAdded:Connect(function(char)
        charAdded(char)
    end)
    player.CharacterRemoving:Connect(function(removingCharacter)
        self.exitDetections[removingCharacter] = nil
    end)
    end
tirliA1234 commented 2 years ago

and good