Letztens, beim Artikel über HotKeySet in AutoIt, fragte HansDampf, wie man denn ohne vorgegebene Pixel/Koordinaten in Scripten arbeiten könne. Ich erwähnte in dem Artikel Farberkennung, war mit der Materie aber noch nicht so vertraut.

Mittlerweile habe ich mich mit der Funktion von Farberkennung in AutoIt beschäftigt und bin begeistert.
PixelSearch() sucht euch den ersten Pixel in einem rechteckigen Zielgebiet, auf den die Farbbeschreibung zustimmt.

Code:

Pixelsearch(x-linksoben, y-linksoben, x-rechtsunten, y-rechtsunten, Hexfarbe[, Abweichung, Schritte])

Was für die Funktion also nötig ist sind 2 Koordinatenpaare und die gesuchte Farbe. Die Koordinate der oberen linken Ecke des Suchfelds (x und y) und von der unteren rechten Ecke (x und y). Um von den fixen Koordinaten wegzukommen sollte man den User 1x auffordern, an eine bestimmte Stelle zu klicken und danach alles relativ zum 1. Klick zusammen mit PixelSearch gestalten.
Je größer der Wert der Abweichung, desto ungenauer kann man die Farbe angeben, desto mehr Pixel werden gefunden.
Das letzte Argument gibt an, jeder wievielte Pixel untersucht werden soll. 10 würde bewirken, dass nur jeder 10 Pixel getestet wird. Das pusht natürlich die Geschwindigkeit.

Ein Beispiel:

