InGame v2.0

Post gaming related scripts
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Using INI / REGISTRY like FIFO

07 Nov 2014, 12:55

It is side effect from my project Cut & Plot that I will post later.
The idea of FIFO - First IN First OUT - I cant explain.

Now the idea is one tread to write something in list and other tread read from this same list and do something.
The usual usage of IniWrite and IniRead:
IniWrite, Value, Filename, Section [, Key] in this case:
[Section]
Key=Value

but in this case we cant delete first element easy.
Lets rearrange the data
IniWrite, IDENTIFIRE, Filename, Section , Value in this case:
[Section]
Value=IDENTIFIRE

now we have "Key" that we can delete with IniDelete and in the same time we can read from the same file Loop, Read

Code: Select all

IniWrite("IDENT" , "myINI.ini", "FileList", "FirstFile.ext")
IniWrite("IDENT" , "myINI.ini", "FileList", "SecondFile.ext")
IniWrite("IDENT" , "myINI.ini", "FileList", "ThirdFile.ext")
Result myINI.ini is:

Code: Select all

[FileList]
FirstFile.ext=IDENT
SecondFile.ext=IDENT
ThirdFile.ext=IDENT
LOL where is the trick ??? Still not visible. But let see reading:

Code: Select all

Loop, read, myINI.ini
  if InStr(A_LoopReadLine, "IDENT")
  { file:= StrSplit(A_LoopReadLine, "=")
    MsgBox(file[1])
    IniDelete("myINI.ini", "FileList", file[1]) ;<< deleting first record of list the trick
  }
This way we can write items to list using one tread or process and read/delete managed items from the same list and from another tread or process. If you dont like ini files you can use the same principal using registry.
As I said early I use this technics to fill list with FileNames and to manage them in my project CutAndPlot http://ahkscript.org/boards/viewtopic.p ... 939#p29939.
Last edited by _3D_ on 19 Oct 2017, 03:31, edited 2 times in total.
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

FunnySyntax

11 Nov 2014, 15:39

Just Funny Syntax Example

Code: Select all

;Copyright © D.Donchev
try { loop 1 ;switch
{     goto Case_%(MsgBox(4,,"Yes / No / Timeout",5), A_MsgBoxResult)% ;(<expr1>, <expr2>) return last value in list
Case_Yes: 
      MsgBox("Yes") 
      break ;break the loop
Case_No:
      MsgBox("No")
} } catch   ;default
      MsgBox("Timeout")
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

FunnySyntax

12 Nov 2014, 12:58

This while is result from optimizing loop mechanizm in CutAndPlot http://ahkscript.org/boards/viewtopic.php?f=6&t=5104 :

Code: Select all

#SingleInstance Force
;Copyright © D.Donchev
auto:=5
while InStr((A_Index>1? "Yes": "YesTimeout")
            ,(MsgBox((A_Index>1?0x104:4),ttle
                     ,(A_Index>1?"[ " A_Index " ]`n":"") "ACTION"
                     . "`n>>> " (A_Index>1?"NO":"YES") " <<<" (auto?" in " auto " sec":"")
                     ,auto)
              ,A_MsgBoxResult))
  MsgBox("ACTION")
MsgBox("END")
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

MsgBox

05 Dec 2014, 14:46

While MsgBox will be reordered dd_msgBox() function.

http://lexikos.github.io/v2/docs/commands/MsgBox.htm

Code: Select all

MsgBox, Text
MsgBox [, Options, Title, Text, Timeout]
Text argument is mostly used and I think Text must be the first argument of the function.

The function:

Code: Select all

dd_msgBox(Text:="", Options:=0, Title:="", Timeout:=0)
{ MsgBox(Options, Title, Text, Timeout)
  return A_MsgBoxResult
}
Why function must return result?
The reason is: To be seen answer from the User or Timeout.

Usage

Code: Select all

;standard
MsgBox("Press OK")
if A_MsgBoxResult == "OK", <action>

Code: Select all

;dd_msgBox
if dd_msgBox("Press OK") == "OK", <action>
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Simple Remote Control [Conceptual Model]

15 Jan 2015, 17:39

Simple Remote Control.
Let we have 2 different computers 1:<WAR> and 2:<ORC> and one player.
Of course player can use 2 different keyboards to operate with <WAR> and <ORC> but using one only keyboard will be more comfortable.

Using local network, shared folder and ini file.
EXAMPLE:

Code: Select all

iniF:="\\192.168.0.12\AHKv2.0\WAR-ORC.ini"

#F1:: IniWrite("WAR" ,iniF, "cmdWAR", "1") ;instant heal
#F3:: IniWrite("WAR" ,iniF, "cmdWAR", "3") ;healing
#F4:: IniWrite("WAR" ,iniF, "cmdWAR", "4") ;dispel
#F5:: IniWrite("WAR" ,iniF, "cmdWAR", "5") ;restore
#F6:: IniWrite("WAR" ,iniF, "cmdWAR", "6") ;healing pool
#F7:: IniWrite("WAR" ,iniF, "cmdWAR", "7") ;resurrection heal
#F9:: IniWrite("WAR" ,iniF, "cmdWAR", "9") ;prayer
#F10::IniWrite("WAR" ,iniF, "cmdWAR", "0") ;aura

#!Q::ExitApp
<WAR> can send 8 commands

Code: Select all

iniF:="\\192.168.0.12\AHKv2.0\WAR-ORC.ini"

