Attempt to Call an Instance Value on Badge Script

Hi, i have been trying to solve this script for a while now but i still get the same on the dev console, I want to make a script that awards a badge to the players when they get a certain amount of kills in the leaderboard, the problem here is the script to give away these badges, i searched on the devforum for anything related to this and found this topic;

I used the code but i ended up getting this on the developer console when testing;

DevForum instance value problem

Take in count the leaderstats code works fine and it’s appart from this one, i’m trying to add this new badges to my game. (Just to let you know, because i’m bad at scripting)

This is the code of the script (Inside ServerScriptService):

local badgeService = game:GetService("BadgeService")
local badge1Id = 2130225321
local badge2Id = 2130228253
local badge3Id = 2130230336
local badge4Id = 2130230426

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats")("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 1 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge1Id) then
			badgeService:AwardBadge(player.UserId, badge1Id) -- Give the badge
			print(player.Name "has achieved the badge First Blood")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats")("Total Kills")-- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 10 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge2Id) then
			badgeService:AwardBadge(player.UserId, badge2Id) -- Give the badge
			print(player.Name "has achieved the badge Newbie Contractor")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats")("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 50 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge3Id) then
			badgeService:AwardBadge(player.UserId, badge3Id) -- Give the badge
			print(player.Name "has achieved the badge Advanced Contractor")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats")("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 100 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge4Id) then
			badgeService:AwardBadge(player.UserId, badge4Id) -- Give the badge
			print(player.Name "has achieved the badge Veteran Contractor")
		end
		end
	end, warn))
end)

If anyone could help me to find out what’s going on here i would really appreciate it! Any response will be thanked.

1 Like

I haven’t read the script yet but that error means you’re trying to call an instance, like a part or a remoteevent as a function. Like this:

part()

You should check your variables, as it seems as the error is occuring on multiple lines.

I think I know where it is.

local scoreVal = player:WaitForChild("leaderstats")("Total Kills")

Are you sure this is what you wanted to do? I think you meant [] brackets.

1 Like

Yeah, that’s where the problem is located, that’s what i didn’t know how to solve, what i try to do there is make “scoreVal” get the Value of the Kills the Player has on the Leaderstats so then we could get it in order to award the badge if the condition is met, how should i write this? Should i use Brackets instead? How’s that so simple?

Try changing this to:

player:WaitForChild("leaderstats"):WaitForChild("Total Kills") 

and repeat that for anything which has a WaitForChild with another instance name at the end of it, I assume you tried to :WaitForChild on Total Kills here with leaderstats also waiting to get to that part, but you need to also clarify that you want to WaitForChild of “Total Kills”, as well as “leaderstats”.

1 Like

Okay thank you, i will be trying that as soon as i go to studio again :smiley:

Alright so i did that and this is what i got;
Devforum problem 2

Can you showcase your script one more time with the edits you’ve made?

Sure, here it is;

local badgeService = game:GetService("BadgeService")
local badge1Id = 2130225321
local badge2Id = 2130228253
local badge3Id = 2130230336
local badge4Id = 2130230426

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats"):WaitForChild("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 1 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge1Id) then
			badgeService:AwardBadge(player.UserId, badge1Id) -- Give the badge
			print(player.Name "has achieved the badge First Blood")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats"):WaitForChild("Total Kills")-- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 10 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge2Id) then
			badgeService:AwardBadge(player.UserId, badge2Id) -- Give the badge
			print(player.Name "has achieved the badge Newbie Contractor")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats"):WaitForChild("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 50 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge3Id) then
			badgeService:AwardBadge(player.UserId, badge3Id) -- Give the badge
			print(player.Name "has achieved the badge Advanced Contractor")
		end
		end
	end, warn))
end)

game.Players.PlayerAdded:Connect(function(player) -- This only happens once
	local scoreVal = player:WaitForChild("leaderstats"):WaitForChild("Total Kills") -- Wait for the leaderstats to be added to the player from your other script
	scoreVal.Changed:Connect(xpcall(function() -- This function is triggered whenever the value changes
		if scoreVal.Value >= 100 then
		if not badgeService:UserOwnsBadgeAsync(player.UserId, badge4Id) then
			badgeService:AwardBadge(player.UserId, badge4Id) -- Give the badge
			print(player.Name "has achieved the badge Veteran Contractor")
		end
		end
	end, warn))
end)```

Sorry for the delay, I stepped away from my PC for a bit. It seems like this new error is in relation to how you’ve set up the xpcall. I’m quite honestly not too familiar with using it however to my understanding, you can set it up as the following (someone please correct me if I’m wrong, I don’t often use anything with xpcall):

local succ, err = xpcall(function()
	print("Example code.")
end, function()
	print("This fires if the code fails to run for whatever reason.")
end)

However in terms of maintainability for your code this might be a hassle to implement, I think it overall is a better idea, if you chose to go down this path, to rewrite the code to something more efficient, I’ve tried my best to provide an example below which only uses one PlayerAdded event, by no means is this the best option (if it fails to give the badge once it won’t give it again because were using the index to compare, but maybe whenever they join the game you can loop through the table and award the badge, or add some logic to retry since youll probably mostly be catching one off internal server errors), but feel free to look at it and see a few ways to achieve what you’re looking for!

local badgeService = game:GetService("BadgeService")

local KillsTable = { -- [1] would be the amount of kills needed, and 2130225321 would be the badge id.
	[1] = 2130225321,
	[10] = 2130228253,
	[50] = 2130230336,
	[100] = 2130230426,
	
}

game.Players.PlayerAdded:Connect(function(player)
	local scoreVal = player:WaitForChild("leaderstats"):WaitForChild("Total Kills") 
	
	scoreVal:GetPropertyChangedSignal("Value"):Connect(function()
		if KillsTable[scoreVal.Value] then
			local succ, err = xpcall(function()
				if not badgeService:UserHasBadgeAsync(player.UserId, KillsTable[scoreVal.Value]) then
					badgeService:AwardBadge(player.UserId, KillsTable[scoreVal.Value])
					print("Awarded Badge!")
				end
			end, function(err)
				warn("Failed to award badge: "..err)
			end)
		end
	end)
end)

Let me know if this code brings you any issues or if you have questions!

1 Like

Interesting! Thank you for the help no problem on the delay, i had to go too. This seems to be a better looking code at least for the server it will be.

I will test it later and let you know the results, again, thank you for the response :+1:

Alright so I tested it and it is working! However I got a small issue, I already had 4 Total Kills and I didn’t get the first badge of 1 kill, when I got 10 Total Kills I received the 2nd Badge but not the 1st one.

I see you have used GetPropertyChangedSignal, i suposse this can still work in order to make the badge be awarded when you have a greater value than 1 and not having the badge already.

Not sure yet if it’s done at line 16, but the code you sent it’s almost working as intended! So thank you for the help

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