Nur eine kurze Hilfe für den Fehlercode: 0xc004f014, der beispielsweise beim Upgrade von Windows 10 Home auf Professional auftreten kann. Vor allem dann, wenn ein neues Gerät mit installiertem Windows 10 Home ausgeliefert wird und dann ein Upgrade auf Pro erfolgen soll.

Lösung:

  1. Windows-Symbol -> Einstellungen -> Update und Sicherheit -> Aktivierung -> Product Key ändern
  2. den offiziellen Universal-Key für Windows 10 Pro eingeben:
    VK7JG-NPHTM-C97JM-9MPGT-3V66T
  3. Tasse Kaffe machen und warten bis die Installation durchgeführt und der PC wieder hochgefahren ist
  4. Startmenü -> Einstellungen -> Update und Sicherheit -> Aktivierung -> Product Key ändern und nun den erworbenen Pro-Key eingeben

via

Klingt seltsam, funktioniert aber. Warum auch immer Microsoft solche Standardsituationen nicht ordentlich behandeln kann…
Dieses Bild zeigt die erfolgreiche Aktivierung des Windows 10 Professional Produkt Keys

Weitere Windows Update Fehler und ihre Lösung findet ihr hier.

Einfache Windows-Admin-Frage: Welcher Mitarbeiter ist in diesem Moment und seit wann an welchem PC eingeloggt?

Einfache Antwort, kurz und knackig: Batch!
Mit Hilfe von PsLoggedOn, welches sich im selben Verzeichnis befinden muss wie das Skript:

@echo on & Color 9f & setlocal
for /f "Tokens=1" %%c in ('net view /domain:"%USERDOMAIN%"^|Findstr /L /C:"\\"') do (
 for /f "Tokens=*" %%u in ('PsLoggedOn -L %%c^|find /i "%USERDOMAIN%\"') do (
  echo %%c %%u
 )
)
endlocal
pause
goto :EOF

via (leicht angepasst)

Das Bild zeigt das gekürzte PsLoggedOn-Script, welches zu allen eingeschalteten Domänencomputern die eingeloggten Nutzer anzeigt.

Der Befehl

sc

aus der Windows Konsole, mit dem sich die Windows Dienste steuern lassen, hat einen entscheidenden Nachteil: Es sind keine Wildcards möglich, der Dienstname muss exakt so angegeben sein, wie er im System registriert ist.
Somit sind

sc stop

und

sc delete

schnell am Ende ihrer Möglichkeiten.

Angenommen ich habe einen oder mehrere Dienste mit einem bestimmten Namenspattern, die angesprochen und verarbeitet werden müssen. Das Namenspattern könnte beispielsweise sein: „[beliebige Zeichenkette]Manager“. Weitere Platzhalter wie „[beliebig]win[beliebig]svc[beliebig]“ sind ebenfalls möglich.

Im Gegensatz zu sc bietet

wmic service

entsprechende Möglichkeiten, mit Wildcards und komplexeren Anfragen umzugehen:

Abfragen:

REM Laufende Dienste mit "Manager" im Namen in der Konsole abfragen und einzelne Informationen filtern
wmic service where (name like "%%Manager%%" and state="running") get caption, name, state, status
REM Export aller Prozesse mit "Manager" im Namen als HTML exportieren
wmic service where (name like "%%Manager%%") get /format:hform >> C:/services.html
REM Namenspattern [beliebig]win[beliebig]svc[beliebig] suchen
wmic service where (name like "%%win%%svc%%") get caption, name, state

Das Bild zeigt den Windows Konsolenbefehl wmic service mit Paaternsuche

Starten/Stoppen/Löschen:

wmic service where (name like "%%win%%svc%%") call startservice
wmic service where (name like "%%Manager%%" and state="running") call stopservice
wmic service where (name like "%%Manager%%") call delete

via, via, via

Effektiv den PC mit dem Smartphone koppeln, das Smartphone vom PC aus verwalten und steuern – das und mehr hat sich AirDroid vorgenommen und kann es auch erfüllen. Im Folgenden zeige ich ein paar Key Features:

Einrichtung

Dieses Bild zeigt AirDroid Installationsmöglichkeiten
Die AirDroid App muss auf jeden Fall auf dem Smartphone installiert werden. Für Non-Root Geräte muss außerdem USB-Debugging aktiviert sein. Anschließend gibt es verschiedene Clients für alle Betriebssysteme und eine Webanwendung – Letztere finde ich ehrlich gesagt am besten.
Desweiteren werden für die Fernsteuerung des Smartphones, für Remote-Bildschirmfotos, Remote-Kameranutzung, Smartphone-Ortung und weitere Funktionen immer wieder vereinzelt Berechtigungen erfordert. Das klingt etwas umständlich, der Nutzer wird von AirDroid aber gut geleitet und die Berechtigungen werden immer erst gefordert, wenn die gewünschte Funktion zum ersten Mal benutzt wird.

Die wichtigsten Funktionen

