RMVX Ace: Schließen der Textbox erzwingen (extern über Skript-Befehl)
Ich arbeite gerade an einem kleinen Projekt, das während der Aufführung einer Oper spielt. Der Spieler darf während der Vorstellung hinter den Kulissen herumrennen und mit den einzelnen Sängern interagieren, die gerade nicht auf der Bühne zu sehen sind. Das Ganze findet in Echtzeit statt; die Musik ist also der Taktgeber. Das Problem: Während eines Gesprächs kann es vorkommen, dass der Gesprächspartner dringend wieder auf die Bühne muss. Falls der Spieler so gemein ist und seinen Text nicht weiterklickt, ist sein Gegenüber quasi in der Textbox gefangen.
Die gewünschte Lösung: Ein Event, das in einem Parallel Process läuft, beendet zum nötigen Zeitpunkt das Gespräch und zwingt die Textbox, sich zu schließen. Funktioniert auch alles wie geplant, ich komme bloß nicht darauf, welchen dämmlichen Skriptbefehl ich eingeben muss, damit die Textbox geschlossen wird. Hat jemand einen Plan?
Um Nachfragen vorzubeugen:
1. Ich könnte natürlich feste Zeiten vorgeben, nach denen sich die einzelnen Textfenster automatisch schließen, will dem Spieler allerdings die Möglichkeit lassen, selbst zu entscheiden, wie schnell er sich durch die Dialoge klicken will.
2. Eine andere Möglichkeit wäre es natürlich, den Gesprächspartner einfach abhauen zu lassen und den Spieler mit seiner Textbox im Regen stehen zu lassen (das Gespräch endet dann trotzdem, sobald der Text weitergeklickt wird); das finde ich jedoch etwas holprig.
3. Grundsätzlich funktioniert es bereits, dass der Script-Befehl während der Textanzeige aufgerufen wird (der parallel process befindet sich in einem loop), das sehe ich daran, dass sich das Spiel manchmal mit entsprechenden Fehlermeldungen aufhängt, wenn ich totalen Mist in das Skriptfenster geschreiben habe.
Nach ein wenig ausprobieren kam ich auf folgende Lösung.
Auch wenn diese nicht sonderlich hübsch ist und es wahrscheinlich auch besser geht muss ich leider sagen, dass das System mit welchem der VX Messages verwaltet übertrieben kompliziert und wenig kontrollierbar ist.
Du müsstest in der Klasse "Scene_Map" folgende Methode hinzufügen:
Ein Aufruf dieser Methode wird leider nicht alle messages entfernen welche hintereinander kommen könnten sondern lediglich die derzeit laufende Message.
Du kannst diese Methode innerhalb eines Events aufrufen lassen mit folgendem Script:
Ich hoffe das kann dir soweit helfen, vielleicht meldet sich bald noch jemand mit einem besseren Vorschlag.
Ui. Das ging ja flott. Leider funktioniert die Methode nur mit RGSS2. Ich brauche jedoch eine RGSS3-Variante für den VX Ace. Ich habe kurz überlegt, ob ich doch noch auf den VX umschwenken soll, aber der bietet keine Funktion, die aktuelle Position der Sounddatei auszulesen, was für dieses Projekt unumgänglich ist. Ich hoffe, du hast dir dafür nicht die Nacht um die Ohren geschlagen.
Ah, verstehe. Nein, ich habe nicht lange daran gearbeitet.
Aber den Ace besitze ich leider nicht daher kann ich dir wahrscheinlich nicht helfen.
Doch du könntest das Script für "Window_Message" und "Game_Message" hier einmal komplett hinein kopieren und vielleicht lässt sich dann etwas machen.
Okay hier ist der RGSS3 Code. Zerbrich dir aber bitte nicht zu sehr deinen Kopf. Ich habe jetzt schon ein schlechtes Gewissen, auch wenn du sagst, dass du nicht so lange daran gearbeitet hast.
(Ach so, wichtig ist außerdem, dass das choice window ebenfalls geschlossen wird. Da einen workaround zu basteln ist nämlich noch krümeliger als für ein normales Gespräch - und ein großer Teil der Gespräche wird über choices stattfinden.)
Ich kann es verständlicherweise nicht ausprobieren, aber zuallererst würde ich dir raten zu versuchen "$game_message.clear" in deinem Event als Script aufzurufen.
Falls das noch nicht das gewünschte Ergebnis liefert musst du, wie in meinem letzten Code-Beispiel, eine neue Funktion in der "Scene_Map" erstellen und etwas in der Richtung ausprobieren:
Oder ähnliches. (Ich weis nicht genau wie das Message_Window in der Szene genannt wird.)
Falls dies zu einem Fehler führt dann melde dich bitte nocheinmal und zeig uns den Fehlertext.
Ich habe den RMVX Ace auch nicht, kann daher also auch nur spekulieren. Wäre mal cool wenn jemand die Help-Datei und die Scripte (also die scripts.rxdata) irgendwo hochlädt (weiß leider nicht ob das legal ist). Vor allem die Methode process_character, die hier für das Verständnis wichtig ist, ist nicht im Script (vermutlich steht sie in der Window_Base Klasse).
Mein Vorschlag wäre folgendes in den Scripteditor über Main einzufügen:
Ist ein übler Hack, aber besser krieg ich es nicht hin ohne genau zu wissen was da passiert (wofür mir die anderen Scripte fehlen). Mit dem Aufruf von
werden alle Messages abgebrochen.
Das generelle Problem ist, dass die RGSS3 offenbar viel mit Fibern arbeitet. Das verändert (und vereinfacht in gewisser Weise) den Kontrollfluss im Programm, führt aber auch dazu das viele Dinge plötzlich anders angegangen werden müssen als in den früheren RGSS. In diesem Fall ist es z.B. so, dass die Messagebox sich einmal den anzuzeigenden Text holt und diesen dann auch gnadenlos prozessiert, ohne das man am Text noch was nachträglich ändern kann.
Eine andere mögliche Herangehensweise wäre wohl den fiber zu überschreiben:
Vorgehensweise ist die selbe wie oben.
Du kannst beide Varianten ausprobieren - vielleicht funktioniert ja eine ^^
Funktioniert leider alles nicht. Fehlermeldung wird auch nicht ausgegeben; es passiert einfach gar nichts. Trotzdem vielen Dank für euren Einsatz. (Wollte das jetzt eigentlich mit einem tollen Smiley bekräftigen, aber hier hat offensichtlich das große Smiley-Sterben stattgefunden.)
@Cornix: Interessanterweise hatte ich die gleiche Methode letzte Nacht bereits ausprobiert, und sofort wieder vergessen. Als ich deinen Code einfügen wollte, stand er schon da.
@KD: Ich glaube nicht, dass man damit rechtliche Probleme bekommt. Schließlich ist die Trial-Version auch legal. Daher: >>Download<<
Die Trial-Version gibt's übrigens hier: http://www.rpgmakerweb.com/download. Ich glaube die funktioniert 30 Tage ohne Einschränkungen. Ich habe direkt ohne Trial zugeschlagen. Bin rpg-maker-Sammler.
Das Problem (weshalb auch nie eine Fehlermeldung kommt) liegt darin, dass während des Anzeigens einer Message keine Events im Hintergrund ablaufen dürfen. Darum wird dein PP nie ausgeführt. Ich habe jetzt die Möglichkeit eingebaut, einem Parallelen Prozess zu sagen, dass er auch während einer Message ausgeführt werden darf. Hierfür musst du als ersten Event-Command ein Comment mit folgendem Inhalt in das Event einfügen.
(Groß- und Kleinschreibung ist egal, das ! muss aber an den Anfang)
Ansonsten funktioniert mein Script zwar, ich habe aber gemerkt das dieses "Die nächste Message wird wieder angezeigt" etwas unflexibel ist. Evtl. willst du ja, das nicht nur eine sondern mehrere Textboxen geschlossen werden. Daher habe ich drei Methoden eingebaut:
Waaahhh! Es funktioniert! Vielen Dank. Wenn ich dir im Gegenzug etwas Gutes tun kann, nur raus damit.
Zitat
Das Problem (weshalb auch nie eine Fehlermeldung kommt) liegt darin, dass während des Anzeigens einer Message keine Events im Hintergrund ablaufen dürfen.
...
Hey! Ich mag zwar ein Rubystheniker sein, aber auf der Event-Ebene bin ich relativ fit. Ich habe alle PPs in einen loop gepackt. Dann laufen sie auch, wenn die Messages angezeigt werden. Es kann aber sein, dass ich beim Rumtesten eine Änderung vorgenommen habe, die dazu geführt hat dass der PP sich im Kreis gedreht hat und (da er im Loop steckte) das komplette Spiel aufgehängt hat. Ich war heute Nachmittag ziemlich unkonzentriert, weil Julie (der Hund aus UiD - mittlerweile 14 Jahre alt) einen Schlaganfall hatte und nicht mehr laufen konnte. Ich konnte sie aber nicht mal zum Tierarzt schleppen, weil ich auf meinen Sohn (8 Monate) aufpassen musste und Libra das Auto hatte.
Eine Merkwürdigkeit ist mir allerdings aufgefallen: Ich habe den Befehl $game_message.break_current_message verwendet. Der Aufbau des Testbereichs sieht etwa so aus:
Event Gesprächpartner (Action Button): Auf Klick: Message: "Jetzt geht gar nichts mehr", zweiter Klick: "Was zu beweisen war": Dazwischen ein
Event PP: Wartet bis Variable bestimmten Wert erreicht. Wenn der Wert erreicht ist, kommt der skript Befehl und danach ein Move Befehl für das Gesprächspartner Event, dass es sich schleunigst entfernen soll (so sehe ich auch, dass der Skript Befehl eingegeben wurde). Dann direkt eine weitere Message: "Keine Zeit, Alter!"
Beim ersten Test war bei dem Move Befehl "Wait until Completion" angegeben, was natürlich dazu geführt hat, dass "Keine Zeit, Alter" erst angezeigt wurde, nachdem der Move ausgeführt war. Die Messagebox hat sich davor korrekt geschlossen.
Beim zweiten Test habe ich "Wait until Completion" entfernt. Ergebnis: Die Message schließt sich nicht.
Beim dritten Test habe ich nach dem Skript Befehl einen wait von einem Frame eingefügt. Die Message schließt sich und öffnet sich sofort wieder, mit dem Hinweis: "Keine Zeit, Alter"
EDIT: Es gibt doch noch ein Problem: Choices werden im VX Ace in einem externen Fenster angezeigt. Dieses Fenster schließt sich bei deinem Script jedoch nicht. Ich, nicht doof aber nicht schlau genug, hab dann einfach unter @gold_window_close ein @choice_window_close eingefügt, was dazu führt, dass das choice window sich tatsächlich schließt, aber gleich wieder aufgeht. Das wartet offensichtlich auf seinen Input. Hrrrmblxxxxx.
Kannst du da noch was drehen? (Und wieder fehlt der Smiley mit den Bambi-Augen.)
Okay, du hast Recht: Während des Anzeigens einer Message darf kein neues Event gestartet werden (bereits laufende dürfen aber weiterlaufen, es sei denn sie führen bestimmte Befehle aus, die nicht während einer Message ausgeführt werden dürfen, z.B. ein weiteres Show Message). Wenn du also in einem Event einen Switch setzt, der einen neuen PP aktiviert, und danach eine Message kommt ohne das zuvor ein wait Befehl gesetzt ist, wird das PP nicht ausgeführt. Achtung: Dieser Wait sollte mindestens 2 sein, sonst wird das Event unter Umständen gleich wieder ausgeführt bevor das neue Event zum Zuge kam.
Wenn du das beachtest brauchst du auch diesen Umweg mit dem !RunWhileMessage nicht mehr.
Ich hab das Script mal entsprechend radikal gekürzt, so dass es nur noch eine Funktion innehat: Alle gerade ablaufenden Messages und Choices zu unterbrechen. Ich verstehe dich so, dass du den Rest möglichst mit Event-Code lösen willst (z.B. in dem vor jedem Anzeigen einer Message per Conditional Branch abgeprüft wird, ob der NPC überhaupt noch da ist).
Hier der (gekürzte und korrigierte) Code:
Aufrufbar mit
Und wie gesagt: Neue Events werden nicht abgearbeitet, solange eine Message läuft. Welche Event-.Befehle noch blockieren bekommst du raus, wenn du im Game_Interpreter mal nach Aufrufen von "wait_for_message" suchst (sind in der Regel nur Message-bezogene Befehle).