LB_ORACLE:
SetTimer LB_ORACLE, Off  
  Loop, read, %inif%
    if InStr(A_LoopReadLine, "WAR")
    { cmd:= StrSplit(A_LoopReadLine, "=")
      if cmd[1] == "4", cmdDISPEL() ;throttle mode
      else Send(cmd[1])
      IniDelete(iniF, "cmdWAR", cmd[1])
    }  
SetTimer LB_ORACLE, 500
return

cmdDISPEL()
{ static disp:=0
  disp:=!disp
LB_DISPEL:
  SetTimer LB_DISPEL, Off
  if disp
  { Send("4")
    SetTimer LB_DISPEL, 1000 ;skill cold down 
  }
RETURN
}
#!Q::ExitApp
<ORC> Just do the commands. Command DISPEL in throttle mode
This example represent ONE-direction control: <WAR> send command and <ORC> just do it.
<WAR> and <ORC> must read/write at shared folder.
Last edited by _3D_ on 09 May 2015, 05:43, edited 1 time in total.
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Ultimate Timed threading

07 Feb 2015, 03:20

The idea is result from 45 mins boss killing and numbness in hands :P
The Idea:
Character have 10 skills (but 8 will be used).
We need mechanism to activate each of that given skills in appropriate moment with low probability of miss.
In addition each skill have different cold down(bad) and different icon(good).

The code represent 8 different timed "threads" responsible to each 8 skills that will be used.
1.Each thread is time relevant initiation.
2.Each skill try 10 times to activate itself.
3.All of threads are together user depends (1 only key start stop for all).
The Code:

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev
SendMode,Event
DD_IOPortInit(1, 0), DD_SetBtnDelay(96, 52)

#!Space::
  armed:=!armed
  GoSub skillTimer_09 ; 550 Hell Lord
  GoSub skillTimer_00 ;1200 Divine Burst

  GoSub skillTimer_04 ;  10 Ground Shock
  GoSub skillTimer_08 ;  25 Stinger
  GoSub skillTimer_02 ;  10 Wind spin
  GoSub skillTimer_05 ;  15 Enhanced Wind Spin
  GoSub skillTimer_06 ;  15 Deadly strike
  GoSub skillTimer_07 ;  15 Explosive Sting
RETURN
#!Q::ExitApp

skillTimer_02:
  SetTimer skillTimer_02, Off
  if armed
  { Skill(2)
    SetTimer skillTimer_02, 11000 ;+1 sec avoid lag 
  }  
RETURN
skillTimer_04:
  SetTimer skillTimer_04, Off
  if armed
  { Skill(4)
    SetTimer skillTimer_04, 11000
  }
RETURN
skillTimer_05:
  SetTimer skillTimer_05, Off
  if armed
  { Skill(5)
    SetTimer skillTimer_05, 16000
  }  
RETURN
skillTimer_06:
  SetTimer skillTimer_06, Off
  if armed
  { Skill(6)
    SetTimer skillTimer_06, 16000
  }  
RETURN
skillTimer_07:
  SetTimer skillTimer_07, Off
  if armed
  { Skill(7)
    SetTimer skillTimer_07, 16000
  }  
RETURN
skillTimer_08:
  SetTimer skillTimer_08, Off
  if armed
  { Skill(8)
    SetTimer skillTimer_08, 31000
  }  
RETURN
skillTimer_09:
  SetTimer skillTimer_09, Off
  if armed
  { Skill(9)
    SetTimer skillTimer_09, 551000  ;09:10 min (must be 10:00 ???)
  }  
RETURN
skillTimer_00:
  SetTimer skillTimer_00, Off
  if armed
  { Skill(0)
    SetTimer skillTimer_00, 1201000 ;20:00 min
  }  
