InGame v2.0

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

Class Task - usage

29 May 2016, 04:19

How ClassTask look like in usage? Master Process: "GameHelper"

Code: Select all

;include ClassTask.ahk, some functions and settings
#include GameHeader.ahk
;Copyright (c) D.Donchev

;inform user that helper is runned
MsgBox(,,"Game Helper.", 3)
;create and push tash to list 
taskAcc:= new Task("AcountLogin.ahk")

;create, push, run and end task
!Space::(new Task("Rewards.ahk")).run().end()
!S::	(new Task("RewardsSnapshot.ahk")).run().end()
#S::	(new Task("ChatSpam.ahk")).run().end()

#0::
	while GetKeyState("LWin")
		Sleep 1
	DD_BtnSend("000000")
return  
#9:: 
#Numpad0::
	while GetKeyState("LWin")
		Sleep 1
	(new Task("AuctionSetup.ahk")).run().end()
return

;init taskAcc and run (no end) >>> taskAcc variable keep DRY (Don`t Repeat Yourself) principle
#Right::taskAcc.run(,iniREAD("GameAccounts.ini", "Status", "CurrAcc")+1) ;it look like .get() but from different .ini
#Left:: taskAcc.run(,iniREAD("GameAccounts.ini", "Status", "CurrAcc")-1)
#Down:: taskAcc.run(,iniREAD("GameAccounts.ini", "Status", "CurrAcc")+0)
#End::  taskAcc.run(,iniREAD("GameAccounts.ini", "Status", "AccNumb")+0)
#1::
#Home:: taskAcc.run(,1)
#2::    taskAcc.run(,2)
#3::    taskAcc.run(,3)
#N::
	a:= InputBox("ACC NUMBER",,"W150 H100",iniREAD("GameAccounts.ini", "Status", "CurrAcc")+0)+0
	if !ErrorLevel, taskAcc.run(,a)
return
;keep tracking for user defined price of goods
#P::(new Task("BuyItemCheck.ahk")).run().end()	;call BuyItemForce.ahk too if check is TRUE
;forced buy goods
!X::(new Task("BuyItemForce.ahk",,0)).run().end()

#!Q::ExitApp
Now in master script only control and any process keep its code separately.
Why (new Task()).run().end()?
1. new Task(TaskName) - create control for TaskName (and push it to Task.List - if master going to close all child processes invited to close too).
2. .run() - run TaskName - when process is short and straight it is not necessary Task.List to keep control till the end of Master, but only till TaskName close itself.
3. .end() - unsubscribe TaskName from Task.List and clear .VAR and/or .AHK depend of options this.exit.
This way we have control over "child" process till it in run and release CPU and Memory resources when it close.
DONT FORGET!
Class Task - create and keep only control to the "child" process - not the same process.
Class Task - give possibilities to run MULTI processing - but real multitasking become from windows.
THE LAST started script hold and cover SHORTCUTS of already started scripts (if SHORTCUTS duplication).
Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Play media with embeded WMPlayer

30 Jun 2016, 01:57

Inspired from jethrow https://autohotkey.com/board/topic/5698 ... ntry399166
class WMPLayer: create and managed hidden Windows Media Player.

Code: Select all

class WMPlayer {
	__new(media:="", start:="", conti:="") {
		this.wmp().settings.autoStart:= 0 ;disable media auto play
		this.set(media, start, conti)
	}
	;set media - media source destination and name (can be URL - can`t be youtube link)
	;	 start - media play start position 	- xml time format "hh:mm:ss.mil"
	;	 conti - media play continuance 	- xml time format "hh:mm:ss.mil"
	set(media, start, conti) { ;set media, play start position, play continuance
		splitPath(media, fname) ;separate media name from full path name or url 
		if fname != "" { 
			FileDelete(fname .= ".asx")
			FileAppend('<Asx Version = "3.0"><Entry>'
					  . (start!=""? '<StartTime value = "' start '" />': "") ;set start point
					  . (conti!=""? '<Duration value = "'  conti '" />': "") ;set continuance
					  . '<Ref href = "' media '" /></Entry></Asx>', fname)	
		}
		this.wmp().url:= fname
	}
	wmp() { ;java inspired
		static wmp:= ComObjCreate("WMPlayer.ocx")
		return wmp ;secure existing of WMP instance
	}
	play()  { ;play media
		this.wmp().controls.play()  
	}
	pause() { ;paused media
		this.wmp().controls.pause()
	}
	stop()  { ;stop media (and revert to begining)
		this.wmp().controls.stop()  
	}
	show(tm:=25) { ;it is example how to get media status 
		static wmp
		wmp:= this.wmp() ;avoid variable scoupe problem
		if tm, SetTimer WMPLABEL, %tm%
		else   SetTimer WMPLABEL, Off	
		WMPLABEL:
			;"this" not visible when timer call WMPLAYER label 
			ToolTip(format("{:s} [{:.3f}]",wmp.url,wmp.currentMedia.duration-wmp.controls.currentPosition))
		return
	}
}
Usage:

