How do I make a sell script? (Roblox) - lua

I have been making a Roblox simulator as a side project to learn how to make games, Now I have gotten some help as you can see below but it is still not working. I have got some pictures and videos in these links:
https://flickr.com/photos/195497771#N05
https://vimeo.com/user173767075
Currently my issue is still the title of my question and my tool not working. I changed it to a remote event and now it stopped changing my leaderstats. I have tried a bunch of different solutions but none work. My first script is my tool script. Here it is:
local player = game.Players.LocalPlayer
script.Parent.Activated:Connect(function()
if player.Debounce.Value == false then
game.ReplicatedStorage.Power:FireServer(script.Parent.Values)
local action = script.Parent.Parent.Humanoid:LoadAnimation(script.Parent.Animation)
action:Play()
end
end)
Now, that is in a LocalScript and that works. It prints that it activated and the animation plays. Now my problem is with a script in ServerScriptService not receiving the remote event. I have a print in it but nothing happens. Here is that script:
game.ReplicatedStorage.Power.OnServerEvent:Connct(function(player, valueFolder)
if player.Debounce.Value == false then
player.leaderstats.Sticks.Value += valueFolder.Power.Value
player.Debounce.Value = true
wait(valueFolder.Cooldown.Value)
player.Debounce.Value = false
end
end)
So, for my original question, the sell knows I touch it and it activates the event but nothing changes in the leaderstats. Here is my script to detect when the player touches the sell part.
local sellevent = game.ReplicatedStorage.Sell
script.Parent.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
print("sell fired")
sellevent:Fire()
end
end)
That script works. But that is a server script. Let me know if I should change it to a LocalScript. Now, here is my script that changes the leaderstats, it detects the the event fired but nothing changes in leaderstats.
game.ReplicatedStorage.Sell.Event:Connect(function(player)
print("bindable event fired")
if player ~= nil then
if player.leaderstats.Sticks.Value > 0 then
player.leaderstats.Cash.Value += player.leaderstats.Sticks.Value
player.leaderstats.Sticks.Value = 0
end
end
end)
I gave as much information as I could. If you need anything else I can get more pictures or videos but that is the best I could give. Any help appreciated!

Okay, after watching the video, I might have a hunch as to what's going wrong.
The code in your original question works just fine. If you were to print out the Sticks.Value before adding it to Cash.Value, you'd see that Sticks.Value stays at 0. And you were always adding 0 to Cash.
This is likely because you are using a Tool to increment Sticks.Value, and it is common for Tools to use LocalScripts to hook up logic. When you make changes to the world (or leaderstats values) in LocalScripts, those changes are only present on that client. They are not replicated up to the server. And since all of your cash logic is in server scripts, the Sticks value stays at 0 on the server.
So to fix this, you need to make sure that the code that increments Sticks.Value happens in a Script. And you can do that by using RemoteEvents in the same way you're using your BindableEvent, to communicate from the tool up to a server script.
So in your Tool's LocalScript you'd do something like this :
-- find the RemoteEvent saved in ReplicatedStorage
local stickEvent = game.ReplicatedStorage.GetSticksEvent
-- listen for when the Tool is used
script.Parent.Activated:Connect(function()
-- tell the server to give us some sticks...
stickEvent:FireServer()
end)
Then, in a server Script, listen for that RemoteEvent to fire to give the player some sticks :
-- find the RemoteEvent saved in ReplicatedStorage
local stickEvent = game.ReplicatedStorage.GetSticksEvent
-- listen for when the client tells us that they got some sticks
stickEvent.OnServerEvent:Connect(function(player)
-- give the player some sticks
player.leaderstats.Sticks.Value += 1
end)
Edit - in this most recent version, your Sell script has stopped working because the player argument is nil. In an earlier version of this code, the Touched script passed in the player, but you removed that code and broke the Sell script. So just rollback the script to its earlier state :
script.Parent.Touched:Connect(function(hit)
if hit.Parent:FindFirstChild("Humanoid") then
local player = game.Players:GetPlayerFromCharacter(hit.Parent)
game.ReplicatedStorage.BindableEvents.Sell:Fire(player)
end
end)

Related

My chest script won't add the gold to my stats

