D2NT "Please Wait" Loop

04/12/2011 18:04 eXoo~#1
Kennen ja bestimmt einige, dass der Bot manchmal nach verlassen eines Spiels in ner "Please Wait" Schleife steckt und nicht weiterläuft

Hab versucht das mal zu fixen mit:
Code:
case 25: // Lobby - Please Wait
     			 if(!locationTimeout(pleaseWaitTimeout, location))
      			 sendEventToOOG(D2NT_MGR_RESTART,location.name,5);
      			 break;
in NTBot.ntj

Allerdings startet er nach ca 90% der Spiele komplett neu, was da ja auch eigentlich steht... -.-"

Jemand ne Idee wie ich das hinkriege, dass er nur dann neustartet, wenn er wirklich in der Schleife hängt und nicht nur nen kleinen Delay?:S
04/12/2011 18:43 Muddy Waters#2
Mit dem Ansatz wird das nichts. Es wäre vielleicht hilfreich, wenn man sich anschaut, was die locationTimeout() eigentlich macht, bevor man deren Rückgabewert auswertet. ;)

In Kurzform:
Die Funktion führt ein Delay aus, solange sich der Char an einer festgelegten Location befindet. (Wie der Begriff Location zu verstehen ist, ist der controlInfo Klasse zu entnehmen)
Ändert sich die Location in der Zwischenzeit, wird die Funktion vorzeitig abgebrochen. Rückgabewert ist aber in jedem Fall der Vergleich der Location zu Anfang im Vergleich zur Location zum Ende der Funktion hin.

Hat sich die Location verändert, gibt die Funktion true zurück, ist die Funktion nach wie vor dieselbe, wird false zurückgegeben.

Der Punkt ist ganz einfach, dass die Funktion eben nicht nur dann false zurückgibt, wenn das Fenster hängt und eine Endlosschleife durchlaufen wird.
Wie du schon gemerkt hast, passiert das auch durchaus mal, während alle in Ordnung ist.

Ich habe die Problematik daher bei mir etwas anders gelöst, wobei meine Lösung eigentlich erschreckend einfach ist.

Hier mal meine aktuelle NTBot.ntj:

Ich habe mal ein paar interessante Teile hervorgehoben, auch wenn man es im passigen Editor sicherlich noch sehr viel besser sieht.

Die Lösung ergibt sich fast automatisch, nachdem man festgestellt hat, dass auch während einer Endlosschleife immer wieder die Funktion NT_LocationAction() aufgerufen wird.
Man macht nun eigentlich nichts anderes, als mitzuzählen, wie oft diese Funktion von derselben location aus aufgerufen wird.
Dazu nimmt man sich ein globales Array und speichert darin zum einen das location Objekt, zum anderen die Anzahl der durchläufe.

In meinem Fall heisst dieses globale Array LocationLoops.

Nun braucht man nurnoch eine kleine Funktion, die das Mitzählen übernimmt.
Bei mir heisst diese Funktion MW_CheckLocationLoops(), als Parameter wird das location Objekt der aktuellen Position übergeben, welches dann mit dem vorher gespeicherten verglichen wird.

Die Implementierung der Funktion sieht so aus:
Code:
function MW_CheckLocationLoops(location)
{
	if(!location)
		return false;
	
	if(!LocationLoops[0] || location.id != LocationLoops[0].id)
	{
		LocationLoops[0] = location;
		LocationLoops[1] = 0;
	}
	else if(LocationLoops[0].id != 5)
	{
		LocationLoops[1]++;
		
		if(LocationLoops[1] >= MaximumLocationLoops)
		{
			if(LocationLoops[1] < 1000)
				NT_SendEventToOOG(D2NT_MGR_PRINT_LOG, "ÿBE0000Location Loop Restart!;ÿc1Location Loops: " + LocationLoops[1] + "\nÿBE0000Location: " + LocationLoops[0].name + "\nÿBE0000Location ID: " + LocationLoops[0].id, 0);
			
			LocationLoops[1] = 1000; // Make sure the location loop notification is only shown once
			
			NT_SendEventToOOG(D2NT_MGR_RESTART, location.name, 0);
		}
	}
	
	return true;
}
Nun passiert eigentlich genau das, was ich oben schon gesagt habe.
Es wird zunächst überprüft, ob das übergebene location Objekt mit dem zuletzt gespeicherten identisch ist respektive die location ids dieselben sind.

Ist dem nicht so, wird das übergeben Objekt im globalen Array zwischengespeichert, sowie der Zähler auf Null gesetzt.
Sind die ids gleich und ist die Location nicht "Join Game" (id == 5), wird nur der Zähler inkrementiert.

Ausserdem wird noch überprüft, ob der Zähler mit der letzten Inkrementierung den vorher festgelegten Grenzwert überschritten kann.
Ist dies der Fall, wird ein Restart des Fensters durchgeführt, sowie eine Ausgabe ins Common Log des Managers ausgeführt.

Die Zählvariable wird ausserdem auf einen unrealistisch hohen Wert gesetzt, um zu verhindern, dass die Ausgabe ins Common Log mehrfach durchgeführt wird.

Das ist es auch eigentlich schon. Alles in allem extrem einfach und eine Arbeit von 5-10 Minuten. :)

LG
Muddy
04/12/2011 19:19 eXoo~#3
Werd das ganze mal overnight testen.
Sofern es funktioniert lass ich dir gerne ne Belohnung zukommen :P

Edit:
Also für den Mainbot funzt es.
Problem habe ich allerdings mit Leechern
da diese /f l commands im channel spammen( quasi loops)
gibt es immer restart nach 5 /f l spams
hab die maxloop anzahl schon aufgedreht, aber trotzdem fliegen sie nach der zahl dann
lässt sich da irgendwie ne ausname für /f l spams einfügen?
04/12/2011 21:56 Muddy Waters#4
Auch nach 30 Minuten darfst auch du noch zum [Only registered and activated users can see links. Click Here To Register...] Button greifen. :rolleyes:

Bau eben eine Ausnahme für bestimmte Chars ein. Oder sollen die das auch mit benutzen?

In dem Fall könnte man auch einfach die betroffene Location ignorieren, so wie ich das bei mir mit der Location "Join Game" mache.

LG
Muddy