How do i do a repeat until E pressed?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve?
    When I press E, the repeat until loop stops and the part stays in place where I pressed E

  2. What is the issue?
    All the methods I’ve tried don’t produce an error, they just don’t work, even with adding something like an IntValue and when it changes to 1 it stops. That doesn’t work either.

  3. What solutions have you tried so far?
    I scoured the creator hub, tried uis:InputEnded:Wait(), and using intvalues

This is what I’ve accomplished:

local ChatService = game:GetService("Chat")
local phrases = "Da mihi lumin."
local follow = game:GetService("ReplicatedStorage"):WaitForChild("Light")
ac = false
local c = follow:Clone()
local uis = game:GetService("UserInputService")

script.Parent.Activated:Connect(function(player)
	local player = script.Parent.Parent
	if ac == false then
		player.Humanoid.WalkSpeed = 0
		player.Humanoid.JumpHeight = 0
		ac = true
		c.Parent = workspace
		wait(.2)
		ChatService:Chat(player.Head, phrases, Enum.ChatColor.White)
		wait(1.1)
		player.Humanoid.WalkSpeed = 16
		player.Humanoid.JumpHeight = 7.2
		ac = false
		c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
		local alllight = c.PrimaryPart:GetChildren()
		
		for i, v in pairs(alllight) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				v.Range = 0
			end
		end
		
		wait(.5)
		repeat
			wait(.01)
			c.PrimaryPart.Transparency = c.PrimaryPart.Transparency - .1
			for i, v in pairs(alllight) do
				if v:IsA("SpotLight") or v:IsA("PointLight") then
					v.Range = v.Range + 1.6
					if v.Range > 16 then
						v.Range = 16
					end
				end
			end
			c.Union.Transparency = c.Union.Transparency - .1
		until c.Union.Transparency <= -0.1
		repeat
			wait(.000000000000001)
			c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
		until --no idea how
	else
		
	end
end)

The part where I put --i have no idea is where I am struggling.

5 Likes

If you want the shortest possible wait (1/60 sec or longer depending on frame rate), use task.wait or RunService.PostSimulation:Wait() (I think the aforementioned two are equivalent to each other) or the Wait method of some other RunService event. The old wait will wait at least 1/30 sec even if you give it a smaller number.

Now, the actual answer: When you wait just a frame, I think this’ll work.

until UserInputService:IsKeyDown(Enum.KeyCode.E)
2 Likes

Your suggestion for task.wait is more efficient! :+1:

Unfortunately I forgot to mention that I tried Iskeydown just earlier and it didn’t work. I did try your version and there was still no error at all, just didn’t do anything. Which probably means that it is tryng to detect when the key is down it just cant recognize when it is :thinking: .

1 Like

Just do debounce
That the most efficient instead of calling method every time.

1 Like

I haven’t worked with debounce much but I could be wrong; if debounce is just like a cooldown, that’s not what I am currently going for. The part follows the player but I am trying to make it so when the player presses E it will stay in place. I’ll make sure to clarify that in the topic :sweat_smile: , sorry for the misunderstanding

1 Like

you should avoid busy waiting, Roblox has events for everything. Why won’t something like this work?

local UserInputService = game:GetService("UserInputService")


local function waitForButtonPressed(button: Enum.KeyCode)
	repeat
		local input, gpe = UserInputService.InputBegan:Wait()
	until not gpe and input.KeyCode == button
end

print("Waiting...")
waitForButtonPressed(Enum.KeyCode.E)
print("E pressed")
2 Likes
LoaclScript
local ChatService = game:GetService("Chat")
local phrases = "Da mihi lumin."
local follow = game:GetService("ReplicatedStorage"):WaitForChild("Light")
local uis = game:GetService("UserInputService")

ac = false
ePressed = false

uis.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.E then
		ePressed = true
	end
end)

script.Parent.Activated:Connect(function()
	local player = script.Parent.Parent
	if ac then return end
	ac = true
	player.Humanoid.WalkSpeed = 0
	player.Humanoid.JumpHeight = 0
	local c = follow:Clone()
	c.Parent = workspace
	task.wait(.2)
	ChatService:Chat(player.Head, phrases, Enum.ChatColor.White)
	task.wait(1.1)
	player.Humanoid.WalkSpeed = 16
	player.Humanoid.JumpHeight = 7.2
	c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
	local alllight = c.PrimaryPart:GetChildren()
	for i,v in pairs(alllight) do
		if v:IsA("SpotLight") or v:IsA("PointLight") then
			v.Range = 0
		end
	end
	task.wait(.5)
	repeat
		task.wait(.01)
		c.PrimaryPart.Transparency -= .1
		for i,v in pairs(alllight) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				v.Range += 1.6
				if v.Range > 16 then
					v.Range = 16
				end
			end
		end
		c.Union.Transparency -= .1
	until c.Union.Transparency <= -0.1
	repeat
		task.wait()
		c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
	until ePressed
	ePressed = false
	ac = false
end)

