Search code examples
luaroblox

How can I change color depending on health?


I want to know how to edit my script below to make the color lower or higher depending on the health amount instead of a set amount in the script. Everything works currently, i'm just trying to edit the script to do what I said above.

local parts = script.Parent.Parent:WaitForChild("Collectables"):GetChildren()

for i, v in pairs(parts) do
    if v:IsA("Part") then
        if v:WaitForChild("ClickDetector") then
            if v:FindFirstChild("Values") then
                local Values = v:FindFirstChild("Values")
                Values.Red.Value = 0
                Values.Green.Value = 255
                Values.Blue.Value = 0
                Values.Health.Value = 100
                Values.Change.Value = true
                v.SurfaceGui.TextLabel.Text = 100
                Values.Color.Value = Color3.fromRGB(Values.Red.Value,Values.Green.Value,Values.Blue.Value)
                v.SurfaceGui.TextLabel.TextColor3 = Values.Color.Value
                v.ClickDetector.MouseClick:Connect(function()
                    if Values.Health.Value > 5 then
                        Values.Health.Value -= 5
                    else
                        v:Destroy()
                    end
                    if v:FindFirstChild("SurfaceGui") then
                        v.SurfaceGui.TextLabel.Text = v.SurfaceGui.TextLabel.Text - 5
                        if Values.Change.Value == true then
                            if Values.Red.Value < 250 then
                                Values.Red.Value += 50
                            elseif Values.Red.Value == 250 then
                                Values.Red.Value += 5
                            elseif Values.Red.Value == 255 and Values.Green.Value > 5 then
                                Values.Green.Value -= 50
                            elseif Values.Green.Value == 5 then
                                Values.Green.Value -= 5
                                Values.Change.Value = false
                            end
                            Values.Color.Value = Color3.fromRGB(Values.Red.Value,Values.Green.Value,Values.Blue.Value)
                            v.SurfaceGui.TextLabel.TextColor3 = Values.Color.Value
                        end
                    end
                end)
            end
        end
    end
end

Solution

  • Rather than use your stepwise function for calculating the color, a more simple way to handle this might be to define the colors you want ahead of time or simplify it down to ranges of colors based on health. Like,

    • if it's between 100 - 60, the color is green.
    • if it's between 60 - 30, it's yellow.
    • if it's less than 30, it is red.

    And to make the color react to the health, I would set up a series of dependencies using the Changed signal on your NumberValue objects.

    The ClickDetector's only job is to modify the health of the block. But when the health changes, the color values change. And when the color values change, the text color changes too.

    First off, delete the R, G, and B NumberValues, you can set the text color without them.

    local DEFAULT_HEALTH = 100
    local HEALTH_PER_CLICK = 5
    -- colors are sorted by health in descending order, add more as desired
    local COLORS = {
        { health = 60, color = Color3.fromRGB(  0, 255, 0)}, -- green
        { health = 30, color = Color3.fromRGB(255, 255, 0)}, -- yellow
        { health =  0, color = Color3.fromRGB(255,   0, 0)}, -- red
    }
    
    local function observeHealthChanges(values, textLabel)
        -- whenever the health changes, update the text and the text color
        local health = values.Health
        health.Changed:Connect(function(newValue)
            textLabel.Text = tostring(newValue)
    
            -- set the color based on the health by looping through the colors to find the right ones
            for i, colorData in ipairs(COLORS) do
                local colorRange = colorData.health
                local healthColor = colorData.color
                if newValue > colorRange then
                    textLabel.TextColor3 = healthColor
                    break
                end
            end
        end)
    end
    
    local function observeClicks(part, values, detector)
        local health = values.Health
    
        -- listen for clicks to reduce the health            
        detector.MouseClick:Connect(function()
            if health.Value > HEALTH_PER_CLICK then
                health.Value -= HEALTH_PER_CLICK
            else
                part:Destroy()
            end
        end)
    end
    
    local parts = script.Parent.Parent:WaitForChild("Collectables"):GetChildren()
    for _, v in ipairs(parts) do
        -- escape if the object isn't a part
        if v:IsA("Part") then
            
            -- escape if the part doesn't have Values, a ClickDetector, and a SurfaceGui
            local Values = v.Values
            local Detector = v.ClickDetector
            local Gui = v.SurfaceGui
            if Values and Detector and Gui then
            
                -- register the change listeners
                local textLabel = v.SurfaceGui.TextLabel
                observeHealthChanges(Values, textLabel)
                observeClicks(v, Values, Detector)
    
                -- set the health and all the rest will follow
                Values.Health.Value = DEFAULT_HEALTH
            end
        end
    end