Probleme beim Schleifen basteln

06/08/2012 00:27 Vaioria#1
Hallo zusammen,

als blutige AutoIT Anfängerin habe ich einige Infos aus dem "Netz" zusammen getragen und daraus wollte ich mir ein mini bot für mein Lieblingsspiel schreiben, nur leider klappt das nicht so wie ich es mir denke.

Der bot sollte wenn es klappt Tastatur und Maus simulieren in form von:

Beispiel:
alle 1 sec. die Taste 1 drücken
alle 6 sec. die Taste 2 drücken
alle 17 sec. Taste 3 drücken + MausKlick
sowie die Taste B drücken 30 sec. warten dann wieder B, dann 60 sec. warten und wieder B.
Das ganze soll endlos wiederholt werden bis nen HotKey gedrückt wird.

hier mein bisheriger code:

Problem ist das jetzt die Taste 1 nicht alle 1 sec. gedrückt wird sondern alle 114,5 sec. wenn es wieder von vorn beginnt.

Selbst beim ersten druchlauf passt die schleife schon nicht wirklich.
Ein kürzeres Sleep würde zwar bedeuten das die Zeit sich verringert aber dann kommt der Rythmus der anderen Tasten auch durcheinander.


Ich habe ein Beispiel für eine problemlösung als vbs code entdeckt, aber ich wüsste nicht wie ich das auf AutoIT Übertragen sollte.
Hier der vbs code(lediglich als bsp):


Hier wird ein Timer runtergezählt und wenn null erreicht ist dann wird die Taste gedrückt.


Ich bitte um Hilfe,Vorschläge,Tipps.

LG Vaioria
06/08/2012 00:58 butter123#2
guck dir mal [Only registered and activated users can see links. Click Here To Register...] und [Only registered and activated users can see links. Click Here To Register...] an. starte einfach für jede taste einen timer
06/10/2012 22:58 uragan#3
butter hat recht, da musste mit timern arbeiten

Quote:
Local $timer1 = TimerInit()
Local $timer2 = TimerInit()
Local $timer3 = TimerInit()

while 1

if TimerDiff($$timer1) > 1000 Then ...
if TimerDiff($$timer2) > 6000 Then ...
if TimerDiff($$timer3) > 17000 Then ...

Wend

wichtig ist dann, dass du die timer immer zurücksetzen nicht vergisst, sonst haste ein problem, dass die immer wieder ausgeführt werden
06/11/2012 22:55 butter123#4
Quote:
Originally Posted by uragan View Post
wichtig ist dann, dass du die timer immer zurücksetzen nicht vergisst, sonst haste ein problem, dass die immer wieder ausgeführt werden
oder mit modulo arbeiten geht auch. läuft aber aufs gleiche hinaus^^
06/15/2012 20:47 Vaioria#5
So endlich wieder Zeit gefunden was zu basteln.
Aus einem Anfall von geistigem "durchfall" ist folgendes entstanden:

funktioniert natürlich nicht :)
hoffe man versteht wenigstens worauf ich hinaus möchte...

könnte das vielicht so klappen oder ist das ein gar ganz falscher ansatz?

hab mich bei den Variablen für Dim entschieden mein Vorredner nutzte Local und ein Beispiel hab ich ge"google"t da wars global...

Würde für mein vorhaben Dim genügen, da mein script so vollständig wäre wenn das tastendrücken mal so funktioniert wie ich möchte ? :)

