LocalScript in StarterPlayerScripts checking for Attributes Constantly?

This script checks if the player has an attribute called “healthBuff” activated and then makes all of the ProximityPrompts named “HealthUpgradePrompt” in my game invisible while this player has it, however, if another script makes it visible again, it overrides this script.

Is there a way to have this script constantly checking so even when it does override, it will fix itself?

local Players = game:GetService("Players")
local player = Players.LocalPlayer
local healthBuffAttribute = "healthBuff"
local promptName = "HealthUpgradePrompt"

local function updatePromptVisibility()
	-- Check if the player has the healthBuff attribute and if it is true
	local hasHealthBuff = player:GetAttribute(healthBuffAttribute)

	-- Iterate through all the HealthUpgradePrompt instances in the workspace
	for _, prompt in pairs(workspace:GetDescendants()) do
		if prompt:IsA("ProximityPrompt") and prompt.Name == promptName then
			prompt.Enabled = not hasHealthBuff
		end
	end
end

-- Listen for attribute changes on the player
player:GetAttributeChangedSignal(healthBuffAttribute):Connect(updatePromptVisibility)

-- Initial check when the script runs
updatePromptVisibility()
1 Like

Honestly I think the best way to do this by being the most efficient is by going through each prompt and connecting them to a GetPropertyChangedSignal.
This is possibly within the for _,prompt in pairs loop you already have.
It’d be something along the lines of:

for i,v in pairs(array) do
 if v:IsA("ProxPromptAndAllThatOtherStuff") then
  v:GetPropertyChangedSignal("Enabled"):Connect(function()
   --change prompt visibility here
--insert ends here

The LocalScript can listen for the Enabled property to change for each ProximityPrompt through :GetPropertyChangedSignal() so that it can perform a check to see if the new value makes sense given the current value of the healthBuffAttribute. If the Enabled property was changed to a Value that it wasn’t supposed to be, it can override the change that was made by the other script.


To make this easier to do, with the side benefit of improving the performance of the script as a whole so that it wouldn’t need to loop through the entire Workspace every time that Attribute changes, you could assign a CollectionService Tag to each of the ProximityPrompts once on the server-side when the game first starts so that the client can retrieve all of them with CollectionService:GetTagged().

Along with that, it can keep track of all the relevant ProximityPrompts that are streamed in and out with the :GetInstanceAddedSignal() / :GetInstanceRemovedSignal() methods, which is especially important if you have StreamingEnabled enabled for your game.

  • Note: If there’s only a set number of ProximityPrompts named “HealthUpgradePrompt” in the game and none are added / created during runtime, then it’d be better to apply the tags in bulk while editing the game (either by selecting each one and adding it or through the command bar).

    If that’s the case, the code in the first example below would not need to be used during runtime, and could be pasted into the Command Bar instead (excluding the last line of code since it would not need to listen for new objects to be added to the Workspace while editing the game).


Here’s an example:

Example Script #1 (Server-sided code)

local CollectionService = game:GetService("CollectionService")


local promptName = "HealthUpgradePrompt"

local function applyProximityPromptTag(item)
    if item:IsA("ProximityPrompt") and item.Name == promptName then
        CollectionService:AddTag(item, promptName)
    end
end

for _, item in workspace:GetDescendants() do
    task.spawn(applyProximityPromptTag, item)
end

--[[ This could be improved further if you know specifically where all of the
relevant ProximityPrompts will be stored in the game --]]
workspace.DescendantAdded:Connect(applyProximityPromptTag)

Example Script #2 (Client-sided code; revision of code in original post)

(Reminder that this might not work right away, so it may need further revisions)

local CollectionService = game:GetService("CollectionService")
local Players = game:GetService("Players")

local player = Players.LocalPlayer
local healthBuffAttribute = "healthBuff"
local promptName = "HealthUpgradePrompt"

---

local currentHealthUpgradePrompts = {}
local enabledEventConnections = {}

local function updatePromptTable(prompt, add)
    local tableCheck = table.find(currentHealthUpgradePrompts, prompt)

    if add == true and tableCheck == nil then
        table.insert(currentHealthUpgradePrompts, taggedItem)
        return true

    elseif add == false and tableCheck ~= nil then
        table.remove(currentHealthUpgradePrompts, tableCheck)
        
        if enabledEventConnections[prompt] ~= nil then
            enabledEventConnections[prompt]:Disconnect()
            enabledEventConnections[prompt] = nil
        end
    end
end

local function checkEnabledProperty(prompt)
    local addedPromptToTable = updatePromptTable(prompt, true)

    if addedPromptToTable == true then

        enabledEventConnections[prompt] = prompt:GetPropertyChangedSignal("Enabled"):Connect(function()
     	    local hasHealthBuff = player:GetAttribute(healthBuffAttribute)
            if typeof(hasHealthBuff) ~= "bool" then return end

            if prompt.Enabled == hasHealthBuff then
                prompt.Enabled = not hasHealthBuff
            end
        end)

    end
end

for _, taggedItem in CollectionService:GetTagged(promptName) do
    checkEnabledProperty(taggedItem)
end

CollectionService:GetInstanceAddedSignal(promptName):Connect(checkEnabledProperty)

CollectionService:GetInstanceRemovedSignal(promptName):Connect(function(prompt)
    updatePromptTable(prompt, false)
end)

---

local function updatePromptVisibility()
	local hasHealthBuff = player:GetAttribute(healthBuffAttribute)
    if typeof(hasHealthBuff) ~= "bool" then return end

	for _, prompt in currentHealthUpgradePrompts do
		prompt.Enabled = not hasHealthBuff
	end
end

player:GetAttributeChangedSignal(healthBuffAttribute):Connect(updatePromptVisibility)

updatePromptVisibility()