Fehlermeldung: Too many events posted

Fragen zu "Adventure Game Studio"? Hier rein!
Antworten
Benutzeravatar
DieFüchsin
Adventure-Gott
Adventure-Gott
Beiträge: 4406
Registriert: 12.03.2004, 16:55

Fehlermeldung: Too many events posted

Beitrag von DieFüchsin »

Ich bin mit dem ersten Kapitel meines Spiels fertig geworden und gerade beim Testspielen. Manchmal läuft es von vorn bis hinten einwandfrei, aber manchmal bricht AGS mit der Beschwerde: "Too many events posted" ab.

Was ist das für ein komischer Fehler?

Andere Frage: Wenn man Gegenstand zB mit einem Charakter benutzt, fragt man den Gegenstand ja mit "character[EGO].activeinv" ab. Im Inventar selbst, wenn ich Gegenstände kombinieren will, geht das aber irgendwie nicht. Bisher hab ich die Gegenstände nur mit den von AGS vorgegebenen Auswahloptionen kombiniert, aber das wäre jetzt zu aufwändig. Gibts im Inventar einen anderen Befehl dafür oder müsste es eigentlich so klappen?
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Dieser Fehler tritt auf, wenn zu viele Ereignisse abgearbeitet werden müssen, nachdem AGS etwas blockendes ausgeführt hat.

Beispiel: RunDialog() wird bekanntlich nicht sofort ausgeführt, sondern erst am Ende des Skripts. Wenn AGS also auf das Kommando RunDialog() stößt, "postet" AGS es in die "event"-queue. Anschließend wird das Skript weiter bis zum Ende ausgeführt, und jetzt erst wird die queue abgearbeitet, in der sich in diesem Fall lediglich RunDialog() befindet.
Landen aber mehr als 5 Ereignisse in der queue, kommt der Fehler.

In deinen Fall hast Du wahrscheinlich in der repeatedly_execute irgendwas stehen, was in einem ungünstigen Fall zichmal in der queue landet und diese damit überflutet. Geh die rep_exe durch und versuche, sie so umzuschreiben, dass momentan unnötiger Code gar nicht erst ausgeführt wird.

Zur anderen Frage:
Ich nehme mal an, dass Du allgemeine "Das geht so nicht"-Meldungen einbauen willst. Um in der on_mouse_click einen Klick ins Inventar abzufragen, brauchst Du button==LEFTINV/RIGHTINV bzw. eMouseLeftInv/eMouseRightInv.
Use gopher repellent on funny little man
Benutzeravatar
DieFüchsin
Adventure-Gott
Adventure-Gott
Beiträge: 4406
Registriert: 12.03.2004, 16:55

Beitrag von DieFüchsin »

Hmm ich habe im Handbuch deinen Hinweis nachgeschlagen:
"on_mouse_click (int button)
Called when the player clicks a mouse button. BUTTON is either LEFT, RIGHT or MIDDLE, depending on which button was clicked.
[...]
If 'Handle inventory clicks in script' is enabled in the game options, this function can also be called with
LEFTINV or RIGHTINV, which indicate a left or right click on an inventory item, respectively."

Soweit ich das verstehe, überprüft dies, ob ein Inventargegenstand angeklickt wird.

Ich möchte aber überprüfen, welcher Gegenstand gerade aktiv ist, mit dem ein anderer angeklickt wurde,
was ja eigentlich mit activeinv funktionieren müsste. Ich habe jedenfalls keine entsprechende Funktion gefunden.

Hier mal mein Script, vielleicht liegt der Fehler ja darin:

// script for inventory2: Interact inventory item
if (character[EGO].activeinv==8){
DisplaySpeech(EGO, "In meiner hohlen Hand kann ich die beiden Zutaten nicht vermischen.");}
else{
if (character[EGO].activeinv==13){
DisplaySpeech(EGO, "In meiner hohlen Hand kann ich die beiden Zutaten nicht vermischen.");}
else{
if (character[EGO].activeinv==22){
DisplaySpeech(EGO, "In meiner hohlen Hand kann ich die beiden Zutaten nicht vermischen.");}
else{
if (character[EGO].activeinv==23){
DisplaySpeech(EGO, "So rum wird das nichts.");}
else{
kombiniere=Random(4);
if(kombiniere==0){DisplaySpeech(EGO, "Nein.");}
if(kombiniere==1){DisplaySpeech(EGO, "Ich w'sste nicht, was das bringen sollte.");}
if(kombiniere==2){DisplaySpeech(EGO, "Diese Dinge passen nicht zusammen.");}
if(kombiniere==3){DisplaySpeech(EGO, "Das kann man nicht miteinander kombinieren.");}
if(kombiniere==4){DisplaySpeech(EGO, "Das ergibt so keinen Sinn.");}}}}}

Ich hoffe, ich muss nicht den Interaction-Editor benutzen... das wär nämlich ne ganz schöne Klickerei.

P.S.: ich benutze 2.62
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Am Besten schreibst Du eine eigene Funktion.

Hier das Script fürs Item (benutze else if, dass ist übersichtlicher, und die geschweiften Klammern brauchst Du nur, wenn Du mehrere Befehle konditional ausführen willst):

Code: Alles auswählen

  // script for inventory2: Interact inventory item
  int ai=character[EGO].activeinv;
  if (ai==8 || ai==13 || ai==22)
    DisplaySpeech(EGO, "In meiner hohlen Hand kann ich die beiden Zutaten nicht vermischen.");
  else if (ai==23)
    DisplaySpeech(EGO, "So rum wird das nichts.");
  else
    cannot();                             // <- hier die neue Funktion
Du musst jetzt nur diese Funktion aufrufen, statt immer wieder den gleichen Code einzufügen.