LG
06/15/2012 21:25 bollen#6
so wird das nicht klappen vorallem die Zeile
Code:
[COLOR=#660066]If[/COLOR] $Elapsed [COLOR=#006666]1000[/COLOR] [COLOR=#666600]=[/COLOR] [COLOR=#006666]0[/COLOR] [COLOR=#660066]Then[/COLOR]
ist Falsch, um von einem Timer die Zeit zu bekommen Benötigst du die funktion TimerDiff($Timer). Außerdem kannst du nicht $Elapsed 1000=0 schreiben
ich habe dein Code so abgeändert das er funktioniert
06/15/2012 22:47 Vaioria#7
Oh vielen dank, (Thanks vergeben)

erspart mir Arbeit...*freu*

Habs noch bissel modifiziert aber das Prinzip ist sehr gut zu erkennen.

Gibt es noch eine möglichkeit ganze Sekunden zu machen? Weil wenn man das Theoretisch bissel laufen lässt und Autoit immer +1002,4 ms schreibt ist ja rein rechnerisch nach gewisser Zeit eine unregelmäßigkeit drin...oder macht das der timer reset wieder wett?
06/16/2012 09:48 lolkop#8
Quote:
Originally Posted by Vaioria View Post
Gibt es noch eine möglichkeit ganze Sekunden zu machen? Weil wenn man das Theoretisch bissel laufen lässt und Autoit immer +1002,4 ms schreibt ist ja rein rechnerisch nach gewisser Zeit eine unregelmäßigkeit drin...oder macht das der timer reset wieder wett?
durch den timerreset entsteht eine unregelmäßigkeit....

deine 2ms abweichung, würden nach erst nach ca 500durchläufen eine abweichung von einer sekunde ergeben. das sollte soweit hinnehmbar sein, kann aber umgangen werden, wenn du den timer nicht resettest, sondern mit dem startpunkt weiter arbeitest. hierfür bieten sich ein externer counter, oder die modulo funktion an.

beispiel mit externem counter:
Code:
Dim $timer=TimerInit(), $counter=1, $zeit=1000, $diff[2]

While True
	$diff[0] = TimerDiff($timer)
	$diff[1] = $counter*$zeit
	If $diff[0] >= $diff[1] Then
		$counter+=1
		ConsoleWrite($counter-1&" Sekunden sind vergangen seit Timerstart (aktuelle Abweichung = "&$diff[0]-$diff[1]&")"&@CRLF)
	EndIf
WEnd
06/16/2012 14:01 Vaioria#9
Habs mal eingebaut(hoffe richtig)

Hab den ToolTip nochmal rein genommen zur genaueren Kontrolle aber es entstehen immer noch abweichungen. Hab ich was falsch eingebaut?

Da ich mich mit Modulo noch nicht wirklich befasst habe und es hier öffter als "oder" angepriesen wird, ist diese varriante genauer?

LG
06/16/2012 18:20 lolkop#10
sobald du sleeps oder wait funktionen in dein script aufnimmst, zerstörst du automatisch sämtliche getimten funktionen...

WinWaitActive, deine Pause funktion und auch deine hauptschleife, haben in der form nichts in einem script zu suchen. dinge wie pausen bzw waits sollten immer über zustände geregelt werden, da ansonsten der counter wärend dieser zeit nicht hochgezählt werden kann, und somit extreme ungenauigkeiten entstehen können.

von der modulo variante würde ich dir in diesem falle abraten, da sie sehr schwer implemntierbar, und somit für anfänger eher ungeeignet wäre.
06/16/2012 20:15 Vaioria#11
Könntest du mir eine Hilfestellung geben wie ich meine Hauptschleife besser gestalten könnte ohne extreme ungenauigkeiten?

WinWaitAktive + Send kann man ja durch ControlSend ersetzen sowie die Pause Funktion rausnehmen für das gleiche Ergebnis.

Wie sieht eigentlich ein ContolSend für die MouseClick Aktion aus wenn die getimed sein soll?

Wird die Schleife durch Modulo nun besser oder ergibt das keinen unterschied?
Da ich den gedanken hege mich mal damit zu befassen.

LG
06/16/2012 21:50 Lawliet#12
ControlClick gibts glaub ich auch;)
06/16/2012 22:04 lolkop#13
Quote:
Originally Posted by Vaioria View Post
Wird die Schleife durch Modulo nun besser oder ergibt das keinen unterschied?
Da ich den gedanken hege mich mal damit zu befassen.
noch besser als ohne steigende verzögerung geht es nicht...