game.Players.PlayerAdded:Connect(function(player)
script.Parent.Touched:Connect(function(hit)
if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
local players = game:GetService("Players")
local clone = game.Workspace.Sparkles:Clone()
clone.Parent = game.Workspace
clone.CanCollide = false
clone.Position = script.Parent.Position
script.Parent:Destroy()
wait(1)
clone:Destroy()
local player = game.players.LocalPlayer
players.LocalPlayer.leaderstats.gold.value = 10
end
end)
end)
Here, I'm trying to make a script where if you touch a chest it will give you gold[my stat name] but for some reason, it wont run properly. it wont give me the amount of gold i told it to
From my understanding, you have a function that fires whenever a player joins the game. And then when the part is touched, the part then fires the code you have. I would remove the game.Players.PlayerAdded:Connect(function(player) function as when it get's hit it will fire for every single player who has joined.
But why am I not gaining any gold?
If you are using a server sided script you can't just call game.Players.LocalPlayer as that is client sided. LocalPlayer is an object that is in client sided scripts that tell the client sided script(s) what player they are executing on.
How do I fix this?
First, you already have a statement to decide whether the hit part is a character. So, you can do,
local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
Player.leaderstats.gold.Value += 10
I've fixed a few things in your scripts and removed some things as well. First, I added a += 10 to the gold adding script as if you don't it will just set the gold value to 10 and never add any more.
LocalPlayer is not available to be used on server sided scripts and should only be used on Client sided.
(For future references, in your first initial code you have code that sets the variable of player but under that line you call players. (however, that wouldn't still work. Just trying to provide information about code that's syntax was incorrect.))
When you say script.Parent:Destroy() thats going to delete the script's parent right? So it's going to destroy the script's parent's children which includes the script, which means it can't give you the gold.
Tip: If you ever encounter an error, it might help to put some print statements for logging. For example in your code:
game.Players.PlayerAdded:Connect(function(player)
print("Player has joined!")
Just repeat this for every function, loop, if statement, etc.(with different print messages of course) and then test this and see what gets printed. Also put a print statement after you destroy the script's parent to check if the script stays or not.

How do i create a automatic find player script

so I am learning Lua at the moment and wanted to make something that if the player presses f it would print something. I know how to use input service. but what I DO NOT KNOW is how get the server to automatically detect the player. so a combat game for example.
you join with controls already there . I'm really confused!
local player = game:getservice("players")
local input = game:GetService("UserInputService")
input.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.F then
print("hi")
end
end)
You don't need to detect when a player joins to make your controls work. The problem is likely that your code is in a Script, and not a LocalScript. Scripts run on the server, and LocalScripts run on each individual client. Plus, user input needs to be detected on the client as well.
So, create a LocalScript in StarterPlayer > StarterCharacterScripts. This will replicate the code into each player when their Character spawns into the world. Then, move your existing code in there.
local uis = game:GetService("UserInputService")
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.F then
print("hi")
end
end)

Roblox Studio: NPC Humanoid, disabling climbing

I'm very new to Roblox studio and trying to get some basic functionality working. I am spawning some NPCs, and I would like to prevent them from climbing ladders. After reading documentation, it seems I should be able to do this by using Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, false). I am inserting that code right after I create the NPC as follows:
local function spawnEnemy()
local enemy = ServerStorage.Enemies.Zombie:Clone()
enemy.Parent = workspace.Enemies
print("Setting climbing to false")
enemy.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
print(enemy.Humanoid:GetStateEnabled(Enum.HumanoidStateType.Climbing))
enemy.Humanoid.StateEnabledChanged:Connect(function()
print("state changed")
end)
end
The output as I start the game looks like:
Setting climbing to false
false
This is just what I would expect, and also note it does not output "state changed" so I know that no other part of the code is interfering.
However, this doesn't actually prevent the NPC from climbing, and in fact if I immediately type into the console (where it says "Run a command" at the bottom of roblox studio) this command:
print(workspace.Enemies.Zombie.Humanoid:GetStateEnabled(Enum.HumanoidStateType.Climbing))
The output is true.
Why doesn't the variable "stick"? Do I need to put this code somewhere else?
SetStateEnabled doesn't seem to replicate to the client. Your Run-a-command command executes against the client's workspace, and there it is still true.
If you put the same on the server (say add the following into a workspace script):
spawn(function()
while (true) do
print(workspace.Enemies.Zombie.Humanoid:GetStateEnabled(Enum.HumanoidStateType.Climbing))
wait(0.5)
end
end)
...you'll see that on the server, that property is in fact false.
Update:
to set it on the client, you can just hook up a handler on your Enemies folder, that will always set the Humanoid's climbing state for all your zombies:
workspace.Enemies.ChildAdded:Connect(function(child)
if (child.Name == "Zombie") then
child:WaitForChild("Humanoid"):SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
end
end)
just put that above into a LocalScript in StarterPlayerScripts.

Destroyed part is not destroyed globaly in Roblox

What I'm trying to do: I want to have a tree and every few seconds an Apple falls down from that tree. Player can "pick up" that Apple. If more players are in the game, player who picks up the most apples, wins.
What I have: I have a tree and apples are falling down. Until here it works perfect. Player can pick up an apple - if he touches the apple by his foot, apple is destroyed and player gets 1 point. Still OK.
What is wrong: If more players join the game, it looks like every player can see his own (local) apple. So if Player1 picks up an apple, apple is destroyed - but only for him :( all other players can see that apple still there and they can pick it up too. If I test-run the game with 2 players, in the server-window I can see that apple still there, even after all players picked it up. So the server has it's own instance apparently.
But I want just one global apple.
Application is like this:
I have an apple in the Workspace. Every few seconds I clone it in the script (not local script, but Script) which is under the AppleTree model in Workspace:
function GrowNewApple()
local newApplePos = GetRandomPlace()
local appleTemplate = workspace.apples.prototype
local newApple = appleTemplate:Clone()
newApple.Parent = appleTemplate.Parent
newApple.Name = "apple"
newApple.Position = newApplePos
end
In StarterPlayer / StarterPlayerScripts I have a localscript with this:
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
character:WaitForChild("LeftFoot")
character.LeftFoot.Touched:Connect( PickUpApple )
And finally my PickUpApple function looks like this:
function PickUpApple( touchObject )
if touchObject:IsDescendantOf(workspace.apples) then
touchObject:Destroy()
end
end
Any ideas please?
Is it because the PickUpApple() is called from LocalScript? Is it possible that this LocalScript is sending local touchObject into this function?
I have no idea how to do this. Thanks guys.
Deleting the apple from a local script will only delete it for the client, To prevent this, Try it so the apple gets deleted by a server side script, You have 2 options:
1, Make the script a server side script and make sure it's compatible for the server.
2, Make a remote event which is fired once the local script detects the local player touching an apple, And make sure the remote event is connected to a function that deletes the apple and gives the player a point, Should be a server script, To do that:
1, Create a RemoteEvent (Make sure it's a RemoteEvent not a RemoteFunction!) in the ReplicatedStorage and rename it to "PickupApple".
2, Change the local script to:
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local event = game.ReplicatedStorage:WaitForChild("PickupApple")
local apples = workspace:WaitForChild("apples") -- Using WaitForChild() function to prevent errors for requesting the object before it loads
character:WaitForChild("LeftFoot")
character.LeftFoot.Touched:Connect(function(touchObject)
if touchObject:IsDescendantOf(apples) then
event:FireServer(touchObject)
end
end)
3, Create a script (Not a LocalScript!) in the ServerScriptService, And put this:
game.ReplicatedStorage.PickupApple.OnServerEvent:Connect(function(player, item)
if item:IsDescendantOf(workspace.apples) then
item:Destroy()
-- Add here any extra code such as giving points, etc
end
end)
OK, problem solved.
The problem was that Touched event was fired on Local Player parts (feet, legs). This has sent the local instance of the apple to the Touched Event Handler.
Now I removed this:
character.LeftFoot.Touched:Connect( PickUpApple )
and instead of firing Touched on player foot I moved it to the Apple part and now I'm firing Touched event on that Apple part.
apple.Touched:Connect(PickUpApple)
And it works. While Apple part sends to the Touched Event Handler player's foot which is OK - I don't need to destroy it - I can destroy Apple now.
I have to say I moved whole function PickUpApple() into the apple part also so I have direct access to the apple part itself.

Roblox Studio - Warning/Error when i try to sell the "snow" in my backpack

As you can see on the picture below I can't sell what I have in my backpack when I enter the circle. I get this error/warning and I can't figure out what the problem is. I have found out that the problem happens on line 5: player:WaitForChild
The Error/Warning on line 5: Infinite yield possible on Players.asbjornbonde.PlayerGui:WaitForChild("Stats")
Here is the picture:
Here is my code:
script.Parent.Touched:connect(function(Hit)
local player = game.Players:FindFirstChild(Hit.Parent.Name)
if player then
local leaderstats = player:FindFirstChild("leaderstats")
local PlayerGui = player:WaitForChild("PlayerGui"):WaitForChild("Stats").Backpack
if leaderstats and PlayerGui then
local Cash = leaderstats:FindFirstChild("Cash")
local snow = PlayerGui:FindFirstChild("snow")
if Cash and snow then
if snow.Value <= 0 then
else
Cash.Value = Cash.Value + 2 * snow.Value
snow.Value = 0
script.Parent.DigSound:Play()
script.Disabled = true
wait(0.1)
script.Disabled = false
end
end
end
end
end)
I have used many hours on trying to fix this problem but i really can't. I would appreciate help.
Infinite yield possible on is a warning in Roblox Studio that means there is a possibility that your script could be stuck on that line waiting forever if object it is waiting on doesn't exist and is never created.
As the only WaitForChild that is causing an error is two WaitForChild's joined together I'm guessing the script doesn't like you doing that.
First Solution
If you were to split both WaitForChild's into two different variables it shouldn't give you the error however this is creating another variable for no real reason so I would go for the second solution.
Second Solution
As the player has loaded in and touched the part it's safe to assume the GUI has loaded for them so you can change your WaitForChild to FindFirstChild if you still want to check you didn't get a nil or you can reference it normally: player.PlayerGui.Stats.Backpack
Hope this helps.
Think of WaitForChild() as a loop. It is constantly executing in the background, as fast as the Lua engine can execute it. Wouldn't recommend using this or any sort of un controlled loop in Roblox Lua as the engine doesn't handle it very well.
If this is a server script with a filtering enabled game, the issue is that the server cannot access existing members of PlayerGui. To work around this, you either need to run this code on the client (with the necessary changes), or you'll need to make use of a remote event!

Resources