Test script is able to find stringValue in localplayer, but the real script couldn't

  1. What do you want to achieve? Keep it simple and clear!

I have a system that autosaves 2 stringValues in the player’s localcharacter: “HelmetEquipped” and “VestEquipped” with a localscript in StarterPlayerScripts that scans for the values of the two strings and assigns maxhealth buffs based on the combinations of different vests and/or helmets in the strings, updating the healthGUI before firing a serverevent to change the player’s health on the server side.
image
image

  1. What is the issue? Include screenshots / videos if possible!

The healthbuff localscript to update the healthGUI and fire the remoteevent to the server won’t detect the stringvalues of the player’s helmet/vest somehow, while a test script is able to. I referenced the same things but for some reason the test script can always recognize it while the actual script couldn’t

TEST SCRIPT:

local Players = game:GetService("Players")
local Player = Players.LocalPlayer

-- Function to constantly check and print based on EquippedHelmet value
local function checkEquippedHelmet()
	while true do
		-- Wait for the EquippedHelmet to be available
		local EquippedHelmet = Player:WaitForChild("EquippedHelmet")

		-- Check the value of EquippedHelmet and print the corresponding message
		if EquippedHelmet.Value == "EliteHelmet" then
			print("Player is wearing the EliteHelmet")
		else
			print("No longer wearing the EliteHelmet")
		end

		-- Wait for a short period before checking again to avoid performance issues
		wait(1)  -- Adjust the wait time as needed
	end
end


checkEquippedHelmet()

ACTUAL SCRIPT:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local healthUpdateEvent = ReplicatedStorage:WaitForChild("HealthUpdateEvent")

-- Base health and bonuses Table
local baseMaxHealth = 100
local vestBonuses = {
	EliteVest = 250,
	BasicVest = 100,
	SpecVest = 400
}
local helmetBonuses = {
	BasicHelmet = 100,
	GasMask = 100,
	EliteHelmet = 100
}

-- Function to update the health bar
local function updateHealthBar(humanoid)
	print("Updating health bar...")
	if not humanoid then
		warn("Humanoid not found.")
		return
	end

	local player = Players.LocalPlayer
	local healthGui = player.PlayerGui:FindFirstChild("HealthGUI")
	if not healthGui then
		warn("HealthGUI not found.")
		return
	end

	local healthBarFrame = healthGui:FindFirstChild("HealthBarFrame")
	if not healthBarFrame then
		warn("HealthBarFrame not found in HealthGUI.")
		return
	end

	local fillFrame = healthBarFrame:FindFirstChild("FillFrame")
	local bonusFillFrame = healthBarFrame:FindFirstChild("BonusFillFrame")
	local healthText = healthBarFrame:FindFirstChild("HealthText")

	if not fillFrame or not bonusFillFrame or not healthText then
		warn("FillFrame, BonusFillFrame, or HealthText not found in HealthBarFrame.")
		return
	end

	local fillPercentage = humanoid.Health / humanoid.MaxHealth
	fillFrame.Size = UDim2.new(math.min(baseMaxHealth / humanoid.MaxHealth, fillPercentage), 0, 1, 0)
	bonusFillFrame.Size = UDim2.new(math.max(0, fillPercentage - baseMaxHealth / humanoid.MaxHealth), 0, 1, 0)
	bonusFillFrame.Position = UDim2.new(baseMaxHealth / humanoid.MaxHealth, 0, 0, 0)

	healthText.Text = string.format("%d / %d", humanoid.Health, humanoid.MaxHealth)
	print("Health bar updated.")
end

-- Function to calculate and apply health bonuses
local function calculateAndApplyBonuses()
	print("Calculating and applying bonuses...")
	local player = Players.LocalPlayer
	local character = player.Character
	if not character then 
		print("Character not found.")
		return 
	end

	local humanoid = character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		warn("Humanoid not found.")
		return
	end

	local vestBonus = 0
	local helmetBonus = 0

	-- Function to check and apply bonuses
	local function checkBonuses()
		local equippedVest = character:FindFirstChild("EquippedVest")
		local equippedHelmet = character:FindFirstChild("EquippedHelmet")

		if equippedVest and equippedVest:IsA("StringValue") then
			print("Equipped Vest found. Value:", equippedVest.Value)
			if vestBonuses[equippedVest.Value] then
				vestBonus = vestBonuses[equippedVest.Value]
			else
				print("No bonus for vest:", equippedVest.Value)
			end
		else
			print("EquippedVest not found or not a StringValue.")
		end

		if equippedHelmet and equippedHelmet:IsA("StringValue") then
			print("Equipped Helmet found. Value:", equippedHelmet.Value)
			if helmetBonuses[equippedHelmet.Value] then
				helmetBonus = helmetBonuses[equippedHelmet.Value]
			else
				print("No bonus for helmet:", equippedHelmet.Value)
			end
		else
			print("EquippedHelmet not found or not a StringValue.")
		end
	end

	-- Call the function once and then continuously check for updates
	checkBonuses()
	while true do
		checkBonuses()
		local newMaxHealth = baseMaxHealth + vestBonus + helmetBonus
		print("New Max Health:", newMaxHealth)
		humanoid.MaxHealth = newMaxHealth
		humanoid.Health = newMaxHealth
		updateHealthBar(humanoid)

		-- Notify the server
		if healthUpdateEvent then
			healthUpdateEvent:FireServer(newMaxHealth)
			print("Health update event fired to server.")
		else
			print("HealthUpdateEvent not found.")
		end

		wait(1)  -- Adjust the wait time as needed
	end
end

-- Listen for character being added
Players.LocalPlayer.CharacterAdded:Connect(function(character)
	print("Character added:", character.Name)
	character.ChildAdded:Connect(function(child)
		if child:IsA("StringValue") and (child.Name == "EquippedVest" or child.Name == "EquippedHelmet") then
			print(child.Name .. " added to character.")
			child:GetPropertyChangedSignal("Value"):Connect(function()
				print(child.Name .. " value changed to:", child.Value)
				calculateAndApplyBonuses()
			end)
		end
	end)

	-- Wait for the initial character load
	local humanoid = character:WaitForChild("Humanoid", 5)
	calculateAndApplyBonuses()
end)

-- Wait for the initial character load if it already exists
if Players.LocalPlayer.Character then
	print("Initial character detected.")
	local character = Players.LocalPlayer.Character
	local humanoid = character:WaitForChild("Humanoid", 5)
	calculateAndApplyBonuses()
end

I’m pretty sure you need to be searching in the player and not their character.

A couple of other bits as well.

  • I noticed you made a function within a function. It might be better to have that function seperate and pass the required values as parameters to that function so you aren’t creating a new one each time the main function is run.

  • You added an event listener each time one child of the character changes. This creates a lot of unneccessary connections for all the BaseParts and other things within the character which could slow your game down. It might be better to only create connections for each necessary item.

  • In your event listener function calculateAndApplyBonuses(), you use a while true do iteration, you update the humanoid health bar every second. Running this function so often will impact memory, especially considering each time the RBXScriptSignal fires another one of these iterations will be run in a seperate thread, asynchronously to the others. I’d recommend converting that to an event listener as well.

Thanks for your help, I greatly appreciate it and I was able to find the solution given your actionable feedback and clean up the code!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.