Ständiger Deathcheck | Start-Button

05/04/2010 13:38 Kruemelmonsterchen#1
Hey ihr,

nachdem ich über das letzte Event hinweg ein paar der hier zu findenden Bots durchprobiert habe, spinnt seit vorgestern der Wunsch in meinem Kopf rum, sowas tolles möchte ich auch können! :D

Also habe ich mir ein paar Tuts angesehn, da mir AutoIt ja bis dato noch gänzlich unbekannt war und dann einfach mal drauflosgelegt. Ganz nach dem Motto: Learning by Doing. Klappt auch soweit besser als erwartet. Immerhin bin ich schonmal soweit, dass mein kleiner Bot in den nötigen Außenposten reist, auf den HM umschaltet, rausrennt und sich den Weg hin zum Farmort sucht. Hab' die kleinen Teilaufgaben jeweils in seperate Scripts gespeichert und mir nun gedacht, ich sollte mal ganz sauber von vorn anfangen, bevor ich mich dem Farm-Teil widme. Also hab ich mich rangesetzt, und mich um den GUI gekümmert. Der steht auch soweit und besitzt nen Start- und Close-Button. Ich bin stolz auf mich. Doch hier auch schon das erste Problem, über das ich nicht hinwegkomme:

Code:
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Close
			Exit
		Case $Start
			

	EndSwitch
WEnd
Wie man vielleicht erkennen kann, fehlt mir der Befel, der ausgeführt werden soll, wenn der Start-Button beklickt wird. Zuerst hatte ich dort einen Befehl á la "call("Function")" stehen. Doch, wie ich erst später begriff springt der kleine Bot dann an den Punkt, an dem das Unterprogramm beschrieben wird, bearbeitet es und stoppt dann. Das ist nicht so ganz das, was ich mir wünsche. Ist es also irgendwie möglich, das Programm an eine bestimmte Stelle im Programmcode springen zu lassen, sobald ein Hit auf den Start-Button erfolgte?

-----------------

Und weil ich ja schon dabei bin:

In dem Gebiet, durch das der Bot laufen musst, taucht in ca. 1 von 100 Fällen ein einzelner Gegner auf, der mich umnietet. Aus diesem Grund ist es nötig, eine ständige DeathCheck abfrage zu integrieren. Idealerweise fragt das Programm also in geeigneten Abständen die aktuelle Anzahl an Hitpoints ab. Wie ich die Abfrage mit Hilfe von GWCA realisiere, weiß ich, das was Probleme macht, ist das "ständig". Ich könnte natürlich nach jedem Befehl eine Abfrage einbauen aber das wäre schrecklich ineffizient. Ganz abgesehn davon, dass der Charakter ja nur 10 Sekunden lang tot ist und ich diesen Zeitraum mit viel Pech schlicht verpasse. Dann würde der Bot irgendetwas tun, was ich aber mit Sicherheit so nicht möchte ...

----------------

Weils so schön ist:

Vielleicht eine wirklich unwichtige Frage, aber der Koda-Designer besitzt die Funktion, ein Bild in den GUI einzufügen. Vorhin wollte ich diese Funktion benutzen und bekam aber bei der Abfrage der Source den Fehler, dass die Variable, in der das Bild gespeichert wird, nicht deklariert ist. Als ich versuchte, dies von Hand nachzuholen, klappte das nicht. Wie also kann ich diese Bild-Einfüge-Funktion trotzdem nutzen?

Ich hoffe darauf, nette Menschen zu finden, die mir ein wenig helfen. Ganz ohne irgendwelche Diffamierungen, falls es möglich ist. ;) Und bitte, denkt daran, dass ich das, was ihr schreibt auch sehr gern verstehen würde ...
05/04/2010 14:08 menchecktor#2
Code:
Func CheckDeath()
	
	$cbType = "int"
	CmdCB($CA_GETDEAD)
	If $cbVar[0] = 1 Then
		Resign()
	EndIf
EndFunc
Diese Funktion baust du in dein Skript ein,und dann schreibst du am Anfang des Runs:
Code:
AdlibRegister ("CheckDeath", 1000)
und am Ende:
Code:
AdlibUnRegister("CheckDeath")
€: Hier noch die Resign()-Funktion für den Deathcheck:
Code:
Func Resign()
	$cbType = "int"
	Do
		Cmd($CA_RESIGN)
		Sleep(Random(1100, 1400))
		CmdCB($CA_GETDEAD)
	Until $cbVar[0] = 1
	Sleep(Random(3000, 3200))
	Cmd($CA_RETURNTOOUTPOST)
	UpdateStatus("...Zoning...")
	Do
		Sleep(500)
		CmdCB($CA_GETMAPLOADING)
	Until $cbVar[0] = 0
	Sleep(6000)
	Sleep(500)
	Start()
EndFunc
[Start() durch deine Farm-Funktion ersetzen]
05/05/2010 21:24 Kruemelmonsterchen#3
Super, danke dafür.

