How to 'press the same key for the 2nd time to restart script'?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
AnnikaLivia
Posts: 3
Joined: 24 Jun 2017, 21:20

How to 'press the same key for the 2nd time to restart script'?

24 Jun 2017, 21:38

This is my first time using AutoHotkey or any other similar programs.

How to make it so if I press '1' for the 2nd time, my script will restart from the beginning?

This is the script.

1::
sleep 100
MouseMove, 711, 347
sendinput, {Click 2}
sleep 500
sendinput, {Enter}
sleep 2000
sendinput, ^!f
sleep 1000
MouseMove, 851, 577
sendinput, {Click down}
sleep 100
sendinput, {Click up}
return
ThomasPaine
Posts: 25
Joined: 24 Jun 2017, 22:17

Re: How to 'press the same key for the 2nd time to restart script'?

24 Jun 2017, 22:40

Not sure if this is what you're asking, but you need this { }

Code: Select all

1::
{
    sleep 100
    MouseMove, 711, 347
    
    sendinput, {Click 2}
    sleep 500
    
    sendinput, {Enter}
    sleep 2000
    
    sendinput, ^!f
    sleep 1000
    
    MouseMove, 851, 577
    sendinput, {Click down}
    
    sleep 100
    sendinput, {Click up}
}
return
or just this:

Code: Select all

1::
{
    Click 711,347
    sleep 100
    
    click 2
    sleep 100
    
    send, {Enter}
    sleep 2000
    
    send, ^!f
    sleep 1000
    
    Click, 851, 577
    sleep 100
}
return
Last edited by ThomasPaine on 24 Jun 2017, 22:59, edited 1 time in total.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: How to 'press the same key for the 2nd time to restart script'?

24 Jun 2017, 22:54

This is a good question.

So your script takes 3700ms and change to be run.

Is your goal to completely interrupt the execution of the hotkey and start over when 1 is pressed again?

Code: Select all

#MaxThreadsPerHotkey, 255
1::
counter:=1
Send a
Sleep 1000
If counter!=1
  Exit
counter++
Send b
Sleep 1000
If counter!=2
  Exit
counter++
Send c
return
There is probably a better way. But the core of this is, you set a variable that increments. And you use checkpoints that are only true for the most recent launch of the hotkey to validate that this is what should be run.

So, how AHK works is it is single-threaded. With the code above, if you press 1, it'll run up to the Sleep 1000 which tells it to wait 1 second. If you press 1 again, the first instance of the hotkey is interrupted and is put on hold. This will be true until the newest instance of the hotkey hits return or exit. Then the instance of the hotkey that is interrupted may resume. Let's walk through a scenario where we do just that:

Press 1.
Value of counter is 1.
Send a.
Within 1 second, press 1 again. We interrupted the first hotkey.
Value of counter is 1.
Send a.
Wait 1 second.
What is the value of counter? It's 1. So skip the Exit.
Increment counter to 2.
Send b.
Wait 1 second.
What is the value of counter? It's 2. So skip the Exit.
Increment counter to 3.
Send c.
Return. Now we go back to the interrupted hotkey.
What is the value of counter? It's 3. 3 is not equal to 1. So Exit this thread.

I hope that kind of makes sense. I'm interested to see what other people know of.

And if this is not at all what you're looking for, I apologize for not answering it properly. If you can rephrase the question, that would be appreciated.

Also, @ThomasPaine, that block is not necessary. There's not part of the syntax of defining a hotkey. Blocks are used for multi-line if statements, loops, and defining functions.
AnnikaLivia
Posts: 3
Joined: 24 Jun 2017, 21:20

Re: How to 'press the same key for the 2nd time to restart script'?

26 Jun 2017, 21:37

@ThomasPaine
@Exaskrys

Thank you for replying. But that's not what I'm looking for. I'll try to rephrase my question. I'm not fluent in English. I spent almost an hour googling just to make this post.

Let's forget about the code in my first post. Now I have two codes.

1::
sendinput, f1
sleep 1000
sendinput , f2
sleep 1000
sendinput , f3
sleep 1000
sendinput , f4
return