Code: Select all

#SingleInstance Force

WM:= new WMPlayer("AC_DC - Thunderstruck.mp3", "00:00:50.000", "00:00:10.000")
;AC_DC - Thunderstruck.mp3 will be played from 50th second with 10 seconds continuance
;AC_DC - Thunderstruck.mp3 - change with existing at your computer media

1::WM.play()
2::WM.pause()
3::WM.stop()
0::
	if show:=!show, WM.show()
	else			WM.show(0)	
return 
	
Q::ExitApp	

;jethrow https://autohotkey.com/board/topic/56987-com-object-reference-autohotkey-v11/page-8#entry399166
class WMPlayer {
	__new(media:="", start:="", conti:="") {
		this.wmp().settings.autoStart:= 0 ;disable media auto play
		this.set(media, start, conti)
	}
	;set media - media source destination and name (can be URL - can`t be youtube link)
	;	 start - media play start position 	- xml time format "hh:mm:ss.mil"
	;	 conti - media play continuance 	- xml time format "hh:mm:ss.mil"
	set(media, start, conti) { ;set media, play start position, play continuance
		splitPath(media, fname) ;separate media name from full path name or url 
		if fname != "" { 
			FileDelete(fname .= ".asx")
			FileAppend('<Asx Version = "3.0"><Entry>'
					  . (start!=""? '<StartTime value = "' start '" />': "") ;set start point
					  . (conti!=""? '<Duration value = "'  conti '" />': "") ;set continuance
					  . '<Ref href = "' media '" /></Entry></Asx>', fname)	
		}
		this.wmp().url:= fname
	}
	wmp() { ;java inspired
		static wmp:= ComObjCreate("WMPlayer.ocx")
		return wmp ;secure existing of WMP instance
	}
	play()  { ;play media
		this.wmp().controls.play()  
	}
	pause() { ;paused media
		this.wmp().controls.pause()
	}
	stop()  { ;stop media (and revert to begining)
		this.wmp().controls.stop()  
	}
	show(tm:=25) { ;it is example how to get media status 
		static wmp
		wmp:= this.wmp() ;avoid variable scoupe problem
		if tm, SetTimer WMPLABEL, %tm%
		else   SetTimer WMPLABEL, Off	
		WMPLABEL:
			;"this" not visible when timer call WMPLAYER label 
			ToolTip(format("{:s} [{:.3f}]",wmp.url,wmp.currentMedia.duration-wmp.controls.currentPosition))
		return
	}
}
Work perfect at XP, 7, 8, 8.1, 10.
It is possible to be played many medias at the same time - this case you will need different show() method.
It is possible to manage any WMPlayer instance volume and speed rate.
MSDN WMPlayer documentation: https://msdn.microsoft.com/en-us/library/dd564034

Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Using "class" without instantiate.

25 Jul 2016, 04:26

If script will use only ONE instance of "class" - instance not needed:

Code: Select all

#SingleInstance Force

;init internal variables without instantiate
WMPlayer.set("AC_DC - Thunderstruck.mp3", "00:00:50.000", "00:00:10.000")

1::WMPlayer.play(1)
2::WMPlayer.pause()
3::WMPlayer.stop()
0::WMPlayer.show((show:=!show)? 25: 0)
Q::ExitApp	

class WMPlayer {
	__new(media:="", start:="", conti:="") { ;if class will used without instantiate constructor not needed
		this.set(media, start, conti)
	}
	;set media - media source destination and name (can be URL - can`t be youtube link)
	;	 start - media play start position 	- xml time format "hh:mm:ss.mil"
	;	 conti - media play continuance 	- xml time format "hh:mm:ss.mil"
	set(media, start, conti) { ;set media, play start position, play continuance
		this.wmp().settings.autoStart:= 0 ;disable media auto play
		splitPath(media, fname) ;separate media name from full path name or url 
		if fname != "" { 
			FileDelete(fname .= ".asx")
			FileAppend('<Asx Version = "3.0"><Entry>'
					  . (start!=""? '<StartTime value = "' start '" />': "") ;set start point
					  . (conti!=""? '<Duration value = "'  conti '" />': "") ;set continuance
					  . '<Ref href = "' media '" /></Entry></Asx>', fname)	
		}
		this.wmp().url:= fname
	}
	wmp() { ;java inspired
		static wmp:= ComObjCreate("WMPlayer.ocx")
		return wmp ;secure existing of WMP instance
	}
	play(rest:=0)  { ;play media
		if rest && this.wmp().playState == 3, this.pause()
		else this.wmp().controls.play()
	}
	pause() { ;pause media
		this.wmp().controls.pause()
	}
	stop()  { ;stop media (and revert to begining)
		this.wmp().controls.stop()  
	}
	show(tm:=10) { ;it is example how to get media status 
		static wmp
		wmp:= this.wmp()
		SetTimer("WMPLABEL", tm? tm: "Off")
		WMPLABEL:
			ToolTip(format("{:s} [{:.3f}]",wmp.url,wmp.currentMedia.duration-wmp.controls.currentPosition))
		return
}	}
Script use "class" description name (WMPlayer) without using new command (without making instance variable).
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