Die folgenden Funktionen beziehen sich fast ausschließlich auf die AirDroid Webapp.

Dateiaustausch

AirDroid kommt mit einem recht guten und intuitiven Dateimanager, der sowohl das Hoch- als auch Herunterladen von Dateien unterstützt. Also können Dateien über den PC schnell vom oder in das Handy geladen werden. Außerdem können Ordner oder mehrere markierte Dateien als ZIP heruntergeladen werden – sehr praktisch!
Das Bild zeigt den Dateimanager von AirDroid und die Möglichkeit, mehrere Dateien als ZIP herunterzuladen

Smartphone-Display spiegeln und fernsteuern

Äußerst praktisch ist auch die Funktion der Fernsteuerung. Nach der Installation der AirMirror Chrome-Erweiterung kann das Android Smartphone komplett ferngesteuert werden. Der Bildschirm wird gespiegel, Maus und Tastatur an das Handy übertragen. Wie gewohnt gibt es eine kleine Verzögerung und die Aktualisierungsrate des Bildes ist mit wenigen Frames pro Sekunde am Limit der Nutzbarkeit – für einfache Aktionen und Klicks ist das jedoch vollkommen ausreichend. Spiele fernsteuern wird eher keinen Spaß machen.
Über einen einfachen Klick lassen sich so auch Screenshots erstellen, die entweder zum PC heruntergeladen oder auf dem Telefon gespeichert werden.
Während der Fernsteuerung wird das Display des Smartphones aktiviert und zeigt 1:1 den gespiegelten Inhalt. Es kann also nicht „versteckt“ ferngesteuert werden.
Das Bild zeigt die AirMirror Funktion in AirDroid, mit der sich das Smartphone vom PC aus fernsteuern lässt

Telefon orten, sperren, löschen

Hier möchte AirDroid die gefragten Sicherheitsfeatures einer Anti-Diebstahl-App bereitstellen: Telefon orten, auf der Karte anzeigen, Fotos machen wenn die Entsperrung versucht wurde, Telefon mit einem Code sperren und – für den Notfall – das Löschen der Daten. Mit einem kostenlosen Account ist nur die Ortung möglich, die restlichen Funktionen benötigen den Premium-Kauf. Ich empfehle für solche Features jedoch professionellere Produkte die sich darauf spezialisiert haben – ich selber nutze seit Jahren zufrieden Cerberus.
Das Bild zeigt die Telefon-Orten-Funktion von AirDroid

Android Benachrichtigungen am PC

Sowohl die Webapp als auch die PC-Anwendung können die Android-Benachrichtigungen zum PC weiterleiten und anzeigen. Damit muss man nicht ständig das Smartphone in die Hand nehmen und nachschauen.
Das Bild zeigt eine Whatsapp Benachrichtigung am PC

Apps verwalten

Auch die installierten und systemeigenen Apps lassen sich anzeigen, löschen oder die entsprechende APK herunterladen. Das war’s jedoch auch schon.
Das Bild zeigt, wie über die Apps-Funktionen APKs der installierten Apps heruntergeladen werden können

Kamera fernsteuern

Auch die Kamera lässt sich seperat in einer eigenen Funktion fernsteuern – mitsamt LED-Blitz-Steuerung. Wozu auch immer das gut sein kann 😀
Das Bild zeigt die Kamera-Fernsteuern-Funktion von AirDroid

Fazit

AirDroid macht bereits vieles richtig, kann aber in einigen Punkten noch besser werden. Der Dateiaustausch ist unkompliziert, die Fernsteuerung funktioniert gut. Der schnelle Zugriff über die Weboberfläche, ohne Installation und physischer Kabel-Verbindung mit dem Smartphone, ist überaus praktisch – sofort werden auch Benachrichtungen am PC angezeigt. Weitere Funktionen sind praktisch und ergänzen das Angebot. Seitdem die WonderShare MobileGo Suite ihre Funktionalitäten der Free-Version eingeschränkt hat, ist AirDroid eine gute Alternative. Vor allem der Dateiaustausch, der nun bei MobileGo kostenlos gar nicht mehr möglich ist, kann über AirDroid nun problemfrei erledigt werden.

Auch dieser Artikel reiht sich in die Liste der Software-Batch-AD-Deployment-Guides ein.
Im Falle von HipChat wird der Artikel recht kurz, denn hier passiert nichts ungewöhnliches.

Vorbereitung

Das Bild zeigt das HipChat Deployment Verzeichnis mit seinen üblichen DateienDer aktuellste HipChat-Installer (für Windows) ist als .exe immer unter dieser URL verfügbar.
Anschließend wird wieder ein übliches Deployment-Verzeichnis auf einem für die PCs verfügbaren Netzlaufwerk erstellt: Installer, Installer-Batch, allowedPCs.txt und deniedPCs.txt (mehr Informationen zum Clientfilter hier). Im Standardfall (so auch in diesem Deployment-Script) wird die deniedPCs.txt benutzt, um einzelne Clients von der Verteilung auszuschließen. Die Textdatei muss dann Computernamen enthalten, einen pro Zeile.
Der HipChat-Installer muss folgendermaßen umbenannt werden: „HipChat_[Version].exe“ und der Versionsstring muss in das Deployment-Script in Zeile 11.