Ich nehm an, ich kann auch mehrere dieser Register in einem Programm benutzen, sofern sie jeweils beendet werden.

Noch eine kleine Frage:

Es gibt unter GWCA die Funktion, das nächstgelegene Ziel anzuvisieren. Was aber wenn ich wissen muss, ob dieses Ziel in meiner Aggro Range liegt?

Ich bin nicht allwissend auf die Welt gekommen, also bitte ohne diffamierungen. ;)
05/05/2010 22:19 Brumtoc#4
Quote:
...das nächstgelegene Ziel anzuvisieren...
Yess, $CA_TargetNearestFoe...

Quote:
...ob dieses Ziel in meiner Aggro Range liegt...
Ja, du kannst dies mit $CA_GetMyDistanceToAgent überprüfen, 750 entspricht glaub dann dem Agrro Kreis.

Viel Spass damit
05/05/2010 23:09 kknb#5
1012
05/06/2010 19:54 Kruemelmonsterchen#6
Oh danke, also ist dieses Agent-Dings doch für diese Zwecke da ... Konnte damit ja zuerst rein garnichts anfangen. Was würde ich bloß ohne euch tun. :D

Und weil ich so gern nerve, direkt noch ein kleines Problemchen:

Es gibt den Befehl: CA_GetGold (No parameters. Returns integer with gold on your character and integer with gold in your storage.). So. Ich nehme mal stark an, mein eigenes Gold ruf ich mit $cbVar[0] ab. Ich nehm außerdem an, dass die Angabe in Goldstücken passiert. 89,750p wären also 89750g. Aber wie erfrag ich nun den Goldstatus meiner Truhe?
05/06/2010 20:29 OlafTank#7
$cbType = "int"
CmdCB($CA_GetGold)
$GoldOnChar = $cbVar[0]
$GoldInStorage = $cbVar[1]
05/08/2010 17:11 Kruemelmonsterchen#8
Da hätt ich aber auch selber drauf kommen können. :S Danke

Leider bin ich nun beim testen auf ein anderes Problem gestoßen ...

Folgendes findet sich in meinem Programm:

Code:
Func MoveThrough
AdlibRegister ("CheckDeath", 1000)
...
AdlibUnRegister ("CheckDeath")
EndFunc

Func CheckDeath()
...
EndFunc
So, nun mein problem dabei. Wenn mein kleiner Charakter losläuft, in einen Gegner rennt und durch diese Übermacht stirbt, so tut er wie aufgetragen das, was ich in dem Unterprogramm CheckDeath definiert habe. Er reist also zurück in den Außenposten. Hier wird ihm aufgetragen, erneut rauszulaufen, was er auch tut. Ich schicke ihn darauf zurück in die Funktion, MoveThrough. Soweit, so gut. Doch wenn er jetzt durch böse Zufälle erneut stirbt, so greift CheckDeath nicht mehr, mein Charakter steht am RezzSchrein und bleibt dort, bis er an Altersschwäche stirbt. Warum? Ich habe schon überlegt, den Befehl AdlibUnRegister ("CheckDeath") mit in die Funktion CheckDeath zu packen. Keine Besserung. Auch habe ich folgende Bedingung probiert:

Code:
If $DeathCounter1 = 0 Then
	AdlibRegister ("CheckDeath", 1000)
EndIf
und im Unterprogramm CheackDeath:

Code:
$DeathCounter1 = $DeathCounter1 + 1
genutzt. Natürlich habe ich die verwendete Variable weiter oben definiert und ihr den Wert 0 gegeben. Aber wen wundert es: Auch diese Maßnahme löst mein Problem nicht. Ich weiß nicht mehr weiter ...
05/08/2010 18:46 Thompsen#9
Ist etwas schwer zu erklären:

Während deine AdlibRegister Func wirkt(Checkdeath), wird das Hauptscript pausiert.

Wenn dein Charakter stirbt, reagiert deine Func und startet das Script neu, allerdings ist währenddessen das Hauptsript immernoch pausiert.

Dein Script versucht also aus der Registerten Func hinaus Checkdeath erneut zu registern.
Das funktioniert aber nicht.

Versuch stattdessen das ganze mit globalen Variablen(Threadkommunikation, falls dir das was sagt) zu lösen.

Also in der Registerten Func:

Code:
Func CheckDeath()

CmdCB($CA_GetDead)
If $cbVar[0] = 1 Then $death = true
Im Hauptscript checkst du dann regelmäßig ob $Death = true, und erkennst so ob du gestorben bist.
05/08/2010 19:46 Kruemelmonsterchen#10
Heißt im Klartext, ich darf aus einer registerten Funktion nicht verlangen, eine andere Funktion aufzurufen, gell? Ich habs jetzt so gelöst, wie von dir beschrieben und frag also in regelmäßigen Abständen die Variable ab. Das klappt soweit, wenn ich das jetzt schon beurteilen kann. Grad bin ich schon fast erneut verzweifelt, weil ich vergessen hatte, die Variable auch irgendwann zurück auf False zu setzen ... :rolleyes:

