No, that wouldn’t happen. If the player gets out the water while the for loop is still running, it will call return
, ending the function and not allowing the while loop to run.
Not needed for any more variables (unless you add the little last drown effect I stated - this is only for fluidity when running), essentially when you use an IF statement your checking if something exists or is false:
local false_arg = false
local nil_arg = nil
local true_arg = true
local obj_arg = tick()
if false_arg then return end -- As its false.
if nil_arg then return end -- As nothing exists
if true_arg then return end -- As its true.
if obj_arg then return end -- As something exists in that memory pointer.
Checking if an object exists is great especially when using datastore
Why does the character not heal after drowning?
What do you mean by that? If the player steps out the water before dying, Roblox’s default “Health” script should slowly heal the player.
You could use tick()
to check if 30 seconds have passed to deal damage after that time has passed.
The roblox “Health” script is not healing the character but it usually does.
I have made an example for you in a localscript of how I would do this. Currently I do not think that subtracting health through a local script replicates to the server actually happens, which means if you want a multiplayer compatible script, this has to be done server side.
I use Humanoid:GetState() which returns the current state of the humanoid to see if you are still swimming, if you are not swimming the timer in the water resets and will continue from 30 if you are back into the water again.
The localscript example:
repeat wait() until game.Players.LocalPlayer.Character
local PS = game:GetService("Players")
local LP = PS.LocalPlayer
local Character = LP.Character
local Humanoid = Character:WaitForChild("Humanoid")
local Drowning = false
local DrownCount = 0
function HumanoidSwam(Old, State)
if State == Enum.HumanoidStateType.Swimming then
if Drowning == false then
Drowning = true
local StartTick = tick()
DrownCount = 30
while DrownCount > 0 do
DrownCount = DrownCount - 1
print(DrownCount)
if Humanoid:GetState() ~= Enum.HumanoidStateType.Swimming then
Drowning = false
return
end
wait(1)
end
if DrownCount == 0 then
while Humanoid:GetState() == Enum.HumanoidStateType.Swimming do
Humanoid:TakeDamage(5)
wait(5)
end
end
Drowning = false
end
end
end
Humanoid.StateChanged:Connect(HumanoidSwam)
Did this help?
Nvm. I put it in the wrong type of script.
I am doing this for a multiplayer game. I do not know if this would work in one.
It’s a problem with your code. You don’t have a timer.
Humanoid.StateChanged:Connect(function (oldState, newState)
if newState == Enum.HumanoidStateType.Swimming then
print("Swim")
Swimming = true
elseif oldState == Enum.HumanoidStateType.Swimming and newState ~= Enum.HumanoidStateType.Jumping then
print("No swim")
Swimming = false
elseif oldState ~= Enum.HumanoidStateType.Swimming and oldState ~= newState then
print("No swim")
Swimming = false
end
local firstTick = tick()
while Swimming do
wait(1)
if tick() - firstTick >= 30 then
Humanoid:TakeDamage(30 / Humanoid.MaxHealth) -- 0skarian said this
end
end
end)
So anything else your stuck on that we can help with?
- If your player isn’t automatically healing then rename any scripts named “Health” in StarterCharacterScripts that way it doesn’t override the core.
I accidentally put it in the wrong script. Two of the answers worked here but I used yours because it damaged the player more equally.
If you want this to be multiplayer compatible, it is essential to handle it server side in order to have it replicate on both ends.
I have converted my example into a server script, that will do everything as before, it has the drown damage and cooldown between each hit as a variable as well.
To test it, simply open output so you can view the timer and try to swim around in water.
wait()
local PS = game:GetService("Players")
local Drowning = false
local DrownCount = 0
local DrownDamage = 10
local DrownCooldown = 2
PS.PlayerAdded:Connect(function(Player)
Player.CharacterAdded:Connect(function(Character)
local Humanoid = Character:WaitForChild("Humanoid")
Humanoid.StateChanged:Connect(function(Old, State)
if State == Enum.HumanoidStateType.Swimming then
if Drowning == false then
Drowning = true
local StartTick = tick()
DrownCount = 30
while DrownCount > 0 do
DrownCount = DrownCount - 1
print(DrownCount)
if Humanoid:GetState() ~= Enum.HumanoidStateType.Swimming then
Drowning = false
return
end
wait(1)
end
if DrownCount == 0 then
while Humanoid:GetState() == Enum.HumanoidStateType.Swimming do
Humanoid:TakeDamage(DrownDamage)
wait(DrownCooldown)
end
end
Drowning = false
end
end
end)
end)
end)
Hope this helped.
I will test it. 30 Characters
It does not work. You do not have to fix it because the thing is solved.
Yes, it does. You are probably not using the correct script for it, as I have stated this is for a normal script, not localscript and this one above will replicate to the server unlike the others.
I decided to reply to you with a different method since everyone seems to be using the humanoid state only, maybe I could open the doors for ReadVoxels since nobody uses them for some reason when they’re really nice. (maybe for your use case it doesn’t really matter but still)
I used a server script. eeeeee
How do you merge this script with the drowning script? The one I am currently using has some glitches.
On the server you loop through all the players, check if their humanoids floor material is air, if so do what the script does else they’re not drowning.