2
votes

I'm new to programming in LUA, although I've learned similar languages like JS. It's frustrating if I have to alter the same script in many parts in a group by replacing each script, and I don't know of an elegant way to do it. Instead, I decided to nest all the parts inside of the script. I've seen some examples and I've tried to adapt some of them, but they don't exactly apply to what I want to do and I can't get them to work.

In essence, what I'm trying to do is monitor all the bricks for a player to contact them. I took the original disappearing brick script that was nested inside each brick and modified it. If a part (brick) is touched, that should call the onTouch function, which will make the brick's transparency decrease over time until the in pairs loop is done, after which the brick disappears and CanCollide is turned off. After 2 seconds, it then returns back to normal. I think the problem is with the coding I used to monitor the parts as I don't really understand the right way to monitor multiple objects. Can someone please help? Thanks!

File structure:

File structure

function onTouched(brick)
    local delay = .1 -- the delay between each increase in transparency (affects speed of disappearance)
    local RestoreDelay = 2 -- delay before the brick reappears
    local inc = .1 -- how much the brick disappears each time

    -- All characters have a Humanoid object
    -- if the model has one, it is a character
    local h = script.Child:findFirstChild("Humanoid") -- Find Humanoids in whatever touched this
    if (h ~=nil) then -- If there is a Humanoid then
        h.Health = h.MaxHealth -- Set the health to maximum (full healing)
        for x=0,1, inc do
            script.Child.Transparency = x+inc
            script.Child.CanCollide = true
            wait(delay)
        end
        wait(delay)
        script.Child.Transparency = 1
        script.Child.CanCollide = false
        wait(RestoreDelay)
        script.Child.Transparency = 0
        script.Child.CanCollide = true
    else
    end
end

while true do
    local bricks=script:GetChildren():IsA("basic.part")
    for x=1,brick in pairs(bricks) do
        brick.Touched:connect(onTouched(brick)) -- Make it call onTouched when touched
    end
end
end
1

1 Answers

2
votes

For the most part, you've gotten it right, but you've got a few syntax errors where there are different conventions between JavaScript and Lua.

In JS, you would fetch an array of objects and then bee able to filter it immediately, but in Lua, there is limited support for that. So a line like :

var bricks = script.GetChildren().filter(function(item) 
   return item === "basic.part"
end)

cannot be done all in one line in Lua without assistance from some library. So you'll need to move the check into the loop as you iterate over the objects.

Other than that, the only other thing to change is the onTouched handler's function signature. The BasePart.Touched event tells you which object has touched the brick, not the brick itself. But by creating a higher order function, it's easy to get access to the brick, and the thing that touched it.

-- create a helper function to access the brick and the thing that touched it
function createOnTouched(brick)
    -- keep track whether the animation is running
    local isFading = false

    return function(otherPart)
        -- do not do the animation again if it has already started
        if isFading then
            return
        end

        local delay = .1 -- the delay between each increase in transparency (affects speed of disappearance)
        local restoreDelay = 2 -- delay before the brick reappears
        local inc = .1 -- how much the brick disappears each time

        -- All characters have a Humanoid object, check for one
        local h = otherPart.Parent:FindFirstChild("Humanoid")
        if h then
            -- heal the player
            h.Health = h.MaxHealth

            -- start fading the brick
            isFading = true
            brick.CanCollide = true
            for i = 0, 1, inc do
                brick.Transparency = i
                wait(delay)
            end
            -- turn off collision for the brick
            wait(delay)
            brick.Transparency = 1
            brick.Anchored = true
            brick.CanCollide = false

            -- turn the part back on
            wait(restoreDelay)
            brick.Transparency = 0
            brick.CanCollide = true

            -- reset the animation flag
            isFading = false
        end
    end
end

-- loop over the children and connect touch events
local bricks = script:GetChildren()
for i, brick in ipairs(bricks) do
    if brick:IsA("BasePart") then
        local onTouchedFunc = createOnTouched(brick)
        brick.Touched:Connect(onTouchedFunc)
    end
end