What is this … wait(.000000000000001)
task.wait() with no argument waits for the next frame…
(around 1/60th of a second), which is the smallest practical wait.

I think theres just something wrong with my script :man_shrugging:. All of your solutions SHOULD be working but they just don’t and theres no errors.

It’s a script inside of a tool

Yep, that script I posted is for and in the tool. Too much setup for me to test this.
So, I can’t say it’s 100%. Always take what others say with a gain of salt. Testing is the only real measure. Looks right to me, assuming you got your logic right, check everything else also.

Yes, testing is the only real way to see if something works. Unfortunately I do not think there will be a solution to this any time soon because I have tried all the ways it should be working but it just doesn’t. Here is a video with your script:

you cant hear it but I was mashing E

1 Like

Hmm…

2nd try
local ChatService = game:GetService("Chat")
local phrases = "Da mihi lumin."
local follow = game:GetService("ReplicatedStorage"):WaitForChild("Light")
local uis = game:GetService("UserInputService")

ac = false
ePressed = false

uis.InputBegan:Connect(function(input, gp)
	if input.KeyCode == Enum.KeyCode.E and not gp then
		ePressed = true
	end
end)

script.Parent.Activated:Connect(function()
	local player = script.Parent.Parent
	if ac then return end
	ac = true
	ePressed = false
	player.Humanoid.WalkSpeed = 0
	player.Humanoid.JumpHeight = 0
	local c = follow:Clone()
	c.Parent = workspace
	task.wait(.2)
	ChatService:Chat(player.Head, phrases, Enum.ChatColor.White)
	task.wait(1.1)
	player.Humanoid.WalkSpeed = 16
	player.Humanoid.JumpHeight = 7.2
	c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
	local alllight = c.PrimaryPart:GetChildren()
	for i,v in pairs(alllight) do
		if v:IsA("SpotLight") or v:IsA("PointLight") then
			v.Range = 0
			v.Enabled = true
		end
	end
	task.wait(.5)
	repeat
		task.wait(.01)
		c.PrimaryPart.Transparency -= .1
		for i,v in pairs(alllight) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				v.Range += 1.6
				if v.Range > 16 then
					v.Range = 16
				end
			end
		end
		c.Union.Transparency -= .1
	until c.Union.Transparency <= -0.1
	repeat
		task.wait()
		c.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
	until ePressed
	for i,v in pairs(alllight) do
		if v:IsA("SpotLight") or v:IsA("PointLight") then
			v.Enabled = false
		end
	end
	ac = false
end)

If this isn’t working you’re logic is wrong or something is in the wrong place or spelled wrong.
Because this is a bit ridiculous… I’m totally reaching here.

for i,v in pairs(alllight) do
	if v:IsA("SpotLight") or v:IsA("PointLight") then
		v.Enabled = false
	end
end

I’m following what you’re doing. Using your logic with a few refinements.

When this happens to me, I start a fresh program with only what I’m having problems with and hammer it until it’s working. Just to avoid any other possible problems.

1 Like

Is your script a server script? UserInputService only works correctly in client scripts (because there can be multiple players and obviously the results of UserInputService API need to be computer-specific so there’s no sensible way to replicate them to the server, and replicating every input to the server would also cause unnecessary network traffic). For example, UserInputService:IsKeyDown() will always return false on the server.

Tool.Activated works on both client and server.

Because Tool.Activated apparently works in your script and UserInputService:IsKeyDown() doesn’t, I decided to ask this.

I think It’d be nice if Roblox gave an error when trying to access client-only APIs on the server. It could avoid confusing situations where someone either accidentally or because of a lack of understanding uses a server script when a client script is needed. However, considering Roblox’s goal to maintain backwards compatibility, it’s probably too late for them to add such errors now.

3 Likes

it is a server script! Perhaps I can make the first part a local script and then it fires a remote event that starts it instead

it worked perfectly when i checked if it worked on client, now i just have to adjust it so other people can see it

Hi, i refactored the entire script, keeping your desired functionality, because these transitions can be made a lot better performance-wise with TweenService. Also to make the light not be “snappy” i used RunService to update the position every frame with a CFrame:Lerp function. If you need any more help let me know, ill be happy to answer. I tried to comment everything in the script to make it be easier to understand. Oh and instead of using the normal wait() ALWAYS use task.wait() it is MUCH better, because it doesnt throttle the current thread, stopping the entire scripts functionality.

local runService = game:GetService("RunService")

local tweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Circular)

local ChatService = game:GetService("Chat")
local phrases = "Da mihi lumin."
local follow = game:GetService("ReplicatedStorage"):WaitForChild("Light")

local debounce = false

local light = follow:Clone()
local uis = game:GetService("UserInputService")