mit zuständen meinte ich ausserdem nicht das zurückgreifen auf andere funktionen für die aktionen.

anstatt WinWaitActive zu nutzen, kannst du ja auch einfach abfragen, ob das fenster gerade aktive ist, bevor du mit send weiter machst. auf diese weise wird im e-fall der send befehl einfach übersprungen, der counter aber trotzdem weiter hochgezählt.

in diesem beispiel wäre active dein status. diesen kannst du per WinActive prüfen. hierbei handelt es sich um einen status, der dir vom system vorgegeben wird. das fenster kann active sein, oder nicht. im falle von active = true, führe deine aktion aus, also:
Code:
If WinActive(...) Then Send(...)
du kannst dir auch selbst zustände erstellen, zb einen pause zustand. zustände können wir einfach in variablen definieren. zb
Code:
Dim $pause = True
nun setzen wir in unser script einfach eine abfrage, welche checkt, welchen zustand $pause gerade hat. ist $pause = True, so werden einige aktionen einfach übersprungen (in diesem falle die sends), während andere sachen trotzdem weiterhin ausgeführt werden (zb das hochzählen des counters).

deine pausefunktion braucht nun nurnoch den zustand von $pause in den jeweils andere ändern:
Code:
$pause = not $pause
schon kannst du das senden wieder per hotkey pausieren, ohne hierbei dein gesamtes script zu blockieren.

Edit:
hier mal ein beispiel für deine ersten 4 sachen, welche du gerne erledigen wolltest, mit einem kleinen gui, welches zeigt, wie im hintergrund die counter gezählt werden, selbst während der pausemodus aktiv ist:
Code:
HotKeySet("{F1}", "Pause")
AutoItSetOption("WinTitleMatchMode", 4)

Dim $fenster="Unbenannt - Editor", $pause=True, $timers[4]=[TimerInit(),TimerInit(),TimerInit(),TimerInit()]
Dim $counters[4]=[1,1,1,1], $actions[4]=[0,0,0,1], $sleeps[4]=[1000,6000,17000,17000], $text[2]=["Weiter", "Pause"]

Dim $label[UBound($counters)], $taskPos = WinGetPos("classname=Shell_TrayWnd")
GUICreate('Info', 100, UBound($counters)*40+50, @DesktopWidth-100, @DesktopHeight-UBound($counters)*40-50-$taskPos[3], 0x90000000, 0x88)
For $i=0 To 3
	GUICtrlCreateGroup('Counter '&$i+1, 10, 10+$i*40, 80, 40)
	$label[$i] = GUICtrlCreateLabel('', 15, 25+$i*40, 60, 20)
Next
$btn = GUICtrlCreateButton('Start', 10, 173, 80, 30)

While True
	If GUIGetMsg()=$btn Then Pause()
	For $i=0 To 3
		TimedAction($timers[$i], $sleeps[$i], $i+1, $i, $actions[$i])
	Next
	SetGui()
WEnd

Func Pause()
	GUICtrlSetData($btn, $text[$pause])
	$pause = Not $pause
EndFunc

Func TimedAction($timer, $waitTime, $key, $counter, $aktion)
	If TimerDiff($timer) >= $waitTime * $counters[$counter] then
		If WinActive($fenster) And Not $pause Then
			If $aktion = 0 Then
				Send($key)
			ElseIf $aktion = 1 Then
				MouseClick( "left", 725, 450, 1)
			EndIf
		EndIf
		$counters[$counter]+=1
	EndIf
EndFunc

Func SetGui()
	For $i=0 To UBound($counters)-1
		If GUICtrlRead($label[$i]) <> $counters[$i] Then GUICtrlSetData($label[$i], $counters[$i])
	Next
EndFunc