[Function] inList

22 Aug 2016, 07:37

inList(arg, list, [pos])
function create list of positions of the equal to "arg" "list" elements and return number of results. 0 - mean no any equal to "arg".

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

list:= ["dik", "two", "three"]
list[ 0]:= "zero"
list[-1]:= "dik"
list.nik:= "dik" ;nik is dik too

;(1) list contain 6 elements but Length is 3
;    Length is the highest positive integer key contained by the object,
;           or 0 if there aren't any.

msgBox(inList("dik", list, pos) ">>" pos.tostr()) ;USAGE

inList(arg, list, byRef pos:="") {
    pos:= [] ;create object that will contain list of results
    for key, val in list             ;loop in list (1)
        if val == arg, pos.push(key) ;fill the list of results positions
    ;pos is created by indexed order starting with 1 (Length == number of elements)    
    ;advantage (add method)
    pos.tostr:= Func("listtostr")    ;global not needed due to byName translation  
    ;(2) tostr in list but not in length
    return pos.length ;return number of results
}
listtostr(this) { ;convert "indexed" elements, starting by 1, to string
    res:=""
    loop this.length ;(2) loop in results only (excluding any "named" elements)
        res .= (A_Index-1? "|": "") this[A_Index] 
    return res    
}
Function inList use FOR to loop in all list elements, but function listtostr use pure loop to loop only "indexed" elements.
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Using reference as key.

07 Sep 2016, 03:11

In classTask I fill List of tasks in indexed array. This way I know order of creating of tasks but searching inside list is too complicated.
Using reference as key in {key:val} sequence made inserting / deleting / searching easy.

Code: Select all

#SingleInstance Force
;Copyright (c) D.Donchev

;demo example {key:val}
class Task {
	static List:=[]
	__new(name) {
		Task.List[this]:= name ;using reference as key
	}
	end() {
		Task.List.Delete(this) ;delete reference
	}
	run() {
		msgBox(Task.List[this] " action")
	}
} ;class Task

;fill list
new Task("ONE")
new Task("TWO")
new Task("NIK")

;iterate list
for key in Task.List
	key.run()
It is simple example that demonstrate using reference as key.
(+) - extremely simple add / delete and access list elements.
(-) - list element access in random order (due to for nature).
And optimized classTask code:

Code: Select all

;Copyright (c) D.Donchev
class Task {
	static List:= []   ;static list
	__new(n, e:= 0x03) {
		this.name:= n, this.exit:= e
		Task.List[this]:=  "3D" ;key(reference):val(nothing)
		if e & 0x20, this.run()
		if e & 0x40, this.end()
	}
	set(var, val, opt:="") { ;var val [ini:iniName sec:iniSection]
		this.ini(opt, ini, sec)
		iniWrite(val, ini, sec, var)
		return   val
	}
	get(var,      opt:="") { ;var [ini:iniName sec:iniSection]
		this.ini( opt, ini, sec)
		return iniRead(ini, sec, var)
	}
	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
		this.name:= ""
		Task.List.Delete(this) ;use internal mechanism
	}	
	ini(opt, byRef ini, byRef sec) { ;DRY [ini:iniName sec:iniSection]
		ini:= this.name ".VAR", sec:="VAR"
		loop (opt:= StrSplit(opt, [",","|"," "])).length
			if opt[A_Index] {
				if RegExMatch(opt[A_Index], "i)ini:([\w\\:.]+)(p*)", arg), ini:= arg[1]
				if RegExMatch(opt[A_Index], "i)sec:([\w]+)(p*)"    , arg), sec:= arg[1]
	}	}
} ;class Task
__onExit() {
	for key in Task.List
		key.end()
	ExitApp 
}
OnMessage(0x10, "__onExit") ;WM_CLOSE
OnMessage(0x11, "__onExit") ;WM_QUERYENDSESSION
OnExit(         "__onExit")
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Re: InGame v2.0

