Function Triggers even when if statement is false - lua

local Players = game:GetService("Players")
local TouchPart = workspace["Start"]
local target = game.Workspace.Level1
local function teleport()
TouchPart.Touched:Connect(function(touched)
if touched.Parent:FindFirstChild("Humanoid") then
local Player = Players:GetPlayerFromCharacter(touched.Parent)
if Player then
--Player.Character.HumanoidRootPart.CFrame = target.CFrame + Vector3.new(0, 5, 0)
print("Teleport")
end
end
end)
end
while true do
local zeit = game.Workspace.wall1.time.Value
zeit = zeit - 1
game.Workspace.wall1.time.Value = zeit
game.Workspace.wall1.SurfaceGui.Frame.TextLabel.Text = zeit
wait(1)
print(zeit)
if zeit == 0 then
teleport()
game.Workspace.wall1.time.Value = 20
end
end
The Function Teleport should only be called if zeit == 0. And print("Teleport") should only work when zeit hits 0 and the player is touching the part.
My Problem is even if zeit isnt 0 the function teleport() prints "Teleport" into the console when a player touches the part. Am i missing something there ?

Your issue is that you are connecting a Touched listener every time zeit reaches zero. This listener will fire from here on out, until you disconnect it. It also means that after two loops, it will print "teleport" twice, and after three you will see it printed three times with every touch.
You either need to disconnect the listener, or simply teleport the people touching the part when the timer strikes zero. Here's how you would do the latter :
local Players = game:GetService("Players")
local TouchPart = workspace["Start"]
local target = game.Workspace.Level1
local zeit = game.Workspace.wall1.time
local wallText = game.Workspace.wall1.SurfaceGui.Frame.TextLabel
-- function for teleporting all of the players currently touching the TouchPart
local function teleport()
local touchingPlayers = {}
local parts = TouchPart:GetTouchingParts()
for _, touched in ipairs(parts) do
local Player = Players:GetPlayerFromCharacter(touched.Parent)
if Player then
touchingPlayers[Player] = touched.Parent
end
end)
-- teleport all the touching players
for player, character in pairs(touchingPlayers) do
print("Teleporting " .. player.Name)
-- character:PivotTo(target.CFrame + Vector3.new(0, 5, 0))
end
end
-- keep the wall text constantly updated
zeit.Changed:Connect(function(newValue)
wallText.Text = tostring(newValue)
end)
-- update the counter every second
while wait(1) do
zeit.Value -= 1
if zeit.Value == 0 then
teleport()
wait(1)
zeit.Value = 20
end
end

Related

ServerScriptService.MainScript:88: Expected 'end' (to close 'do' at line 15), got <eof>; did you forget to close 'then' at line 82?

Help me with this please.
-- variebles define
local ReplicatedStorage = game: GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local MapsFolder = ServerStorage:WaitForChild("Maps")
local Status = ReplicatedStorage:WaitForChild("Status")
local GameLength = 50
-- loop of the game
while true do
Status.Value = "Waiting for players (This may take a bit)"
repeat wait(1) until game.Players.NumPlayers >= 2
Status.Value = "Intermission"
wait(15)
local plrs = {}
for i, player in pairs(game.Players:GetPlayers()) do
if player then
table.insert(plrs, player) -- add de playr to de plrs table
end
end
wait(2)
local AvailableMaps = MapsFolder:GetChildren()
["Grass,Snow"]
local AvailableMaps = MapsFolder:GetChildren()
local ChosenMap = AvailableMaps[math.random(1,2)]
Status.Value = ChosenMap.Name.." Chosen"
local ClonedMap = ChosenMap:Clone()
ClonedMap.Parent = workspace
--teleport de playr
local grasstelepors = ClonedMap:FindFirstChild("grasstelepors")
if not grasstelepors then
print("no spawn m8")
end
local Availablegrasstelepors = grasstelepors:GetChildren()
["telepor"]"telepor","telepor","telepor"
for i, player in pairs(plrs) do
if player then
character = player.Character
if character then
--telepor em
character:FindFirstChild("HumanoidRootPart").CFrame = Availablegrasstelepors[1]
table.remove(Availablegrasstelepors,1)
--give them swords so they can violence
local Sword = ServerStorage.Sword:Clone()
Sword.Parent = player.Backpack
local GameTag = Instance.new("BoolValue")
GameTag.Name = "GameTag"
GameTag.Parent = player.Character
else
--no charecter m8
if not player then
table.remove(plrs,i)
end
end
end
end
The error is telling you everything.
The code expected there to be an end to close your while true do on line 15, but instead of finding it, it hit the end of the file.
It is even suggesting where you made the mistake, "did you forget to close your if player then statement on line 82?"
Add an end at the end of the code block to fix it.

