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