2::
sendinput , f5
sleep 1000
sendinput , f6
sleep 1000
sendinput , f7
sleep 1000
sendinput , f8
return

If I press [1], I will need to wait it to finish before I can use it again. I want it so when I press [1], it will stop [1] and [2] or just [reload] then immediately start [1] from the beginning. Same thing with [2].

Thank you.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: How to 'press the same key for the 2nd time to restart script'?

26 Jun 2017, 23:25

Yeah, what you're looking for is actually tough to do. My original idea is applicable still where you use checkpoints to essentially cancel the old inputs.

Code: Select all

#MaxThreadsPerHotkey, 255
1::
counter++
sendinput, f1
sleep 1000
If counter!=1
   Exit
counter++
sendinput , f2
sleep 1000
If counter!=2
   Exit
counter++
sendinput , f3
sleep 1000
If counter!=3
   Exit
counter:=0
sendinput , f4
return

2::
counter++
sendinput , f5
sleep 1000
If counter!=1
   Exit
counter++
sendinput , f6
sleep 1000
If counter!=2
    Exit
counter++
sendinput , f7
sleep 1000
IF counter!=3
   Exit
counter:=0
sendinput , f8
return
Additionally, you may want SendInput, {f1} instead of f1.

An alternative is to use a timer, for which you can turn off and turn on the timer again with each launch.

Code: Select all

1::
SetTimer, timer_1, Off
SetTimer, timer_2, Off
counter:=0
SetTimer, timer_1, 1000
GoSub, timer_1 ; so you don't wait 1000 milliseconds for the timer to go
return

2::
SetTimer, timer_1, Off
SetTimer, timer_2, Off
counter:=0
SetTimer, timer_2, 1000
GoSub, timer_2
return

timer1:
counter++
If counter=1
SendInput f1
else if counter=2
SendInput f2
else if counter=3
SendInput f3
else if counter=4
{
SendInput f4
SetTimer, timer_2, Off
}
return

timer2:
counter++
If counter=1
SendInput f5
else if counter=2
SendInput f6
else if counter=3
SendInput f7
else if counter=4
{
SendInput f8
SetTimer, timer_2, Off
}
return
Rohwedder
Posts: 7669
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: How to 'press the same key for the 2nd time to restart script'?

27 Jun 2017, 00:17

Hallo,
the timer alternative, shorter:

Code: Select all

#MaxThreadsPerHotkey, 2
1::
2::
	Delta := (A_ThisHotkey - 1) * 4
	No = 1
	SetTimer, Timer, 1000
Timer:
	Key := No + Delta
	SendInput, {f%Key%}
	no++
	If (no = 5)
		SetTimer, Timer, Off
Return
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: How to 'press the same key for the 2nd time to restart script'?

27 Jun 2017, 01:21

Oi, I want to revisit the timer because we're using timer instead of sleep, and the original code uses different intervals for sleep. So, I'll transcribe the original code:

Code: Select all

1::
sleep 100
MouseMove, 711, 347
sendinput, {Click 2}
sleep 500
sendinput, {Enter}
sleep 2000
sendinput, ^!f
sleep 1000
MouseMove, 851, 577
sendinput, {Click down}
sleep 100
sendinput, {Click up}
return

Code: Select all

1::
SetTimer, Timer_1, Off
SetTimer, Timer_2, Off
counter:=0
SetTimer, Timer_1, -100 ; the - sign means run once
return

Timer_1:
counter++
If counter=1
{
MouseMove, 711, 347
SendInput, {Click 2}
SetTimer, Timer_1, -500
}
else if counter=2
{
SendInput, {Enter}
SetTimer, Timer_1, -2000
}
else if counter=3
{
SendInput, ^!f
SetTimer, Timer_1, -1000
}
else if counter=4
{
MouseMove, 851, 577
sendinput, {Click down}
SetTimer, Timer_1, -100
}
else if counter=5
{
sendinput, {Click up}
SetTimer, Timer_1, Off
}
return
AnnikaLivia
Posts: 3
Joined: 24 Jun 2017, 21:20