RETURN
; 1.Activate skill
; 2.Check if skill activated (max 10 time)
; 3.If skill not activated go to 1.
Skill(s) ;function stack usage
         ;if skill interrupt another then will return to interrupted
         ;all variable must be local
{ res:=1 ; do {} while
  while (A_Index <= 10) && res ;lag and overlap, break by event or 10 times try
  { DD_BtnSend(s)
    X:= ... + (s-1)*40, Y:= ...
    ImageSearch(rx, ry, X, Y, X+33, Y+33, "*50 " A_ScriptDir "\skills\" s ".bmp") 
    ;horizontal skill tab 34x34 skill icon
    res:=!ErrorLevel ; << coincidence, ErrorLevel = 0 mean skill not activated
    ;if skil picture still not activated try once more
} }
;script work only if warr not move around
Enjoy!
Last edited by _3D_ on 09 May 2015, 05:40, edited 1 time in total.
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Ultimate Timed threading

08 Feb 2015, 12:54

As I said many times InGame is different.
I spend many HP pots and with small tuning it work perfect.

Code: Select all

Skill(s) ;function stack ussage
         ;if skill interupt another then will return to interrupted
         ;all variable must be local
{ res:=1 ; do {} while
  while (A_Index <= 5) && res ;lag and overlap 10 going to 5
  { DD_BtnSend(s)
    Sleep(500) ;<<-- half second waiting 100% success
    X:=441 + (s-1)*40, Y:= 968
    ImageSearch(rx, ry, X, Y, X+33, Y+33, "*50 " A_ScriptDir "\skills\" s ".bmp") 
    ;horizontal skill tab 34x34 skill icon
    res:=!ErrorLevel ; << coincidence, ErrorLevel = 0 mean skill not activated
    ;if skil picture still not activated try once more
} }
Very small changes - extremely success.
In the place that I use 24 HP pots (potions) script helped me to use only 8 - 3 times less.
In addition - when <<<ARMED>>> skills start smooth due to Sleep(500). :dance:
Last edited by _3D_ on 09 May 2015, 05:32, edited 1 time in total.
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Opalus

21 Feb 2015, 03:31

Another one "Opalus" activation method
1. Removed while in Skill.
2. Skill return value 0-done / 1-miss

Skill

Code: Select all

Skill(s)
{ DD_BtnSend(s) ;<< activate skill
  Sleep(500)    ;<< avoid skill initial animation
  X:=441 + (s-1)*40, Y:= 968
  ImageSearch(rx, ry, X, Y, X+33, Y+33, "*50 " A_ScriptDir "\skills\" s ".bmp") ;<< check if activated
  return ErrorLevel ;<< return 1-done / 0-miss ;<< edited
}
Function try only once to activate given skill and return to caller.
And revised call method

Code: Select all

skillTimer_02:
  SetTimer skillTimer_02, Off
  if armed
    if Skill(2)
         SetTimer skillTimer_02, 11000 ;<< if done try again after cooldown + 1sec
    else SetTimer skillTimer_02,  2000 ;<< if miss try again after 2sec
RETURN
Now if miss script will try to activate skill any 2 sec till done.

Edit for better reading

return ErrorLevel instead of !ErrorLevel
and if Skill(), wait cooldown else try again
Edit
: Crazy syntax

Code: Select all

skillTimer_2:
  SetTimer skillTimer_2, % armed? Skill(2)? 11000: again: "Off"
RETURN
<<< less text, less readable :crazy:
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Re: InGame v2.0

13 Mar 2016, 09:20

Hello, after long break.
iLL be back with External_Label_Execution.
When in normal flow of script we can write where the script "is" and after a time period to run from "there".
Next Example represent script that flow to the end and in second start go to last "remembered" position.

Code: Select all

ExternalLabel:= iniREAD("External Label.ini", "External Label", "Label")
msgBOX("Read from INI:>" ExternalLabel)
try {
	goto % ExternalLabel
} catch return	

;main script execution

LB_1000_EXTERNAL:
;LB_1000_EXTERNAL execution	
	iniWRITE("LB_1000_EXTERNAL", "External Label.ini", "External Label", "Label")
	msgBOX("LB_1000_EXTERNAL")
;return ;to stop execution	
	
LB_1001_EXTERNAL:
;LB_1001_EXTERNAL execution	
	iniWRITE("LB_1001_EXTERNAL", "External Label.ini", "External Label", "Label")
	msgBOX("LB_1001_EXTERNAL")
;return ;to stop execution
	
LB_1002_EXTERNAL:
;LB_1002_EXTERNAL execution	
	iniWRITE("LB_1002_EXTERNAL", "External Label.ini", "External Label", "Label")
	msgBOX("LB_1002_EXTERNAL")
;return ;to stop execution	
Here 4 execution parts
1: main script execution
2:LB_1000_EXTERNAL
3:LB_1001_EXTERNAL
4:LB_1002_EXTERNAL
How it work?
1.If no ini => script start from main execution
2.If ini => script start from recorded LABEL

CONCLUSIONS:
Combining "write LABEL" and "restart SCRIPT" we can manage SCRIPT flow.
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Search in File

27 Mar 2016, 16:53

This days I work about my OLD robot and want to make it to standby computer till next run. Next function is side effect from my research:

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

;usage
file:= FileOpen("\Path\Filename.ext", "rw") ;r/rw the best open flags

if search(file, "<StartBoundary>") {
	; now file.pos is set just after <StartBoundary>
} else {
	; unfortunately no "<StartBoundary>" in this file
}

file.close()
return

;search next needle inside file and set file.pos after needle
search(file, needle, reset:= 0, bytes:= 2) {
	if reset, file.seek(0)           ;seek to begin
	pos:= file.pos                   ;remember current line start position 
    while line:= file.ReadLine() {
		if ins:= inStr(line, needle) ;if line contain needle
			return file.seek(pos+strlen(needle)*bytes+(ins-1)*bytes)
        pos:= file.pos
	}
    return 0
} ;=====================================================
Function search in file for needle (from current file.pos or from file begin) and set file.pos after needle.
This function I use to manipulate XML files.
AHKv2.0 alpha forever.
User avatar
HinkerLoden
Posts: 93
Joined: 23 Mar 2016, 07:50
Contact:

Re: InGame v2.0

27 Mar 2016, 17:45

Some posting i can not even find out what relation or usability is given for the examples / code you post here. just linked it from another thread what solved the problem there. But without a relation or closer description its quite useless.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Standby & Wakeup

29 Mar 2016, 08:27

Great thanks to shajul: https://autohotkey.com/board/topic/6104 ... ely-ahk-l/
It is based on microsoft msdn: https://msdn.microsoft.com/en-us/librar ... 85%29.aspx
I found only one error, but in truth, it become directly from microsoft example.

Windows Vista, 7, 8, 10 (tested at 7 and 8)

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

msgBOX("main action")

;Windows Vista, 7, 8, 10 Sheduled Tasks format
runwait("ScheduledTask.ahk")   ;call ScheduledTask.ahk
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 1, "int", 0) ;stand by

;script standby here and wakeup here

Send {Esc} ;wake up monitor
;SendMessage, 0x112, 0xF170, -1,, Program Manager ;not work for me
;https://autohotkey.com/board/topic/2030-how-to-trigger-power-management-to-switch-off-displays/#entry12472
RETURN

#F4::ExitApp
Example is a main control action:
1. Run main action.
2. Create and register wakeup task.
3. Put the computer in standby.
zzzzzzzzzz
4. Continue action after wakeup (reload / restart / and so on).

ScheduledTask.ahk
It is long but simple in meaning enough: the idea is to create wakeup task (to wakeup computer), start nothing and delete this task then.

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

;********************************************************
; original post by shajul
; https://autohotkey.com/board/topic/61042-create-a-scheduled-task-natively-ahk-l/
;********************************************************

; Create the TaskService object.
service:= ComObjCreate("Schedule.Service")
service.Connect() ;must be call first
	; Create Task object
	taskDefinition:= service.NewTask(0) 
	taskDefinition.RegistrationInfo.Description:= "WakeUp"
	taskDefinition.RegistrationInfo.Author 	   := "3D"
	taskDefinition.Settings.Enabled:= True
	taskDefinition.Settings.StartWhenAvailable:= True
	taskDefinition.Settings.Hidden:= False
	taskDefinition.Settings.WakeToRun:= True ;wake up computer to run task
	taskDefinition.Settings.DeleteExpiredTaskAfter:= "PT0S"
		; Create a Triger object
		trigger:= taskDefinition.Triggers.Create(1) ;specifies a time-based trigger.
		wakeTime:= DateAdd(A_Now, 1, "Minutes")
		trigger.StartBoundary:= FormatTime(wakeTime, "yyyy-MM-ddTHH:mm:ss")
		trigger.EndBoundary  :=	FormatTime(DateAdd(wakeTime, 1, "Minutes"), "yyyy-MM-ddTHH:mm:ss.0000000")
        ;EndBoundary must de greath enough to give windows time to delete task
		trigger.ExecutionTimeLimit:= "PT0S"
		trigger.Id:= "TimeTriggerId"
		trigger.Enabled:= True
	; Create Action object
	taskDefinition.Actions.Create(0).Path:= "cmd" ;fake run
service.GetFolder("\").RegisterTaskDefinition("WakeUp", taskDefinition
							  ,6  ;TASK_CREATE_OR_UPDATE
							  ,"" ,""
							  ,2) ;TASK_LOGON_S4U
;you must set LogonType here instead of shajul and microsoft examples
Only difference from shajul and microsoft code is setting LogonType - must be at RegisterTaskDefinition instead of

Code: Select all

;shajul code
;********************************************************
; Set the principal for the task
principal := taskDefinition.Principal
principal.LogonType := LogonType  ; Set the logon type to interactive logon
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Nested Expressions

06 Apr 2016, 06:49

Great thanks to guest3456 and tidbit they really helped me.
The idea:
To be made a method that will allow translating formatting string with variables.

Code: Select all

#SingleInstance Force
;Copyright © D.Donchev
;===============================================================================
;function evaluate and format nested expressions in string
;	nested expressions are present in token {expression:format}
;	expression can contain: 
;		1. constants - AHK convention
;		2. variables - "`%variable" ;"`%" needed to be deref variable to value
;		3. actions	 - AHK native actions (ONLY)
;	format can be any valid for function format(f, v) formater 
;	token examples:
;	{1 + `%one + 1:02d} - calculate 1 + one + 1 and format it with 02d
;	{1 + `%one + `%two:}- calculate 1 + one + two unformatted
;	{1 + `%one + `%two}	- format omitted (ErrorLevel is set to 1 if ":" missing)
;	{1 + `%one + 1:X	- missing ended } - break evaluation and set ErrorLevel to 2
;
;	ErrorLevel
;		1: missing : in token (using {:} like formater)
;		2: missing } in token (break)
;		3: missing expression in token {} (break)
;===============================================================================
dd_nestedExp(string) { 
	try {
		while b:= inStr(string, "{",, 1) { ;identify next token begin {
			if !(e:= inStr(string, "}",, b)), throw ErrorLevel:= 2 ;missing closing } in token
			if !(m:= inStr(string, ":",, b)) {        			   ;missing :<format> in token
				ErrorLevel:= 1, fmt:= ":}", m:= e
			} else fmt:= subStr(string, m  , e-m+1)	
			if !(  exp:= subStr(string, b+1, m-b-1)), throw ErrorLevel:= 3 ;missing expression
			;tidbit nested code --------------------------------------------------------
			obj:=ComObjCreate("HTMLfile")
			obj.write("<body><script>document.body.innerText=eval('" exp "');</script>")
			;---------------------------------------------------------------------------
			;replace token with evaluated and formatted expression
			string:= subStr(string, 1, b-1) 
				  .	 format("{" fmt, obj.body.innerText)
				  .	 subStr(string, e+1   )
	}	} catch {
	}		   
	return string 
} ;simple evaluation version ===================================================
Now let see simple usage to get clear:

Code: Select all

;simple usage 
one:= 10
two:= 11
msgBOX(dd_nestedExp(deref("{1+`%one+1:02d} | {test} | {1+`%one+`%two}")) " <" ErrorLevel ">")
What deref() do: deref() convert any "known" variables to there values - deref() define variable scope too
Some advanced usage:

To be seen example needed next two functions

Code: Select all

dd_toolTip(text:= "", time:= 0) ;timedFunction
{ ToolTip % text
  SetTimer, LABEL_dd_toolTip,% time? -time:"Off" ;(-) run only once
  return
  LABEL_dd_toolTip: 
    ToolTip
  RETURN
} ;===========================================

Code: Select all

dd_sleep(tm, flag:= "DD_SleepFlag") { ;flag is send "byName"
    global
    Sleep(tm)
    if %flag%, throw %flag%
    return !%flag%
} ;===============================================
And examples:

Code: Select all

dd_waitColor(x, y, color, insec, fmt) { ;wait insec seconds for color at x:y possition
	global
	loop insec
	{	if PixelGetColor(X, Y) == color, return 1 ;original code dd_pixelGetColor(X, Y) but gdip.ahk needed 
		dd_toolTip(dd_nestedExp(deref(fmt)), 2000)
		dd_sleep(998) ;1000 too long
	}
	return 0
} ;===========================================
dd_waitColor(100, 100, 0xFF0000, 5, "Wait for RED {`%A_Index}") 
dd_waitColor(100, 100, 0x00FF00, 5, "Wait for 0x{`%color:06X} {`%insec - `%A_Index + 1:02d} seconds.")
dd_waitColor() can void different hints in its action just with changing formatting string and without changing code
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Nexted Expressions - revised

09 Apr 2016, 12:14

Revised version avoid breaking if empty token {}.

Code: Select all

dd_nestEx(str) { ;NestEx like RegEx
	try {
		while b:= inStr(str, "{",, 1) { ;identify next token begin {
			if !(e:= inStr(str, "}",, b)), throw ErrorLevel := 2 ;missing closing } in token
			if !(m:= inStr(str, ":",, b)) {        			     ;missing :<format> in token
				ErrorLevel:= 1, fmt:= ":}", m:= e
			} else fmt:= subStr(str, m  , e-m+1)
			if exp:= subStr(str, b+1, m-b-1) { ;avoid throw 
				;tidbit nested code --------------------------------------------------------
				obj:=ComObjCreate("HTMLfile")
				obj.write("<body><script>document.body.innerText=eval('" exp "');</script>")
				;---------------------------------------------------------------------------
				exp:= format("{" fmt, obj.body.innerText)
				obj:= ""	  
			} else ErrorLevel:= 3 ;missing expression
			str:= subStr(str, 1, b-1) . exp . subStr(str, e+1)
	}	} catch {
	}		   
	return str
} ;dd_nestEx(str)
Probably in the future iLL change ErrorLevel value to bitfield.
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

dd_waitColor() - revised

15 Apr 2016, 09:22

New and more flexible dd_waitColor().
What new:
1. Nested Expressions.
2. Wait for COLOR or wait not COLOR (parameter: n).
3. Hint can void what color at the place of COLOR (variable: pixl).
4. Revised wait method (getting color + nested expressions + tooltip cost too much time and now A_Tickcount compensation).

Code: Select all

dd_waitColor(x, y, color, insec, fmt:="", n:=0) { ;wait insec seconds for color at x:y possition
	global
	loop insec {
		__t:= A_Tickcount
			comp:= ((pixl:= dd_pixelGetColor(x, y)) == color) ;use pixelGetColor(x, y) for ordinary usage
			if(n? !comp: comp), return 1
			if fmt, dd_toolTip(dd_nestEx(deref(fmt)), 2000)
		dd_sleep(998 - A_Tickcount + __t) ;1000 too long
	}
	return 0
} ;==========
If parameter: n == 1 then dd_waitColor() will wait color to become different.
If parameter: n == 0 then dd_waitColor() will wait color to become equal (default).
Variable: pixl contain current color at given position (it is only for user usage).

Code: Select all

;pixl usage example
dd_waitColor(x, y, color, insec, "Wait 0x{`%pixl:06X} to become 0x{`%color:06X}")
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

DD_GetPixel - revised movement

27 Apr 2016, 16:12

https://autohotkey.com/boards/viewtopic ... 400#p17615
Long time I look for method to add comma "," to delimiters

Code: Select all

#P:: ;move mouse pointer to possition
  m:= StrSplit(InputBox("Position(X Y)",,"W150 H100",mX " " mY), array(" ", ":", "|"))
  MouseMove(m[1], m[2])        
return
And after hours of tests the result:

Code: Select all

#P:: ;move mouse pointer to possition
	m:= StrSplit(InputBox("Position(X Y)",,"W150 H100",mX " " mY), [",",":","|"," "])
	MouseMove(m[1], m[m.length])            
return
- array(...) became [...]
- delimiter space " " is moved last in line
- y coordinate became m[m.length]
StrSplit - split string in next order
1. 100,200 -> m=[100, 200] (length= 2) - one only delimiter - comma ","
2. 100, 200 -> m=[100, , 200] (length= 3) - two delimiters - comma "," and space " "
Now We can copy x, y pair and paste it to InputBox.
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

[Lib] dd Small Functions AHKv2.0

06 May 2016, 17:14

It is well known small functions but this time at once in library.
WARNING all functions are written for maximum speed - SO many checks for correct arguments or values omitted.
Remember it is your own program think before write - best condition check.

Code: Select all

dd_varExist(ByRef v) { ;check if v exist
	return !(&v = &_) 
} ;==========
Compare if address of v variable is equal to address of non existing variable _ .

Code: Select all

dd_leading(v, p:= 2, c:= "0") { ;Adding string (c) (p) times at the front of (v)
	Loop p - StrLen(v)
		v:= c v
	return v
} ;==========
Function format() is more complicated and more flexible use it instead.

Code: Select all

dd_toolTip(text:= "", time:= 0) { ;timedFunction - hide text ToolTip after time miliseconds
		ToolTip % text
		SetTimer, LABEL_dd_toolTip,% time? -time:"Off" ;(-) run only once
		return
	LABEL_dd_toolTip: 
		ToolTip
	RETURN
} ;==========
Advanced ToolTip. The main goal is to void a message and after time it is disappear automatically.

Code: Select all

dd_sleep(tm, flag:= "DD_SleepFlag") { ;throw exception that terminate curent action, flag byName
    global
    Sleep(tm)
    if %flag%, throw %flag%
    return !%flag%
} ;==========
When script run long in time user need to break it this function made it possible using try catch mechanism.

Code: Select all

dd_msgBox(Text:="", Options:=0, Title:="", Timeout:=0) {
	MsgBox(Options, Title, Text, Timeout)
	return A_MsgBoxResult
} ;==========
Advanced MsgBox() same arguments, same action but return A_MsgBoxResult.

Code: Select all

dd_setDelim(param, delim:=",", range:=3) { ;set delim delimiters in range into param
	while(strLen(param) > range) {
		r:= delim substr(param,    -range) r
		param:=   substr(param, 1, -range)
	}
	return param r
} ;==========
Example: 1234567890 -> 1,234,567,890 (written for this example)
Example: attenchars -> a,tte,nch,ars

Code: Select all

;function evaluate and format nested expressions in string
;	nested expressions are present in token {expression:format}
;	expression can contain: 
;		1. constants - AHK convention
;		2. variables - "`%variable" ;"`%" needed to be deref variable to value
;   	   need deref() to convert variable to value
;		   example: dd_waitColor(x, y, color, insec
;								,"Nested Expresion: waiting {`%insec-`%A_Index+1} seconds for {`%color:06X} at {`%x}:{`%y}")	
;			        deref() is inside dd_waitColor() that mean deref() "see" all variables seen inside dd_waitColor()
;		3. actions	 - AHK native actions (ONLY)
;	format can be any valid for function format(f, v) formatter 
;	token examples:
;	{expression:02d} - calculate expression and format it with 02d
;	{expression:}	- calculate expression unformatted
;	{expression}		- format omitted (ErrorLevel is set to 1 if ":" missing)
;	{expression:X	- missing ended } - break evaluation and set ErrorLevel to 2
;
;	ErrorLevel
;		1: missing : in token (using {:} like formatter)
;		2: missing } in token (break)
;		3: missing expression in token {}
dd_nestEx(str) { ;NestEx like RegEx
	b:=1
	try {
		while b:= inStr(str, "{",, b) { ;identify next token begin {
			if !(e:= inStr(str, "}",, b)), throw ErrorLevel:= 2 ;missing closing } in token
			if !(m:= inStr(str, ":",, b)) || m > e {        	;missing :<format> in token
				ErrorLevel:= 1, fmt:= ":}", m:= e
			} else fmt:= subStr(str, m  , e-m+1)
			if (exp:= subStr(str, b+1, m-b-1)) != "" { ;eval
				obj:=ComObjCreate("HTMLfile")  ;tidbit code ------------------------------------
				obj.write("<body><script>document.body.innerText=eval('" exp "');</script>") ;--
				exp:= format("{" fmt, obj.body.innerText), obj:= ""	  
			} else ErrorLevel:= 3 ;missing expression
			str:= subStr(str, 1, b-1) . exp . subStr(str, e+1)
	}	} catch {
	}		   
	return str
} ;==========
Cool thing that give freedom when need to void some hints.