07 Sep 2016, 15:15

ty for example I like this instance less
guest3456
open my eyes with this post https://autohotkey.com/boards/viewtopic ... 001#p95001
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

classTask again

14 Sep 2016, 14:10

When I change Task.List to list of references I made major revision of code:

Code: Select all

;Copyright (c) D.Donchev
class Task {
	static List:= []   ;static list
	__new(n, e:= 0x03) {
		this.name:= n, this.exit:= e, this.PID := 0
		Task.List[this]:=  "3D" ;key(reference):val(nothing)
		if e & 0x20, this.run()
		if e & 0x40, this.end()
	}
	set(var, val, opt:="") { ;var val [ini:iniName sec:iniSection]
		this.ini(opt, ini, sec)
		iniWrite(val, ini, sec, var)
		return   val
	}
	get(var,      opt:="") { ;var [ini:iniName sec:iniSection]
		this.ini( opt, ini, sec)
		return iniRead(ini, sec, var)
	}
	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
	}
	end() { ;
		if this.exit & 0x01 {							  ;0x01 - terminate task
			DetectHiddenWindows On  
			WinClose("ahk_pid" this.PID)
			ProcessWaitClose(this.PID)
		}
		if this.exit & 0x02, FileDelete(this.name ".VAR") ;0x02 - delete    task.ahk.VAR
		if this.exit & 0x04, FileDelete(this.name)		  ;0x04 - delete    task.ahk
		this.name:= "", this.PID:= 0
		Task.List.Delete(this) ;use internal mechanism
	}	
	ini(opt, byRef ini, byRef sec) { ;DRY [ini:iniName sec:iniSection]
		ini:= this.name ".VAR", sec:="VAR"
		loop (opt:= StrSplit(opt, [",","|"," "])).length
			if opt[A_Index] {
				if RegExMatch(opt[A_Index], "i)ini:([\w\\:.]+)(p*)", arg), ini:= arg[1]
				if RegExMatch(opt[A_Index], "i)sec:([\w]+)(p*)"    , arg), sec:= arg[1]
	}	}
} ;class Task
__onExit() {
	for key in Task.List
		key.end()
	ExitApp 
}
__myExit() {
	ExitApp
}
OnMessage(0x10, "__myExit") ;WM_CLOSE
OnMessage(0x11, "__myExit") ;WM_QUERYENDSESSION
OnExit(         "__onExit")
1. Any new task is subscribed to task list.
2. Winclose("ahk_pid" pid) - instead of name - it is exactly process that need to be closed.
3. WM_CLOSE and WM_QUERYENDSESSION call __myExit that call __onExit tought ExitApp - this way avoid double calling of __onExit

Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

[FUNCTION] ColorIs()

11 Oct 2016, 14:32

Hi,
In many scripts We need to check what color is at a given coordinate - it is simple task:

Code: Select all

if PixelGetColor(x, y) == 0xC1C2C3, do action
BUT there different video resolutions and different video cards, so we have a method to check color at "unknown coordinates" with "unknown color" and script to keep the same functionality.
At advance we can have some TRUE colors and some FALSE colors:
0xFFFFFF:1, 0xFFFF00:1 - TRUE colors
0x000000:0, 0x0000FF:0 - FALSE colors
Lets We take the same syntax: <color>:<boolean>
And let We organize colors in list:
0xFFFFFF:1, 0xFFFF00:1, 0x000000:0, 0x0000FF:0
So we have 4 different colors 2xTRUE(1) and 2xFALSE(0).
At this time We have a next syntax:

Code: Select all

Color=x, y, color:1, color:0
And in different resolutions and different video cards We must need different sign for the same action:

Code: Select all

