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

Random Event then Destory() not working?

Asked by
iFlusters 355 Moderation Voter
9 years ago

So what the code is suppose to do, when there are no more Parts in 'Trunk' then it randomly select a Part from Leaves and remove it, here's the code:

function DLeaves()
    local Leaves = script.Parent:WaitForChild("Leaves"):GetChildren()
    local Trunk = script.Parent:WaitForChild("Trunk"):GetChildren()
    if #Leaves == 0 then
        return;
    end

    if #Trunk == 0 then
        Random = math.random(1, #Leaves)
        Random2 = Random

        while Random == Random2 do
            Random2 = math.random(1, #Leaves)
            wait()
        end
    Chosen = Leaves[Random] 
    Chosen2 = Leaves[Random2]
    end
    Chosen:Destroy()
    Chosen2:Destroy()
end

while true do
    wait(0.5)
    DLeaves()
end

Output: http://prntscr.com/9qk5gy

0
Nothing works with it, added output in a prntscr. iFlusters 355 — 9y
0
is return suposed to be break? lukeb50 631 — 9y

2 answers

Log in to vote
2
Answered by
XAXA 1569 Moderation Voter
9 years ago

In addition to what Spongocardo said:

*while Random == Random2 do will loop forever when #Leaves is 1, since math.random(1, 1) will always return 1. .

*math.random can be called without a second argument (i.e. using math.random(10) will return a random integer from 1 to 10)

*The while true do loop in the bottom will run even if the tree doesn't need to wilt. While this might not be a problem when there's only one tree, it will when you have more.

*In addition, the loop will never stop even if there are no leaves left in the tree.

*This program overall is poorly designed (what if you want to change how many leaves are removed per tick? What if you want to change how the leaves disappear?)

Try this:

-- Load some variables into the script
local Trunk = script.Parent:WaitForChild("Trunk")
local Leaves = script.Parent:WaitForChild("Leaves")
-- Delay between wilting steps
local WILT_DELAY = 0.5
-- Amount of leaves to wilt per step
local WILT_AMOUNT = 2

-- Once called, the leaves on the tree will start to wilt
function Wilt()
    Leaves_Parts = Leaves:GetChildren()
    -- Called whenever a leaf is shed.
    local function ShedLeaf(leaf)
        leaf:Destroy()
    end
    -- Wilts a number of leaves specified by "number"
    local function WiltStep(number)
        -- if there are less than "number" parts left in Leaves, wilt the rest.
        for i = 1, math.min(number, #Leaves_Parts) do
            -- select a random leaf to wilt
            local rand = math.random(#Leaves_Parts)
            ShedLeaf(Leaves_Parts[rand])
            table.remove(Leaves_Parts, rand)
        end
    end

    --loops until there are no leaves left
    while #Leaves_Parts > 0 do 
        wait(WILT_DELAY)
        WiltStep(WILT_AMOUNT)
    end
    --print("Wilting Ended")
end

-- Called whenever something is removed from Trunk. When there are no parts left in the trunk, Wilt() is executed.
Trunk.ChildRemoved:connect(function (_)
    local Trunk_Parts = Trunk:GetChildren()
    if #Trunk_Parts == 0 then
        -- print("Wilting...")
        Wilt()
    end
end)

--print("Script Loaded")
0
I appreciate what you are saying, and your help too. But I am not very good at coding so please don't criticise me, after all this is a help site. iFlusters 355 — 9y
0
Very good answer, upvoted. Spongocardo 1991 — 9y
Ad
Log in to vote
2
Answered by 9 years ago

The problem is that if there are parts in the trunk, the Random and Random2 variables will never be assigned, therefore the script would be trying to destroy a nil value. This is why the output says that you're attempting to index 'Chosen', which would be a nil value.

To fix this, you should have the Destroy method(s) inside of the if statement so that the leaves are only destroyed when the number of parts in 'Trunk' equals 0, which will be when the random variables are assigned.


function DLeaves()
    local Leaves = script.Parent:WaitForChild("Leaves"):GetChildren()
    local Trunk = script.Parent:WaitForChild("Trunk"):GetChildren()
    if #Leaves == 0 then
        return;
    end

    if #Trunk == 0 then
        local Random = math.random(1, #Leaves) --It's quicker to access local variables than global ones.
        local Random2 = Random --Same as above.

        while Random == Random2 do
            Random2 = math.random(1, #Leaves) --No need for local before Random2 here since we've already assigned Random2 earlier.
            wait()
        end
        Leaves[Random]:Destroy() --No need to assign a variable here, just do Leaves[Random].
        Leaves[Random2]:Destroy() --Same as above.
    end
end

while true do
    wait(0.5)
    DLeaves()
end


I hope my answer helped you. If it did, be sure to accept it.

Answer this question