Next functions need Gdip.ahk and Gdip.dll

Code: Select all

;get color at x:y coordinates direct (d==1) or with picture of pixel (d==0)
dd_pixelGetColor(X, Y, dc:= 0, Mask:= 0x00FFFFFF) {
	if dc, RGB:= PixelGetColor(X, Y)
	else { RGB:= Gdip_GetPixel((pBmp:= Gdip_BitmapFromScreen(X "|" Y "|1|1", 0x40CC0020)), 0, 0), Gdip_DisposeImage(pBmp)
	} 
	return RGB & Mask
} ;==========
Advanced PixelGetColor() - it can take color even "game" prevent that or even A color attribute is set (ARGB format - A ignored by default).

Code: Select all

;Wait for COLOR or not COLOR (parameter: n).
;Hint can void what color at the place of COLOR (variable: pixl).
;Revised wait method (getting color + nested expressions + tooltip cost too much time and now A_Tickcount compensation).
dd_waitColor(x, y, color, insec, fmt:="", n:=0) {
	global
	loop insec {
		t:= A_Tickcount
			comp:= ((pixl:= dd_pixelGetColor(x, y)) == color)
			if(n? !comp: comp), return 1
			if fmt, dd_toolTip(dd_nestEx(deref(fmt)), 2000)
		dd_sleep(998 - A_Tickcount + t) ;1000 too long
	}
	return 0
} ;==========
Wait color at coordinates x:y to become color or to become different from color. (Nested Expressions dd_nextEx() is written for this function).