Atempted to index nil error when trying to find the playergui component of a player

I'm trying to make a cutscene sorta thing for a dorr in roblox studio. My solution was to set up a collision detector on the door which would then make a gui template and set its parent to the playergui component.
I did this using the code
local afterIntoTransform = script.Parent.Parent.DoorUnion.Position.Z -6
local afterOutwardsTransform = script.Parent.Parent.DoorUnion.Position.Z + 6
local debounce = false
local function executeFadeSceneAndTpPlayer(player)
local fadeScene = Instance.new("ScreenGui")
local fadeSceneFrame = Instance.new("Frame")
fadeScene.Name = "fadeScene"
fadeSceneFrame.Name = "fadeFrame"
fadeSceneFrame.Size = UDim2.new(1,0,1,0)
fadeSceneFrame.Parent = fadeScene
fadeSceneFrame.BorderSizePixel = 0
fadeSceneFrame.BackgroundColor3 = Color3.new(1, 1, 1)
fadeSceneFrame.BackgroundTransparency = 1
print(game.Players:GetPlayerFromCharacter(player).Name)
fadeScene.Parent = game.Players:GetPlayerFromCharacter(player).PlayerGui
for i = 0, 20, 1 do
fadeSceneFrame.BackgroundTransparency -= 0.05
wait(0.01)
end
player.HumanoidRootPart.Position = Vector3.new(player.HumanoidRootPart.Position.X, player.HumanoidRootPart.Position.Y, afterOutwardsTransform)
for i = 0, 20, 1 do
fadeSceneFrame.BackgroundTransparency += 0.05
wait(0.01)
end
fadeScene:Destroy()
end
script.Parent.Touched:Connect(function(hit)
if not debounce then
debounce = true
executeFadeSceneAndTpPlayer(hit.Parent)
wait(0.2)
debounce = false
end
end)
It tells me: Attempted to index nil with name on line 15.
It works sometimes and sometimes doesnt but recently Ive noticed a trend that I can walk into the door then out again and then it breaks. I haven't coded in a while so I'm a little rusty but I hope I can get some help.
You are running into the same issue as this person : Roblox - attempt to index nil with 'leaderstats'
You are not accounting for the fact that the Touched event fires for every single part that touches it, and some of those parts might not belong to a player.
You can protect against this error by making sure that the object belongs to a player before you call executeFadeSceneAndTpPlayer()
script.Parent.Touched:Connect(function(hit)
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
if not plr then
return
end
if not debounce then
debounce = true
executeFadeSceneAndTpPlayer(hit.Parent)
wait(0.2)
debounce = false
end
end)

Script timeout: exhausted allowed execution time