Deployment-Script

19.09.2016: Version 4.27.1.1658 getestet und verteilt.

Hinweis: Wer nicht nur ein Update sondern eine komplette Reinstallation von Hipchat im Netzwerk ausrollen will, kann mein angepasstes Script – hier als Download – nutzen. Die benötigte VersionCompare.exe erhaltet ihr hier.

Hier das Script für ein normales Update:

@echo off && color 9f && setlocal
set wd=\\lea\Deployment\Software\Hipchat
set log=%wd%\hipchat.log
set tools=\\lea\Deployment\Sonstiges\tools
set hipEL=999
set instversion=0.0
set versionEL=9
set exepath=none
set retry=0
REM:: ######## EDIT THIS ####
set newversion=4.1658
REM:: #######################


REM:: Clientfilter: nur die Computer aus der allowedPCs.txt dürfen installieren
::for /f %%f in (%wd%\allowedPCs.txt) do if "%computername%"=="%%f" goto check
::goto end

REM:: Clientfilter: die Computer aus der deniedPCs.txt dürfen nicht installieren
for /f %%f in (%wd%\deniedPCs.txt) do if "%computername%"=="%%f" goto end

:check
if exist "C:\Program Files (x86)\Atlassian\HipChat4\HipChat.exe" set exepath="C:\Program Files (x86)\Atlassian\HipChat4\HipChat.exe"
::if exist "c:\Program Files (x86)\Skype\Phone\skype.exe" set exepath="c:\Program Files (x86)\Skype\Phone\skype.exe"
if %exepath%==none echo %date% %time:~0,8% - %computername% findet das .exe Verzeichnis nicht && goto taskkill
goto checkversion

:checkversion
for /f "tokens=1-3" %%i in ('%tools%\sigcheck %exepath%') do ( if "%%i %%j"=="File version:" set instversion=%%k )
%tools%\VersionCompare.exe %instversion% %newversion%
set versionEL=%errorlevel%
if "%versionEL%"=="-1" goto taskkill
if "%versionEL%"=="0" echo %date% %time:~0,8% - %computername% hat bereits %instversion% installiert >> %log% & goto end
if "%versionEL%"=="1" echo %date% %time:~0,8% - %computername% hat bereits %instversion% (neuer) installiert >> %log% & goto end
goto end

:taskkill
TASKKILL /f /im hipchat.exe
goto install

:install
echo %date% %time:~0,8% - %computername% installiert... >> %log%
::msiexec.exe /i %wd%\deploy\%newversion%\SkypeSetup.msi /qn /norestart FEATURE_IEPLUGIN=0 FEATURE_FFPLUGIN=0
start /w %wd%\HipChat_%newversion%.exe /verysilent /norestart /restartapplications /lang=german /lang=1031 /64 /64bit /x64
set hipEL=%errorlevel%
if %hipEL%==1618 goto retry REM:: msiexec process in use, installation already in progress (eg. windows updates running)
if %hipEL%==1602 goto retry REM:: user canceled installation (eg. taskkill)
if %hipEL%==1603 goto retry REM:: fatal error, some use it for "already installed" (eg. java)
if %hipEL%==1638 goto uninstall REM:: another product is already installed, denies an update
if %hipEL%==1625 goto uninstall REM:: skype installer sometimes threw this one, don't know why
set hipEL=%errorlevel%
echo %date% %time:~0,8% - %computername% hat Version %newversion% mit EL %hipEL% abgeschlossen >> %log%
md %wd%\done\%computername%
goto end

:retry
if %retry%==1 goto retryfailed
echo %date% %time:~0,8% - %computername% hatte den Fehler %hipEL%, retry in 500Sek... >> %log%
set retry=1
REM:: 5 Minuten warten
ping localhost -n 500 > nul
goto taskkill

:retryfailed
echo _!_ %date% %time:~0,8% - %computername% hat die Installation abgebrochen, RETRY FAILED! >> %log%
goto end

:uninstall
if %retry%==1 goto retryfailed
TASKKILL /f /im hipchat.exe
echo %date% %time:~0,8% - %computername% deinstalliert Version %instversion%... >> %log%
start /w "" "C:\Program Files (x86)\Atlassian\HipChat4\unins000.exe" /s /silent /qn
del /q /s "C:\Program Files (x86)\Atlassian"
echo %date% %time:~0,8% - %computername% - %instversion% deinstalliert, retry... >> %log%
set retry=1
goto taskkill

:end
endlocal
exit