[Section1]
USER_check= 100, 100, 0x010203
[Section2]
USER_check= 110, 110, 0x010101
Now in this INI We have 2 different sections Section1 and Section2, but for one action USER_check.
Now We have method to activate the same action with the different attributes.
Let made method to read from this INI

Code: Select all

IniReadPixel(f:="", s:="", varr:="", byRef pixl:= "") {
	static file:=A_ScriptName, sect:= ""
	pixl:= [] ;create object
	if f != "", file:= f
	if s != "", sect:= s ;set static 
	if varr != "" {
		varr:= strSplit(IniRead(file, sect, varr), [",","|"," "])
		cnt:= 0
		for key, val in varr
			if val != "" 
				if    ++cnt == 1, pixl.x:= val ;add x to pixl
				else if cnt == 2, pixl.y:= val ;add y to pixl
				else {						   ;add {color:action}
					val:= strSplit(val, ":")
					pixl[val[1]]:= val[2]
	}			}
	return pixl
}
Function READ from INI record that define coordinates and colors that give TRUE and FALSE.
Now We need to check what color We have at the screen:

Code: Select all

ColorIs(sec, byRef pix:="", mis:= 998) {
	cnt:= 0
	loop sec {
		tooltip(sec--) ;
		pix.c:= PixelGetColor(pix.x, pix.y) ;add c to pix
		for key, val in pix 
			if key == pix.c, return val
		sleep(mis)
	}	
	return ""
}
This function return color:action if screen color is equal to color or "" if time out.
I chose "" instead of 0 because in some variations function return 0, 1, 2 and "".
1. Advantage - create virtual class:
The 2 functions creates and modified (class) pixl, used to keep parameters for a given pixel and to communicate between functions. Like result pixl keep coordinates, color actions and color of given coordinate that we get from screen.
2. Advantage - use script like INI file

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

CoordMode, Pixel, Screen
	;ini name A_ScriptName
	;ini section IE8-W7
	;ini section key OPEN_chk
msgBOX(ColorIs(10, IniReadPixel(A_ScriptName, "IE8-W7", "OPEN_chk", p)) "|" p.x "|" p.y "|" p.c)

IniReadPixel(f:="", s:="", varr:="", byRef pixl:= "") { ;set f and s for further use
	static file:= A_ScriptName, sect:= ""
	pixl:= [] ;create object
	if f != "", file:= f
	if s != "", sect:= s ;set static 
	if varr != "" {
		varr:= strSplit(IniRead(file, sect, varr), [",","|"," "])
		cnt:= 0
		for key, val in varr
			if val != "" 
				if    ++cnt == 1, pixl.x:= val ;add x to pixl
				else if cnt == 2, pixl.y:= val ;add y to pixl
				else {						   ;add {color:action}
					val:= strSplit(val, ":")
					pixl[val[1]]:= val[2]
	}			}
	return pixl
}

