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)

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!

    Ich arbeite seit Kurzem mit jQuery und versuche Stück für Stück die enormen Möglichkeiten kennenzulernen.

    Ziel: 2 „Buttons“, die beim Klick, ohne Reload, versteckte Elemente angezeigen. Einmal indem die CSS Eigenschaft display geändert wird, einmal mit der jQuery slide Animation. Das Ganze wird in Funktionen verpackt die mit Übergabeparametern arbeiten. Letztenendes soll dank toggleClass ein wechselndes Hintergrundbild realisiert werden.
    javascript“ line=“1″>
    $(document).ready(function() {

    $(„#changelog-btn“).click(function(){ BtnCss(„#changelog“); });
    $(„#impressum-btn“).click(function(){ BtnSlide(„#impressum“); });

    function BtnCss(BtnId) {
    if( $(BtnId).css(„display“)==“block“ ) {
    $(BtnId).css(„display“, „none“);
    } else {
    $(BtnId).css(„display“, „block“);
    }
    $(BtnId+“-btn“).toggleClass(„active-btn“);
    }; //BtnImg

    function BtnSlide(BtnId) {
    $(BtnId).slideToggle(„slow“);
    $(BtnId+“-btn“).toggleClass(„active-btn“);
    }; //BtnSlide

    }); //$(document).ready

    html4strict“ line=“1″>

    changelog (set css style) |
    impressum (jQuery slide)

    Beispiel

    Details:

    $(document).ready(function() {

    stellt sicher, dass die jQuery Code erst reagiert, wenn das DOM komplett fertig geladen wurde. Damit wird verhinder, dass jQuery auf Elemente zugreift/manipuliert, die noch nicht geladen wurden.
    Der Changelog Button fragt beim Klick mit

    .css("attribut")

    das aktuelle CSS Attribut „display“ der „#changelog“ ID ab und setzt den Wert mit

    .css("attribut", "wert")

    dann entweder auf none oder block.
    Zusätzlich wird mit

    .toggleClass

    dem Tag eine Klasse, basierend auf den aktuellen Status, hinzugefügt oder entfernt, die das Hintergrundbild des Tags (den Pfeil) ändert.
    Mit

    .slideToggle

    aktiviere ich, je nach aktuellem Status, die slide Animation (

    .slideUp, .slideDown

    oder

    .slideToggle

    ) für die „#changelog“ ID.
    Funktionen sollte klar sein. Sind hier eigentlich unnötig, zeigen aber den generellen Aufbau.