Logitech Lua Scripting and Looping - loops

I'm having a little problem with my script here using a Logitech mouse. I will be using it for farming in a game.
function OnEvent(event, arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 5 then
for i = 0, 300 do
PressAndReleaseKey("f9")
Sleep(400)
PressAndReleaseKey("enter")
Sleep(600)
PressAndReleaseKey("f5")
Sleep(50)
PressMouseButton(1)
Sleep(50)
ReleaseMouseButton(1)
end
PressAndReleaseKey("1")
repeat
until IsMouseButtonPressed(3)
end
end
So it will loop for 300 times and then press 1 when it's done, then repeat the loop again for 300 times, so on & so on. Problem I'm facing is, when I'm trying to abort the script, it will first finish the for-loop before being stopped by using Right-click button(IsMouseButtonPressed(3)), which is really hard to time (300x is a lot)
How can I pause/stop it during the for-loop, would it be possible?

Frequently check if the button is pressed and break the loop.
Break up those long blocking Sleeps.
Instead of Sleep(400) consider doing something like
for i = 1, 400, 50 do
Sleep(50)
if IsMouseButtonPressed(3) then break end
end

You can use break to jump out of your for loop when IsMouseButtonPressed(3)
for i = 0, 300 do
if IsMouseButtonPressed(3) then
break -- exit for loop.
end
PressAndReleaseKey("f9")
Sleep(400)
PressAndReleaseKey("enter")
Sleep(600)
PressAndReleaseKey("f5")
Sleep(50)
PressMouseButton(1)
Sleep(50)
ReleaseMouseButton(1)
end
doing it like this means you can expect a maximum delay of 1.1 seconds due to the sleep calls, for the exit to be registered.
You could change your code by adding a function to poll IsMouseButtonPressed(3) during your sleep intervals.
local function MousePollingSleep(time)
loopCount = time / 50
for i = loopCount, 0, -1 do
if IsMouseButtonPressed(3) then
return false
end
sleepTime = (i >= 1 and 1 or i) * 50
Sleep(sleepTime)
end
return true
end
and change your for loop to
function OnEvent(event, arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 5 then
repeat
for i = 0, 300 do
PressAndReleaseKey("f9")
if MousePollingSleep(400) == false then break end
PressAndReleaseKey("enter")
if MousePollingSleep(600) == false then break end
PressAndReleaseKey("f5")
if MousePollingSleep(50) == false then break end
PressMouseButton(1)
if MousePollingSleep(50) == false then break end
ReleaseMouseButton(1)
end
ReleaseMouseButton(1)
PressAndReleaseKey("1")
until IsMouseButtonPressed(3)
end
end

Related

I want it to loop only once

I have a problem with looping. I want it to loop only once, but it prints constantly. If I do return, the script will stop, i don't want that, because i would have to restart server always the script would be triggered. Any idea how to solve this problem?
local hit = GetPedLastDamageBone(ped)
local chance = math.random(0,10)
local ped = PlayerPedId()
while true do
Wait(0)
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
end
I want it to loop only once
The whole purpose of a loop is to execute a block of code multiple times.
So if you only want to loop once, you don't need a loop. Just remove the loop from your code.
local hit = GetPedLastDamageBone(ped)
local chance = math.random(0,10)
local ped = PlayerPedId()
Wait(0)
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
but it prints constantly.
while true do end
is an infinite loop. The condition is always true and will never change so the loop will run forever.
If I do return, the script will stop
Your script file is compiled as a chunk. Chunks are treated as the body of an anonymous function. return will terminate that function and hence your script unless you use it inside a function definiton in that chunk.
If you want to stop a loop prematurely use break
Please read the Lua manual and do a beginners tutorial.
if hit == 45454 or 33646 then
print("Foot")
end
Is eqivalent to
if hit == 45454 or true then
print("Foot")
end
which simplifies to
if true then
print("Foot")
end
or simply
print("Foot")
Any value that is neither nil nor false is true
So 33646 is logically true. oring anything with true yields true
An if statement with a condition that is always met is pointless.
Instead of nesting several if statements you can simply combine the conditions using logical operators.
So instead of
if GetEntityHealth(ped) > 0 then
if DMGByWeapon then
if hit == 45454 or 33646 then
print("Foot")
end
end
end
You could write
if GetEntityHealth(ped) > 0 and DMGByWeapon then
print("Foot")
end
But if you really want to use that if statement you need to fix the condition:
if hit == 45454 or hit == 33646 then
print("Foot")
end

Nested for loop slowing down for unknown reason (autoit)

My code:
Func myFunc()
$lag = 1300
while (1)
MouseMove(870, 189)
sleep(10)
LC(870, 189)
sleep(1200 + $lag)
LC(1010,333)
sleep(100)
RC(826,115)
sleep(50)
LC(870,212)
sleep(50)
send("{ESC}")
sleep(150)
$x = 0
$y = 0
For $i = 0 To 27 Step 1
sleep(11)
MouseClick("left", 1158 + $x ,260 + $y)
$x+=42
if ($x = 168) Then
$x = 0
$y+=36
EndIf
Next
WEnd
EndFunc
The only delay within the for loop is the sleep(11) but it takes about .5 seconds (500ms) for each iteration rather than 11ms + whatever small delay. Also, completely removing the sleep(11) part of the loop still results in an approximately 500ms delay.
Incase anyone was wondering, it's a video game macro; the first part of the while loop opens an interface and sets something up while the second part (the for loop) is suppose to click through the inventory very quickly.
The mouse cursor takes time to move. Set the speed parameter to 0 to make it move instantly
MouseClick("left", 1158 + $x ,260 + $y,1,0)

How to make an infinite-loop screensaver in smallbasic?

I'm making a screensaver and I need to know what's wrong with my code.
GraphicsWindow.title="Screen Saver"
GraphicsWindow.Width=500
GraphicsWindow.Height=500
For i=1 To
Colour = GraphicsWindow.GetRandomColor()
GraphicsWindow.BrushColor=Colour
XCoord = Math.GetRandomNumber(1200)
YCoord = Math.GetRandomNumber(1200)
width=math.GetRandomNumber (300)
GraphicsWindow.Fillellipse(XCoord,YCoord,width,width)
Program.Delay(200)
EndFor
ContinueForEver = "Yes"
While ContinueForEver = "Yes"
EndWhile
I'm supposed to use for i=? to ? to make an infinite loop and I'm supposed to use While EndWhile for the continuation. So basically I'm supposed to make a screensaver which generates circles forever.
Something like this?
GraphicsWindow.title="Screen Saver"
GraphicsWindow.Width=500
GraphicsWindow.Height=500
While 1 = 1
Colour = GraphicsWindow.GetRandomColor()
GraphicsWindow.BrushColor=Colour
XCoord = Math.GetRandomNumber(1200)
YCoord = Math.GetRandomNumber(1200)
width=math.GetRandomNumber (300)
GraphicsWindow.Fillellipse(XCoord,YCoord,width,width)
Program.Delay(200)
EndWhile
You were very close. But you can not have a For loop without an end number like this:
For i = 1 to
You need to have an end number:
For i = 1 to 10 '<-- the loop will run 10 times
A While statement will run as long as its input is true. So in this case, as long as 1 = 1 the loop will continue (Which is forever).
Does that help? :D

End execution without script closure by keypress?

Question
Basically, the title says it all! How do I stop execution of my hotkey via a hotkey?
How do I do so without closing the script?
How do I explicitly set a hotkey to take priority over a specific loop?
Explanation
I have a loop that executes several hundred times (code attached), and I would like to create a kill switch. I don't want to have to re-open the script if I stop it running, and I need to have lengthy sleeps, so I can fool with the mouse, as it is.
I'm looking at various pages, such as tutorial and break.
What I've tried
For example, should I name my loop somehow? Because Break takes no parameters, I'm thinking: there's no way to specify what to break.
Another example: should I add a hotkey into my loop to break? If so, how do I do that? Just throw ^!p:: into a nest under each hotkey? Or is there another way to add a hotkey to a hotkey (for example, with GetKeyState)?
Answer format
If possible, please show don't tell your answers, using the following code:
^!i::
{
Loop 1300
{
Send ^+{PrintScreen}
Sleep 1500
MouseClickDrag, left, 0, 100, 600, 400
Sleep 1000
Send 1
Sleep 500
}
Return
}
^!o::
{
Loop 1323
{
Send ^+{PrintScreen}
Sleep 1500
MouseClickDrag, left, 0, 200, 600, 400
Sleep 1000
Send 1
}
Return
}
If you want a controlled stop, i.e. at a certain point in the script, then you could use a hotkey to set a variable and test that variable in the script. When the variable has been set and the IF statement is true, you reset that variable and exit the loop. Otherwise, you could kill the script at a random point through the reload command. This way the script is closed, but immediately reopened.
^!i::
MyStopVariable:=0 ; Set the variable to 0
Loop 1300
{
If MyStopVariable
Exit ; Or Break if you want to finish something of after the loop
Send ^+{PrintScreen}
Sleep 1500
MouseClickDrag, left, 0, 200, 600, 400
Sleep 1000
If MyStopVariable
Exit ; Or Break if you want to finish something of after the loop
Sleep 500
}
Return
^!o::
MyStopVariable:=0 ; Set the variable to 0
Loop 1323
{
If MyStopVariable
Exit ; Or Break if you want to finish something of after the loop
Send ^+{PrintScreen}
Sleep 1500
MouseClickDrag, left, 0, 200, 600, 400
Sleep 1000
If MyStopVariable
Exit ; Or Break if you want to finish something of after the loop
Send 1
}
Return
^!s:: ; Ctrl+Alt+s = stop
MyStopVariable:=1
Return
Alternatively, you could use your original code and add a reload.
^!s:: ; Ctrl+Alt+s = stop
Reload
Return

Create Loop So Whole Task Repeats

import sgenrand
# program greeting
print("The purpose of this exercise is to enter a number of coin values")
print("that add up to a displayed target value.\n")
print("Enter coins values as 1-penny, 5-nickel, 10-dime,and 25-quarter.")
print("Hit return after the last entered coin value.")
print("--------------------")
#print("Enter coins that add up to 81 cents, one per line.")
total = 0
#prompt the user to start entering coin values that add up to 81
while True:
final_coin= sgenrand.randint(1,99)
print ("Enter coins that add up to", final_coin, "cents, on per line")
user_input = int(input("Enter first coin: "))
if user_input != 1 and user_input!=5 and user_input!=10 and user_input!=25:
print("invalid input")
total = total + user_input
while total != final_coin:
user_input = int(input("Enter next coin:"))
total = total + user_input
if user_input == input(" "):
break
if total > final_coin:
print("Sorry - total amount exceeds", (final_coin))
if total < final_coin:
print("Sorry - you only entered",(total))
if total== final_coin:
print("correct")
goagain= input("Try again (y/n)?:")
if goagain == "y":
if goagain == "n":
print("Thanks for playing ... goodbye!" )
I've been trying to create this loop, so it can repeat the whole program at the end when the user accepts/ if he accepts to do it again at the end.
I know you have to have a while statement around your whole program, but with my while true statement at the top, it only repeats the first part of my program and not the whole thing.
Well one thing you should be careful of is that you do not set the
total = 0
at the start of each loop. So when the user plays the game again. He will continue using his previous total. You should move total = 0 to the start of the loop
while True:
total = 0
Additionally, you need to deindent you first
while True
statement as it does not align properly with the rest of your code.
Finally, you need to allow the user to exit the while loop after he selects No for trying again.
if goagain == "n":
print("Thanks for playing ... goodbye!" )
break
This can be done by applying a break statement.

Resources