Und das war’s auch schon. Bei einem Update muss nur die neue .exe-Datei heruntergeladen und die Version in Zeile 11 angepasst werden.
Das Script kommt als Computer-Startscript in das GPO und schon startet die Verteilung:
Das Bild zeigt die Logausgaben des HipChat-Deployments
Das Bild zeigt das Deployment der 1648er Version anhand des allnew-Update-Scripts (siehe Hinweis und Download oben). Dabei wird an jedem PC, unabhängig der installierten Version (deswegen wird überall „Version 0.0“ deinstalliert), HipChat komplett deinstalliert und neu installiert. Beim Umstieg auf 1648 würde ich das empfehlen, weitere Update werden ich auch wieder mit dem normalen Script erledigen.


Letztens hat ein Leser in meinem Artikel Skype Werbung entfernen einen guten Kommentar hinterlassen, hier zu sehen. Es ging darum, dass es doch sicherheitstechnisch sehr bedenklich sei, von mir entwickelte, ausführbare Dateien (seien es .exe oder .bat) zu starten. Diese gesunde Skepsis begrüße ich und versuche in meinen Artikeln doch den offenen Code und viel Hintergrundinformationen die nötige Transparenz zu schaffen, um diese Sorgen zu reduzieren.
Ausführbare Dateien bleiben jedoch immer ein Risiko für Computersysteme und sollten immer mit Vorsicht behandelt werden. In meiner Kommentar-Antwort hatte ich ein paar generelle Tipps dazu gegeben:

  • immer kritisch und skeptisch sein (vor allem bei Downloads im Netz)
  • immer Virenscanner seperat (per Rechtsklick meistens) über jeden Download schicken, obwohl sie auch im Hintergrund immer aktiv aufpassen
  • immer Dateigrößen prüfen, ob sie zu den erwarteten Inhalten passen (Musikdateien sind selten kleiner als 1MB)
  • immer den kompletten Dateinamen mit all seinen Dateiendungen überprüfen (Explorer Einstellungen setzen, dass Dateiendungen angezeigt werden) und prüfen, ob die Dateiendungen zum erwarteten Dateityp passen (Bilder haben selten .exe als Dateiende)
  • Vorsicht vor typischen Malware-Dateitypen: .exe, .dot, .dotm (sowieso alle Office Dateitypen mit einem „m“ am Ende), .vbs und weitere
  • im Verdachtsfall bei Online-Diensten wie VirusTotal hochladen und schauen, was diese analysieren

Diese Liste möchte ich heute noch um ein Tool ergänzen, dass an dieser Stelle ansetzt: pestudio. pestudio ist eine Analysesoftware, die ausführbare Dateien auf Binärcode-Ebene untersuchen und alle Erkentnisse „leicht lesbar“ und übersichtlich auflisten. Dabei wird die Datei nicht ausgeführt, der Vorgang ist also gefahrenfrei.
Besonders praktisch ist die Schnittstelle zum VirusTotal Dienst, die in der Software verbaut ist, sodass jede analysierte Datei auch an diesen Dienst geschickt und dort bewertet wird. Das kann auch für PC-Ottonormalnutzer besonders hilfreich sein, weil dafür nicht extra der Browser geöffnet und die VirusTotal Homepage geöffnet werden muss. pestudio kann sogar in das Rechtsklick-Kontextmenü integriert werden, eine entsprechende .reg-Datei liegt bei. (Leider haben die Entwickler hier gepfuscht: in der Reg-Datei ist der feste Pfad „C:/pestudio/pestudio.exe“ verbaut, der Weg über das Rechtsklick funktioniert also nur, wenn das Programm dort liegt oder man den Pfad der .reg vor dem Import anpasst.)
Davon abgesehen eignet sich die Software jedoch eher für fortgeschrittenere PC-Anwender, da die Informationen nur mit etwas Hintergrundwissen eingeschätzt werden können.

Im folgenden habe ich mal die Dateien des Skype Posts analysiert: disableSkypeAds.bat und disarmSkypeConfigs.ps1.
analyse-executable-files-pestudio-skype2analyse-executable-files-pestudio-skype1

Sieht erwartungsgemäßig unspannend aus – sind schließlich auch keine ausführbaren Dateien und somit werden die einzelnen Codezeilen fast fehlerfrei als Strings erkannt.

Ausführbare Dateien sind jedoch wesentlich komplexer und enthalten viel mehr Funktionalitäten, die vom Programm vielleicht auch gar nicht genutzt werden. Die .exe Datei aus meinem letzten Beitrag, dem Swords and Souls Bot, sieht beispielsweise verhältnismäßig gruselig aus:
analyse-executable-files-pestudio-bot-exe
Das liegt hauptsächlich daran, wie ich mit AutoIt ausführbaren Dateien kompiliere. Beispielsweise lasse ich den Code von benötigten Bibliotheken in die .exe Datei mergen, damit ich meine Programme nicht mit zusätzlichen .dll (oder anderen) Dateien ausliefern muss. Das bläht natürlich die .exe Datei auf und plötzlich hätte diese, laut pestudio, sogar die Fähigkeit, FTP Verbindungen aufzubauen 😀

