Ergebnis 1 bis 12 von 12

Thema: RMVX Ace: Schließen der Textbox erzwingen (extern über Skript-Befehl)

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1

    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.

  2. #2
    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:
    Code:
      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:
    Code:
    $scene.end_message_instantly

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

  3. #3
    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.

  4. #4
    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.

  5. #5
    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:
    Code:
    #==============================================================================
    # ** 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

    Code:
    #==============================================================================
    # ** 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

  6. #6
    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:
    Code:
    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.

  7. #7
    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:
    Code:
    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
    Code:
    $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:
    Code:
    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 ^^

  8. #8
    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.

  9. #9
    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.
    Code:
    !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:

    Code:
    # 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):
    Code:
    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

  10. #10
    Waaahhh! Es funktioniert! Vielen Dank. Wenn ich dir im Gegenzug etwas Gutes tun kann, nur raus damit.

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

    Geändert von Grandy (04.04.2012 um 11:21 Uhr)

  11. #11
    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:
    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
    Code:
    $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).

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •