I've been trying on numerous different attempts and I thought this would be the closest I could get to what I wanted the outcome to be. Any help or hints are appreciated =)
local players = game:GetService("Players") local teams = game:GetService("Teams") local rs = game:GetService("ReplicatedStorage") local showgui = rs:FindFirstChild("ShowGui") local touching = false local user = nil local plr = nil local grabbed = nil script.Parent.Touched:Connect(function(hit) if hit.Parent:FindFirstChild("Humanoid") then plr = workspace[hit.Parent.Name] user = players:GetPlayerFromCharacter(plr) if user ~= nil then if user.Robbing.Value == true then grabbed = user:WaitForChild("CashCollected") touching = true print("true") if user.Team.Name == "Citizens" then showgui:FireClient(user,"Show") end end end end end) script.Parent.TouchEnded:Connect(function(Player2) if user ~= nil then if user.Robbing.Value == true then touching = false print("false") end end end) local function died() if plr ~= nil then plr:FindFirstChild("Humanoid").Died:Connect(function() break end end while wait(1) do if user ~= nil then died() if touching == true and user.Robbing.Value == true then print("giving money") grabbed.Value = grabbed.Value + 100 if grabbed.Value == 2500 then return end end end end
It much easier than you think! All you have to do is simply get the Humanoid's health and once it reaches 0 health you could break the loop.
Here is a sample that should help you understand how it works.
local player = game.Players.LocalPlayer local character = player.Character if not character or not character.Parent then character = player.CharacterAdded:wait() end while wait(1) do print("Hello") -- Your Code Here if character.Humanoid.Health == 0 then break end end
Your "died" function is trying to listen to an event, ie you're wanting to exit a loop when an event occurs. To do this, you listen to the event but save the connection you've made to a variable so that you can disconnect it when the loop ends. Inside the event listener, you change a boolean variable that you periodically check to see if you should keep running the loop. (This is shown below.)
Notes:
* you'll probably want to run that code every time the user touches the brick, so put it in a function (and add debounce - you don't want several 'while' loops running, all giving the player 100s of dollars every second)
* (Minor) Use Connect
, not connect
(which is deprecated)
* if user ~= nil then
can be shortened to if user then
so long as you don't expect user
to ever equal false
* if touching == true and...
can be shortened to if touching and...
unless you expect touching
to be any random value and only want to do something if it's specifically true
* You don't want to be using variables like grabbed
to refer to things like a player's CashCollected, since this is a server script that needs to handle many players (if 2+ players try to touch the part at once, one player will be awarded the other player's money as well as his/her own). You should either use a dictionary to track all players's CashCollected objects or make it local to the function(s) that use it (passing it to other functions as needed). For the touching
variable, you'll definitely need a dictionary for that one (the key is the player, the value is true or false -- be sure to set it to nil when a player leaves to prevent memory leaks)
* Variables should be local to the function they are used in; try to avoid sharing variables between functions (though you always need some and that's okay)
Improved code:
local players = game:GetService("Players") local teams = game:GetService("Teams") local rs = game:GetService("ReplicatedStorage") local showgui = rs:FindFirstChild("ShowGui") local touching = {} -- touching[player] = true if the player is touching script.Parent local db = {} -- debounce: ensure the "give money" loop doesn't run more than once simultaneously for any one player local function mainLoop(player) if db[player] then return end db[player] = true local hasDied = false local con = player.Character.Humanoid.Died:Connect(function() hasDied = true end) local grabbed = user:WaitForChild("CashCollected") local robbing = player.Robbing while wait(1) and not hasDied and grabbed.Value < 2500 do if touching[player] and robbing.Value then print("giving money") grabbed.Value = grabbed.Value + 100 end end con:Disconnect() db[player] = false end script.Parent.Touched:Connect(function(hit) if hit.Parent:FindFirstChild("Humanoid") then local plr = hit.Parent user = players:GetPlayerFromCharacter(plr) if user then if user.Robbing.Value == true then touching[user] = true print("true") if user.Team.Name == "Citizens" then showgui:FireClient(user,"Show") end mainLoop(user) end end end end) script.Parent.TouchEnded:Connect(function(hit) if hit.Parent:FindFirstChild("Humanoid") then user = players:GetPlayerFromCharacter(hit.Parent) if user then touching[user] = false if user.Robbing.Value == true then print("false") end end end end) players.PlayerRemoving:Connect(function(player) -- Cleanup db[player] = nil touching[player] = nil end)
By the way, I'm unsure if TouchEnded is guaranteed to work (last time I checked it doesn't); you should periodically check the character's position to see if they've left the area (then do touching[player] = false
if so). Also, if the player's arm briefly touches script.Parent (in addition to the torso), money will stop being awarded even if the player's torso is still touching it.
[Edit: DAsanicmaster's answer of checking the humanoid's health is definitely superior in this case, but I leave this answer here because everything else I said is still fine and sometimes you need to listen to an event instead of checking a value.]