So I was making a script that gives you 5 cash every minute, I also made a game pass for the script if someone owns the game pass they get double money as the Non-game pass holders. Here is my script
I Haven't any scripts to give cash but the problem is in the 2nd script block, the console print an error :
09:10:57.466 ServerScriptService.CashGiver:6: attempt to index nil with 'UserId' - Server - CashGiver:6
local Give5Cash = game.ReplicatedStorage:WaitForChild("Give5Cash")
local Give10Cash = game.ReplicatedStorage:WaitForChild("Give10Cash")
Give5Cash.OnServerEvent:Connect(function()
print("Player Will Be Given 5 Cash")
end)
Give10Cash.OnServerEvent:Connect(function()
print("Player Will Be Given 10 Cash")
end)
while wait() do
local MPS = game:GetService("MarketplaceService")
local id = 16031172
local player = game.Players.LocalPlayer
if MPS:UserOwnsGamePassAsync(player.UserId, id) then
game.ReplicatedStorage:WaitForChild("Give10Cash"):FireServer()
print("Player Owns 2x Cash")
else
print("Players Doesnt Owns 2x Cash")
game.ReplicatedStorage:WaitForChild("Give5Cash"):FireServer()
end
wait(5)
end
local player = Players.LocalPlayer
if MPS:UserOwnsGamePassAsync(player.UserId, id) then
...
Here you assign a nil value to player which you may not index but do.
From the Roblox manual:
Players.LocalPlayer
NotReplicated
This item is not replicated across Roblox’s server/client boundary.
LocalPlayer is a read-only property which refers to the Player whose
client is running the game.
This property is only defined for LocalScripts (and ModuleScripts
required by them), as they run on the client. For the server (on which
Script objects run their code), this property is nil.
So I figured out a way to solve this issue and I have got the answer for my question.
Here is how I did it I made 3 scripts in ServerScriptService with the name of CashGiver5, CashGiver10, and CashGiverHandler
here are the scripts I added to each script.
CashGiver5:
while wait(1) do
print("Giving Player 5 Cash ")
for i, player in pairs(game.Players:GetPlayers()) do
player:WaitForChild("leaderstats").Cash.Value += 5
end
end
CashGiver10:
while wait(1) do
print("Giving Player 10 Cash ")
for i, player in pairs(game.Players:GetPlayers()) do
player:WaitForChild("leaderstats").Cash.Value += 10
end
end
CashGiverHandler:
local MarketPlace = game:GetService("MarketplaceService")
game.Players.PlayerAdded:Connect(function(player)
local g = 16031172 -- DOUBLE CASH ID
local Give5Script = game.ServerScriptService.CashGiver5
local Give10Script = game.ServerScriptService.CashGiver10
if MarketPlace:UserOwnsGamePassAsync(player.UserId, g) then
Give5Script:Destroy()
else
Give10Script:Destroy()
end
end)
WHAT THE SCRIPT DOES?
So basically the CashGiver scripts are basic scripts giving player Cash every second.
so the Handler script Destroys one of the scripts (s) when a player is added to the game.
Related
I'm making a game where you ram cars into houses and it unanchored the parts that are touched by a part in the front of the car. I want to have it so that whenever you unanchor a part, you get a coin
local HitPart = script.Parent
local function onTouch(otherPart)
local player = otherPart.Parent
if otherPart then
local player = game.Players:FindFirstChild(otherPart.Parent.Name)
if otherPart then
game.Players.LocalPlayer.leaderstats.coins.Value = game.Players.LocalPlayer.leaderstats.coins.Value + 1
end
end
end
HitPart.Touched:Connect(onTouch)
HitPart is the part that is touching the other parts. However, I keep getting "attempt to index nil with 'leaderstats'" error. does anyone know whats wrong?
Have you created the leaderstats inside the player? Here's an in-depth article about In-game leaderboards by Roblox
The error is telling you that you are trying to access the leaderstats of a player that doesn't exist.
You have a few issues.
Since this is (probably) a Script, game.Players.LocalPlayer doesn't exist. LocalPlayer only exists in LocalScripts.
Since the Touched signal will fire for any object that touches it, you need to add safety checks that the player object actually exists
To make finding a player easier, I would recommend the Players:GetPlayerFromCharacter function. You pass it a Model from the Workspace, and it tells you if you've got a Player.
local HitPart = script.Parent
local function onTouch(otherPart)
local characterModel = otherPart.Parent
local player = game.Players:FindPlayerFromCharacter(characterModel)
if player then
local coins = player.leaderstats.coins
coins.Value = coins.Value + 1
end
end
HitPart.Touched:Connect(onTouch)
I have made a major part of the code, but I am stuck in the important part. Here is what I'm doing:
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local productID = 1218445231
local productInfo = MarketplaceService:GetProductInfo(productID, Enum.InfoType.Product)
script.Parent.MouseButton1Click:Connect(function()
local function promptPurchase()
local player = Players.LocalPlayer
MarketplaceService:PromptProductPurchase(player, productID)
purchased = true
end
end)
if purchased == true then
--stuck here (if you don't understand, the tsunami that I've made is supposed to become visible and start moving towards the map, however the part is in "Workspace". The button is in "StarterGUI". Please help.)
end
EDIT: Now updated the code, still don't know what to do. Do I get the workspace Service? If so, how do I code it that it sets the transparency of the tsunami to "0", and starts moving? This is my code:
local MarketplaceService = game:GetService("MarketplaceService")
local player = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PurchaseEvent = ReplicatedStorage.PurchaseEvent
local productID = 1218445231
script.Parent.MouseButton1Click:Connect(function()
PurchaseEvent:FireServer(productID)
end)
if MarketplaceService:PlayerOwnsAsset(1218445231) then
--Make tsunami become visible and start moving
end
In the docs for MarketplaceService, there's a note
the callback ProcessReceipt which must be well defined so that transactions do not fail.
After the purchase prompt is shown to the player, ProcessReceipt is called with the results of their choice. So that callback is how you make something happen after a user buys something.
A good structure for this kind of code is to have product purchases handled in a server Script, and to have UI elements communicate purchase intents using RemoteEvents. So do some setup :
Create a RemoteEvent in ReplicatedStorage, name it something like "PurchaseEvent"
Create a Script in ServerScriptService
Then update your LocalScript to look like this :
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PurchaseEvent = ReplicatedStorage.PurchaseEvent
local productID = 1218445231
-- listen for when players click the button to buy the product
script.Parent.MouseButton1Click:Connect(function()
-- tell the server that we want this product
PurchaseEvent:FireServer(productID)
end)
Then add this code to the server Script to handle the purchase :
local MarketplaceService = game:GetService("MarketplaceService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local PurchaseEvent = ReplicatedStorage.PurchaseEvent
-- listen for when players want to buy things :
PurchaseEvent.OnServerEvent:Connect(function(player, productID)
-- show the purchase prompt to the user
MarketplaceService:PromptProductPurchase(player, productID)
end)
-- Define what should happen if a player buys something
-- NOTE - ADD FUNCTIONS FOR EACH SPECIFIC PRODUCT
local productHandlers = {}
productHandlers[1218445231] = function(player)
print("TODO : spawn a tsunami")
end
-- Listen for when someone clicks on any of the buttons in the purchase prompt
MarketplaceService.ProcessReceipt = function(receiptInfo)
-- Find the player who made the purchase in the server
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if not player then
-- The player probably left the game, don't charge them yet
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- Look up handler function from 'productHandlers' table above
local handler = productHandlers[receiptInfo.ProductId]
if not handler then
error(string.format("No handler is defined for %d", receiptInfo.ProductId))
end
-- Call the handler function and catch any errors
local success, result = pcall(handler, player)
if not success or not result then
local message = table.concat({
"Error occurred while processing a product purchase",
" - ProductId: " .. tostring(receiptInfo.ProductId),
" - Player: " .. player.Name,
}, "\n")
warn(message)
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- IMPORTANT: Tell Roblox that the game successfully handled the purchase
return Enum.ProductPurchaseDecision.PurchaseGranted
end
If you want to check if a user has bought something in the past and you don't want to charge them again, you can always check before you show the purchase prompt with the MarketplaceService:PlayerOwnsAsset function.
I'm scripting a lawn-mowing game in Roblox Studio and I've come across a problem. So every time I cut the grass(trawa) the IntValue goes up by 1. It works fine when it is assigned to a pick-up object and the points go straight to Player's Inventory folder:
local trawa = script.Parent
local function collect(otherPart)
local player = game.Players:FindFirstChild(otherPart.Parent.Name)
if player then
local trawaType = trawa.Name
local trawaStat = player.Inventory:FindFirstChild(trawaType)
if trawaStat then
trawa:Destroy()
trawaStat.Value = trawaStat.Value + 1
end
end
end
trawa.Touched:Connect(collect)
So that script works fine, but that's not the way I want it to work. I want the points to be assigned directly after cutting grass, not after I collect a pick-up it drops. So I changed the script above so that the points are assigned to the tool's inventory and then are copied to player's inventory.
local trawa = script.Parent
local function onTouch(otherPart)
local tool = otherPart.Parent
if tool:IsA('Tool') and tool.Kosa.Value == true then
trawa.Parent = nil
local trawaType = trawa.Name
local trawaStat = tool.Inventory:FindFirstChild(trawaType)
trawaStat.Value = trawaStat.Value + 1
print(trawaStat.Value)
wait(3)
trawa.Parent = workspace
end
end
trawa.Touched:Connect(onTouch)
The value does indeed change because it goes up when I print it, but it's not changing in the properties and is not registered by other scripts, because it's not copied to player's inventory.
Then this is the script in ServerScriptService that should transfer points from the tool to player:
local starter = game:GetService("StarterPack")
local tool = starter:FindFirstChildWhichIsA('Tool')
local player = game:GetService("Players").LocalPlayer
function points(player)
player.Inventory.Trawa2.Value = player.Inventory.Trawa2.Value + tool.Inventory.Trawa2.Value
tool.Inventory.Trawa2.Value = 0
end
tool.Inventory.Trawa2.Changed:Connect(points)
Changing IntValue to NumberValue doesn't solve the problem.
Use a local script with a RemoteEvent that runs it in server script, local scripts are client side. So they don't save to the server, but if you run it on the server, it saves.
Click this link if you want to know more about RemoteEvents.
https://roblox.fandom.com/wiki/Class:RemoteEvent
I made a cash for kill script in Roblox, but wanted to go further than that and implement a script where when a player has a gamepass, then that player would recieve more cash than another normal player would.
This is for a battle royale styled game in Roblox, and when I playtested it, there were no errors, but the script didn't work.
game.Players.PlayerAdded:connect(function(player)
local folder = Instance.new("Folder",player)
folder.Name = "leaderstats"
local currency1 = Instance.new("IntValue",folder)
currency1.Name = "Cash"
local increment = 50
if game:GetService("MarketplaceService"):PlayerOwnsAsset(player,7382818)then
increment = increment + 50
end
player:WaitForChild("Humanoid").Died:connect(function()
local tag = player.Humanoid:FindFirstChild("creator")
if tag ~= nil then
local killer = tag.Value
if killer ~= nil then
-- Find the killer's leaderstats folder
local killerStats = killer:FindFirstChild("leaderstats")
if killerStats ~= nil then
-- Find the killer's Cash IntValue
local killerCash = killerStats:FindFirstChild("Cash")
-- Increase cash as before
killerCash.Value = killerCash.Value + increment
end
end
end
end)
I expected a VIP player, who has the gamepass, to receive more cash, but when I tested it, no player received any cash for killing another player at all.
How to fix an end expected error near eof
If the Lua interpreter complains about a missing end you`re missing it somewhere.
Read through your code and make sure everything that is supposed to be closed with an end has one. Read through the Lua Reference Manual to find out which keywords need an end.
In your code it's if statements and function definitions. Checking each pair from inside out you'll end up one end) short to close this game.Players.PlayerAdded:connect(function(player) as mentioned in the comments.
Some simple code
script.Parent.MouseButton1Up:connect(function()
????.leaderstats.lvl.Value = 0
????.leaderstats.xp.Value = 0
????.leaderstats.gold.Value = 0
It's not even working. So the player clicks the gui, but how can it reset the players leaderstats, specifically lvl, xp, and gold, I run a fairly popular roblox rpg game with about 400 people right now and this would be an immense help.
You could put the following code in a LocalScript inside your button.
Player = game.Players.LocalPlayer --Only works inside a localscript, replace with the line below it if you need it as a Script.
-- Player=script.Parent while (not Player:IsA("Player")) do Player = Player.Parent end
script.Parent.MouseButton1Up:connect(function()
local index, stat
for index, stat in pairs(Player.leaderstats:GetChildren()) do
stat.Value = 0
end
end)
It should be in a LocalScript, so you can just use the LocalPlayer variable to get the leaderstats and set them.