Great question, Local scripts and Server scripts are two diffrent things, luckly there is a sort of work around this whole problem.
and according to the Robox Wiki API:Class/BadgeService/UserHasBadge
it says that this should be called from a script as opposed to a local script, here's a quote
This item should be used with a Script (As opposed to a LocalScript) in order to work as expected in online mode. This method cannot be used in Edit mode. It should only be used from an online game server.
That being said you can easily avoid said problem with a script on the server side to check to see if they own said badge then reply back, you'll need a remote event for this.
P.S I've made a few changes to your initial code, but there should be a way to query the server and get a response and continue your code besides this.
P.P.S: You'll need to create a RemoteEvent in ReplicatedStorage.
Server Code:
Local BS = game:GetService("BadgeService")
Local event = game.ReplicatedStorage:WaitForChild("RemoteEvent")
event.OnServerEvent:Connect(function(plr, ...)
local tuple = {...}
if tuple[1] == "HasBadgeRequest" then
if BS:UserHasBadge(plr.UserId, tuple[2]) then
game:FireClient(plr, "HasBadge", tuple[2])
else
game:FireClient(plr, "NoBadge", tuple[2])
end
end
end)
LocalScript code:
local buyButton = script.Parent
local productId = 1280923639
event = game.ReplicatedStorage:WaitForChild("RemoteEvent")
local BadgesHas = {}
local BadgesNo = {}
event:FireServer("HasBadgeRequest", 0000)
event.OnClientEvent:Connect(function(...)
local tuple = {...}
if tuple[1] == "HasBadge" then
table.Insert(BadgesHas, tuple[2])
end
if tuple[1] == "NoBadge" then
table.Insert(BadgesNo, tuple[1])
end
end)
buyButton.MouseButton1Click:connect(function()
local badge = false
local badgeID = 000
for i,v in pairs(BadgesHas) do
if v == badgeID
badge = true
end
end
for i,v in pairs(BadgesNo) do
if v == badgeID then
badge = false
end
end
if badge == false then
game:GetService("MarketplaceService"):PromptProductPurchase(game.Players.LocalPlayer, productId)
else
game.Players.LocalPlayer.Character.Health = 0
end
end)
what I did was create a method encase you want to have multiple badge checks in one script.
the script asks the server if the user has a badge and returns a response, from there the script saves this response in the correct table, this may not be the best method as others may know of a different ones, but this is the only one I could think of.
(Edit: Fixed up version for the asker)
local buyButton = script.Parent
local productId = 1280923639
event = game.ReplicatedStorage:WaitForChild("RemoteEvent")
local PassHas = {}
local PassNo = {}
event:FireServer("HasPassRequest", 0000)
event.OnClientEvent:Connect(function(...)
local tuple = {...}
if tuple[1] == "HasPass" then
table.insert(PassHas, tuple[2])
end
if tuple[1] == "NoPass" then
table.insert(PassNo, tuple[1])
end
end)
buyButton.MouseButton1Click:connect(function()
local pass = false
local PassID = 000
for i,v in pairs(PassHas) do
if v == PassID then
pass = true
end
end
for i,v in pairs(PassNo) do
if v == PassID then
pass = false
end
end
if pass == false then
game:GetService("MarketplaceService"):PromptProductPurchase(game.Players.LocalPlayer, productId)
else
game.Players.LocalPlayer.Character.Health = 0
end
end)
server side
local mps = game:GetService("GamePassService")
local event = game.ReplicatedStorage:WaitForChild("RemoteEvent")
event.OnServerEvent:Connect(function(plr, ...)
local tuple = {...}
if tuple[1] == "HasPassRequest" then
if mps:PlayerHasPass(plr, tuple[2]) then
event:FireClient(plr, "HasPass", tuple[2])
else
event:FireClient(plr, "NoPass", tuple[2])
end
end
end)