Code: Select all

;made picture at x:y coordinates w width and h height and save it to file
DD_GetImage(x, y, w, h, file) {
	Gdip_SaveBitmapToFile((pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h, 0x40CC0020)), file)
	Gdip_DisposeImage(pBmp)
} ;==========
Snapshot a rectangle and save to file.
Again: AHKv2.0 syntax.
Enjoy!
Attachments
DD.zip
DD.ahk 32/64 AHKv2.0
(1.99 KiB) Downloaded 792 times
Gdip.zip
Gdip.ahk 32/64 AHKv2.0
(19.04 KiB) Downloaded 763 times
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Advanced snapshot to file

13 May 2016, 11:26

Next function is like DD_GetImage() but more flexible syntax of input parameters.

Code: Select all

;dd_snapShot - function save snapshot to file
;param syntax
;	begin point end point   : x <delimiter> y <delimiter> x <delimiter> y
;	begin point width height: x <delimiter> y <delimiter> W<width> <delimiter> H<height>
;Examples:
;	100 200 199 299	=> x=100 y=200 w=100 h=100
;	100,200,199 H100	=> the same
;	100|200|W100|H100	=> the same 
;	100:200 W100:299	=> the same
;	100 200 W100 H100	=> the same 
dd_snapShot(param:="", path:= ".\", file:="") { ;save snapshot to file at path folder
	if !param {
		Suspend On  ;disable hotkeys to be used in InputBox
		param:= InputBox("SnapShot",,"W150 H100")
		Suspend Off ;enable hotkeys
	}
	loop (param:= StrSplit(param, [",",":","|"," "])).length ;delimiters
		if param[A_Index] {
			goto % "CASE_" (++cnt) ;switch
			CASE_1: ;begin point x coordinate
				x:= param[A_Index]
				continue
			CASE_2: ;begin point y coordinate
				y:= param[A_Index]
				continue
			CASE_3: ;width or end point x coordinate   
				if RegExMatch(param[A_Index], "i)W([\-\d\.]+)(p*)", arg), w:= arg[1]
				else w:= param[A_Index] - x + 1 ;calculate x2-x1+1
				continue
			CASE_4: ;height or end point y coordinate
				if RegExMatch(param[A_Index], "i)H([\-\d\.]+)(p*)", arg), h:= arg[1]
				else h:= param[A_Index] - y + 1 ;calculate y2-y1+1
				break ;break loop
		}
	Gdip_SaveBitmapToFile(pBmp:= Gdip_BitmapFromScreen(x "|" y "|" w "|" h), path (name? name: x "-" y ".bmp"))
		Gdip_DisposeImage(pBmp)
} ;======
More complicated input parameters syntax. This function is invented to combine x y w h and x1 y1 x2 y2 types of rectangle.
And Usage:

