Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Send changed variables to already running function without pausing macro? Solved
#1
Hey,

I hope someone can help me or give me some hints. I would be very grateful!

I got a Macro that calls several functions. To have my code clean and with a good overview (i need that because im a noob and i want to expand the macro with more functions), I use sel case with registered Hotkeys. I hope this also helps me to not waste too many resources.

The Hotkeys are used as toggles to change variables. These variables should then be passed to a function that updates and runs without pausing the main macro (that's my main problem).
The function can or should be restarted if a parameter(variable) changes but I don't know how to do it.

This is the Macro I created. I make it to help me save some clicks and actions but I want to be able to change the macro settings so I can choose what kind of clicks it should do (or not).
 
Code:
Copy      Help
Macro [b]PlayerHelper[/b] [help1][/help1]
[code]__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F12)

int x ;;Kampfsperre
x=0

int y ;;Zuschauverbot
y=0

int c ;;Taktikmodus
c=0

MSG z
rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,x+1
,,,if(x=1)
,,,,out "X = %i" x
,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,mac "CombatSettings" "%i" "%i" "%i" x y c
,,,else
,,,,x=0
,,,,out "X = %i" x
,,,,OsdHide "1"
,,,,;; end function
,,,,
,,,case 2
,,,y+1
,,,if(y=1)
,,,,out "Y = %i" y
,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,mac "CombatSettings" "%i" "%i" "%i" x y c
,,,else
,,,,y=0
,,,,out "Y = %i" y
,,,,OsdHide "2"
,,,,;; end function
,,,,
,,,case 3
,,,c+1
,,,if(c=1)
,,,,out "C = %i" c
,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,mac "CombatSettings" "%i" "%i" "%i" x y c
,,,else
,,,,c=0
,,,,out "C = %i" c
,,,,OsdHide "3"
,,,,;; end function
,,,,
,,,case 4
,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF
,,,ret
,DispatchMessage &z
[/code]

