PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RMVX Ace: Schließen der Textbox erzwingen (extern über Skript-Befehl)



Grandy
02.04.2012, 02:31
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.

Cornix
02.04.2012, 07:06
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:

def end_message_instantly
$game_message.main_proc.call if $game_message.main_proc != nil
$game_message.clear
@message_window.finish_message
@message_window.terminate_message
end
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:

$scene.end_message_instantly


Ich hoffe das kann dir soweit helfen, vielleicht meldet sich bald noch jemand mit einem besseren Vorschlag.

Grandy
02.04.2012, 22:19
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.

Cornix
02.04.2012, 23:12
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.

Grandy
02.04.2012, 23:54
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.)

Game_Message:

#==============================================================================
# ** Game_Message
#------------------------------------------------------------------------------
# This class handles the state of the message window that displays text or
# selections, etc. The instance of this class is referenced by $game_message.
#==============================================================================

class Game_Message
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :texts # text array (in rows)
attr_reader :choices # choice array
attr_accessor :face_name # face graphic filename
attr_accessor :face_index # face graphic index
attr_accessor :background # background type
attr_accessor :position # display position
attr_accessor :choice_proc # show choices: call back (Proc)
attr_accessor :choice_cancel_type # show choices: cancel
attr_accessor :num_input_variable_id # input number: variable ID
attr_accessor :num_input_digits_max # input number: digit count
attr_accessor :item_choice_variable_id # item selection: variable ID
attr_accessor :scroll_mode # scroll text flag
attr_accessor :scroll_speed # scroll text: speed
attr_accessor :scroll_no_fast # scroll text: disable fast forward
attr_accessor :visible # displaying a message
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
clear
@visible = false
end
#--------------------------------------------------------------------------
# * Clear
#--------------------------------------------------------------------------
def clear
@texts = []
@choices = []
@face_name = ""
@face_index = 0
@background = 0
@position = 2
@choice_cancel_type = 0
@choice_proc = nil
@num_input_variable_id = 0
@num_input_digits_max = 0
@item_choice_variable_id = 0
@scroll_mode = false
@scroll_speed = 2
@scroll_no_fast = false
end
#--------------------------------------------------------------------------
# * Add Text
#--------------------------------------------------------------------------
def add(text)
@texts.push(text)
end
#--------------------------------------------------------------------------
# * Determine Existence of Text
#--------------------------------------------------------------------------
def has_text?
@texts.size > 0
end
#--------------------------------------------------------------------------
# * Determine if Choices Mode
#--------------------------------------------------------------------------
def choice?
@choices.size > 0
end
#--------------------------------------------------------------------------
# * Determine if Number Input Mode
#--------------------------------------------------------------------------
def num_input?
@num_input_variable_id > 0
end
#--------------------------------------------------------------------------
# * Determine if Item Selection Mode
#--------------------------------------------------------------------------
def item_choice?
@item_choice_variable_id > 0
end
#--------------------------------------------------------------------------
# * Determine if Busy
#--------------------------------------------------------------------------
def busy?
has_text? || choice? || num_input? || item_choice?
end
#--------------------------------------------------------------------------
# * New Page
#--------------------------------------------------------------------------
def new_page
@texts[-1] += "\f" if @texts.size > 0
end
#--------------------------------------------------------------------------
# * Get All Text Including New Lines
#--------------------------------------------------------------------------
def all_text
@texts.inject("") {|r, text| r += text + "\n" }
end
end


Window_Message


#==============================================================================
# ** Window_Message
#------------------------------------------------------------------------------
# This message window is used to display text.
#==============================================================================