Für mich trotzdem ein spannendes Tool, mit dem ich bestimmt gerne mal ein paar fremde Dateien analysiere, die man im Netz manchmal so zugespielt bekommt 😉
Also halten wir fest: Immer schön skeptisch und vorsichtig bleiben.

Worum geht’s?

swords-and-souls-iconIch stelle kurz und knackig meinen in AutoIt 3 programmierten aktiven Bot für das Browserspiel Swords and Souls vor. Dieser ist hauptsächlich dafür da, Arena-Stages zu farmen. Außerdem nutzt er aktiv (und clever) alle Skills, leert regelmäßig die Bank, tauscht Kleeblätter ein, kauft EXP und speichert zwischendurch. Er könnte also ohne Probleme über Stunden durchlaufen und den Charakter damit verbessern.

Funktionen

Steuerung durch Shortcuts:

  • Shift+Alt+A – In der Arena kämpfen
  • Shift+Alt+M – Bank leeren und Kleeblätter eintauschen
  • Shift+Alt+O – Zurück zur Übersicht gehen, um andere Funktionen zu nutzen
  • Shift+Alt+H – Diese Hilfe noch einmal zeigen
  • Shift+Alt+X / ESC – Programm beenden

Farmingpausen mit:

  • Speichern
  • Gold von der Bank einsammeln
  • Kleeblätter eintauschen
  • Erfahrung für Gold kaufen (erst nach dem Besiegen des Endgegners möglich)

Cleveres Skillsystem:

  • Priorität 1: Heilen (Skill 5): nur wenn HP unter 40%
  • Priorität 2: Schildschlag (Skill 2): in Bosskämpfen immer benutzen, bei normalen Gegnern nur wenn dessen HP > 25%
  • Priorität 3: Schutzschild (Skill 4): immer wenn möglich
  • Priorität 4: Gift (Skill 3): in Bosskämpfen immer benutzen, bei normalen Gegnern nur wenn dessen HP > 50%
  • Priorität 5: Hack’n’Slay (Skill 6): in Bosskämpfen immer benutzen, bei normalen Gegnern nur wenn dessen HP > 50%
  • Priorität 6: Doppelangriff (Skill 1): in Bosskämpfen immer benutzen, bei normalen Gegnern nur wenn dessen HP > 25%

Screenshots

Die Einrichtung muss direkt nach dem Start geschehen und erfolgt durch einen Klick auf den obersten linkesten Pixel des Spielfensters:
swords-and-souls-bot-start-prepare-topleft-corner-pixel
Das Browserfenster muss so groß sein, dass das Spiel komplett angezeigt wird. Am Anfang werden in einem Hilfedialog alle Funktionen gelistet:
swords-and-souls-bot-start-help
In der Arena wird zuerst das Level für das Farming gewählt, anschließend noch ob das Pausenfeature genutzt werden soll und schon legt der Bot los:
swords-and-souls-bot-arena-start
swords-and-souls-bot-arena-fight

Video

Download und Code

Hier gibts den Bot als Download für 32/64bit Windows und, falls jemand den Bot weiterentwickeln oder anpassen möchte, den kompletten Code 1:1.

Download section
swords-and-souls-bot.exe (32bit)
swords-and-souls-bot_x64.exe (64bit)

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

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=swords-and-souls-bot.ico
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_Res_Description=AutoIt Bot for the browsergame "Swords and Souls", developed by Hannes Schurig in 2016
#AutoIt3Wrapper_Res_Fileversion=1.0
#AutoIt3Wrapper_Res_LegalCopyright=Hannes Schurig
#AutoIt3Wrapper_Res_Language=1031
#AutoIt3Wrapper_Add_Constants=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <Misc.au3>
#include <Array.au3>
#include <MsgBoxConstants.au3>

AutoItSetOption("SendKeyDelay", 40)
AutoItSetOption("SendKeyDownDelay", 40)
AutoItSetOption("MouseClickDelay", 40)
AutoItSetOption("WinTitleMatchMode", 2)
AutoItSetOption("MouseCoordMode", 1)

$noCoords = True
Local $ol[2]
$i = 0 ; fight counter
$survival = False
Local $levelcoords[2] = [0,0]
$clickCriticals = True
$pauseFarming = True
$pauseFarmingAfterXMatches = 2

HotKeySet("{Esc}", "exitnow") ; ESC
HotKeySet("+!x", "exitnow") ; Shift+Alt+X
HotKeySet("+!a", "arenaFight") ; Shift+Alt+A
HotKeySet("+!m", "museum") ; Shift+Alt+M
HotKeySet("+!o", "overview") ; Shift+Alt+O
HotKeySet("+!h", "help") ; Shift+Alt+H

Func exitnow()
	Exit
EndFunc

; prepare
WinActivate("Swords")
Sleep(300)
MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK,"Ecke oben links anklicken","Klicke in den obersten linkesten Pixel des Spiels.")
While $noCoords
		If _IsPressed("01") Then
		$ol = MouseGetPos()
		ConsoleWrite("####### Koords: " & $ol[0] & " " & $ol[1] & @CRLF)
		$noCoords = False
		EndIf