$waittime = 3000
MsgBox(0,"Ecke oben links","Führe die Maus über die Ecke des Flash-Games oben links, du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$ol = MouseGetPos()
; Nur zur Kontrolle
MsgBox(0,"pos",""&$ol[0]&" | " &$ol[1]&" | " &$ol[0]+472& " | " &$ol[1]+315&"")
$center = PixelSearch($ol[0],$ol[1],$ol[0]+472,$ol[1]+315, 0xFFFFFF)
MouseMove($center[0],$center[1],1)

while True
	If Hex(PixelGetColor($center[0]+170,$center[1]+110),6)="FFFFFF" Then
		MouseClick("left",$center[0]+170,$center[1]+110,1,1)
		Sleep(2000)
	EndIf
[...]

Ich frage den Benutzer bewusst nach 1 Koordinate; die der oberen linken Ecke des Flash Games. Diese bekomme ich einfach in dem der Spieler die Maus darüber bewegt und ich die Mauskoordinaten auslese. Da ich weiß wie groß das Flash Game Fenster ist kann ich PixelSearch auch das 2. Koordinatenpaar der Ecke unten rechts übergeben, ohne es vom Nutzer zu fordern.
Ab dem Punkt gehe ich nur noch über relative Pixelangaben vor, keine festen Werte mehr, die angepasst werden müssen.

Der Code geht noch weiter und funktioniert wunderbar in allen Browsern, in allen Monitorauflösungen und Fensterpositionen. Die Lösung kostet auf jeden Fall viel mehr Zeit als wenn der User am Anfang ein paar Koordinaten angibt aber einmal programmiert ist es eben die bessere Lösung.

Stay Tuned, morgen oder Übermorgen zeige ich den ersten Bot basierend auf PixelSearch und PixelGetColor.

Das Geheimnis der Trainer/Cheatprogrammierung: das Manipulieren von Speicheradressen! Just kiddin‘, but, weil ihr es seid, die Basics zum Lesen/Schreiben von Speicheradressen in AutoIt:

#include <nomadmemory .au3>
#RequireAdmin

$Adresse = 0x091ED140;

$Open = _memoryopen(ProcessExists("7100"))
$Read = _MemoryRead($Adresse , $Open, 'dword')
$write = _MemoryWrite($Adresse, $Open, "9999", 'dword')

Ihr braucht zuerst die NomadMemory.au3 (oder auch Memory.au3), ein AutoIt Add-in zur Speicherverwaltung.
Zusätzlich ist es ratsam die Adminrechte vorauszusetzen, da diese höchstwahrscheinlich nötig sein werden.

Nun sucht euch die Adresse, die ihr auslesen oder beschreiben wollt.. logisch, huh. Entweder in eine Variable packen, das spart Zeit, Nerven und Hornhaut oder später halt immer die Adresse eingeben.

Als nächstes den Prozessnamen oder sicherer wäre der Process Identifier (PID). In Zeile 6 wird der Prozess, wenn er gestartet ist, praktisch ge-hijackt.
Zeile 7 und 8 brauchen diesen Schritt, um in die Adresse schreiben oder daraus lesen zu können. Dass Zeile 8 den Wert 9999 in die Speicheradresse schreibt sollte klar sein.

Dieser Weg funktioniert bei statischen Speicheradressen. Diese statischen Adressen sind eher unüblich, normalerweise werden Pointer für Adressen genutzt, die ge“hackt“ werden wollen. Das heißt bei jedem Neustart ändert sich die Adresse, verweißt intern aber auf das selbe Ziel. Solche Pointer sind schwerer zu finden und zu manipulieren, ich kann es selber noch nicht mal. Aber Stay Tuned, es wird kommen.


So, ich habe das Cursed Treasure Script mal erweitert und gleich ein Release draus gebastelt.

Was kann es?
Cursed Treasure Hotkeys hilft im Spiel Cursed Treasure, in dem es Hotkeys für die 3 Skills, die 3 Towers und den Attack Button erstellen kann.
Die 3 Skills und der Attack Button sind Standard, die 3 Gebäude sind optional.

Wie funktioniert es?
Startet das Spiel, dann das Programm und folgt einfach den Anweisungen bis die Hotkeys fertig eingerichtet sind. CTH sammelt am Anfang die Koordinaten mit Hilfe des Spielers und erstellt dann die Tastenkombinationen.

Die Tastenkombinationen sind:
Alt + yAbholzen
Alt + xFrenzy (Hast)
Alt + cMeteor
Alt + SpaceAttack (Wave)
Wenn vom Spieler gewollt auch:
Alt + 1Den
Alt + 2Crypta
Alt + 3Temple

Danke an awesomeIT für die gute MsgBox Zusammenfassung.

Code

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=..\..\..\..\Desktop\1274800419_treasure.ico
#AutoIt3Wrapper_outfile=..\..\..\..\Desktop\Cursed-Treasure-Hotkeys.exe
#AutoIt3Wrapper_Compression=3
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
; #############################
; #  Cursed Treasure Hotkeys  #
; #############################
;
; Author: Hannes Schurig
; URL: www.hannes-schurig.de
; Created: 21.05.2010
; Changed: 25.05.2010
;
; Version: 2.2
; Changelog:
; 2.2 - Wartezeit jetzt per Variable anpassbar und dynamisch in den MsgBoxen
; 2.1 - Fehler bereinigt, 3 Sekunden, optimiert, kommentiert
; 2.0 - Tastenkombinationen für Skills, Gebäude und Wave
; 1.0 - Tastenkombinationen für die 3 Skills, feste Koordinaten
;
; ToDo:
; 3.0 - Code kürzen, Hotkeyfunktionen zusammenfassen, Zeiteingabe vom User?
;       MsgBoxen Breite variiert je nach Auflösung?

; Ich zwinge niemanden, wer nicht will der hat schon ;)
$run = MsgBox(36, "Cursed Treasure Hotkeys", "Run Hotkeys for Cursed Treasure?")
If $run = 7 Then
    Exit
EndIf

$anz = 4
$waittime = 3000
MsgBox(0,"Starte ein Spiel","Starte jetzt in CT Spiel (Level 1 oder 2 sollten reichen) und stell Starttower hin. Klicke dann auf [OK]")