When I was trying to make and run a script for coins in my game the output said "Script timeout: exhausted allowed execution time"
Script:
game.Players.PlayerAdded:Connect(function(player)
local Coins = Instance.new("IntValue")
Coins.Name = "Coins"
local coinvalue = Coins.Value
coinvalue = 0
Coins.Parent = player
wait(0.01)
if player.Name == "Vlo_tz" then
coinvalue = 25
end
wait(0.01)
local cointext = game.StarterGui.SideGuis.InventoryFrame.CoinsTextValue
while true do
cointext = coinvalue
end
end)
Your script is executing for too long without any kind of break.
The error is complaining that this loop has no exit case :
while true do
cointext = coinvalue
end
Adding a wait() inside the loop would get rid of the error, but it looks like you're using it to keep some kind of TextValue updated.
A safer way to do this is with event based callbacks. Instead of running a loop that will always try to update the cointext, you can listen for when the Coins value changes and then call a function to update it instead.
game.Players.PlayerAdded:Connect(function(player)
local Coins = Instance.new("IntValue")
Coins.Name = "Coins"
Coins.Value = 0
Coins.Parent = player
if player.Name == "Vlo_tz" then
Coins.Value = 25
end
-- update the gui whenever Coins changes
Coins.Changed:Connect(function()
-- find the player's copy of the UI, if it has loaded
-- (I'm assuming this is a TextValue and not a TextLabel)
local coinText = player.PlayerGui.SideGuis.InventoryFrame.CoinTextValue
-- keep this TextValue updated
coinText.Value = tostring(Coins.Value)
end)
end)

If all the players were killed or resetting during a round, how do you stop the game and display a message for everybody?

I am developing a remastered game, and want to figure how the round will stop if all players were killed or reset, and display a message for all players, "Game over", and returns back to the lobby intermission.
This is my main script for the game I am making. In the past, I've tried If statements in this script, however it didn't work and it ends up not displaying my another scripts as well.
local s = script.Stat
t = 0
while true do
local plrs = game.Players:GetPlayers()
t = 15
repeat
t = t - 1
s.Value = t.." seconds left"
wait(1)
if plrs == 0 then
s.Value = "Alive: "..plrs
end
until t == 0
s.Value = "Game over!"
wait(5)
end
I expect the script to find all the players in a round that is killed, but the output seems to work only for the seconds remaining.
If you add a listener to every player's Humanoid.Died signal, you can keep track of which players die in a round.
In a Script, write something like this :
-- use a map of player names to keep track of who is still alive
local playersAlive = {}
local listenerTokens = {}
local SPAWN_LOCATION = CFrame.new()
-- make some helper functions
local function getCountPlayersAlive()
local numPlayersAlive = 0
for playerName, isAlive in pairs(playersAlive) do
numPlayersAlive = numPlayersAlive + 1
end
return numPlayersAlive
end
local function beginRound()
-- get the list of all of the players in the round
local allPlayers = game.Players:GetChildren()
for _, player in ipairs(allPlayers) do
-- find the associated Player in the workspace
local character = game.Workspace:FindFirstChild(player.Name)
if character then
-- add an event listener for when they die
local humanoid = character:FindFirstChildOfClass("Humanoid")
local deathSignalToken = humanoid.Died:Connect(function()
-- when this player dies, signal that there is one less player
playersAlive[player.Name] = nil
end)
-- add the player to the list of players for this round
playersAlive[player.Name] = true
-- move the players into the game arena
player.Character:SetPrimaryPartCFrame(SPAWN_LOCATION)
-- disconnect this signal at the end of the round
table.insert(listenerTokens, deathSignalToken)
else
-- could not find the player, make them sit out this round
end
end
end
local function endRound()
-- clean up the game board, reload the players, do whatever you have to
-- clean up any death signals from last round
for _, token in ipairs(listenerTokens) do
token:Disconnect()
end
end
-- set up the game loop
local GAME_LENGTH = 30 -- seconds
local INTERMISSION_LENGTH = 15 -- seconds
spawn(function()
while true do
-- phase 1 - set up the round
beginRound()
-- phase 2 - play the round
local gameTimer = GAME_LENGTH
while gameTimer > 0 and getCountPlayersAlive() > 0 do
local count = getCountPlayersAlive()
print(string.format("Time Left : %d - Players Left : %d", gameTimer, count))
wait(1)
gameTimer = gameTimer - 1
end
-- phase 3 - celebrate winners and clean up the previous round
endRound()
-- phase 4 - intermission before the next round
wait(INTERMISSION_LENGTH)
end
end)
Sorry for the lengthy example, but I hope this helps.

How can I implement a debounce in this code

My first thought was to ask on Roblox devforum but since imo they got a really messed up admission system, I might as well ask it here.
I've got a tool that shoots a block (wedge) to wherever the mouse is pointing when clicked. It also casts a ray and the block itself sets the health of any humanoid that makes contact with it to 0. But I have got no idea on how to actually implement a cooldown on the gun so you can't just literally spam blocks that kill anything that touches them arround. I think implementing a debounce here is the best option, but I got stuck with that since day 1 and I have no idea how to write it down correctly
I already tried with most of the things that I thought of after visiting this page Roblox dev page about Debounce, also read through some articles that had similar issues in the dev forum, but I can just spam blocks arround whatever I do.
The tool has just two parts (one being the handle) a localscript to wield the parts together, a localscript to catch the mouse position when clicked, two remote events to pass the info from the localscript to the server script and the following server script
local tool = script.Parent
local clickEvent = tool.ClickEvent
local clickEventConnection
local Players = game:GetService("Players")
local Teams = game:GetService("Teams")
--Function that creates the part with a touched listener that kills any humanoid that comes into contact with said block
local function createPart(location)
local part = Instance.new("WedgePart")
part.CFrame = location
part.Parent = workspace
part.BrickColor = BrickColor.new("Black")
part.Touched:connect(function(hit)
if hit.Parent then
local hum = hit.Parent:FindFirstChild("Humanoid")
if hum then
hum.Health = 0
end
end
end)
game:GetService("Debris"):AddItem(part, 2)
end
--With the information on the click position of the localscript, this function creates a ray and a beam that accompanies the block, as well as executing the createpart() function on said location
local function onClick(player, clickLocation, ignore)
createPart(clickLocation)
local ray = Ray.new(
tool.Handle.CFrame.p,
(clickLocation.p - tool.Handle.CFrame.p).unit * 500
)
local hit, position, normal = workspace:FindPartOnRay(ray, player.Character, ignore)
local beam = Instance.new("Part", workspace)
if player.Team == Teams["Blue Team"] then
beam.BrickColor = BrickColor.new("Bright blue")
elseif player.Team == Teams["Red Team"] then
beam.BrickColor = BrickColor.new("Bright red")
else
beam.BrickColor = BrickColor.new("Ghost grey")
end
beam.FormFactor = "Custom"
beam.Material = "Neon"
beam.Transparency = 0.25
beam.Anchored = true
beam.Locked = true
beam.CanCollide = false
local distance = (tool.Handle.CFrame.p - position).magnitude
beam.Size = Vector3.new(0.3, 0.3, distance)
beam.CFrame = CFrame.new(tool.Handle.CFrame.p, position) * CFrame.new(0, 0, -distance / 2)
game:GetService("Debris"):AddItem(beam, 1)
end
--subscribing onclick() when equiping the weapon and unsubscribig when unequipping it
local function onEquip()
clickEventConnection = clickEvent.OnServerEvent:connect(onClick)
end
local function onUnequip()
clickEventConnection:disconnect()
end
tool.Equipped:connect(onEquip)
tool.Unequipped:connect(onUnequip)
I just wanted to make a 'cooldown' so a block can be fired each 3 seconds. As is, you can just spam as much as you like to
A simple way to debounce the clicks is to use a variable to decide whether to quickly escape from a function.
You can modify your onClick function so it does not execute if a cooldown is still in place :
-- make a cooldown tracker
local isGunOnCooldown = false
local cooldownTime = 3.0 --seconds
local function onClick(player, clickLocation, ignore)
-- debounce any spammed clicks
if isGunOnCooldown then
return
end
-- put the gun on cooldown
isGunOnCooldown = true
-- fire a bullet
createPart(clickLocation)
local ray = Ray.new(
tool.Handle.CFrame.p,
(clickLocation.p - tool.Handle.CFrame.p).unit * 500)
local hit, position, normal = workspace:FindPartOnRay(ray, player.Character, ignore)
local beam = Instance.new("Part", workspace)
if player.Team == Teams["Blue Team"] then
beam.BrickColor = BrickColor.new("Bright blue")
elseif player.Team == Teams["Red Team"] then
beam.BrickColor = BrickColor.new("Bright red")
else
beam.BrickColor = BrickColor.new("Ghost grey")
end
beam.FormFactor = "Custom"
beam.Material = "Neon"
beam.Transparency = 0.25
beam.Anchored = true
beam.Locked = true
beam.CanCollide = false
local distance = (tool.Handle.CFrame.p - position).magnitude
beam.Size = Vector3.new(0.3, 0.3, distance)
beam.CFrame = CFrame.new(tool.Handle.CFrame.p, position) * CFrame.new(0, 0, -distance / 2)
game:GetService("Debris"):AddItem(beam, 1)
-- start the gun's cooldown and reset it
spawn(function()
wait(cooldown)
isGunOnCooldown = false
end)
end

Resources