WEnd

If checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52) Then
		ConsoleWrite("####### Location: Map Overview" & @CRLF)
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK, "Deine Position", "Du befindest dich in der Übersichtskarte.")
EndIf

If checkSingleCoordWithColor($ol[0]+394, $ol[1]+460, 0x745818) Then
		ConsoleWrite("####### Location: Museum" & @CRLF)
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK, "Deine Position", "Du befindest dich im Museum.")
EndIf

If checkSingleCoordWithColor($ol[0]+66, $ol[1]+64, 0xC8B05E) Then
		ConsoleWrite("####### Location: Arena" & @CRLF)
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK, "Deine Position", "Du befindest dich in der Arena.")
EndIf

help()

Func help()
	MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK, "Hilfe", "Du kannst folgende Shortcuts nutzen:" & @CRLF & _
	"Shift+Alt+A - In der Arena kämpfen" & @CRLF & _
	"Shift+Alt+M - Bank leeren und Kleeblätter eintauschen" & @CRLF & _
	"Shift+Alt+O - Zurück zur Übersicht gehen, um andere Funktionen zu nutzen" & @CRLF & _
	"Shift+Alt+H - Diese Hilfe noch einmal zeigen" & @CRLF & _
	"Shift+Alt+X / ESC - Programm beenden" & @CRLF & _
	"Dies ist ein Maus/Tastatur-Bot. Der PC ist, während der Bot läuft, nicht direkt benutzbar.")
EndFunc

Func overview()
	; force-go to overview map
	While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
		MouseClick("left", $ol[0]+25, $ol[1]+20,1)
		Sleep(800)
	WEnd
EndFunc

Func arenaFight()
	; check for overview map
	If checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52) Then
		; go to arena
		MouseClick("left",$ol[0]+235, $ol[1]+165,1)
	; check for arena
	ElseIf checkSingleCoordWithColor($ol[0]+66, $ol[1]+64, 0xC8B05E) Then
		; continue
	Else
		; force-go to overview map
		While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
			MouseClick("left", $ol[0]+25, $ol[1]+20,1)
			Sleep(800)
		WEnd
		; go to arena
		MouseClick("left",$ol[0]+235, $ol[1]+165,1)
	EndIf

	; level input
	$level = InputBox("Welches Level?", "Bitte gib das Level ein, dass gefarmt werden soll." & @CRLF & _
	"Möglich Eingaben sind '1' - '30', 'survival' und 'final'", "", " M", 280, 150)

	If $level > 0 And $level <= 10 Then
		$levelcoords[0] = $ol[0] + 119 + (($level - 1)*62)
		$levelcoords[1] = $ol[1] + 292
	ElseIf $level > 10 And $level <= 20 Then
		$levelcoords[0] = $ol[0] + 97 + (($level - 11)*66)
		$levelcoords[1] = $ol[1] + 334
	ElseIf $level > 20 And $level <= 30 Then
		$levelcoords[0] = $ol[0] + 75 + (($level - 21)*71)
		$levelcoords[1] = $ol[1] + 392
	ElseIf $level = "final" Then
		$levelcoords[0] = $ol[0] + 489
		$levelcoords[1] = $ol[1] + 482
	ElseIf $level = "survival" Then
		$levelcoords[0] = $ol[0] + 339
		$levelcoords[1] = $ol[1] + 456
		$survival = True
	Else
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONERROR + $MB_OK, "Falsche Eingabe", "Die Eingabe konnte nicht verwertet werden." & @CRLF & _
		"Der Bot setzt sich zurück, anschließend kannst Du erneut den Arena-Modus starten.")
		; force-go to overview map
		While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
			MouseClick("left", $ol[0]+25, $ol[1]+20,1)
			Sleep(800)
		WEnd
		Sleep(1000)
		Return
	EndIf

	If $levelcoords[0] == 0 Then
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONERROR + $MB_OK, "Unerwarteter Fehler", "Der Bot setzt sich zurück, anschließend kannst Du erneut den Arena-Modus starten.")
		; force-go to overview map
		While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
			MouseClick("left", $ol[0]+25, $ol[1]+20,1)
			Sleep(800)
		WEnd
		Sleep(1000)
		Return
	EndIf

	; pause farming regulary after some matches - save, grab income, turn in cloverleafs frequently, get exp for gold?
	$save = MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONQUESTION + $MB_YESNO, "Farming mit Pausen?", "Soll der Bot während des Farmens weitere hilfreiche Aufgaben übernehmen? Folgende Aufgaben würde der Bot alle " & $pauseFarmingAfterXMatches & " Matches ebenfalls übernehmen:" & @CRLF & _
	"- Speichern" & @CRLF & _
	"- Gold von der Bank einsammeln" & @CRLF & _
	"- Kleeblätter eintauschen" & @CRLF & _
	"- Erfahrung für Gold kaufen (erst nach dem Besiegen des Endgegners möglich)", "", " M")
	If $save = $IDYES Then
		$pauseFarming = True
	Else
		$pauseFarming = False
	EndIf

	; arena:
	while 1
		WinActivate("Swords")
		Sleep(1200)

