-
Notifications
You must be signed in to change notification settings - Fork 9
/
LGS_script_template.lua
515 lines (479 loc) · 28.7 KB
/
LGS_script_template.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
---------------------------------------------------------------------------------------------
-- LGS_script_template.lua
---------------------------------------------------------------------------------------------
-- Version: 2020-05-13
-- Author: Egor Skriptunoff
-- License: MIT License
--
-- This is a template for writing your own Lua scripts in the 'Logitech Gaming Software' programming environment.
-- Both LGS and GHUB are supported.
-- Five additional useful features are implemented here:
-- 1. Function 'print()' now displays messages in the bottom window of the script editor, you can use it the same way as in original Lua;
-- 2. 'random()' is an improved drop-in replacement for 'math.random()': better random numbers quality, no need to explicitly set the seed;
-- 3. LGS standard functions 'PressMouseButton()', 'IsMouseButtonPressed()',... now accept strings "L", "R", "M" (instead of numbers) for the first 3 mouse buttons;
-- 4. You can get and set mouse coordinates in pixels: 'GetMousePositionInPixels()', 'SetMousePositionInPixels()';
-- 5. Global variable 'D' in your Lua script is now a persistent Lua table: it is automatically saved to disk on profile exit and is automatically loaded from disk on profile start.
--
-- Prior to using this template for writing your own LGS scripts, you have to copy some additional files to your disk.
-- See details in 'How to install' section at the line #202 in this file.
--
--
--
-- ------------------------------------------------------------------------------------------
-- FEATURE #1 - You can see the output of 'print()' in the LGS script editor
-- ------------------------------------------------------------------------------------------
-- print(...)
-- ------------------------------------------------------------------------------------------
-- This function is reimplemented to display messages in the bottom window of the script editor.
-- You can use 'print()' just like you do in standard Lua!
-- When using 'print()' instead of 'OutputLogMessage()', don't append "\n" to a message.
--
--
--
-- ------------------------------------------------------------------------------------------
-- FEATURE #2 - Random numbers of very high quality
-- ------------------------------------------------------------------------------------------
-- random() -- float 0 <= x < 1
-- random(n) -- integer 1 <= x <= n
-- random(m, n) -- integer m <= x <= n
-- ------------------------------------------------------------------------------------------
-- This new function is a drop-in replacement for standard Lua function 'math.random()'.
-- It generates different sequences of random numbers on every profile load, so you don't need to set the seed explicitly.
-- The random number generator absorbs entropy from every event processed by 'OnEvent()'.
-- It takes into account everything: event type, button index, mouse position on the screen, current date and running time.
-- This entropy is converted by SHAKE128 (SHA3 hash function) into a stream of pseudo-random bits.
-- That's why function 'random()' returns random numbers having excellent statistical properties.
-- Actually, after user clicked mouse buttons 100-200 times (no hurry please),
-- these pseudo-random numbers might be considered cryptographically strong.
--
-- The code example #1 (at the end of this file) shows how you could simulate typing random alphanumeric string in Lua script.
-- A user should open a text editor and press-and-hold middle mouse button until the string is long enough.
-- This is the easiest way to generate a strong password.
--
-- ------------------------------------------------------------------------------------------
-- GetEntropyCounter()
-- ------------------------------------------------------------------------------------------
-- This function returns estimation of lower bound of number of random bits consumed by random numbers mixer.
-- Wait until it reaches 256 bits prior to generating crypto keys.
--
-- ------------------------------------------------------------------------------------------
-- SHA3_224(message)
-- SHA3_256(message)
-- SHA3_384(message)
-- SHA3_512(message)
-- SHAKE128(digest_size_in_bytes, message)
-- SHAKE256(digest_size_in_bytes, message)
-- ------------------------------------------------------------------------------------------
-- I don't know why you might need them, but SHA3 hash functions are available :-)
-- The first four (SHA3_224, SHA3_256, SHA3_384, SHA3_512) generate message digest of fixed length.
-- The last two (SHAKE128, SHAKE256) generate message digest of potentially infinite length.
-- Example: How to get SHA3-digest of your message:
-- SHA3_224("The quick brown fox jumps over the lazy dog") == "d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795"
-- SHAKE128(5, "The quick brown fox jumps over the lazy dog") == "f4202e3c58"
-- Example: How to convert your short password into infinite sequence of very high quality pseudo-random bytes:
-- -- start the sequence, initialize it with your password
-- local get_hex_byte = SHAKE128(-1, "your password")
-- while .... do
-- -- get next integer number from the inifinite sequence of pseudo-random bytes
-- local next_random_byte = tonumber(get_hex_byte(), 16) -- integer 0 <= n <= 255
-- local next_random_dword = tonumber(get_hex_byte(4), 16) -- integer 0 <= n <= 4294967295
-- -- get next floating point number 0 <= x < 1
-- local next_random_double = (tonumber(get_hex_byte(3), 16) % 2^21 * 2^32 + tonumber(get_hex_byte(4), 16)) / 2^53
-- ....
-- end
--
--
--
-- ------------------------------------------------------------------------------------------
-- FEATURE #3 - Handy names for first three mouse buttons
-- ------------------------------------------------------------------------------------------
-- "L", "R", "M" are now names for the first three mouse buttons
-- ------------------------------------------------------------------------------------------
-- There is an unpleasant feature in LGS: Logitech and Microsoft enumerate mouse buttons differently.
-- In 'OnEvent("MOUSE_BUTTON_PRESSED", arg, "mouse")' parameter 'arg' uses Logitech order:
-- 1=Left, 2=Right, 3=Middle, 4=Backward(X1), 5=Forward(X2), 6,7,8,...
-- In 'PressMouseButton(button)' and 'IsMouseButtonPressed(button)' parameter 'button' uses Microsoft order:
-- 1=Left, 2=Middle, 3=Right, 4=X1(Backward), 5=X2(Forward)
-- As you see, Right and Middle buttons are swapped; this is very confusing.
-- To make your code more clear and less error-prone, try to avoid using numbers 1, 2 and 3.
-- Now you can use strings "L", "R", "M" for the first three mouse buttons in all the functions.
-- Two modifications have been made:
-- 1) The following standard LGS functions now accept strings "L", "R", "M" as its argument:
-- PressMouseButton(),
-- ReleaseMouseButton(),
-- PressAndReleaseMouseButton(),
-- IsMouseButtonPressed()
-- 2) 'mouse_button' variable was defined inside OnEvent() function body, it contains:
-- either string "L", "R", "M" (for the first three mouse buttons)
-- or number 4, 5, 6, 7, 8,... (for other mouse buttons).
-- These modifications don't break compatibility with your old code.
-- You can still use numbers if you want:
-- if event == "MOUSE_BUTTON_PRESSED" and arg == 2 then -- 2 = RMB in Logitech order
-- repeat
-- ...
-- Sleep(50)
-- until not IsMouseButtonPressed(3) -- 3 = RMB in Microsoft order
-- But using "L"/"M"/"R" allows you to avoid inconsistent numbers:
-- if event == "MOUSE_BUTTON_PRESSED" and mouse_button == "R" then
-- repeat
-- ...
-- Sleep(50)
-- until not IsMouseButtonPressed("R")
--
--
--
-- ------------------------------------------------------------------------------------------
-- FEATURE #4 - Pixel-oriented functions for mouse coordinates
-- ------------------------------------------------------------------------------------------
-- GetMousePositionInPixels()
-- SetMousePositionInPixels(x,y)
-- ------------------------------------------------------------------------------------------
-- You can now get and set mouse cursor position IN PIXELS.
-- GetMousePositionInPixels() returns 6 values (you would probably need only the first two):
-- x_in_pixels, -- integer from 0 to (screen_width-1)
-- y_in_pixels, -- integer from 0 to (screen_height-1)
-- screen_width_in_pixels, -- for example, 1920
-- screen_height_in_pixels, -- for example, 1080
-- x_64K, -- normalized x coordinate 0..65535, this is the first value returned by 'GetMousePosition()'
-- y_64K -- normalized y coordinate 0..65535, this is the second value returned by 'GetMousePosition()'
-- We already have standard LGS function 'MoveMouseRelative' which operates with distance in pixels, but it has two problems:
-- The first problem: 'MoveMouseRelative' is limited to narrow distance range: from -127 to +127 pixels from the current position.
-- MoveMouseRelative(300, 300) -- This invocation will work incorrectly because 300 is greater than 127
-- Now you can move mouse cursor farther than 127 pixels away using the new functions:
-- local current_x, current_y = GetMousePositionInPixels()
-- SetMousePositionInPixels(current_x + 300, current_y + 300)
-- The second problem with 'MoveMouseRelative' is that it works incorrectly when 'Acceleration (Enhance Pointer Precision)' flag
-- is checked in 'Pointer settings' tab (this is the third icon from the left at the bottom of the LGS application window):
-- the real distance (how far the mouse pointer moves after you have invoked the function) does not equal
-- to the number of pixels requested in the arguments of 'MoveMouseRelative'.
-- The 'Acceleration' flag is set by default, so this problem hits every user who tryes to use 'MoveMouseRelative' in his scripts.
-- Meanwhile the new functions 'GetMousePositionInPixels' and 'SetMousePositionInPixels' work fine independently of 'Acceleration' flag.
--
-- Don't forget that you must wait a bit, for example Sleep(10), after simulating any of the following actions:
-- mouse move,
-- button press,
-- button release.
-- In other words, if you read 'GetMousePositionInPixels' right after invocation of 'SetMousePositionInPixels'
-- without a 'Sleep' in between, you will get the old mouse coordinates instead of the new ones.
-- This is because Windows needs some time to perform your simulation request.
-- Windows messaging system works slowly, there is nothing you can do to make the simulations instant.
--
--
-- Important note:
-- The script 'LGS_script_template.lua' requires one second for initialization.
-- In other words, when this LGS profile is started, you will have to wait for 1 second before you're able to play.
-- Explanation:
-- Every time this profile is activated (and every time when your game changes the screen resolution)
-- the process of automatic determination of screen resolution is restarted
-- This is necessary for correct working of pixel-oriented mouse functions.
-- This process takes about one second.
-- During this second, mouse cursor will be programmatically moved some distance away from its current location.
-- This cursor movement might be a hindrance to use your mouse, so just wait until the cursor stops moving.
--
--
--
-- ------------------------------------------------------------------------------------------
-- FEATURE #5 - Persistent table D
-- ------------------------------------------------------------------------------------------
-- Now you have special global variable 'D' which contains a Lua table; you can store your own data inside this table.
-- The variable 'D' is persistent: it is automatically saved to disk on profile exit and is automatically loaded from disk on profile start.
-- So, 'D' means 'Disk'.
-- You can accumulate some information in table 'D' across years of playing (e.g the total number of times you run this game).
-- Table 'D' is allowed to contain only simple types: strings, numbers, booleans and nested tables.
-- Circular table refrences (non-tree tables) are allowed, for example: D.a={}; D.b={}; D.a.next=D.b; D.b.prev=D.a
-- Functions, userdatum and metatables will not be saved to disk (they will be silently replaced with nils), so don't store functions inside D.
-- The table 'D' data will be stored in a file; you should give it a name:
D_filename = "D_for_profile_1.lua"
-- Replace 'profile_1' with your profile name (use only English letters and digits).
-- This file will be located in the 'C:\LGS extension' folder and will contain human-readable data.
-- If two profiles have the same 'D_filename' then they share the same table 'D'.
-- That's why you might want to make 'D_filename' different for every profile.
--
-- To avoid using my .EXE and .DLL files on your computer, you can turn feature #5 off:
-- 1) Remove the assignment 'D_filename = ...' from this file (line #187)
-- 2) (optional) Delete all the files from the folder 'C:\LGS extension' except the main module 'LGS_extension.lua'
-- 3) (optional) Delete command 'RUN_D_SAVER' from LGS/GHUB application
--
--
--
--
-- ------------------------------------------------------------------------------------------
-- How to install
-- ------------------------------------------------------------------------------------------
-- 1) Create folder 'C:\LGS extension'
-- 2) Copy the following 5 files into the folder 'C:\LGS extension' (SHA256 sums are provided for binary files):
-- LGS_extension.lua the main module
-- D_SAVER.lua external script which actually writes table D to the file
-- wluajit.exe windowless LuaJIT 2.1 x64 (doesn't create a console window) E9C320E67020C2D85208AD449638BF1566C3ACE4CDA8024079B97C26833BF483
-- lua51.dll LuaJIT DLL 112CB858E8448B0E2A6A6EA5CF9A7C25CFD45AC8A8C1A4BA85ECB04B20C2DE88
-- luajit.exe LuaJIT 2.1 x64 (does create a console window) 0F593458024EB62035EC41342FC12DAA26108639E68D6236DCF3048E527AE6E5
-- 3) Create new command:
-- In LGS:
-- Run 'Logitech Gaming Software' application
-- Open 'Customise buttons' tab
-- Select profile
-- In the left side you will see the 'Commands' pane (list of bindable actions such as keyboard keys, macros, etc), press the big plus sign to add new command.
-- In the 'Command Editor', select the 'Shortcut' in the left pane
-- Set the 1st text field 'Name' to 'RUN_D_SAVER'
-- Set the 2nd text field 'Enter a shortcut' to 'wluajit.exe D_SAVER.lua'
-- Set the 3rd text field 'Working Directory' to 'C:\LGS extension'
-- Press 'OK' button to close the 'Command Editor'
-- Important note:
-- DO NOT bind this new command to any button, this action must not be used by a human.
-- In GHUB:
-- Run 'G HUB' application
-- Click on the mouse picture to open 'Gear page'
-- Select 'Assignments' icon (plus-inside-square) at the left edge
-- Select 'SYSTEM' tab (it's the last one in the row of tabs: COMMANDS-KEYS-ACTIONS-MACROS-SYSTEM)
-- Click 'ADD APPLICATION' under the 'Launch Application' list, a file selection dialogue window will appear
-- Find the file 'C:\LGS extension\luajit.exe' and click it
-- Click 'ADD ARGUMENTS' and replace 'New argument' with 'D_SAVER.lua'
-- Click 'SAVE'
-- Select 'MACROS' tab (in the row of tabs: COMMANDS-KEYS-ACTIONS-MACROS-SYSTEM)
-- Click 'CREATE NEW MACRO'
-- Set 'RUN_D_SAVER' as macro name
-- Select 'NO REPEAT' type of macro
-- Click 'START NOW'
-- Click 'LAUNCH APPLICATION'
-- Select 'luajit'
-- Click 'SAVE'
-- Select 'SYSTEM' tab
-- Click 'luajit' in the 'Launch Application' list
-- Click 'DELETE'
-- Click 'YES' to confirm
-- Important note:
-- Now you have the 'RUN_D_SAVER' macro on the 'MACROS' tab.
-- NEVER manually assign this macro to any button, this macro must not be invoked by a human.
-- 4) Copy this script into LGS/GHUB Lua script editor.
--
--
--
-- ------------------------------------------------------------------------------------------
-- How to move the folder 'C:\LGS extension' to another location
-- ------------------------------------------------------------------------------------------
-- 1) Move all the files from 'C:\LGS extension' to your new folder.
-- 2) Change the path in the assignment 'extension_module_full_path = ...' in this file at line #280.
-- Please note that LGS and GHUB don't allow you to use non-English letters in string literals in your Lua script.
-- All symbols beyond 7-bit ASCII in your folder path must be converted to their Windows ANSI codes.
-- Example: 'D:\Папка\LGS' should be written as
-- either path = "D:\\\207\224\239\234\224\\LGS"
-- or path = [[D:\]]..string.char(207,224,239,234,224)..[[\LGS]]
-- 3) Modify the command 'RUN_D_SAVER':
-- In LGS:
-- Edit the command 'RUN_D_SAVER' and write your new folder path to the 3rd text field 'Working Directory'
-- In GHUB:
-- Select 'MACROS' tab (in the row of tabs: COMMANDS-KEYS-ACTIONS-MACROS-SYSTEM)
-- Click 'RUN_D_SAVER' to enter macro editor
-- Click 'MACRO OPTIONS' in the top right corner
-- Click 'DELETE THIS MACRO'
-- Click 'YES' to confirm
-- Create the command 'RUN_D_SAVER' again:
-- follow the instructions from step 3 'Create new command' in 'How to install' section above,
-- but use your new folder path instead of 'C:\LGS extension'
-- ------------------------------------------------------------------------------------------
-- Loading the main module
extension_module_full_path = [[C:\LGS extension\LGS_extension.lua]]
dofile(extension_module_full_path)
----------------------------------------------------------------------
-- FUNCTIONS AND VARIABLES
----------------------------------------------------------------------
-- insert all your functions and variables here
--
function OnEvent(event, arg, family)
local mouse_button
if event == "MOUSE_BUTTON_PRESSED" or event == "MOUSE_BUTTON_RELEASED" then
mouse_button = Logitech_order[arg] or arg -- convert 'arg' (number) to 'mouse_button' (either a string "L","R","M" or a number 4, 5, 6, 7, 8...)
elseif event == "PROFILE_ACTIVATED" then
ClearLog()
EnablePrimaryMouseButtonEvents(true)
update_internal_state(GetDate()) -- it takes about 1 second because of determining your screen resolution
----------------------------------------------------------------------
-- CODE FOR PROFILE ACTIVATION
----------------------------------------------------------------------
-- set your favourite mouse sensitivity
SetMouseDPITableIndex(2)
-- turn NumLock ON if it is currently OFF (to make numpad keys 0-9 usable in a game)
if not IsKeyLockOn"NumLock" then
PressAndReleaseKey"NumLock"
end
D = Load_table_D and Load_table_D() or {} -- load persistent table 'D' from disk
------ this is the first part of example how to use the persistent table 'D':
D.profile_run_cnt = (D.profile_run_cnt or 0) + 1
D.profile_total_time_in_msec = D.profile_total_time_in_msec or 0
print("Total number of times this profile was started = "..D.profile_run_cnt)
local t = math.floor(D.profile_total_time_in_msec / 1000)
print("Total amount of time spent in this profile (hr:min:sec) = "..string.format("%d:%02d:%02d", math.floor(t / 3600), math.floor(t / 60) % 60, t % 60))
------ (end of the first part of example)
-- insert your code here (initialize variables, display "Hello" on LCD screen, etc.)
--
end
update_internal_state(event, arg, family) -- this invocation adds entropy to RNG (it's very fast)
----------------------------------------------------------------------
-- LOG THIS EVENT
----------------------------------------------------------------------
-- print(
-- "event = '"..event.."'",
-- not mouse_button and "arg = "..arg or "mouse_button = "..(type(mouse_button) == "number" and mouse_button or "'"..mouse_button.."'"),
-- "family = '"..family.."'"
-- )
--
if event == "PROFILE_DEACTIVATED" then
EnablePrimaryMouseButtonEvents(false)
----------------------------------------------------------------------
-- CODE FOR PROFILE DEACTIVATION
----------------------------------------------------------------------
-- to avoid LGS/GHUB crash, profile deactivation event must be handled in less than 1 second
-- insert your code here (display "Bye!" on LCD screen, etc.)
--
------ this is the second part of example how to use the persistent table 'D':
D.profile_total_time_in_msec = D.profile_total_time_in_msec + GetRunningTime()
------ (end of the second part of example)
if Save_table_D then Save_table_D() end -- save persistent table 'D' to disk
return
end
----------------------------------------------------------------------
-- MOUSE EVENTS PROCESSING
-- (you need it if you have Logitech G-series mouse)
----------------------------------------------------------------------
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == "L" then -- left mouse button
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == "L" then -- left mouse button
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == "R" then -- right mouse button
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == "R" then -- right mouse button
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == "M" then -- middle mouse button
-- (this is code example #1, remove it after reading or testing)
-- press-and-hold MMB (middle mouse button) in your text editor to simulate typing a random string
-- press Ctrl+MMB to cyclically change mode: alphanumeric/digit/hexadecimal/disabled
random_string_mode = random_string_mode or "alphanumeric"
if IsModifierPressed"Ctrl" then
local next_mode = {alphanumeric = "digits", digits = "hexadecimal", hexadecimal = "disabled", disabled = "alphanumeric"}
random_string_mode = next_mode[random_string_mode]
elseif not IsModifierPressed"Shift" and not IsModifierPressed"Alt" and random_string_mode ~= "disabled" then
local alpha = "abcdefghijklmnopqrstuvwxyz"
local all_chars =
"0123456789"..(
random_string_mode == "hexadecimal" and alpha:sub(1, 6)
or random_string_mode == "digits" and ""
or alpha..alpha:upper()
)
repeat
for j = 1, random_string_mode == "hexadecimal" and 2 or 1 do -- in "hexadecimal" mode hex digits are generated in pairs (whole bytes)
local k = random(#all_chars)
local c = all_chars:sub(k, k)
local shift_needed = c:find"%u"
if shift_needed then
PressKey"RShift"
end
PressKey(c)
Sleep()
ReleaseKey(c)
if shift_needed then
ReleaseKey"RShift"
end
Sleep()
end
Sleep(40)
until not IsMouseButtonPressed("M")
end
-- (end of code example #1)
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == "M" then -- middle mouse button
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == 4 then -- 'backward' (X1) mouse button
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == 4 then -- 'backward' (X1) mouse button
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == 5 then -- 'forward' (X2) mouse button
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == 5 then -- 'forward' (X2) mouse button
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == 6 then
-- (this is code example #2, remove it after reading or testing)
-- move mouse cursor along a circle
local R = 50 -- the radius
if IsModifierPressed"Shift" then
-- with Shift pressed, the mouse is moving CCW using MoveMouseRelative()
local prev_x, prev_y = R, 0
for j = 1, 90 do
local angle = (2 * math.pi) * (j / 90)
local x = math.floor( R * math.cos(angle) + 0.5)
local y = math.floor(-R * math.sin(angle) + 0.5)
MoveMouseRelative(x - prev_x, y - prev_y)
prev_x, prev_y = x, y
Sleep()
end
else
-- without Shift, the mouse is moving CW using SetMousePositionInPixels()
local x_center, y_center = GetMousePositionInPixels()
x_center = x_center + R
for j = 1, 90 do
local angle = (2 * math.pi) * (j / 90)
SetMousePositionInPixels(x_center - R * math.cos(angle), y_center - R * math.sin(angle))
Sleep()
end
end
-- actual radii of these two circles (CW and CCW) may appear different due to quirks of MoveMouseRelative()
-- (end of code example #2)
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == 6 then
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == 7 then
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == 7 then
end
if event == "MOUSE_BUTTON_PRESSED" and mouse_button == 8 then
-- (this is code example #3, remove it after reading or testing)
-- print misc info (in the bottom panel of LGS/GHUB script editor) on mouse button 8 press
print("=============================================================")
print("Current date & time: "..GetDate())
local t = math.floor(GetRunningTime() / 1000)
print("profile running time (hr:min:sec) = "..string.format("%d:%02d:%02d", math.floor(t / 3600), math.floor(t / 60) % 60, t % 60))
print("approximately "..GetEntropyCounter().." bits of entropy were collected from button press events")
local i = random(6) -- integer 1 <= i <= 6
print("random dice roll:", i)
local b = random(0, 255) -- integer 0 <= b <= 255
print("random byte:", ("%02X"):format(b))
local x = random() -- float 0 <= x < 1
print("random float:", x)
local mouse_x, mouse_y, screen_width, screen_height = GetMousePositionInPixels()
print("your screen size is "..screen_width.."x"..screen_height)
print("your mouse cursor is at pixel ("..mouse_x..","..mouse_y..")")
print("=============================================================")
-- (end of code example #3)
end
if event == "MOUSE_BUTTON_RELEASED" and mouse_button == 8 then
end
----------------------------------------------------------------------
-- KEYBOARD AND LEFT-HANDED-CONTROLLER EVENTS PROCESSING
-- (you need it if you have any Logitech device with keys G1, G2, ...)
----------------------------------------------------------------------
if event == "G_PRESSED" and arg == 1 then -- G1 key
end
if event == "G_RELEASED" and arg == 1 then -- G1 key
end
if event == "G_PRESSED" and arg == 12 then -- G12 key
end
if event == "G_RELEASED" and arg == 12 then -- G12 key
end
if event == "M_PRESSED" and arg == 1 then -- M1 key
end
if event == "M_RELEASED" and arg == 1 then -- M1 key
end
if event == "M_PRESSED" and arg == 2 then -- M2 key
end
if event == "M_RELEASED" and arg == 2 then -- M2 key
end
if event == "M_PRESSED" and arg == 3 then -- M3 key
end
if event == "M_RELEASED" and arg == 3 then -- M3 key
end
----------------------------------------------------------------------
-- EXIT EVENT PROCESSING
----------------------------------------------------------------------
-- After current event is processed, we have some time before the next event occurs, because a human can't press buttons very frequently
-- So, it's a good time for 'background calculations'
perform_calculations() -- precalculate next 25 strong random numbers (only if needed), it will take about 30 ms on a modern PC
end