class Window_Message < Window_Base
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
super(0, 0, window_width, window_height)
self.z = 200
self.openness = 0
create_all_windows
create_back_bitmap
create_back_sprite
clear_instance_variables
end
#--------------------------------------------------------------------------
# * Get Window Width
#--------------------------------------------------------------------------
def window_width
Graphics.width
end
#--------------------------------------------------------------------------
# * Get Window Height
#--------------------------------------------------------------------------
def window_height
fitting_height(visible_line_number)
end
#--------------------------------------------------------------------------
# * Clear Instance Variables
#--------------------------------------------------------------------------
def clear_instance_variables
@fiber = nil # Fiber
@background = 0 # Background type
@position = 2 # Display position
clear_flags
end
#--------------------------------------------------------------------------
# * Clear Flag
#--------------------------------------------------------------------------
def clear_flags
@show_fast = false # Fast forward flag
@line_show_fast = false # Fast forward by line flag
@pause_skip = false # Input standby omission flag
end
#--------------------------------------------------------------------------
# * Get Number of Lines to Show
#--------------------------------------------------------------------------
def visible_line_number
return 4
end
#--------------------------------------------------------------------------
# * Free
#--------------------------------------------------------------------------
def dispose
super
dispose_all_windows
dispose_back_bitmap
dispose_back_sprite
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
update_all_windows
update_back_sprite
update_fiber
end
#--------------------------------------------------------------------------
# * Update Fiber
#--------------------------------------------------------------------------
def update_fiber
if @fiber
@fiber.resume
elsif $game_message.busy? && !$game_message.scroll_mode
@fiber = Fiber.new { fiber_main }
@fiber.resume
else
$game_message.visible = false
end
end
#--------------------------------------------------------------------------
# * Create All Windows
#--------------------------------------------------------------------------
def create_all_windows
@gold_window = Window_Gold.new
@gold_window.x = Graphics.width - @gold_window.width
@gold_window.y = 0
@gold_window.openness = 0
@choice_window = Window_ChoiceList.new(self)
@number_window = Window_NumberInput.new(self)
@item_window = Window_KeyItem.new(self)
end
#--------------------------------------------------------------------------
# * Create Background Bitmap
#--------------------------------------------------------------------------
def create_back_bitmap
@back_bitmap = Bitmap.new(width, height)
rect1 = Rect.new(0, 0, width, 12)
rect2 = Rect.new(0, 12, width, height - 24)
rect3 = Rect.new(0, height - 12, width, 12)
@back_bitmap.gradient_fill_rect(rect1, back_color2, back_color1, true)
@back_bitmap.fill_rect(rect2, back_color1)
@back_bitmap.gradient_fill_rect(rect3, back_color1, back_color2, true)
end
#--------------------------------------------------------------------------
# * Get Background Color 1
#--------------------------------------------------------------------------
def back_color1
Color.new(0, 0, 0, 160)
end
#--------------------------------------------------------------------------
# * Get Background Color 2
#--------------------------------------------------------------------------
def back_color2
Color.new(0, 0, 0, 0)
end
#--------------------------------------------------------------------------
# * Create Background Sprite
#--------------------------------------------------------------------------
def create_back_sprite
@back_sprite = Sprite.new
@back_sprite.bitmap = @back_bitmap
@back_sprite.visible = false
@back_sprite.z = z - 1
end
#--------------------------------------------------------------------------
# * Free All Windows
#--------------------------------------------------------------------------
def dispose_all_windows
@gold_window.dispose
@choice_window.dispose
@number_window.dispose
@item_window.dispose
end
#--------------------------------------------------------------------------
# * Free Background Bitmap
#--------------------------------------------------------------------------
def dispose_back_bitmap
@back_bitmap.dispose
end
#--------------------------------------------------------------------------
# * Free Background Sprite
#--------------------------------------------------------------------------
def dispose_back_sprite
@back_sprite.dispose
end
#--------------------------------------------------------------------------
# * Update All Windows
#--------------------------------------------------------------------------
def update_all_windows
@gold_window.update
@choice_window.update
@number_window.update
@item_window.update
end
#--------------------------------------------------------------------------
# * Update Background Sprite
#--------------------------------------------------------------------------
def update_back_sprite
@back_sprite.visible = (@background == 1)
@back_sprite.y = y
@back_sprite.opacity = openness
@back_sprite.update
end
#--------------------------------------------------------------------------
# * Main Processing of Fiber
#--------------------------------------------------------------------------
def fiber_main
$game_message.visible = true
update_background
update_placement
loop do
process_all_text if $game_message.has_text?
process_input
$game_message.clear
@gold_window.close
Fiber.yield
break unless text_continue?
end
close_and_wait
$game_message.visible = false
@fiber = nil
end
#--------------------------------------------------------------------------
# * Update Window Background
#--------------------------------------------------------------------------
def update_background
@background = $game_message.background
self.opacity = @background == 0 ? 255 : 0
end
#--------------------------------------------------------------------------
# * Update Window Position
#--------------------------------------------------------------------------
def update_placement
@position = $game_message.position
self.y = @position * (Graphics.height - height) / 2
@gold_window.y = y > 0 ? 0 : Graphics.height - @gold_window.height
end
#--------------------------------------------------------------------------
# * Process All Text
#--------------------------------------------------------------------------
def process_all_text
open_and_wait
text = convert_escape_characters($game_message.all_text)
pos = {}
new_page(text, pos)
process_character(text.slice!(0, 1), text, pos) until text.empty?
end
#--------------------------------------------------------------------------
# * Input Processing
#--------------------------------------------------------------------------
def process_input
if $game_message.choice?
input_choice
elsif $game_message.num_input?
input_number
elsif $game_message.item_choice?
input_item
else
input_pause unless @pause_skip
end
end
#--------------------------------------------------------------------------
# * Open Window and Wait for It to Fully Open
#--------------------------------------------------------------------------
def open_and_wait
open
Fiber.yield until open?
end
#--------------------------------------------------------------------------
# * Close Window and Wait for It to Fully Close
#--------------------------------------------------------------------------
def close_and_wait
close
Fiber.yield until all_close?
end
#--------------------------------------------------------------------------
# * Determine if All Windows Are Fully Closed
#--------------------------------------------------------------------------
def all_close?
close? && @choice_window.close? &&
@number_window.close? && @item_window.close?
end
#--------------------------------------------------------------------------
# * Determine Whether to Continue Displaying Text
#--------------------------------------------------------------------------
def text_continue?
$game_message.has_text? && !settings_changed?
end
#--------------------------------------------------------------------------
# * Determine if Background and Position Changed
#--------------------------------------------------------------------------
def settings_changed?
@background != $game_message.background ||
@position != $game_message.position
end
#--------------------------------------------------------------------------
# * Wait
#--------------------------------------------------------------------------
def wait(duration)
duration.times { Fiber.yield }
end
#--------------------------------------------------------------------------
# * Update Fast Forward Flag
#--------------------------------------------------------------------------
def update_show_fast
@show_fast = true if Input.trigger?(:C)
end
#--------------------------------------------------------------------------
# * Wait After Output of One Character
#--------------------------------------------------------------------------
def wait_for_one_character
update_show_fast
Fiber.yield unless @show_fast || @line_show_fast
end
#--------------------------------------------------------------------------
# * New Page
#--------------------------------------------------------------------------
def new_page(text, pos)
contents.clear
draw_face($game_message.face_name, $game_message.face_index, 0, 0)
reset_font_settings
pos[:x] = new_line_x
pos[:y] = 0
pos[:new_x] = new_line_x
pos[:height] = calc_line_height(text)
clear_flags
end
#--------------------------------------------------------------------------
# * Get New Line Position
#--------------------------------------------------------------------------
def new_line_x
$game_message.face_name.empty? ? 0 : 112
end
#--------------------------------------------------------------------------
# * Normal Character Processing
#--------------------------------------------------------------------------
def process_normal_character(c, pos)
super
wait_for_one_character
end
#--------------------------------------------------------------------------
# * New Line Character Processing
#--------------------------------------------------------------------------
def process_new_line(text, pos)
@line_show_fast = false
super
if need_new_page?(text, pos)
input_pause
new_page(text, pos)
end
end
#--------------------------------------------------------------------------
# * Determine if New Page Is Needed
#--------------------------------------------------------------------------
def need_new_page?(text, pos)
pos[:y] + pos[:height] > contents.height && !text.empty?
end
#--------------------------------------------------------------------------
# * New Page Character Processing
#--------------------------------------------------------------------------
def process_new_page(text, pos)
text.slice!(/^\n/)
input_pause
new_page(text, pos)
end
#--------------------------------------------------------------------------
# * Icon Drawing Process by Control Characters
#--------------------------------------------------------------------------
def process_draw_icon(icon_index, pos)
super
wait_for_one_character
end
#--------------------------------------------------------------------------
# * Control Character Processing
# code : the core of the control character
# e.g. "C" in the case of the control character \C[1].
# text : character string buffer in drawing processing (destructive)
# pos : draw position {:x, :y, :new_x, :height}
#--------------------------------------------------------------------------
def process_escape_character(code, text, pos)
case code.upcase
when '$'
@gold_window.open
when '.'
wait(15)
when '|'
wait(60)
when '!'
input_pause
when '>'
@line_show_fast = true
when '<'
@line_show_fast = false
when '^'
@pause_skip = true
else
super
end
end
#--------------------------------------------------------------------------
# * Input Pause Processing
#--------------------------------------------------------------------------
def input_pause
self.pause = true
wait(10)
Fiber.yield until Input.trigger?(:B) || Input.trigger?(:C)
Input.update
self.pause = false
end
#--------------------------------------------------------------------------
# * Choice Input Processing
#--------------------------------------------------------------------------
def input_choice
@choice_window.start
Fiber.yield while @choice_window.active
end
#--------------------------------------------------------------------------
# * Number Input Processing
#--------------------------------------------------------------------------
def input_number
@number_window.start
Fiber.yield while @number_window.active
end
#--------------------------------------------------------------------------
# * Item Selection Processing
#--------------------------------------------------------------------------
def input_item
@item_window.start
Fiber.yield while @item_window.active
end
end