; ------------- MANAGING MATCHES --------------------------------------------------

		; lost/survival done, retry
		If checkSingleCoordWithColor($ol[0] + 351, $ol[1] + 326, 0x5A3D1D) Then
			MouseClick("left",$ol[0] + 351, $ol[1] + 326, 1)
			$i += 1
		EndIf

		; survival start
		If $survival And checkSingleCoordWithColor($ol[0]+292, $ol[1]+175, 0x938D6F) Then
			; click survival
			MouseClick("left", $levelcoords[0], $levelcoords[1], 1)
			Sleep(500)
			; click "start"
			MouseClick("left", $levelcoords[0], $levelcoords[1], 1)
			Sleep(1500)
		EndIf

		; survival ended, "ok"
		If $survival And checkSingleCoordWithColor($ol[0] + 426, $ol[1] + 448, 0x5D3F1D) Then
			MouseClick("left", $ol[0] + 426, $ol[1] + 448, 1)
			Sleep(1000)
		EndIf

		; final ended, scarecrow talk
		If checkSingleCoordWithColor($ol[0] + 360, $ol[1] + 511, 0xE6DFC7) Then
			MouseClick("left", $ol[0] + 360, $ol[1] + 511, 1)
			Sleep(1000)
		EndIf

		; normal match start
		If checkSingleCoordWithColor($ol[0]+292, $ol[1]+175, 0x938D6F) Then
			MouseClick("left", $levelcoords[0], $levelcoords[1], 1)
		EndIf

		; normal match finished, continue
		If checkSingleCoordWithColor($ol[0]+378, $ol[1]+454, 0xFFFFFF) Then
			MouseClick("left", $ol[0]+378, $ol[1]+454, 1)
			$i += 1
		EndIf

; ------------- FIGHTING --------------------------------------------------

		; Skill 5 - Healing
		; check if available
		If checkSingleCoordWithColor($ol[0]+490, $ol[1]+560, 0xFFE7C1) Then
			; just use if u're below 50% health
			If checkSingleCoordWithColor($ol[0]+284, $ol[1]+453, 0x730520) Then
				; enough health
			Else
				Send("5")
			EndIf
		EndIf

		; Skill 2
		; check if available
		If checkSingleCoordWithColor($ol[0]+306, $ol[1]+565, 0xFFE7C1) Then
			; if in boss battle - use it anytime
			If checkCoordRangeWithColor($ol[0]+404, $ol[1]+451, $ol[0]+442, $ol[1]+469, 0xFFD23E) Then
				Send("2")
			Else
				; if not: only if enemy health 25% or more
				If checkSingleCoordWithColor($ol[0]+485, $ol[1]+453, 0x730520) Then
				Send("2")
				EndIf
			EndIf
		EndIf

		; Skill 4
		; if available
		If checkSingleCoordWithColor($ol[0]+430, $ol[1]+560, 0xFFE7C1) Then
			Send("4")
		EndIf

		; Skill 3 - Poison
		If checkSingleCoordWithColor($ol[0]+369, $ol[1]+552, 0xFFE7C1) Then
			; if in boss battle - use it anytime
			If checkCoordRangeWithColor($ol[0]+404, $ol[1]+451, $ol[0]+442, $ol[1]+469, 0xFFD23E) Then
				Send("3")
			Else
				; if not: only if enemy health 50% or more
				If checkSingleCoordWithColor($ol[0]+515, $ol[1]+453, 0x730520) Then
				Send("3")
				EndIf
			EndIf
		EndIf

		; Skill 6 - Slashing
		If checkSingleCoordWithColor($ol[0]+548, $ol[1]+561, 0xFFE7C1) Then
			; if in boss battle - use it anytime
			If checkCoordRangeWithColor($ol[0]+404, $ol[1]+451, $ol[0]+442, $ol[1]+469, 0xFFD23E) Then
				Send("6")
			Else
				; if not: only if enemy health 50% or more
				If checkSingleCoordWithColor($ol[0]+515, $ol[1]+453, 0x730520) Then
				Send("6")
				EndIf
			EndIf
		EndIf

		; Skill 1
		; if available
		If checkSingleCoordWithColor($ol[0]+249, $ol[1]+559, 0xFFE7C1) Then
			; if in boss battle - use it anytime
			If checkCoordRangeWithColor($ol[0]+404, $ol[1]+451, $ol[0]+442, $ol[1]+469, 0xFFD23E) Then
				Send("1")
			Else
				; if not: only if enemy health 25% or more
				If checkSingleCoordWithColor($ol[0]+485, $ol[1]+453, 0x730520) Then
				Send("1")
				EndIf
			EndIf
		EndIf