Aber: Die Dunktion CA_GetDeath, ist die nicht schrecklich ungenau? :S Andauernd hab ichs, dass ich zurück in den Außenposten geschickt werde, ganz ohne Gegnerkontakt. Nun mach ichs mit Hitpointsabfrage und es scheint mir doch, ein wenig besser zu klappen.

Irgendwer hat mir mal gesagt, das schwierige beim Programmieren ist es, seine Worte in Porgrammcode zu füllen. Haha, ich weiß es besser. Das schwierigste ist ganz eindeutig die Fehlersuche und das darauffolgende debugging ... :awesome:

Gut weiter gehts, auf zum nächsten Problem. :D
05/08/2010 19:51 kknb#11
aus der befehlsreferenz

CA_GetDead No parameters, returns boolean, but kinda obsolete though.
05/08/2010 21:42 Killerzwerg829#12
Ich bin da etwas faul und lasse den Bot einfach über 2 Scripte laufen. Einmal den Bot und der andere ist die Gui + Deathcheck.
Wenn der Character Tot ist, einfach den Process vom Bot beenden, in die Stadt zurück und wieder die exe vom Bot starten.
05/08/2010 23:16 Kruemelmonsterchen#13
Zwei Programme laufen zu lassen, wär mir schon wieder zu ineffizient und nervig. :D Nein, es läuft ja jetzt. Zumindest was den Weg zur Farmstelle angeht. Nur während des Kampfes greift die ganze Geschichte noch nicht und derzeit weiß ich noch nicht ganz, wieso. Das muss aber ein Fehler in meinem Skript sein und vermutlich bin ich grad einfach zu verpeilt, den zu finden. Am Besten mal drüber schlafen ... :rolleyes:

Achso, naja ... Die Kommandoliste lesen, das schaff ich bereits. Nur mit dem Begriff obsolete kann ich persönlich jetzt nicht alzu viel anfangen. Liegt im Auge des Betrachters, ob man "überholt" oder "veraltet" Dinge bezeichnet, die nicht funktionieren, nicht gut genug funktionieren oder ob es einfach elegantere Lösungen gibt und diese aber trotzdem seinen Nutzen erfüllt. Wie auch immer, die Idee, den Befehl $CA_GetMyMaxHP zu nutzen, ist auch nicht so ganz das gelbe vom Ei. Hin und wieder ertapp ich meinen Charakter nach wie vor dabei, dass er zurück reist, während er an einem Stein vorbeihuscht. Aber um solche Feinheiten kümmer ich mich dann, wenn ich mal einen Run stabil über die Bühne gebracht hab ... :S

Mal was ganz anderes: Ihr habt teilweise in eurem GUI so hübsche Übersichten, die den momentanen Fortschritt im Script anzeigen. Also praktisch sowas, wie "Char läuft raus", "Char benutzt Skillxyz" etc. Wie ich diese coolen Sätze an den GUI weitergebe, habe ich mir schon abgesehen, mein ich. Aber ich suche verzweifelt die zugehörige Schaltfläche im Koda Designer ... Den Knopf, mit dem ich so ein hübsches Fenster aufziehe, in dem dann später mein Roman erscheint. Wo ist denn der oder wie mache ich das ... ? Lacht mich bitte nicht aus :S
05/09/2010 00:03 kknb#14
du kannst text in fast allen guicontrols wiedergeben, ich benutze am liebsten das list object, ansonsten kannste editboxen, textboxen, label einfach alles was text wiedergeben kann benutzen^^
05/09/2010 13:32 Kruemelmonsterchen#15
Ach so einfach ist das also ... Naja dann kann ich jetzt ja fleißig meinen GUI zuspammen. :D

So ähnlich, wie ich das hier mache ... :S Wieder ein Problem ...

Code:
#include "GWCAConstants.au3"

$cbType = "int"
	CmdCb($CA_FindEmptySlot, 1)
	If $cbVar[0] > 34 OR $cbVar[0] = 0 Then
		MsgBox(1, "Test", "Test")
	EndIf
Exit
Natürlich ist das da völlig aus dem Zusammenhang gerissen, um es besser testen zu können. Und mitlerweile habe ich schon so viel ausprobiert, dass es eigentlich nur noch an der Bemerkung "Parameter = bag index to start searching from." liegen kann. Ich habe da eine 1 angegeben. Nach dem Motto: Such vom ersten Slot aus ... Aber irgendwie scheint das ja nicht richtig zu sein. Ich weiß ja nicht, aber ein wenig mehr Informationen hätte man dieser Befehlsliste irgendwie schon anhängen können ...

Haut mich nicht, weil ich hier eine Frage nach der anderen Stelle ... Vermutlich werde ich wegen des Identens & Verkaufens auch noch ankommen, gleichwohl ich da schöne Beispielscripts auf meinem Desktop liegen habe. Naja, vom abschaun habe ich halt nicht so viel, wenn ich nicht verstehe, was ich tue ... Drum schreib ich lieber, was ich für richtig halte ...