Cornix
03.04.2012, 10:57
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:

def end_message_instantly
$game_message.clear
@window_message.clear_instance_variables
@window_message.close_and_wait
end
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.

-KD-
03.04.2012, 13:44
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:

module BreakTextDisplay
def process_character character, text, pos
if $game_message.break_display_text
text.clear
else
super
end
end
end
class Window_Message
include BreakTextDisplay
end
class Game_Message
attr_reader :break_display_text
def break
@break_display_text = true
@texts.clear
end
alias add_text add
def add *args
@break_display_text = false
add_text *args
end
end
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

$game_message.break
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:

module BreakTextDisplay
def update
super
if $game_message.break_display_text
@fiber &&= Fiber.new do
@gold_window.close
close_and_wait
$game_message.visible = false
@fiber = nil
end
end
end
end
class Window_Message
include BreakTextDisplay
end
class Game_Message
attr_reader :break_display_text
def break
@break_display_text = true
@texts.clear
end
alias add_text add
def add *args
@break_display_text = false
add_text *args
end
end
Vorgehensweise ist die selbe wie oben.

Du kannst beide Varianten ausprobieren - vielleicht funktioniert ja eine ^^

Grandy
03.04.2012, 17:35
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<< (http://ingmar-hahnemann.de/maker/ace.zip)
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.

-KD-
03.04.2012, 19:04
Ah okay, damit kann ich ja was anfangen.

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.

!RunWhileMessage
(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:


# Messages werden ab jetzt nicht mehr angezeigt. Bereits angezeigte Messages
# werden ausgeblendet
$game_message.dont_display_messages
# Messages werden ab jetzt wieder angezeigt
$game_message.continue_display_messages
# blendet die aktuelle Message aus, zeigt die nächste aber wieder an
$game_message.break_current_message

Der Code ist hier (über Main einfügen):

module BreakTextDisplay
def update
super
if $game_message.break_display_text
@fiber &&= Fiber.new do
@gold_window.close
close_and_wait
$game_message.visible = false
@fiber = nil
end
end
end
end
class Window_Message
include BreakTextDisplay
end
class Game_Message
attr_reader :break_display_text
def dont_display_messages
@break_display_text = :dont_display
@texts.clear
end
def break_current_message
@break_display_text = :break_current
@texts.clear
end
def continue_display_messages
@break_display_text = nil
end
alias add_new_messages_ifnot_break add
def add *args
return if @break_display_text == :dont_display
if @break_display_text == :break_current
@break_display_text = nil
else
add_new_messages_ifnot_break(*args)
end
end
end
class Game_Interpreter
alias wait_for_message_unless_commented wait_for_message
def wait_for_message
wait_for_message_unless_commented if should_wait_for_message?
end
def should_wait_for_message?
return @should_wait_for_message unless @should_wait_for_message.nil?
return false if @list.nil?
@should_wait_for_message = (@list.reduce("") {|txt, c|
if (c.code == 108 || c.code == 408) then (txt<<c.parameters.first) else break txt end
}) !~ /\!RunWhileMessage/i
end
end

Grandy
03.04.2012, 23:23
Waaahhh! Es funktioniert! Vielen Dank. Wenn ich dir im Gegenzug etwas Gutes tun kann, nur raus damit.


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.)

-KD-
04.04.2012, 23:47
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:

module BreakTextDisplay
def update
super
if (n = $game_message.break_display_text_at) && (Graphics.frame_count <= n)
@fiber &&= Fiber.new do
[@gold_window,@choice_window,@number_window,@item_window].each(&:close)
close_and_wait
$game_message.visible = false
@fiber = nil
end
end
end
end
class Window_Message
include BreakTextDisplay
end
class Game_Message
attr_reader :break_display_text_at
def break_current_message
@break_display_text_at = Graphics.frame_count+1
clear
end
end

Aufrufbar mit

$game_message.break_current_message

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).

Grandy
05.04.2012, 22:04
Funktioniert perfekt! Vielen, vielen Dank! Dummerweise habe ich jetzt keine Ausrede mehr, um das Projekt vor mir herzuschieben - Horrido!