Und im global script:

Code: Alles auswählen

function cannot() {             // diese Funktion sollte ganz an den Anfang
  int kombiniere=Random(4);
    if(kombiniere==0) DisplaySpeech(EGO, "Nein.");
    if(kombiniere==1) DisplaySpeech(EGO, "Ich w'sste nicht, was das bringen sollte.");
    if(kombiniere==2) DisplaySpeech(EGO, "Diese Dinge passen nicht zusammen.");
    if(kombiniere==3) DisplaySpeech(EGO, "Das kann man nicht miteinander kombinieren.");
    if(kombiniere==4) DisplaySpeech(EGO, "Das ergibt so keinen Sinn.");
}
...
...
function on_mouse_click (int button) {
  int x=mouse.x;
  int y=mouse.y;
  ...
  ...
  else if (button==LEFTINV) {
    int clicked_item=GetInvAt(x, y);
    int ai=player.activeinv;
    if (ai>0 && ai!=clicked_item) {   // Item mit einem anderen benutzen
      if (IsInventoryInteractionAvailable(clicked_item, MODE_USEINV)==0)     // keine Use Inventory-Interaction definiert
        cannot();
      else if (ai==-1)
        ProcessClick(x, y, GetCursorMode());
    }
    else
      ProcessClick(x, y, GetCursorMode());
  }
  ...
}
Der Vorteil dieser Methode ist, dass Du bei Items, bei denen jegliches "Benutze [irgendwas] mit Item" sinnlos ist (Streichholz, Stift o.ä.) die Use inventory on inv-Interaction einfach leerlassen kannst, und trotzdem wird eine der zufälligen Mitteilungen ausgegeben.
(Die cannot()-Funktion muss übrigens nicht ex-/importiert werden, da Inventory-bezogener Code auch im global script landet.)

Statt meinem LEFTINV-Code kannst Du auch die folgende Funktion im global script einfügen:
(AGS ruft sie auf, wenn keine entsprechenden Interactions existieren, Erklärung im helpfile unter Reference -> Text script event reference)

Code: Alles auswählen

unhandled_event(int what, int type) {
  ...
  else if (what==5) {
    ...
    else if (type==3)
      cannot();
    ...
  }
}
Meine Version ignoriert allerdings das Benutzen eines Items mit sich selbst.
Use gopher repellent on funny little man
Benutzeravatar
DieFüchsin
Adventure-Gott
Adventure-Gott
Beiträge: 4406
Registriert: 12.03.2004, 16:55

Beitrag von DieFüchsin »

Ehrlich gesagt blick ich durch deine Zeilen nicht ganz durch, was muss wo genau im Global Script hin?
Was hast du weggelassen, wo du die "..." gesetzt hast? Sorry, ich bin noch nicht so der checker, was Programmieren angeht,
ich leb von dem, was ich mir abguck und was vom C++ Unterricht hängen geblieben ist.

Wozu ist die Funktion on_mouse_click eigentlich da, reicht es nicht, wenn ich nur die oben geschriebenen Zeilen (einschl der
Funktion "cannot") benutze?
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

"..." steht für vorhandenen Code.
In der on_mouse_click steht dort z.B., was bei einem Links- oder Rechtsklick gemacht wird, das wollte ich natürlich nicht nochmal alles abschreiben.

Theoretisch reicht natürlich die cannot()-Funktion.

Der Rest dient nur dazu, dir zusätzliche Arbeit zu ersparen.
Wenn Inventory Item A mit Inventory Item B benutzt wird, dann ist player.activeinv=A und die "Use Inventory on inv" von B wird aufgerufen. Soweit klar, oder?
Wenn das aber bei bestimmten Items B nie zu etwas führt, egal was für ein Item A ist, dann musst Du bei allen diesen B ein cannot() einfügen.
Mit meinem Skript musst Du das nicht, da der Klick schon vorher abgefangen und bearbeitet wird.

Wie gesagt, unhandled_event reicht theoretisch, meine Version erkennt es halt, wenn A=B.

Die "..." in der unhandled_event beziehen sich auf die anderen Ereignisse, bei denen diese Funktion aufgerufen wird. Siehe hier.
5, 3 steht für "Use an inventory item on another", idealerweise wird jede Aktion, für die keine Interactions existieren hier entsprechend kommentiert.
Use gopher repellent on funny little man
Benutzeravatar
DieFüchsin
Adventure-Gott
Adventure-Gott
Beiträge: 4406
Registriert: 12.03.2004, 16:55

Beitrag von DieFüchsin »

achso, ich glaube, so ausführlich brauche ich das gar nicht, mir reicht die cannot-meldung nur bei den Objekten

danke dir!
Benutzeravatar
KhrisMUC
Adventure-Gott
Adventure-Gott
Beiträge: 4674
Registriert: 14.03.2005, 00:55
Wohnort: München

Beitrag von KhrisMUC »

Kein Problem.

Aber nur als Tip:
Dir mag es reichen, aber für den Spieler ist es sehr frustrierend, wenn er Sachen ausprobiert und nichtmal eine "Das geht so nicht"-Meldung erhält. So etwas wirkt immer unprofessionell und lieblos.
Mit der unhandled_event lässt sich das sehr einfach und gründlich lösen.
Use gopher repellent on funny little man
Benutzeravatar
DieFüchsin
Adventure-Gott
Adventure-Gott
Beiträge: 4406
Registriert: 12.03.2004, 16:55

Beitrag von DieFüchsin »

Hm nun ja bei den Objekten außerhalb des Inventars hab ich noch keine "Fehlermeldung" eingebaut. Das sollte ich wohl noch machen.

Danke nochmal für deine Hinweise, sie haben das ganze etwas Übersichtlicher gemacht...
Antworten