MsgBox(0,"Attack Button","Klicke auf [OK] und bewege die Maus über Attack (neue Wave), du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$wavebtn = MouseGetPos()
MsgBox(0,"Abholzen Button","Klicke auf [OK] und bewege die Maus über Abholzen, du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$woodbtn = MouseGetPos()
MsgBox(0,"Hast Button","Klicke auf [OK] und bewege die Maus über Hast (Frenzy), du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$frenzybtn = MouseGetPos()
MsgBox(0,"Meteor Button","Klicke auf [OK] und bewege die Maus über Meteor, du hast " & ($waittime/1000) & " Sekunden.")
Sleep($waittime)
$meteorbtn = MouseGetPos()

; Optional: Sammel Daten für Tower Shortcuts
$towerhotkeys = MsgBox(36, "Tower Shortcuts?", "Sollen auch für die 3 Tower Shotcuts erstellt werden?")
If $towerhotkeys = 6 Then
	MsgBox(0,"Den(Grün) Button","Klicke auf [OK] und bewege die Maus über Den (Grün), du hast " & ($waittime/1000) & " Sekunden.")
	Sleep($waittime)
	$denbtn = MouseGetPos()
	MsgBox(0,"Crypt (Blau) Button","Klicke auf [OK] und bewege die Maus über Crypt (Blau), du hast " & ($waittime/1000) & " Sekunden.")
	Sleep($waittime)
	$cryptbtn = MouseGetPos()
	MsgBox(0,"Temple (Rot) Button","Klicke auf [OK] und bewege die Maus über Temple (Rot), du hast " & ($waittime/1000) & " Sekunden.")
	Sleep($waittime)
	$templebtn = MouseGetPos()

	; Habe die Koords, setze Hotkeys auf Alt+1/2/3
	HotKeySet("!1", "den")
	HotKeySet("!2", "crypt")
	HotKeySet("!3", "temple")

	$anz = 7
EndIf

; Setze die 4 Standardhotkeys
HotKeySet("!{SPACE}", "wave")
HotKeySet("!y", "wood")
HotKeySet("!x", "frenzy")
HotKeySet("!c", "meteor")

MsgBox(0,"Fertig!", "Alle Daten gesammelt, alle " & $anz & " Hotkeys gesetzt")

; Hotkeyfunktionen
Func wave()
	; Speichere aktuelle Mauskoordinaten
	$coords = MouseGetPos()
	; Klicke auf die anfangs gespeicherten Button-Koords
	MouseClick("left",$wavebtn[0],$wavebtn[1],1,1)
	; Klicke auf die gespeicherten Koords
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func wood()
	$coords = MouseGetPos()
	MouseClick("left",$woodbtn[0],$woodbtn[1],1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func frenzy()
	$coords = MouseGetPos()
	MouseClick("left",$frenzybtn[0],$frenzybtn[1],1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func meteor()
	$coords = MouseGetPos()
	MouseClick("left",$meteorbtn[0],$meteorbtn[1],1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func den()
	$coords = MouseGetPos()
	MouseClick("left",$denbtn[0],$denbtn[1],1,1)
	MouseMove($coords[0],$coords[1],1)
EndFunc

Func crypt()
	$coords = MouseGetPos()
	MouseClick("left",$cryptbtn[0],$cryptbtn[1],1,1)
	MouseMove($coords[0],$coords[1],1)
EndFunc

Func temple()
	$coords = MouseGetPos()
	MouseClick("left",$templebtn[0],$templebtn[1],1,1)
	MouseMove($coords[0],$coords[1],1)
EndFunc

; Halte das Programm am Leben
while 1
    sleep(100000000)
WEnd
Download

Cursed Treasure Hotkeys [.exe]
cursed-treasure-hotkeys [.au3] (Source Code)

Der Start in diese Woche wird mal etwas anders aussehen. Ich habe ein E-Mail Interview für euch. Im Rampenlicht steht @viermalbe, ein aktiver Twitter-User und Wortjongleur. Meine Lieblingsauswahl seiner Tweets ist hier. Auf Favstar.fm gibt es noch mehr beliebte Tweets zu sehen. Man merkt es schnell, viermalbe kann gut mit Wörtern. Und weil das nicht unbedingt meine Stärke ist geht es auch gleich los:

Es ist schwer, im Internet Persönliches über Dich zu erfahren. Möchtest du dich kurz vorstellen, ein wenig plaudern?

Hallo Hannes, zuerst einmal vielen Dank für das Interview. Ich habe mich wirklich sehr gefreut, als ich gehört habe, dass sich scheinbar doch jemand für meine Tweets interessiert ;-). Weshalb man so wenig über mich erfährt, hat einen ganz einfachen Grund. Nachdem ich im letzten Jahr mein Studium abgeschlossen habe, bin ich momentan noch auf Jobsuche. Und man weiß ja nie, wie das alles beim zukünftigen Arbeitgeber so ankommt.

Ich bin 23 Jahre alt und komme ursprünglich aus einem kleinen Kaff im Norden von Sachsen-Anhalt. Nach dem Abi ging’s nach Mannheim und jetzt wohne ich seit Kurzem zusammen mit meiner Freundin in Duisburg.

Woher nimmst Du deine Inspiration?

Mein Kopf ist meist den ganzen Tag voller Wortspiele, oder solcher, die es noch werden wollen. Ich achte sehr auf Schlagwörter, Themen und Begriffe aus meiner Umwelt. Ob in einem Gespräch, auf der Straße oder im Internet, alles wird irgendwie abgespeichert und so lange im Kopf zerplückt und auseinander genommen, dass sich ein anderer Sinn ergibt. Jetzt gerade musste ich beispielsweise unterbewusst an „Jongleur“ denken und über die Silbe „Jong“ in einem anderen Bezug, war plötzlich dieser Tweet da: „Zirkusdiktator: Kim Jong-leur“. Fertig. Wirklich konstruiert sind bei mir die wenigsten Tweets. Ich denke, je spontaner man eine Idee in 140 Zeichen presst (und meist brauche ich diese nicht mal), desto natürlicher und witziger wirkt es auf den Leser.

Meine Freundin hat sich mittlerweile daran gewöhnt, dass ich plötzlich beim Frühstück aufspringe, das Handy zücke und einen Tweet schreibe. Manchmal liege ich auch Abends noch wach, weil mein Kopf voller Eindrücke ist, die noch formuliert werden möchten. Ich habe dann schon öfter Ideen noch kurz notiert und mit dem Gedanken an hoffentlich gute Reaktionen darauf am nächsten Tag besser in den Schlaf gefunden.

Wie ist das Feedback aus Deinen privaten und virtuellen Kreisen?

In einem Tweet schrieb ich „Früher wurde ich wegen schlechter Wortspiele oft gescholten. Dank Twitter habe ich gelernt: Irgendwer findet es immer lustig.“ Ich denke, das beschreibt es wirklich ganz gut. Ich war auch schon vor der Erfindung von Twitter so. Nur habe ich dort mein Umfeld damit genervt. Mittlerweile liest sogar meine Mutter auf Twitter mit, was zum Teil witzig, aber auch verstörend sein kann. In meiner Themen- oder Wortwahl beschränkt mich das aber nicht wirklich. Sie findet es wohl sehr kreativ.

Meine Freundin möchte abends immer lesen, was ich am Tag geschrieben habe und welche anderen Tweets von mir gefavt wurden (also einen Stern gekriegt haben).

Im virtuellen Umfeld war das größte Lob bisher, möglichst viele Sterne für einen Tweet zu bekommen oder aber häufig retweeted zu werden. Du hast mit dieser Interview-Anfrage die Definition von „Lob“ natürlich auf eine ganz neue Ebene gehoben. Ich denke, so viel Anerkennung habe ich bisher für meine Mühen noch nicht bekommen.

Eine Bekannte hat mich neulich ernsthaft gefragt, von welcher Internetseite oder aus welchem Buch ich eigentlich meine ganzen Tweets abschreibe, ein Mensch könne sich das doch unmöglich ausdenken. Das war natürlich ein tolles Kompliment.

Du konzentrierst Dich momentan sehr auf dieses Talent, wie planst Du Deine Zukunft, wird Deine Gabe dort eine Rolle spielen?

In meinem beruflichen Alltag wohl leider nicht. Ich wollte immer Germanistik studieren und dann auch beruflich „irgendwas mit Wörtern“ machen. Hat so nicht geklappt, bin jetzt Wirtschaftsinformatiker. Aber so lange mir das Erfinden und Entdecken neuer Wortspiele noch Spaß macht, und das wird es noch eine ganze Weile, sehe ich keinen Grund, damit aufzuhören.

Random(): Welche Superheldenfähigkeit hättest du gerne?

Wie ich schon in einem meiner Tweets sagte: „Müsste ich ein Superheld sein, ich wäre wohl Nichternstzuneh-Man.“


Vielen Dank für deine Zeit. Ich kann viermalbe nur empfehlen, seine Sprüche lichten jeden noch so dichten Arbeitsnebel im trüben Alltag.

So, heute mal etwas AutoIt.
Mein Hintergrund: Cursed Treasure ist, mal abgesehen von den letzten 2 Level nicht sonderlich schwer. In diesen 2 letzten Spielen allerdings wird man praktisch gezwungen sehr schnell zu klicken. Es gibt in dem Spiel 3 Skills aber diese haben keine Tastenkürzel. Man muss tatsächlich immer drauf klicken.

Um das Problem schnell zu beheben habe ich mir eine neue Funktion in AutoIt gesucht:

HotKeySet("[kürzel]", "[funktion]")

Mit dem Code kann man eine Überwachung starten, die auf eine bestimmte Tastenkombination eine bestimmte Funktion startet.

Ein Beispiel:

HotKeySet("!c", "meteor") ; Überwache ALT+C

Func meteor()
	$coords = MouseGetPos() ; Speichere aktuelle Position
	MouseClick("left",1030,600,1,1) ; Koordinaten des Skills
	MouseClick("left",$coords[0],$coords[1],1,1) ; Skill auf der gespeicherten Position nutzen
EndFunc

; Script am Leben halten
while 1
    sleep(100000000)
WEnd

Mein WordPress Syntax Highlighting Plugin kennt sogar AutoIt, nicht schlecht.

Jedenfalls reagiert Zeile 1 auf die Tastenkombination ALT+C. Alt wird dabei zu einem „!“, mehr dazu auf der Send() Infoseite von AutoIt.
Beim Drücken dieser Tasten wird die meteor Funktion aufgerufen. Diese speichert die aktuellen Mauskoordinaten, klickt eine feste Stelle des Bildschirms an und klickt danach wieder auf der Stelle, auf der die Maus stand, als die Tastenkombination gedrückt wurde.

Ich stelle also die Koordinaten des Meteor Skills ein, führe die Maus über ein Zielobjekt (jetzt mal rein theoretisch z.B. einen Wave 40 unsichtbaren Ninja Champion aus Level 15) und drücke die Tastenkombination. Die Maus speichert den Ort, klickt auf den Skill und führt diesen an der alten Stelle aus. Das ganze dauert nur wenige Millisekunden 🙂

Zeile 10-12 sorgen dafür, dass das Script endlos lange läuft und man beliebig oft die Tastenkombinationen nutzen kann.

So sähe also ein kleines Cursed Treasure Script aus:

HotKeySet("!{SPACE}", "wave")
HotKeySet("!y", "wood")
HotKeySet("!x", "haste")
HotKeySet("!c", "meteor")

Func wave()
	$coords = MouseGetPos()
	MouseClick("left",970,450,1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func wood()
	$coords = MouseGetPos()
	MouseClick("left",920,600,1,1) ; 
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func haste()
	$coords = MouseGetPos()
	MouseClick("left",1135,773,1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

Func meteor()
	$coords = MouseGetPos()
	MouseClick("left",1030,600,1,1)
	MouseClick("left",$coords[0],$coords[1],1,1)
EndFunc

while 1
    sleep(100000000)
WEnd

Neue Wave mit Alt+Leertaste, Alt+Y/X/C nutzen die 3 Skills. Koordinaten anpassen ist aber Voraussetzung.
Das ganze ließe sich auf weniger als 10 Zeilen zusammenstampfen und statt Koordinaten vielleicht mit Farberkennung verallgemeinern aber war ja nur so ein kleiner Spaß.

Okay ich gebe zu, hier war ich faul.
Eigentlich sollte ich selber etwas schreiben, um Tabellen beim Klick auf den Header sortieren zu lassen. Aber wenn es SO einfach ist wie mit diesem externen Plugin, da spar ich mir gern die Mühe.

Beispiel

javascript“ line=“1″>

$(document).ready(function() {
$(„#sortable“).tableSorter();
});

html4strict“ line=“1″>


Ich nutze hier das externe Tablesorter Plugin von Christian Bach. Mal abgesehen vom simplen Sortieren kann man die Tabelle mit wenigen Statements auch dynamisch gestalten, das Verhalten steuern und weitere Feinheiten. Ein paar Beispiele auf dieser Seite.

Heute nutzen wir das bereits bekannte .slideToggle() um ein dynamisches Menü (vertikal, horizontal kommt später) zu erstellen.

Beispiel

javascript“ line=“1″>
$(document).ready(function() {
$(„.erweiterbar“).click(function() {
$(this).toggleClass(„expanded“);
$(this).next().slideToggle(„300“);
});
}); //$(document).ready

html4strict“ line=“1″>

  • Als kleiner Augenschmaus, die Pünktchen 😉
    Ansonsten nicht weiter kompliziert und nicht weiter spannend.
    Kann allerdings noch verbessert werden, hab jetzt jedoch keine Zeit mehr.
    Soweit, stay tuned!