Re: How to 'press the same key for the 2nd time to restart script'?

28 Jun 2017, 19:23

@Exaskryz

1::
counter++
sendinput, f1
sleep 1000
If counter!=1
Exit
counter++
sendinput , f2
sleep 1000
If counter!=2
Exit
counter++
sendinput , f3
sleep 1000
If counter!=3
Exit
counter:=0
sendinput , f4
return

2::
counter++
sendinput , f5
sleep 1000
If counter!=1
Exit
counter++
sendinput , f6
sleep 1000
If counter!=2
Exit
counter++
sendinput , f7
sleep 1000
IF counter!=3
Exit
counter:=0
sendinput , f8
return

^
This one doesn't work. [1] cancels [2], but it doesn't cancel itself. And after one cancellation both hotkey won't work properly anymore. Same thing with [2] to [1].

1::
SetTimer, Timer_1, Off
SetTimer, Timer_2, Off
counter:=0
SetTimer, Timer_1, -100 ; the - sign means run once
return

Timer_1:
counter++
If counter=1
{
MouseMove, 711, 347
SendInput, {Click 2}
SetTimer, Timer_1, -500
}
else if counter=2
{
SendInput, {Enter}
SetTimer, Timer_1, -2000
}
else if counter=3
{
SendInput, ^!f
SetTimer, Timer_1, -1000
}
else if counter=4
{
MouseMove, 851, 577
sendinput, {Click down}
SetTimer, Timer_1, -100
}
else if counter=5
{
sendinput, {Click up}
SetTimer, Timer_1, Off
}
return

^
This one works perfect. Thank you so much andhave a wonderful day!

@Rohwedder Thank you to you too! But how do I make your code work if I want to change the input from [f1,f2,f3,f4] to [q,w,e,r] and/or something else.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: How to 'press the same key for the 2nd time to restart script'?

28 Jun 2017, 21:09

Oops, I forgot the #MaxThreadsPerHotkey, 255 in the code.

For future reference, code can be wrapped in [ code ] tags (no spaces).

But you are right, each line of Exit needs to become:

Code: Select all

{
counter:=0
Exit
}
Rohwedder
Posts: 7669
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: How to 'press the same key for the 2nd time to restart script'?

28 Jun 2017, 23:48

Hallo,
if you want to change the input from [f1,f2,f3,f4] to [q,w,e,r] :

Code: Select all