ColorIs(sec, byRef pix:="", mis:= 998) {
	cnt:= 0
	loop sec {
		tooltip(sec--) ;
		pix.c:= PixelGetColor(pix.x, pix.y) ;add c to pix
		for key, val in pix 
			if key == pix.c, return val
		sleep(mis)
	}	
	return 0
}
/* ;This line prevent AutoHotkey.exe to void errors. NEXT IS INI
[IE8-W7]
URL_btn		=  95,  42
User_chk	= 769, 485, 0x3A91FC:1
User_btn	= 560, 350
Time_chk	= 636, 689, 0xFFBB11:1, 0x575556:0
OPEN_chk	= 645, 354, 0xFFFFFF:1, 0xC9CED4:0
OPEN_btn	= 645, 354
REDE_chk	= 659, 233, 0xFFFFFF:1
REDE_btn	= 659, 233
LOAD_chk	= 430, 680, 0x461705:1
There only one section but demonstrate all explained things.
Enjoy!
Last edited by _3D_ on 19 Oct 2017, 03:22, edited 1 time in total.
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

IniReadPixel

17 Oct 2016, 15:21

IniReadPixel ini variants

Let We have next source:

Code: Select all

[Computer-1-1280x800]
OPEN_btn_chek= 100, 100, 0x010203:1, 0x010200:0
OPEN_btn_push= 110, 110
And another source:

Code: Select all

[Computer-2-1280x800]
OPEN_btn_chek= 100, 100, 0x112233:1, 0x010200:0
OPEN_btn_push= 110, 110
Here We have two sections that have only one color difference.

VARIANT 1

Code: Select all

[Computer-1-1280x800]
OPEN_btn_chek= 100, 100, 0x010203:1, 0x010200:0
OPEN_btn_push= 110, 110
[Computer-2-1280x800]
OPEN_btn_chek= 100, 100, 0x112233:1, 0x010200:0
OPEN_btn_push= 110, 110
Complete description.

VARIANT 2

Code: Select all

[Computer-1-1280x800]
OPEN_btn_chek= 100, 100, 0x010203:1, 0x112233:1, 0x010200:0
OPEN_btn_push= 110, 110
Short description but the same functionality due to action OPEN_bnt_chek have two TRUE colors.

Enjoy !
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

WakeUp-Run-Sleep

30 Oct 2016, 07:16

After several months of testing on my WakeUp robot - I get next conclusions.
1. MS Documentation - not so accurate.
2. MS Windows - cant work fine if system used Sleep-Wakeup.
Edit:
3. Mandatory disable hibernation. (run cmd as administrator then type powercfg -h off)
Now how the robot must to work to avoid MS troubles:

1. Start Robot in clean environment.
This is most important if you have your robot to work longer without strange errors. After several wakeup-sleep cycles script become nonfunctional but restart return script to normal condition (I dont know why and cant investigate). Let just say: this is initial part.

2. If you using computer for other activities.
This part describe the robot action and Ill named: action part.

3. Autorun after restart.

AutoRun part became last in list but Ill explain it first:

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

msgBOX(,"AUTORUN", "RUN Robot  after 120 sec", 120) ;inital waiting till computer became ready
run c:\develop\ahkv2.0\robot\action.ahk
Yep, just 2 lines. And let name it: AutoRun.ahk
1. You must copy Autohotkey.exe near to initial script AutoRun.ahk.
2. You must rename Autohotkey.exe to AutoRun.exe
3. You must plase shortcut of AutoRun.exe to your startup folder (Win+R then write shell:startup).
MS not start .ahk files no matter if it registered or no for known extensions.

Action part the part in the middle.
It is main action that we need but in most cases we need to check and reorganizing this part - so it must be written that way to avoid forced running easily.

Code: Select all

aTime:= IniRead(A_ScriptName, "Status", "NextRun", A_Now) ;read when will be next run
;if record missing A_Now will be return as default value
if DateDiff(A_Now, aTime, "S") < 0 ;if > (after time) or == (in time) run action
{	msgBOX(,,"Run at " FormatTime(aTime, "HH:mm:ss"),5)
	ExitApp
}
If not still the time Exit. This simple lines avoid accidental running.
DONT FORGET: script must end with /*

Code: Select all

;script code

service:= ComObjCreate("Schedule.Service") ;prepare TaskScheduler event
service.Connect() ;must be call first
	taskDefinition:= service.NewTask(0) 
	taskDefinition.Settings.WakeToRun:= True ;wake up computer to run task
	taskDefinition.Settings.DeleteExpiredTaskAfter:= "PT0S" ;remove task immediately when EndBoundary
		trigger:= taskDefinition.Triggers.Create(1) ;specifies a time-based trigger.
		trigger.StartBoundary:= FormatTime(t:= DateAdd(aTime, aNext, "M"), "yyyy-MM-ddTHH:mm:ss")
		IniWrite(t, A_ScriptName, "Status", "NextRun") ;write to ini part
		trigger.EndBoundary  := FormatTime(    DateAdd(    t,     5, "S"), "yyyy-MM-ddTHH:mm:ss") ;must have enough time to become MS ready to understand
		trigger.Enabled:= True
	taskDefinition.Actions.Create(0).Path:= "c:\develop\ahkv2.0\robot\InitialRun.ahk" ;after wakeup run initial.run
service.GetFolder("\").RegisterTaskDefinition("WakeUp", taskDefinition, 6, "", "", 3) ;3 the right value
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 1, "int", 0) ;stand by
;script will sleep-wakeup here
ExitApp ;exit when wakeup
/* ;text begin marker <<< mandatory (ini part)
[Status] 
NextRun= ... ;ini record (must be avoided)
You can use other ini file of course and then this part not needed A_ScriptName must be changed to your.ini.

Initial part. LOL "initial" but last in line why?
I named this part initial because it initiate the whole action sequence. At my example this section just will restart computer.

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

msgBOX(,"ATENTION", "RESTART after 120 sec", 120) ;waiting user to became ready
Shutdown 6
Conclusions:
It is sequence of actions that guarantee wake up running of main action in clear environment (after reset) wait user to end his activities if have (before restart) in appropriate time, do the action and sleep again.
My robot wake-run-sleep in 323 seconds any 6 hours.

Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

EndTask

11 Jan 2017, 13:34

Hi,
In my practice have an "great" programmer with "great" programs. Unfortunately some, probably most, have problems to catch and to execute system event messages. So SHUTDOWN, RESTART, LOG OFF and so on cant be properly do it due to cycling inside the "programs".
I just write a simple script that KILL looped processes.
VARIANT 1:

Code: Select all

#SingleInstance force
#NoTrayIcon
;Copyright (c) D.Donchev

OnMessage(0x10, "__myExit") ;WM_CLOSE
OnMessage(0x11, "__myExit") ;WM_QUERYENDSESSION
OnMessage(0x12, "__myExit") ;WM_QUIT
OnMessage(0x16, "__myExit") ;WM_ENDSESSION

#!Q::ExitApp

__myExit()
{	loop (apps:=[ "prnspool.exe"
				, "wprofile.exe"]).length
		ProcessClose(apps[A_Index])
	ExitApp
}
It work perfect extremely small code BUT there a maintenance problem, just ONE. It is extremely unreadable and editable for ordinary person.
VARIANT 2:

Code: Select all

#SingleInstance force
#NoTrayIcon
;Copyright (c) D.Donchev

OnMessage(0x10, "__myExit") ;WM_CLOSE
OnMessage(0x11, "__myExit") ;WM_QUERYENDSESSION
OnMessage(0x12, "__myExit") ;WM_QUIT
OnMessage(0x16, "__myExit") ;WM_ENDSESSION

#!Q::ExitApp

__myExit()
{	Loop, read, %A_ScriptName%						;read line
		if ini, ProcessClose(A_LoopReadLine)
		else ini:= inStr(A_LoopReadLine, "/*") == 1 ;this line == 43
	ExitApp
}	
/* Todor's-stupid-apps-list							;this line ==  1
prnspool.exe
wprofile.exe
What is goal here - you can call by phone to pretty girl and ask her to white at the end of file new process. :bravo:

Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

for vs loop in array

30 Apr 2017, 12:47

Hi
There is a simple test that represent 3 different search methods in array (actually in Autohotkey no arrays but lists).

Code: Select all

#SingleInstance force
#NoTrayIcon
;Copyright (c) D.Donchev

a:= []
loop 100 ;try with 10
	a[A_Index]:= A_Index

dt:= A_TickCount
loop 100000
	inarr(55, a) ;when 10 - search 5
msgBOX(A_TickCount - dt)	

inarr(c, a, n:="") {
	;variant 1
	for r, v in a
		if v == c, return r
	
	;variant 2
	;loop a.length
	;	if a[A_Index] == c, return A_Index
	
	;variant 3
	;loop j:=a.length
	;	if a[--j] == c, return j
	
	return n
}
First test with array of 10 elements and we search value 5
variant 1 - 421
variant 2 - 390
variant 3 - 500
what many operations inside loop - so low

Second test with array of 100 elements and we search value 55
variant 1 - 1859
variant 2 - 2360
variant 3 - 2828
amazing result

So for faster than loop in large arrays.
If you need to search inside arrays use for to get best performans.
Enjoy!
AHKv2.0 use the future now.
User avatar
SnowFlake
Posts: 368
Joined: 28 Apr 2015, 05:41
Google: floowsnaake
GitHub: floowsnaake
Contact:

Re: InGame v2.0

30 Apr 2017, 15:05

i don't know how to use any of your scripts sorry
:yawn:
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Re: InGame v2.0

15 May 2017, 14:29

RegExNMatch Function

Code: Select all

;--------------------------------------------------------------------------------------
;RegExNMatch(Haystack, NeedleRegEx [, OutputVar, Numbers:= 1, StartingPosition:= 1])
;	find first Numbers matches of NeedleRegEx in Haystack from StartingPosition
;	return numbers of actually found NeedleRegEx
;
RegExNMatch(Haystack, NeedleRegEx, ByRef OutputVar:="", Numbers:= 1, StartingPosition:=1) {
	OutputVar:=[] ;create OutputVar object
	loop Numbers  ; 
		if StartingPosition:= RegExMatch(Haystack, NeedleRegEx, v, StartingPosition) {
			OutputVar.push(v[1])
			StartingPosition += v.len(1)
		} else break
	return OutputVar.length()	
} ;------------------------------------------------------------------------------------
There no "ALL" option at the moment but Ill think about.
Last edited by _3D_ on 25 May 2017, 04:11, edited 1 time in total.
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Re: InGame v2.0

15 May 2017, 14:36

SnowFlake wrote:i don't know how to use any of your scripts sorry
You don`t need know - you need to understand.
AHKv2.0 use the future now.
User avatar
SnowFlake
Posts: 368
Joined: 28 Apr 2015, 05:41
Google: floowsnaake
GitHub: floowsnaake
Contact:

Re: InGame v2.0

15 May 2017, 15:07

then teach me/show me how to understand and also im sure a lot of other ppl want to know and understand also :)
:yawn:
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

Re: InGame v2.0

23 May 2017, 14:10

In this post I explain how to OCR digits https://autohotkey.com/boards/viewtopic ... 400#p14243
There many many changes that I forgоt to post so:

Code: Select all

ocrGetDigit(recBmp, color, varia, nores:= "") {
	static _i:= 10, _bmp:= [] ;still not possible initializing static 
	;first  time loop 10
	;second time loop  0 => no loop by language default
	Loop _i
		_bmp[_i]:= Gdip_CreateBitmapFromFile(".\ocr\" --_i ".bmp") ;it work perfect 
	Loop 10
		if ocrBWCompare(recBmp, _bmp[A_Index-1], color, varia), return A_Index-1
	return nores ;added extra return if no match
}
Shorter code - just optimized - there only one arithmetic operation in first loop (--_i) for both sides.

Code: Select all

			mX:=X+295, mY:=Y+147, itemP:= "" ;ocr item price RED digits
			loop 10 {
				bmp:= Gdip_BitmapFromScreen(mX "|" mY "|5|7")
				itemP .= ocrGetDigit(bmp, 0xFF0000, 50, 0) ;concatenate as string
				Gdip_DisposeImage(bmp)
				mX += (mod(A_Index, 3) == 1)? 9: 6
			} 
			itemP += 0 ;force conversion to value
Shorter code - the same - calculations is replaced to concatenation and added forced conversion to value (simple enough).
Enjoy!
Last edited by _3D_ on 25 May 2017, 08:32, edited 1 time in total.
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

RegExNMatch

25 May 2017, 08:17

RegExNMatch - revised.

Code: Select all

;--------------------------------------	
;Haystack		  - The string whose content is searched.
;NeedleRegEx	  - The pattern to search for, which is a Perl-compatible regular expression (PCRE). 
;OutputVar		  - Output list with found matches.
;Numbers		  - Numbers of searched matches.
;						+ - first Numbers matches
;						0 - nothing
;						- - all matches (DEFAULT)
;StartingPosition - Initial starting possition.

RegExNMatch(Haystack, NeedleRegEx, ByRef OutputVar:="", Numbers:= -1, StartingPosition:= 1) {
	OutputVar:=[]    ;create OutputVar
	while Numbers--  ;
		if (StartingPosition:= RegExMatch(Haystack, NeedleRegEx, v, StartingPosition)) && v.count() {
			OutputVar.push(v.value())
			StartingPosition += v.len()
		} else break
	return OutputVar.length()	
} ;--------------------------------------
Changes:
1. while Numbers-- instead of loop Numbers - negative value produced loop until break.
2. check if v.count() - stop iterations if pattern match nothing (void looping).

Enjoy!
AHKv2.0 use the future now.
_3D_
Posts: 189
Joined: 29 Jan 2014, 14:40

dd_ToolTip

28 May 2017, 17:09

Function dd_ToolTip - revised

Code: Select all

#SingleInstance force
;Copyright (c) D.Donchev

dd_ToolTip("Set Tip")			;set tip 
	msgBOX(,,"T5")

loop 10 { ;main usage of dd_ToolTip
	dd_ToolTip(," " A_Index)	;use  txt 
	sleep 998
}

dd_ToolTip("New Tip") 			;change tip
	msgBOX(,,"T5")
dd_ToolTip()					;clear  tip
	msgBOX(,,"T5")
	
dd_ToolTip(arg:="", txt:="") { ;-----------
	static tip:=""
	if txt == "", tip:= arg ;main idea is:
							;if you call function without txt argument
							;then you call function with tip argument
	ToolTip(tip txt)
	return arg				;it is extra and may be omitted
} ;----------------------------------------
Function dd_ToolTip is usable when in one place you set message and in other place you need to add extra text to message. In example sleep and count.

Enjoy!
AHKv2.0 use the future now.

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 9 guests