The Function needs to stay active and repeat but only scan for the images that are activated by the variables. That means, if the main macro changes variables, they need to be passed to the function without the function pausing the main macro (but thats what's happening now). I hope this explained my problem well enough.
 
Code:
Copy      Help
Function [b]CombatSettings[/b] [help1][/help1]
[code]function# x y c ;;x=kampfsperre y=zuschauverbot c=taktikmodus

rep
,if(x=1)
,,if(scan("resource:Kampfmodus_Sperren.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
,
,if(y=1)
,,if(scan("resource:Kampfmodus_zuschauer.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
,
,if(c=1)
,,if(scan("resource:Kampfmodus_map.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
,
[/code]

Actually it looks like it only calls the function once and pauses the macro when i use one of the hotkeys (when the function starts). But the macro should continue to run and "update" the function - give it the new variables. It wouldn't be a problem if the function stops and restarts if that would be the only way to do it. I just don't know how to do it. xD

The function should also repeat, maybe until I give it a fourth variable to stop it (that would be awesome but its also beyond my skills!). I consider myself as QM noob so please (if the solution is complicated) give me an explanation of what happens. Thank you!

I already managed to have asynchronous copies of the function running, but when I play and always change the few hotkey toggles, there are more and more functions that cause lag after some time.

I also found out that I  can get the id of a function withgetopt itemid

QM Help says this would be faster than qmitem command.int i=qmitem("MyFunctionName" 1)


But i can't find examples of how to use getopt itemid.

I already got qmitem working (partially). But when I run the macro and try to get access to the function it always gives me an "Exception Error 0xC0000005. Access violation"
No matter how I tried, it didn't work for me. Please help! Sad

Thanks in advance for any tips or help!
#2
I don't know what you are trying to do, but your code has some flaws, try this one instead. This macro combines your "CombatSettings" function inside too:

Macro PlayerHelper
Code:
Copy      Help
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F10)

int x=0 ;; Kampfsperre
int y=0 ;; Zuschauverbot
int c=0 ;; Taktikmodus

MSG z
rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,x += 1
,,,if (x=1)
,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,sub.CombatSettings x y c
,,,else
,,,,x=0
,,,,OsdHide "1"
,,,;end function
,,,,
,,,case 2
,,,y +=1
,,,if (y=1)
,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,sub.CombatSettings x y c
,,,else
,,,,y = 0
,,,,OsdHide "2"
,,,;end function
,,,,
,,,case 3
,,,c += 1
,,,if (c=1)
,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,sub.CombatSettings x y c
,,,else
,,,,c = 0
,,,,OsdHide "3"
,,,;end function
,,,,
,,,case 4
,,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF

,,,ret
,DispatchMessage &z

#sub CombatSettings
function x1 y1 c1

;out F"X1={x1}, Y1={y1}, C1={c1}"

if (x1=1)
,if (scan("resource:Kampfmodus_Sperren.bmp" 0 0 1|16 30))
,,wait 0.5
,,lef
,
if (y1=1)
,if (scan("resource:Kampfmodus_zuschauer.bmp" 0 0 1|16 30))
,,wait 0.5
,,lef
,
if (c1=1)
,if (scan("resource:Kampfmodus_map.bmp" 0 0 1|16 30))
,,wait 0.5
,,lef
#3
Thanks, TeddyBear for trying to help me!

I tried the code but it does not work as I need it to do. Also, I tried to repeat the subfunction as I need it to do, but when I do that, I can't use the hotkeys anymore to toggle what the function does.

I want the Macro and the function to run simultaneously. When a variable of the macro changes, it should restart or even better update the function. the function should always run and repeat if one of the variables is not 0. If all of the variables that are passed to the function are 0, the function should stop and (re)start if one of the variables is 1.

It would be best if it is not a subfunction (at least for me) for better readability because I want to add a lot of other functions too and they also should run simultaneously and repeat. I'm not sure, but I think these are called asynchronous functions then?


They also get variables from the main macro and should restart (or even better update their variables at runtime) when something changes. I'm not sure if this even works but I would wonder if there isn't a way to do what I need. I just don't know how to code it.

I would be very happy if you can help me with that!

Thanks again!
#4
Give this a try:

Macro PlayerHelper
Code:
Copy      Help
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F10)

;Kampfsperre
int x=0

;Zuschauverbot
int y=0

;Taktikmodus
int c=0

MSG z
rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,,x += 1
,,,,if (x=1)
,,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,,CombatSettings x y c
,,,,else
,,,,,x=0
,,,,,OsdHide "1"
,,,,,;;;end function
,,,,
,,,case 2
,,,,y +=1
,,,,if (y=1)
,,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,,CombatSettings x y c
,,,,else
,,,,,y = 0
,,,,,OsdHide "2"
,,,,,;;;end function
,,,,
,,,case 3
,,,,c += 1
,,,,if (c=1)
,,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,,CombatSettings x y c
,,,,else
,,,,,c = 0
,,,,,OsdHide "3"
,,,,,;;;end function
,,,,
,,,case 4
,,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF

,,,ret
,DispatchMessage &z

Function CombatSettings
Code:
Copy      Help
;/exe
function x1 y1 c1

rep
,if (x1=1)
,,if(scan("resource:Kampfmodus_Sperren.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
,
,if (y1=1)
,,if(scan("resource:Kampfmodus_zuschauer.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
,
,if (c1=1)
,,if(scan("resource:Kampfmodus_map.bmp" 0 0 1|16 30))
,,,wait 0.5
,,,lef
#5
I can only use one Hotkey. The function doesn't even start and also the macro doesn't respond if I want to toggle the variable with the same hotkey. I wonder if you just looked at my code or also reading my text? Is my english that bad? I tried to translate it with deepl.com and it looks like its easy to understand and i got everything right. But thanks again for trying to help...

I try to explain it again short and simple:
  • Macro should always run and respond to hotkeys. No macro-pause if function starts.
  • Hotkeys toggle variables between 0 and 1. Changes should be passed to function.
  • Function should loop as long as at least one of the variables is 1.
  • If all variables are 0 the function should stop.
  • If a variable is 1 again, function should restart if it stopped before.
It should be so simple for someone with programming skills and the Macro OnScreenDisplay itself shows exactly what the function is supposed to do if you run it. You dont need to understand the OSD Text. Its just a placeholder for a if then else in the function that gets activated by a variable. I guess this should be easy if you know how to pass variables to functions without pausing the macro.

I just cant hook it to the function because I'm a programming noob and I can't find the commands or syntax I need.  Undecided
#6
Here is what I've tested with your code and it seems working fine. The hotkeys did call the function and pass the variable with correct value to the function.

Macro PlayerHelper
Code:
Copy      Help
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F10)

;Kampfsperre
int x=0

;Zuschauverbot
int y=0

;Taktikmodus
int c=0

MSG z

rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,,x += 1
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (x=1)
,,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,,CombatSettings x y c
,,,,else
,,,,,x=0
,,,,,OsdHide "1"
,,,,,;;;end function
,,,,
,,,case 2
,,,,y +=1
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (y=1)
,,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,,CombatSettings x y c
,,,,else
,,,,,y = 0
,,,,,OsdHide "2"
,,,,,;;;end function
,,,,
,,,case 3
,,,,c += 1
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (c=1)
,,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,,CombatSettings x y c
,,,,else
,,,,,c = 0
,,,,,OsdHide "3"
,,,,,;;;end function
,,,,
,,,case 4
,,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF

,,,ret
,DispatchMessage &z

In "CombatSettings" function I limit the "rep" to "rep 3" so you could easily see the changes. Later on you could remove the number 3 to let it run continuously. I've changed the logic to just output something to easy to see what's going on...

Function CombatSettings
Code:
Copy      Help
;/exe
function x1 y1 c1

rep 3
,if (x1=1)
,,out "x1 = 1 Do something here..."
,
,if (y1=1)
,,out "y1 = 1 Do something here..."
,
,if (c1=1)
,,,out "c1 = 1 Do something here..."
#7
Thank you for still trying to help me!

I copied the code and tested it, and it still produces the same results. When I start the macro and press Shift+Ctrl+X for instance, i can't press any other key to switch the hotkey toggles. It looks like the main macro pauses when I press the first hotkey.

Do I need to change some settings for the macro or function? I tried around a bit in the item properties but it didn't help.
#8
On my PC I could press the following hotkeys:
Ctrl-Shift-X
Ctrl-Shift-Y
Ctrl-Shift-C
Ctrl-Shift-F10

So that I could see it works correctly.
The OSD starts for each different hotkey.
The OSD stops when the same hotkey press again.
Ctrl-Shift-F10 will end the macro.
#9
try this for macro PlayerHelper

Macro PlayerHelper
Code:
Copy      Help
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F10)

;Kampfsperre
int x=0

;Zuschauverbot
int y=0

;Taktikmodus
int c=0
int hthread1 hthread2 hthread3
MSG z
rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,,x = !x
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (x)
,,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,,if(!hthread1)
,,,,,,hthread1=mac("CombatSettings" "" x 0 0)
,,,,else
,,,,,OsdHide "1"
,,,,,shutdown -6 0 "CombatSettings" hthread1
,,,,,hthread1 = !hthread1
,,,,
,,,case 2
,,,,y = !y
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (y)
,,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,,if(!hthread2)
,,,,,,hthread2=mac("CombatSettings" "" 0 y 0)
,,,,else
,,,,,OsdHide "2"
,,,,,shutdown -6 0 "CombatSettings" hthread2
,,,,,hthread2 = !hthread2
,,,case 3
,,,,c = !c
,,,,out F"x={x}, y={y}, c={c}"
,,,,if (c)
,,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,,if(!hthread3)
,,,,,,hthread3=mac("CombatSettings" "" 0 0 c)
,,,,else
,,,,,OsdHide "3"
,,,,,shutdown -6 0 "CombatSettings" hthread3
,,,,,hthread3 = !hthread3
,,,,
,,,case 4
,,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF
,,,,shutdown -6 0 "CombatSettings"
,,,,ret
,DispatchMessage &z
#10
Great! Thank you Kevin! This works and now i know why and how to use hthread and mac the right way.

I changed the threads all to 1 and added a if command that checks if all the variables (x y and c) are 0 and only ends the thread in that case. When thinking about it, i guess it would be better to have three functions for each hotkey to not waste resources but i can do that easily by myself now.

Thanks again Kevin and TeddyBear for helping me! Smile
#11
had an extra command in PlayerHelper. now fixed.

After looking at this further you can simplified this alot.
since action is the same in CombatSettings and the only thing that is different is the image that is being scanned for
simpler to just pass resource from PlayerHelper to CombatSettings and scan.

Macro PlayerHelper
Code:
Copy      Help
__RegisterHotKey hk1.Register(0 1 MOD_CONTROL|MOD_SHIFT 'X')
__RegisterHotKey hk2.Register(0 2 MOD_CONTROL|MOD_SHIFT 'Y')
__RegisterHotKey hk3.Register(0 3 MOD_CONTROL|MOD_SHIFT 'C')
__RegisterHotKey hk4.Register(0 4 MOD_CONTROL|MOD_SHIFT VK_F10)

int x;; Kampfsperre
int y;; Zuschauverbot
int c;; Taktikmodus
int hthread1 hthread2 hthread3
MSG z
rep
,if(GetMessage(&z 0 0 0)<1) break
,sel z.message
,,case WM_HOTKEY
,,sel z.wParam
,,,case 1
,,,,x = !x
,,,,if (x)
,,,,,OnScreenDisplay "Kampfsperre" -1 20 100 "Arial" 20 0x00FFFF 8 "1"
,,,,,hthread1=mac("CombatSettings" "" "resource:Kampfmodus_Sperren.bmp")
,,,,else
,,,,,OsdHide "1"
,,,,,shutdown -6 0 "CombatSettings" hthread1
,,,case 2
,,,,y = !y
,,,,if (y)
,,,,,OnScreenDisplay "Zuschauverbot" -1 20 140 "Arial" 20 0x00FFFF 8 "2"
,,,,,,hthread2=mac("CombatSettings" "" "resource:Kampfmodus_zuschauer.bmp")
,,,,else
,,,,,OsdHide "2"
,,,,,shutdown -6 0 "CombatSettings" hthread2
,,,case 3
,,,,c = !c
,,,,if (c)
,,,,,OnScreenDisplay "Taktikmodus" -1 20 180 "Arial" 20 0x00FFFF 8 "3"
,,,,,hthread3=mac("CombatSettings" "" "resource:Kampfmodus_map.bmp")
,,,,else
,,,,,OsdHide "3"
,,,,,shutdown -6 0 "CombatSettings" hthread3
,,,case 4
,,,if(x=0 and y=0 and c=0);; end macro only if x  y and c are zero
,,,,OnScreenDisplay "END" 3 50 400 "Arial" 20 0x00FFFF
,,,,ret;; end macro
,DispatchMessage &z

 and here is new CombatSettings function
Function CombatSettings
Code:
Copy      Help
function ~resource
rep
,if(scan(resource 0 0 1|16 30))
,,wait 0.5
,,lef
#12
Thank you, Kevin!

That's really good to know that I can even pass resources to a function, but I want to stick with the method you showed to me before because of the good readability.


Forum Jump:


Users browsing this thread: 7 Guest(s)