Code: Select all

pToken:= Gdip_Startup()
dd_snapShot("595 397 686 408") ;usaga x y x y
dd_snapShot("100 200 W99 H99") ;usage x y w h
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Multi / Chain / Grid / Processing

22 May 2016, 04:22

Conceptual model that combine itself most things needed to run / control / communicate processes.
Why?
It is fun but all is side effect from optimizing script that helped me in my game. It became too big and looping inside became complicated. So I split actions and put in different scripts. Nothing unusual.
BUT:
1. How to run process
2. How to set and get values between processes
3. How to terminate process

1. How to RUN process
It is simple question without simple answer. There 2 main methods to run process:
1. RUN and leave http://lexikos.github.io/v2/docs/commands/Run.htm
2. RUN and wait RunWait
Both functions have identical parameters and last one is PID. But in both cases PID is know just when function return to caller. That mean till we waiting (RunWait) we haven`t PID at all.

Code: Select all

;Master.ahk
RunWait("ChildTask.ahk",,,PID) ;script will wait ChildTask.ahk to end
MsgBox(PID)
If anything OK this 2 lines are perfect, but what if Master.ahk ended before ChildTask.ahk ended. We must terminate ChildTask.ahk manualy (if 10 child tasks it mean terminate all 10 tasks manualy).

Code: Select all

myRun(name, wait:=1, para:="") { ;execute task
		global PID
		run(name " " para,,,PID)
		if wait, ProcessWaitClose(PID) ;runwait not usable 
	}
Now we RUN process GET PID and if wait WAIT task to exit. If Child freeze or waste too much time We can kill it by PID.
2. How to set and get values between processes
I use iniREAD / iniWRITE functions due to very simple but effective way. Name of INI is just script name .VAR (ChildTask.ahk.VAR).
Now tasks can read / write to all possible VAR files - that made inter-process communication.
3. How to terminate process
The easy way is:

Code: Select all

ProcessClose(PID)
but actually not so clever and usable. So We need mechanism to terminate child process controllable.

Code: Select all

__goExit() {
	ExitApp ;terminate current process
}
OnMessage(0x10, "__goExit") ;made script persistent
Now script CAN be invited to EXIT by its methods and to made closing procedures. In other case if child task is terminated (manually or other ways) its own child tasks cant be invited to exit. So let init one more function:

Code: Select all

__onExit() {
;Exit code here
}
OnExit(         "__onExit")
Class Task - combine all this things in small but effective way for multiprocessing:

Code: Select all

;Copyright (c) D.Donchev
class Task {
	static List:= {} ;static list
	__new(n, o:= 0x03, p:= 1) {
		this.name:= n, this.exit:= o 
		if p, Task.List.push(this) ;new instance of Task add itself to list
	}	
	set(name, valu, sect:="VAR") { ;set variable value into ini
		iniWrite(valu, this.name ".VAR", sect, name)
		return valu
	}
	get(name,       sect:="VAR") { ;get variable value from ini
		return iniRead(this.name ".VAR", sect, name)
	}
	run(wait:=1, para:="") { ;execute task
		;run(this.name " " para,,,pid) ;this way parameters cannot be send to script
		;probably windows specific - shortcut to script with parameters not work too
		run("autohotkey.exe " this.name " " para,,,pid) ;now script will take parameters
		this.PID:= pid ;take PID immediately 
		if wait, ProcessWaitClose(this.PID) ;runwait not usable
	}
	del(pos:=0) {
		if this.exit & 0x01 {							  ;0x01 - terminate task
			DetectHiddenWindows  On ;see hidden processes
			SetTitleMatchMode RegEx	;case insensitive i)
			SplitPath(this.name, t) ;get title
			WinClose("i)" t)		;case INsensitive 
		}
		if this.exit & 0x02, FileDelete(this.name ".VAR") ;0x02 - delete    task.ahk.VAR
		if this.exit & 0x04, FileDelete(this.name)		  ;0x04 - delete    task.ahk
		Task.List.removeAt(pos? pos: this.ind()) ;remove task from list		  
		this.base:="" ;clear object
	}
	ind() {
		while this.name != Task.List[++res].name {
		}
		return res > Task.List.length? 0: res
	}
} ;class Task
__onExit() {
	while Task.List.length
		Task.List[Task.List.length].del(Task.List.length)
}
__goExit() {
	ExitApp ;terminate current process
}
OnMessage(0x10, "__goExit") ;made script persistent
OnExit(         "__onExit")
classTask.ahk contain all parts of multi-processing.
USAGE - It is more complicated to be explained than real usage itself - so let see the examples:

Code: Select all

#SingleInstance Force
#include classTask.ahk

t1:= new Task("add.ahk") ;add task to list
t2:= new Task("sub.ahk") ;add task to list

1:: ;process 1 runWAIT
	t1.set("Arg1",  1)
	t1.set("Arg2", 10)
	t1.run(), msgBOX("Result:=" t1.get("Result") " PID:=" t1.PID)
return
2:: ;process 2 run
	t2.set("Arg1",  2)
	t2.set("Arg2", 20)
	t2.run(0), msgBOX("PID:=" t2.PID)
return	

#!Q::ExitApp
Master.ahk - it is process that run other processes (like task manager).

Code: Select all

#SingleInstance Force
#include classTask.ahk

t:= new Task(A_ScriptName,,0)
t.set("Result",t.get("Arg1") + t.get("Arg2"))
ExitApp ;needed because of OnMessage()
add.ahk - contain (+) operator and demonstrate straight process. ExitApp is needed because OnMessage() made script persistent.

Code: Select all

#SingleInstance Force
#include classTask.ahk

t:= new Task(A_ScriptName,,0)
t.set("Result",t.get("Arg1") - t.get("Arg2"))

#!3::__goExit()
sub.ahk - contain (-) operator. Here no ExitApp and script will stay runned till user press WIN+ALT+3 or script catch WM_CLOSE.
CONCLUSIONS:
( + ) One only mechanism for "parent" and "child" processes.
( + ) Can be made chains or trees of processes.
( + ) If "parent" process will be closed it will invite all its "child" processes to be closed (kill process prevent closing invitations).
( - ) All processes became Persistent and ExitApp is needed.
( - ) Process clean start (variable values can be stored in .VAR or other way).
( - ) Relatively SLOW start.
Method void real multi-processing.
Enjoy!
AHKv2.0 alpha forever.
_3D_
Posts: 277
Joined: 29 Jan 2014, 14:40

Class Task - revised

28 May 2016, 13:56

It is revised Class Task

Code: Select all

;Copyright (c) D.Donchev
class Task {
	static List:= {}   ;static list
	__new(n, e:= 0x13) {
		this.name:= n
		if (this.exit:= e) & 0x10, Task.List.push(this) ;0x10 push flag
	}	
	set(name, valu, sect:="VAR") { ;set variable value into ini
		iniWrite(valu, this.name ".VAR", sect, name)
		return valu
	}
	get(name,       sect:="VAR") { ;get variable value from ini
		return iniRead(this.name ".VAR", sect, name)
	}
	run(wait:=1, para:="") { ;execute task
		run("autohotkey.exe " this.name " " para,,,pid) ;send parameters correctly
		this.PID:= pid 									;take PID immediately 
		if wait, ProcessWaitClose(this.PID) 			;runwait
		return this	
	}
	end() {
		if this.exit & 0x01 {							  ;0x01 - terminate task
			DetectHiddenWindows On  ;see hidden processes
			SetTitleMatchMode 	3	;exactly match
			SplitPath(this.name,t)  ;get title
			WinClose(t)		    	
		}
		if this.exit & 0x02, FileDelete(this.name ".VAR") ;0x02 - delete    task.ahk.VAR
		if this.exit & 0x04, FileDelete(this.name)		  ;0x04 - delete    task.ahk
		if pos:= this.pos(), Task.List.removeAt(pos) ;remove task from list		  
		this.base:="" ;clear object
	}
	pos() {
		loop Task.List.length
			if Task.List[A_Index] == this, return A_Index
		return 0
	}
} ;class Task
__onExit() {
	while Task.List.length
		Task.List[1].end() ;less search iterations
}
__goExit() {
	ExitApp ;terminate current process
}
OnMessage(0x10, "__goExit") ;made script persistent
OnExit(         "__onExit")
What changed?
1. 0x10 - push flag
2. Title match became "3 - Exactly match instead of RegEx" - now WinClose - close only one process.
3. run(this.name " " para,,,pid) became run("autohotkey.exe " this.name " " para,,,pid) - now "child" process can accept command line parameters.
4. del() method renamed to end() and pos parameter omitted. In any cases end() check if this in list and if - removed it.
5. pos() method search process by its variable not by name.
Enjoy!
AHKv2.0 alpha forever.

Return to “Gaming Scripts (v2)”

Who is online

Users browsing this forum: No registered users and 6 guests