; ------------- REST --------------------------------------------------

		; save every 5th fight
		If $pauseFarming And $i >= $pauseFarmingAfterXMatches Then
			Sleep(1000)
			; force-go to overview map
			While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
				MouseClick("left", $ol[0]+25, $ol[1]+20,1)
				Sleep(800)
			WEnd

			museum()
			expForGold()

			; go to arena
			MouseClick("left",$ol[0]+235, $ol[1]+165,1)
			$i = 0
			Sleep(1000)
		EndIf

	WEnd
EndFunc

Func museum()
	; force-go to overview map
	While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
		MouseClick("left", $ol[0]+25, $ol[1]+20,1)
		Sleep(800)
	WEnd

	; go to museum
	MouseClick("left",$ol[0]+329, $ol[1]+459, 1)
	Sleep(1000)

	; get cash
	MouseClick("left",$ol[0]+479, $ol[1]+431, 1)
	Sleep(1000)

	; auto-invest clovers if u're in the room and have some
	While checkSingleCoordWithColor($ol[0]+651, $ol[1]+311, 0xE8E5C2)
		MouseClick("left",$ol[0]+651, $ol[1]+311,1)
		MouseMove($ol[0]+551, $ol[1]+211, 1)
		Sleep(2000)
	WEnd
	Sleep(1000)

	; get cash again
	MouseClick("left",$ol[0]+479, $ol[1]+431, 1)
	Sleep(1000)

	; force-go to overview map
	While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
		MouseClick("left", $ol[0]+25, $ol[1]+20,1)
		Sleep(800)
	WEnd
	Sleep(1000)
EndFunc

Func expForGold()
	; force-go to overview map
	While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
		MouseClick("left", $ol[0]+25, $ol[1]+20,1)
		Sleep(800)
	WEnd

	; go to shop
	MouseClick("left",$ol[0]+528, $ol[1]+213, 1)
	Sleep(1000)

	For $x = 1 To 30 Step +1
		MouseClick("left",$ol[0]+396, $ol[1]+548,1)
		Sleep(300)
	Next

	; force-go to overview map
	While Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52)
		MouseClick("left", $ol[0]+25, $ol[1]+20,1)
		Sleep(800)
	WEnd
	Sleep(1000)
EndFunc

Func training()

	; this feature is not ready yet
	Return

	; check for overview map
	If Not checkSingleCoordWithColor($ol[0]+578, $ol[1]+400, 0xB65D52) Then
		MsgBox($MB_TOPMOST + $MB_SETFOREGROUND + $MB_DEFBUTTON1 + $MB_ICONINFORMATION + $MB_OK, "Übersichtskarte", "Bitte gehe in die Übersichtskarte, um die Botfunktionen zu starten.")
		Return
	EndIf

	;training crit:
	While 1
		If checkSingleCoordWithColor(685, 382, 0xffffff) Then
			MouseClick("left")
			Sleep(700)
			MouseClick("left")
			$i +=1
			ContinueLoop
		EndIf
		If checkSingleCoordWithColor(789, 381, 0xffffff) Then
			MouseClick("left")
			Sleep(700)
			MouseClick("left")
			$i +=1
			ContinueLoop
		EndIf
		If $i>50 Then
			; quit crit training
			MouseClick("left", $ol[0]+25, $ol[1]+20, 1)
			Sleep(5000)
			; quit training room & go to map
			MouseClick("left", 298, 123, 1)
			Sleep(3000)
			; go to training room
			MouseClick("left", 673, 415, 1)
			Sleep(3000)
			$i = 0
			; start crit training
			MouseClick("left", 872, 147, 1)
			Sleep(3000)
		EndIf
	WEnd

	; training attack:
	While 1
		If Not checkSingleCoordWithColorV(326, 455, 0xCC9362, 3) Then
			Send("{LEFT}")
			ContinueLoop
		EndIf
		If Not checkSingleCoordWithColorV(560, 466, 0xAD794C, 4) Then
			Send("{RIGHT}")
			ContinueLoop
		EndIf
		If Not checkSingleCoordWithColorV(563, 541, 0x926743, 3) Then
			Send("{Down}")
			ContinueLoop
		EndIf
		If Not checkSingleCoordWithColorV(511, 373, 0xCF996B, 3) Then
			Send("{Up}")
			ContinueLoop
		EndIf
		If Not checkSingleCoordWithColorV(322, 424, 0xD4A57D, 3) Then
			Send("{LEFT}")
			ContinueLoop
		EndIf
	WEnd
EndFunc

Func checkSingleCoordWithColor($x, $y, $color)
		Return IsArray(PixelSearch($x-3, $y-3, $x+3, $y+3, $color, 3))
EndFunc

Func checkSingleCoordWithColorV($x, $y, $color, $variation)
		Return IsArray(PixelSearch($x-3, $y-3, $x+3, $y+3, $color, $variation))
EndFunc

Func checkCoordRangeWithColor($x1, $y1, $x2, $y2, $color)
		Return IsArray(PixelSearch($x1-3, $y1-3, $x2+3, $y2+3, $color, 3))
EndFunc

; keep-alive for shotcuts
while 1
	sleep(100000000)
WEnd