script.Parent.Activated:Connect(function()
	local player = script.Parent.Parent
	
	if debounce == false then
		-- Reset transparency so it can be used multiple times
		light.PrimaryPart.Transparency = 1
		light.Union.Transparency = 1
		
		-- Stop movement
		player.Humanoid.WalkSpeed = 0
		player.Humanoid.JumpHeight = 0
		debounce = true
		task.wait(.2)
		
		-- Make the player chat
		ChatService:Chat(player.Head, phrases, Enum.ChatColor.White)
		task.wait(1.1)
		
		-- Resume movement, spawn the light
		player.Humanoid.WalkSpeed = 16
		player.Humanoid.JumpHeight = 7.2
		debounce = false
		
		light.Parent = workspace
		light.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
		
		-- Disable the lights, then reenable after 0.5 seconds
		local lights = light.PrimaryPart:GetChildren()
		local tweens = {}
		
		for i, v in pairs(lights) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				v.Range = 0
				table.insert(tweens, tweenService:Create(v, tweenInfo, { Range = 16 }))
			end
		end
		
		task.wait(.5)
		
		for i, v in tweens do
			v:Play()
		end
		
		tweenService:Create(light.PrimaryPart, tweenInfo, { Transparency = 0 }):Play()
		tweenService:Create(light.Union, tweenInfo, { Transparency = 0 }):Play()
		
		local connection : RBXScriptConnection
		
		connection = runService.Heartbeat:Connect(function()
			light.PrimaryPart.CFrame = light.PrimaryPart.CFrame:Lerp(player.Head.CFrame * CFrame.new(2,2,-1), 0.2)
		end)
		
		uis.InputBegan:Connect(function(input, gp)
			if gp then return end
			
			if input.KeyCode == Enum.KeyCode.E then
				connection:Disconnect()
			end
		end)
	end
end)

Reply if you need any more clarifications!

Edit: i accidentally made two waits for the reappearing section, sorry :stuck_out_tongue:

2 Likes

Thank you for the new script but I already got the answer and I have now made adjustments with a localscript firing a script that will activate it but make me still be able to use E to stop it while other people still see the object. Thank you though!

Oh, sorry i didnt realize there was a solution marked lol. I hope you dont mind me dropping a video of my final solution. Just in case somebody stumbles upon this thread in the future and finds it useful.

Script Here
local runService = game:GetService("RunService")

local tweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Circular)

local ChatService = game:GetService("Chat")
local phrases = "Da mihi lumin."
local follow = game:GetService("ReplicatedStorage"):WaitForChild("Light")

local debounce = false

local light = follow:Clone()
local uis = game:GetService("UserInputService")

script.Parent.Activated:Connect(function()
	local player = script.Parent.Parent
	
	if debounce == false then
		-- Reset transparency so it can be used multiple times
		local lights = light.PrimaryPart:GetChildren()
		
		light.PrimaryPart.Transparency = 1
		--light.Union.Transparency = 1
		for i, v in pairs(lights) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				v.Range = 0
			end
		end
		
		-- Stop movement
		player.Humanoid.WalkSpeed = 0
		player.Humanoid.JumpHeight = 0
		debounce = true
		task.wait(.2)
		
		-- Make the player chat
		ChatService:Chat(player.Head, phrases, Enum.ChatColor.White)
		task.wait(1.1)
		
		-- Resume movement, spawn the light
		player.Humanoid.WalkSpeed = 16
		player.Humanoid.JumpHeight = 7.2
		debounce = false
		
		light.Parent = workspace
		light.PrimaryPart.CFrame = player.Head.CFrame * CFrame.new(2,2,-1)
		
		-- Disable the lights, then reenable after 0.5 seconds
		local tweens = {}
		
		for i, v in pairs(lights) do
			if v:IsA("SpotLight") or v:IsA("PointLight") then
				table.insert(tweens, tweenService:Create(v, tweenInfo, { Range = 16 }))
			end
		end
		
		task.wait(.5)
		
		for i, v in tweens do
			v:Play()
		end
		
		tweenService:Create(light.PrimaryPart, tweenInfo, { Transparency = 0 }):Play()
		--tweenService:Create(light.Union, tweenInfo, { Transparency = 0 }):Play()
		
		local connectionHeartbeat : RBXScriptConnection
		local stop = false
		local desiredPosition
		
		connectionHeartbeat = runService.PreRender:Connect(function()
			if not stop then desiredPosition = player.Head.CFrame else
				if ((desiredPosition * CFrame.new(2,2,-1)).Position - light.PrimaryPart.CFrame.Position).Magnitude < 0.03 then connectionHeartbeat:Disconnect() print("STOPPED!") end
			end
			light.PrimaryPart.CFrame = light.PrimaryPart.CFrame:Lerp(desiredPosition * CFrame.new(2,2,-1), 0.03)
		end)
		
		local connectionInput : RBXScriptConnection
		connectionInput = uis.InputBegan:Connect(function(input, gp)
			if gp then return end
			
			if input.KeyCode == Enum.KeyCode.E then
				print("Pressed E, stopping...")
				stop = true
				desiredPosition = player.Head.CFrame
				connectionInput:Disconnect()
			end
		end)
	end
end)
2 Likes