Hey,
I was trying to open a derma panel after holding a key for x seconds.
Unfortunately, I failed hehe
So here's my code:
[CODE]function GM:PlayerButtonDown(ply, b)
if b == KEY_R then
timer.Simple(3, function()
frame:MoveTo(ScrW()-230, ScrH()-400, 2, 0, -1, function()
frame:MakePopup()
end)
end)
end
end[/CODE]
The problem is that it obviously doesn't open after holding "r" for 3 seconds. It instead wait 3 seconds after you clicked on "R" and open the panel after that.
So I would like to know how to achieve that.
Thank you !
If you wanted to achieve whatever you wanted to achieve, you'd use some hook that runs every frame, tick or generally very often and check in that hook if the key is held, and if increment some value in it.
I'd use it that way:
[code]
local opened = false -- we can either track the panel open status by checking if the panel is visible or valid, or by keeping a var
local timepressed = 0 -- Track the time pressed
local time = 0 --internal value - the hook runs every tick, but we gonna make the statement pass true only every second
local function btndown()
/*
The following statement will run only if the KEY_R is pressed, if the derma isn't open, if the key pressed is
pressed for three seconds or more and if the variable 'time' is one second before CurTime, aka one second before present time.
*/
if input.IsKeyDown(KEY_R) and not opened and time < CurTime() and timepressed <= 3 then
timepressed = timepressed + 1
time = CurTime() + 1
if timepressed == 3 then -- you could check if the panel isn't valid first, could make sure that it doesn't open twice. After all, it is a hook that runs per tick, never know what will happen
opened = true
--Open your derma here
--Do not forget to either switch the var 'opened' for validity check for the panel, or to simply set 'opened' to false on the OnClose function of the base panel. Up to you
end
elseif not input.IsKeyDown(KEY_R) and timepressed > 0 then
timepressed = 0
end
end
hook.Add("Think", "ButtonCheck_UNIQ", btndown)
[/code]
Ofc, using hooks like KeyReleased and KeyPressed would probably be much, much more efficient, but that works too. The code is untested so I have no idea how it would work. I had an idea how to realize it using only KeyReleased and KeyPressed and one timer, but it would be untested and I'd be uncertain. I have tried to explain it in the best way possible. Also, keep in mind that my method might be horrible and I might get burned on a stake for this, but it should work.
I think this is the simplest way to do it:
[CODE]
local time -- this makes the variable local even though it has no value
local open = false -- this variable defines whether the menu is opened already
hook.Add( "Think", "DoStuff", function()
if input.IsKeyDown( KEY_R ) then -- if R is currently down
if !time then time = CurTime() + 3 end -- set the time to be 3 seconds from now
if CurTime() > time and !open then -- if it's been 3 seconds and the panel isn't already open
frame:MoveTo(ScrW()-230, ScrH()-400, 2, 0, -1, function() -- move the frame
frame:MakePopup() -- focus the menu
end)
open = true -- set the panel as being open
end
else
open = false -- let them open it again
time = nil -- reset the timer
end
end )
[/CODE]
[URL="https://github.com/Mysterypancake1/GMod-Binding/"]By the way, I made a binding module that might help someone in the future[/URL], but it doesn't account for a time delay.
It does work, because the check goes further only if CurTime() is higher than time.
Where if the check is successful, I set the time var to be higher than current CurTime() by one, which means the check will be successful again after one second.
edit: edited my code since I forgot ()'s on my CurTime. Soz
- snip -
[QUOTE=MPan1;52357491]snip
[CODE]
local time -- this makes the variable local even though it has no value
local open = false -- this variable defines whether the menu is opened already
hook.Add( "Think", "DoStuff", function()
if input.IsKeyDown( KEY_R ) then -- if R is currently down
if !time then time = CurTime() + 3 end -- set the time to be 3 seconds from now
if CurTime() > time and !open then -- if it's been 3 seconds and the panel isn't already open
frame:MoveTo(ScrW()-230, ScrH()-400, 2, 0, -1, function() -- move the frame
frame:MakePopup() -- focus the menu
end)
open = true -- set the panel as being open
end
else
open = false -- let them open it again after letting go of R
time = nil -- reset the time
end
end )
[/CODE][/QUOTE]
Why are you setting the var open to false upon letting the key go? What if there is already a previous menu opened and user presses the R button for 3 seconds again? Second menu would pop up, the var open should be set to false only by closing the derma frame, just to be sure.
[QUOTE=RaKo;52358621]Why are you setting the var open to false upon letting the key go? What if there is already a previous menu opened and user presses the R button for 3 seconds again?[/QUOTE]
It wouldn't open another menu. MakePopup doesn't create a new menu, vgui.Create does. All MakePopup does is make the menu interactive.
Here's a version with R only working once:
[CODE]
local time -- this makes the variable local even though it has no value
local open = false -- this variable defines whether the menu is opened already
hook.Add( "Think", "DoStuff", function()
if input.IsKeyDown( KEY_R ) then -- if R is currently down
if !time then time = CurTime() + 3 end -- set the time to be 3 seconds from now
if CurTime() > time and !open then -- if it's been 3 seconds and the panel isn't already open
frame:MoveTo(ScrW()-230, ScrH()-400, 2, 0, -1, function() -- move the frame
frame:MakePopup() -- focus the menu
end)
open = true -- set the panel as being open
end
end
end )
[/CODE]
[QUOTE=RaKo;52358606]It does work, because the check goes further only if CurTime() is higher than time.
Where if the check is successful, I set the time var to be higher than current CurTime() by one, which means the check will be successful again after one second.
edit: edited my code since I forgot ()'s on my CurTime. Soz[/QUOTE]
What I don't get about your code is the point of having the timepressed variable at all. It's easier to just use one variable - CurTime().
Well, thanks everyone for the help and sorry for that late reply haha
Sorry, you need to Log In to post a reply to this thread.