#MaxThreadsPerHotkey, 2
Key = q,w,e,r,t,z,F1,F2
StringSplit, Key, Key, `,
1::
2::
	Delta := (A_ThisHotkey - 1) * 4
	No := Delta + 1
	SetTimer, Timer, 1000
Timer:
	Key := Key%No%
	SendInput, {%Key%}
	No++
	If (No = Delta + 5)
		SetTimer, Timer, Off
Return
draganoth77
Posts: 5
Joined: 13 Jan 2016, 12:20

Re: How to 'press the same key for the 2nd time to restart script'?

02 Feb 2019, 12:37

Hello everyone, I thought that this thread could help me but I don't have a lot of experience with programming.

From other thread and a lot of testing I've been able to put together a script that would show a progress bar when pressing "d" and turns red for 1 sec after the duration of the progress bar:

Code: Select all

~d:: ; hotkey to start up the script
Progress, b p50 r0-50 h5 w100 y600 z20 zy0 zx0 cbLime cwBlack
time_passed:=50
Loop, 50
{
Sleep 100 ; wait for 0.1 second
time_passed-- ; Subtract 1 to the value of time_passed
Progress, %time_passed% ; the value on progress is decreased by 1
}
Progress, Off ; the progress bar turns off on it's own after 5 seconds.

Progress, b p50 r0-50 h15 w100 y600 z20 zy0 zx0 cbRed cwBlack
time_passed:=50
Sleep 1000 ; Wait 1 second
Progress, Off ;

return
This progress bar is used to keep track of a buff in a game.
I'd like it to start over if I reapply the buff before the progress bar is over. In other words, reset the script on second keypress.

For example:
T = 0 sec : I apply the buff
T = 2 sec: There is 3 seconds left to the progress bar but I press "d" again and reapply the buff, it's time goes back to 5 sec. Script stops and restart at T = 0 sec.

Also, I'd like this script to run only when I'm playing my game (Path of Exile), is there a way to put this condition in the script?

From my researches it's possible to do both of these but I'm too stupid to understand the tutorials... :(

Thank you!
Last edited by draganoth77 on 02 Feb 2019, 12:39, edited 1 time in total.
Rohwedder
Posts: 7669
Joined: 04 Jun 2014, 08:33
Location: Germany

Re: How to 'press the same key for the 2nd time to restart script'?

03 Feb 2019, 03:52

Hallo,
try:

Code: Select all

#IfWinActive Path of Exile
#MaxThreadsPerHotkey 2
~d:: ; hotkey to start up the script
#MaxThreadsPerHotkey
If time_passed
{
	time_passed:=50
	Return
}
Progress, b p50 r0-50 h5 w100 y600 z20 zy0 zx0 cbLime cwBlack
time_passed:=50
While, time_passed
{
	Sleep 100 ; wait for 0.1 second
	time_passed-- ; Subtract 1 to the value of time_passed
	Progress, %time_passed% ; the value on progress is decreased by 1
}
Progress, Off ; the progress bar turns off on it's own after 5 seconds.
Progress, b p50 r0-50 h15 w100 y600 z20 zy0 zx0 cbRed cwBlack
Sleep 1000 ; Wait 1 second
Progress, Off ;
return
User avatar
evilC
Posts: 4823
Joined: 27 Feb 2014, 12:30

Re: How to 'press the same key for the 2nd time to restart script'?

04 Feb 2019, 09:18

FYI, if you want to have a series of repeating actions, and allow interrupting that sequence, then rather than manually writing the sequence out and inserting IF blocks between each action to check if you want to restart, then a more elegant solution would be to codify the actions you wish to take into an array, and just write code to iterate through the array, taking the actions as appropriate.

For example:

Code: Select all

#SingleInstance force

; Array of Action objects
Actions := [{Type: "MM", x: 711, y: 347}
	, {Type: "Send", Keys: "{Click 2}"}
	, {Type: "Sleep", Param: 500}
	, {Type: "Send", Keys: "{Enter}"}
	, {Type: "Sleep", Param: 2000}
	, {Type: "Send", Keys: "^!f"}
	, {Type: "Sleep", Param: 1000}
	, {Type: "MM", x: 851, y: 577}
	, {Type: "Send", Keys: "{Click down}"}
	, {Type: "Sleep", Param: 1000}
	, {Type: "Send", Keys: "{Click up}"}]

; State flags
TimerRunning := 0
CurrentAction := 1
MaxActions := Actions.Length()
return

; Start / restart macro
1::
	CurrentAction := 1
	if (!TimerRunning){
		SetTimerState(1)
	}
	return

; Stop macro
2::
	if (TimerRunning){
		SetTimerState(0)
	}
	return

SetTimerState(state){
	global TimerRunning
	if (state && !TimerRunning){
		; Launch the loop in a pseudo-thread, so that hotkey thread ends and can fire again to stop
		SetTimer, DoAction, -0
	} else if (!state && TimerRunning){
		SetTimer, DoAction, Off
	}
	TimerRunning := state
}

; Loop through Actions
DoAction:
	while (TimerRunning){
		action := Actions[CurrentAction]
		DoAction(action)
		CurrentAction++
		if (CurrentAction > MaxActions){
			CurrentAction := 1
		}
	}
	return

; Processes an Action object
DoAction(action){
	if (action.Type = "Send"){
		Send % action.Keys
	} else if (action.Type = "MM"){
		MouseMove, % action.x, % action.y
	} else if (action.Type = "Sleep"){
		Sleep % action.Param
	} else {
		throw % "Unknown action " action.Type
	}
}

^Esc::
	ExitApp


Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], gabelynn1, watashiakilla and 342 guests