Saba Kan's Galge Conversation System 0.7

Discussion in 'RGSS3 Scripts (RMVX Ace)' started by kirinelf, Mar 29, 2012.

    Tags:
  1. kirinelf

    kirinelf *Stare* Veteran

    Messages:
    64
    Likes Received:
    26
    First Language:
    Hakka
    This script was not written by me! I simply translated it from Japanese and posted it here to share! Do NOT ask me for support, I'm not a scripter (I'll try, but most likely fail)!

    Now that that's over. The script I've got for you guys this time is:

    Galge Conversation System

    Version 0.7

    by Saba Kan of

    [​IMG]

    プチレア - PetitRare

    Updated: 2012/01/21


    Email asking for and being granted permission to translate and share:

    kirinelf さんへわざわざメールありがとうございます。

    日本語ですみません。

    もちろん歓迎します、どうぞ翻訳なさってください。

    > http://www.rpgmakervxace.net

    > http://forums.rpgmakerweb.com

    おお! これからもチェックさせていただきます!

    2012年3月26日21:42 Kirin:

    > こんにちは、

    >

    > 僕は英語のRPGVXAのコッムニティからのkirinelf です。キリンで呼びますこと

    > もいいです。あの。。。日本語があまり上手でわありませんですから申し訳あり ません。よろしくおねがいします!

    >

    > 今回のメールの理由はRPGVXAのRGSS3スクリプトを翻訳したいことです。貴方様 のスクリプトを英語に翻訳してもいいでしょうか?もちろん

    > 貴方様の記載もあ ります。自分を書いた事も絶対言いません。

    >

    > 僕の目的は面白そうなスクリプトを翻訳して、このサイトにほかの英語のユーサ と分かち合います:

    >

    > http://www.rpgmakervxace.net

    > http://forums.rpgmakerweb.com

    >

    > そのサイトは英語RPGVXAの一番大きいコッムニティです。

    >

    > お返事を根気よくて待ています。

    >

    > kirinelf (キリン) より。
    The above, translated:

    To kirinelf:Thank you for going out of your way to send an email to me.

    Sorry for this being in Japanese.

    Please be my guest and translate them as you wish.

    > http://www.rpgmakervxace.net

    > http://forums.rpgmakerweb.com

    Oh! I'll be sure to check these sites from now on too!

    2012年3月26日21:42 Kirin:

    > Hello,

    >

    > I am kirinelf from the English speaking RMVXA community. You can call me Kirin.

    > I'm not very good at Japanese, so I apologize for that. Pleased to make your acquaintance!

    >

    > The purpose of this email is to ask about translating RMVXA's RGSS3 scripts. Is it alright

    > to translate your scripts into English? Of course, you will be credited. I will not claim

    > to have written any of your scripts.

    >

    > My aim is to translate scripts I find interesting and to share them with the rest of the

    > English speaking community, namely at these sites:

    >

    > http://www.rpgmakervxace.net

    > http://forums.rpgmakerweb.com

    >

    > These sites are the largest English RMVXA communities.

    >

    > I will await your reply patiently.

    >

    > From kirinelf (Kirin)
    So what does this script do? Well, ever played a visual novel? AIR or Clannad or Fate/Stay Night? Well, maybe not the latter; it uses a different message system, but. Most visual novels use this style of message system. Here're some screenshots so you can get the gist of it (Spoilered for size).

    [​IMG]

    [​IMG]

    [​IMG]

    Message Log screen:

    [​IMG]

    Features

    • Potraits! Have large character potraits ingame.
    • Dynamically adjusts emoticons so you can show them over the head of the character speaking.
    • Has a function that switches windowskins and speech balloon graphic colors so your characters can have their unique message window color.
    • Allows you to have a name display window at the cost of losing a line in message input, or you can turn it off and have four lines at once.
    • Can be set up through common events so you don't have to turn every switch on and off every time.
    • Easily choose whether the potrait is displayed on the left or the right.
    • You can use a key to fast forward through conversations!
    • Sub scripts allow you to hide the message window, access the save menu from within the message, and display a message log.

    There really are quite a few features and setting up shenanigans that you need to be aware of, and for that reason I've included a How to Use text file I wrote up myself after experimenting with the demo that I hope will help you guys.

    There are three scripts: A main script that handles the conversation details such as potrait placements and such, and two sub scripts. The first sub script allows you to have keys that let you hide the message window and/or access the save screen from within the message window. The second subscript lets you access a message log in the Visual Novel style as seen in the screenshots.

    Without further ado, here're the three scripts:

    1. Main script

    Code:
    #==============================================================================
    # ■ Galge Conversation System
    #   @version 0.7 12/02/15 RGSS3
    #   @author Saba Kan
    #   @translator kirinelf (Made a small edit to picture IDs)
    #------------------------------------------------------------------------------
    #  
    #==============================================================================
    module Saba
      module Gal
        # --------------------Config---------------------
    
        # Fine tuning of actor graphic positioning.
        # {Actor ID=>pixels shifted} E.g. {1=>-4} (Actor ID 1's graphic shifted 4 
        # pixels to the left/up)
        OFFSET_X = {1=>0, 2=>-30, 3=>-30, 6=>-40, 7=>-45, 8=>-40}
        OFFSET_Y = {1=>0, 2=>10, 3=>40, 4=>10, 7=>-15, 8=>5}
    
        # This only applies to OFFSET_X above, for displaying character graphics on 
        # the left.
    	  # 座標に -1 をかける場合 true に設定します。
        # If the coordinates above have '-1', set to true. <= ?
        MIRROR_LEFT_OFFSET_X = false
    
        # Speech balloon graphic coordinates.
        BALLOON_LEFT_X = 210  # X Coordinate when it appears on the left.
        BALLOON_RIGHT_X = 300 # X Coordinate when it appears on the right.
        BALLOON_Y = 254       # Y Coordinate
    
        # Name window width. Default of 114 is for a name 4 characters long. 
        NAME_WINDOW_WIDTH = 114
    
        # For skipping text. A is Shift on the keyboard. 
        SKIP_BUTTON = Input::A
    
        # This switch ID disables skipping of the text. 
        SKIP_DISABLE_SWITCH = 131
    
        # This switch changes the message display mode. 
        MESSAGE_MODE_SWITCH = 132
    
        # This switch ID toggles display of the name.
        DISPLAY_NAME_SWITCH = 133
    
        # This switch toggles display of speech balloon graphics. 
        DISPLAY_BALLOON_SWITCH = 134
    
        # This switch clears all speech balloon graphics. 
        CLEAR_BALLOON_SWITCH = 135
    
        # This switch toggles playing of message sound effects. 
        PLAY_MESSAGE_SE_SWITCH = 136
    
        # Variable to determine speech balloon color.
        # ※Will be automatically entered into the variable.
        BALLOON_VARIABLE = 131
    
        # Variable to determine speech balloon location.
        # ※Will be automatically entered into the variable. 
        BALLOON_POSITION_VARIABLE = 132
    
        # If you want character graphics displayed on the right to be mirrored, 
        # set to 'true'.
        MIRROR_LEFT = false
    
        # If you want character graphics displayed on the left to be mirrored, 
        # set to 'true'.
        MIRROR_RIGHT = false
    
        # This setting changes the base picture ID of the potraits. Generally
        # speaking, the lower this is the better. However, some people might use
        # a lot of pictures, and it's a hassle to remember which IDs the script uses.
        # This setting allows you to define the base picture ID of the potraits. 
        # Potraits on the right will have this ID, and potraits on the left will have
        # this ID + 2. For example, the default setting has the picture IDs of 10 
        # and 12.
        BASE_PICTURE_ID = 10
    
        # If you don't want different characters to have different windowskins,
    	  # set to 'true'. 
        # Window1.png and Balloon1.png will be used if 'true'. 
        USE_SINGLE_WINDOW_SKIN = false
    
        # Tone overlay of characters in conversation.
        # Red, Green, Blue, Gray
    	  # Active Character
        ACTIVE_TONE = Tone.new(0, 0, 0, 0)
        # Inactive Character (0, 0, 0, 0) <= No change.
        INACTIVE_TONE = Tone.new(-104, -104, -104, 0)
    
        # Frames to wait after tone change during character switching.
        TONE_CHANGE_DURATION = 17
    
        #  Event Command "Show Balloon Icon" Icon Positioning
        OFFSET_EVENT_BALLOON_X = {1=>0, 2=>0, 3=>-30, 6=>-40, 7=>-45, 8=>-40}
        OFFSET_EVENT_BALLOON_Y = {1=>0, 2=>10, 3=>40, 4=>10, 7=>-15, 8=>5}
      end
    end
    
    #=========================================================================
    # Do not edit anything under this line unless you know what you're doing!
    #=========================================================================
    
    $imported = {} if $imported == nil
    $imported["GalGameTalkSystem"] = true
    
    
    # ピクチャ表示用
    class Game_Interpreter
    
      def pic(name, index, position)
        actor_id = name["actor".length..-1].to_i
        $game_variables[Saba::Gal::BALLOON_POSITION_VARIABLE] = position
        x = picture_base_x(position) + offset_x(position, actor_id)
        y = picture_base_y(position) + offset_y(actor_id)
        $game_variables[Saba::Gal::BALLOON_VARIABLE] = actor_id
        picture = screen.pictures[position + Saba::Gal::BASE_PICTURE_ID]
    
        name = name + "_" + (index + 1).to_s
        @actor1_position = nil if @actor1_position == position
        if Saba::Gal::MIRROR_LEFT && position == 1
          picture.mirror_pic = true
        elsif Saba::Gal::MIRROR_RIGHT && position == 2
          picture.mirror_pic = true
        else
          picture.mirror_pic = false
        end
        picture.show(name, 0, x, y, 100, 100, 255, 0)
        if @actor_id != actor_id 
          picture.start_tone_change(Saba::Gal::INACTIVE_TONE, 0) 
    
          deactivate_other_pictures(position)
          activate(picture, position, actor_id)
        end
        @actor_id = actor_id
      end
      #--------------------------------------------------------------------------
      # ● ピクチャのオフセット位置のx座標取得
      #--------------------------------------------------------------------------
      def offset_x(position, actor_id)
        n = Saba::Gal::OFFSET_X[actor_id]
    
        return 0 if n == nil
        if position == 1 && Saba::Gal::MIRROR_LEFT_OFFSET_X
          return -n
        else
          return n
        end
      end
      #--------------------------------------------------------------------------
      # ● ピクチャのオフセット位置のy座標取得
      #--------------------------------------------------------------------------
      def offset_y(actor_id)
        n = Saba::Gal::OFFSET_Y[actor_id]
        return 0 if n == nil
        return n
      end
      #--------------------------------------------------------------------------
      # ● イベントバルーンのオフセット位置のx座標取得
      #--------------------------------------------------------------------------
      def offset_event_balloon_x(position, actor_id)
        n = Saba::Gal::OFFSET_EVENT_BALLOON_X[actor_id]
        return 0 if n == nil
        if position == 1 && Saba::Gal::MIRROR_LEFT_OFFSET_X
          return -n
        else
          return n
        end
      end
      #--------------------------------------------------------------------------
      # ● イベントバルーンのオフセット位置のy座標取得
      #--------------------------------------------------------------------------
      def offset_event_balloon_y(actor_id)
        n = Saba::Gal::OFFSET_EVENT_BALLOON_Y[actor_id]
        return 0 if n == nil
        return n
      end
      #--------------------------------------------------------------------------
      # ● 指定のピクチャを明るく
      #--------------------------------------------------------------------------
      def activate(picture, position, actor_id)
        if Input.press?(Saba::Gal::SKIP_BUTTON)
          picture.start_tone_change(Saba::Gal::ACTIVE_TONE, 1)
        else
          picture.start_tone_change(Saba::Gal::ACTIVE_TONE, 25)
        end
        $game_temp.pic_actors[position] = actor_id
      end
      #--------------------------------------------------------------------------
      # ● 指定のピクチャ以外を暗く
      #--------------------------------------------------------------------------
      def deactivate_other_pictures(position)
        screen.pictures.size.times do |index|
          next if screen.pictures[index].number == 1
          next if index == position + 10
          deactivate(screen.pictures[index])
        end
      end
      #--------------------------------------------------------------------------
      # ● 指定のピクチャを暗く
      #--------------------------------------------------------------------------
      def deactivate(picture)
        unless Input.press?(Saba::Gal::SKIP_BUTTON)
          picture.start_tone_change(Saba::Gal::INACTIVE_TONE, 25)
        end
      end
      def picture_base_x(position)
        case position
        when 2
          return 25
        when 0
          return Graphics.width - 244
        when 3
          return 200
        end
      end
      def picture_base_y(position)
        return 30
      end
      def act(position)
        $game_variables[Saba::Gal::BALLOON_VARIABLE] = $game_temp.pic_actors[position]
        if position < 3
          $game_variables[Saba::Gal::BALLOON_POSITION_VARIABLE] = position
        end
        picture = screen.pictures[position + 10]
        deactivate_other_pictures(position)
        if Input.press?(Saba::Gal::SKIP_BUTTON)
          picture.start_tone_change(Saba::Gal::ACTIVE_TONE, 1)
          @wait_count = 0
        else
          picture.start_tone_change(Saba::Gal::ACTIVE_TONE, Saba::Gal::TONE_CHANGE_DURATION)
         @wait_count = 0
        end
      end
      def dis(position)
        picture = screen.pictures[position + 10]
        picture.erase
      end
    end
    
    class Scene_Map
      #--------------------------------------------------------------------------
      # ● メッセージウィンドウの作成
      #--------------------------------------------------------------------------
      alias saba_gal_create_message_window create_message_window
      def create_message_window
        saba_gal_create_message_window
        create_gal_window
      end
      #--------------------------------------------------------------------------
      # ● フレーム更新
      #--------------------------------------------------------------------------
      alias saba_gal_update update
      def update
        create_gal_window
        update_gal_event_balloon
        saba_gal_update
      end
      #--------------------------------------------------------------------------
      # ● ギャルゲーウィンドウ作成
      #   ギャルゲーモードの時、ウィンドウを切り替えます。
      #--------------------------------------------------------------------------
      def create_gal_window
        if $game_switches[Saba::Gal::MESSAGE_MODE_SWITCH]
          if ! @message_window.is_a?(Window_MessageGal)
            # ギャルゲーウィンドウにする
            @message_window.dispose
            @message_window = Window_MessageGal.new
          end
        else
          if @message_window.is_a?(Window_MessageGal)
            # 通常ウィンドウに戻す
            @message_window.dispose
            @message_window = Window_Message.new
          end
        end
      end
      def on_a
        p 11
      end
      #--------------------------------------------------------------------------
      # ● ギャルゲーウィンドウのフキダシアイコン作成
      #--------------------------------------------------------------------------
      def create_gal_event_balloon(character)
        dispose_gal_event_balloon
        @saba_balloon_sprite = Sprite_Character.new(@viewport, character)
      end
      #--------------------------------------------------------------------------
      # ● ギャルゲーウィンドウのフキダシアイコン破棄
      #--------------------------------------------------------------------------
      def dispose_gal_event_balloon
        if @saba_balloon_sprite
          @saba_balloon_sprite.dispose
          @saba_balloon_sprite = nil
        end
      end
      #--------------------------------------------------------------------------
      # ● ギャルゲーウィンドウのフキダシアイコン更新
      #--------------------------------------------------------------------------
      def update_gal_event_balloon
        if @saba_balloon_sprite
          if @saba_balloon_sprite.character.balloon_id == 0 || Input.press?(Saba::Gal::SKIP_BUTTON)
            dispose_gal_event_balloon
          else
            @saba_balloon_sprite.update
          end
        end
      end
      #--------------------------------------------------------------------------
      # ● スプライトセットの解放
      #--------------------------------------------------------------------------
      alias saba_gal_dispose_spriteset dispose_spriteset
      def dispose_spriteset
        saba_gal_dispose_spriteset
        dispose_gal_event_balloon
      end
    end
    
    
    class Window_MessageGal < Window_Message
      #--------------------------------------------------------------------------
      # ● オブジェクト初期化
      #--------------------------------------------------------------------------
      def initialize
        super
        self.x = 10
        create_baloon_sprite
        $game_temp.window_number = -1
        update_balloon
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウ幅の取得
      #--------------------------------------------------------------------------
      def window_width
        Graphics.width - 20
      end
      #--------------------------------------------------------------------------
      # ● 表示行数の取得
      #--------------------------------------------------------------------------
      def visible_line_number
        return 3
      end
      #--------------------------------------------------------------------------
      # ● 改ページが必要か判定
      #--------------------------------------------------------------------------
      def need_new_page?(text, pos)
        pos[:y]  > contents.height && !text.empty?
      end
      #--------------------------------------------------------------------------
      # ● 通常文字の処理
      #--------------------------------------------------------------------------
      def process_normal_character(c, pos)
        if Input.press?(Saba::Gal::SKIP_BUTTON) && skip_enabled?
          @pause_skip = true
        end
        text_width = text_size(c).width
        if display_name? && (pos[:y] == 0)
          @name_sprite.bitmap.draw_text(pos[:x], 26, text_width * 2, pos[:height], c)
          pos[:x] += text_width
          return
        end
        if display_name?
          draw_text(pos[:x], pos[:y] - pos[:height], text_width * 2, pos[:height], c)
        else
          draw_text(pos[:x], pos[:y], text_width * 2, pos[:height], c)
        end
        pos[:x] += text_width
        unless Input.press?(Saba::Gal::SKIP_BUTTON) && skip_enabled?
          wait_for_one_character
        end
      end
      #--------------------------------------------------------------------------
      # ● 制御文字によるアイコン描画の処理
      #--------------------------------------------------------------------------
      def process_draw_icon(icon_index, pos)
        if display_name?
          draw_icon(icon_index, pos[:x], pos[:y] - pos[:height])
        else
          draw_icon(icon_index, pos[:x], pos[:y])
        end
        pos[:x] += 24
      end
      #--------------------------------------------------------------------------
      # ● 全ウィンドウの作成
      #--------------------------------------------------------------------------
      def create_all_windows
        super
        @name_window = Window_Base.new(20, Graphics.height - 126, Saba::Gal::NAME_WINDOW_WIDTH, 37)
        @name_window.z = 480
        @name_window.visible = false
    
        @name_sprite = Sprite_Base.new(nil)
        @name_sprite.z = 500
        @name_sprite.x = 30
        @name_sprite.y = Graphics.height - 146
        @name_sprite.bitmap = Bitmap.new(230, 300)
      end
      #--------------------------------------------------------------------------
      # ● フキダシスプライトを生成します。
      #--------------------------------------------------------------------------
      def create_baloon_sprite
        @balloon_sprite = Sprite_Base.new
        @balloon_sprite.z = 500
        @balloon_sprite.y = Graphics.height - 384
        @balloon_sprite.bitmap = Bitmap.new(400, 300)
        @balloon_sprite.visible = false
      end
      #--------------------------------------------------------------------------
      # ● 全ウィンドウの解放
      #--------------------------------------------------------------------------
      def dispose_all_windows
        super
        @name_window.dispose
        @name_sprite.bitmap.dispose
        @name_sprite.dispose
        @balloon_sprite.dispose
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウの更新
      #--------------------------------------------------------------------------
      def update
        super
        update_name_visibility
        update_balloon_visibility
        update_balloon
        update_opacity
      end
      #--------------------------------------------------------------------------
      # ● 不透明度の更新
      #--------------------------------------------------------------------------
      def update_opacity
        if @background != 0
          self.opacity = 0
          return
        end
        return if self.opacity == 255
        self.opacity += 9
      end
      #--------------------------------------------------------------------------
      # ● 入力待ち処理
      #--------------------------------------------------------------------------
      def input_pause
        self.pause = true
        wait(10)
        Fiber.yield until Input.trigger?(: || Input.trigger?(:C) || (Input.press?(Saba::Gal::SKIP_BUTTON) && skip_enabled?)
        if self.visible == false
          self.visible = true
          Sound.play_cursor
          input_pause
          return
        end
        Input.update
        self.pause = false
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウを開き、完全に開くまで待つ
      #--------------------------------------------------------------------------
      def open_and_wait
        open
        update_picture
        until open?
          update_balloon
          Fiber.yield 
        end
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウを閉じ、完全に閉じるまで待つ
      #--------------------------------------------------------------------------
      def close_and_wait
        close
        @name_window.visible = false
        @name_sprite.visible = false
    
        until all_close?
          Fiber.yield
        end
      end
      #--------------------------------------------------------------------------
      # ● 改ページ処理
      #--------------------------------------------------------------------------
      def new_page(text, pos)
        @name_sprite.bitmap.clear
        contents.clear
        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
      #--------------------------------------------------------------------------
      # ● 立ち絵の更新
      #--------------------------------------------------------------------------
      def update_picture
        return if $game_message.face_name.empty?
        $game_map.interpreter.pic($game_message.face_name, $game_message.face_index, $game_message.position)
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウ位置の更新
      #--------------------------------------------------------------------------
      def update_placement
        @position = 2
        self.y = @position * (Graphics.height - height) / 2
        @gold_window.y = y > 0 ? 0 : Graphics.height - @gold_window.height
      end
      #--------------------------------------------------------------------------
      # ● 背景と位置の変更判定
      #--------------------------------------------------------------------------
      def settings_changed?
        @background != $game_message.background
      end
      #--------------------------------------------------------------------------
      # ● 改行位置の取得
      #--------------------------------------------------------------------------
      def new_line_x
        return 0
      end
      #--------------------------------------------------------------------------
      # ● 次の語を表示すべきかどうかを判定します。
      #--------------------------------------------------------------------------
      def show_next_message?
        if skip_enabled?
          return Input.trigger?(Input::C) || Input.trigger?(Input:: || Input.trigger?(Saba::Gal::SKIP_BUTTON)
        else
          return Input.trigger?(Input::C) || Input.trigger?(Input::
        end
      end
      #--------------------------------------------------------------------------
      # ● メッセージスキップが有効かどうかを判定します。
      #--------------------------------------------------------------------------
      def skip_enabled?
        return $game_switches[Saba::Gal::SKIP_DISABLE_SWITCH] != true
      end
      #--------------------------------------------------------------------------
      # ● スイッチに従って、名前ウィンドウの表示を切り替えます。
      #--------------------------------------------------------------------------
      def update_name_visibility
        if @closing || close? || ! self.visible
          @name_window.visible = false
          @name_sprite.visible = false
          return
        end
        if $game_switches[Saba::Gal::DISPLAY_NAME_SWITCH] != true
          @name_window.visible = false
          @name_sprite.visible = false
        else
           @name_window.visible = true
          @name_sprite.visible = true
        end
      end
      #--------------------------------------------------------------------------
      # ● ふきだしの表示を切り替えます。
      #--------------------------------------------------------------------------
      def update_balloon_visibility
        if self.openness < 255
          @balloon_sprite.visible = false
          return
        end
        if @balloon_sprite.visible != $game_switches[Saba::Gal::DISPLAY_BALLOON_SWITCH]
          @balloon_sprite.visible = $game_switches[Saba::Gal::DISPLAY_BALLOON_SWITCH]
          update_balloon
        end
      end
      #--------------------------------------------------------------------------
      # ● 名前を表示すべきかどうかを判定します。
      #--------------------------------------------------------------------------
      def display_name?
        return $game_switches[Saba::Gal::DISPLAY_NAME_SWITCH] == true
      end
      #--------------------------------------------------------------------------
      # ● フキダシをまっさらにします。
      #--------------------------------------------------------------------------
      def clear_balloon
        @balloon_sprite.bitmap.clear_rect(100, 254, 300, 100)
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウの色が変わったかどうかを判定します。
      #--------------------------------------------------------------------------
      def window_color_changed?
        if $game_temp.window_number != $game_variables[Saba::Gal::BALLOON_VARIABLE] || $game_switches[Saba::Gal::CLEAR_BALLOON_SWITCH]
          $game_temp.window_number = $game_variables[Saba::Gal::BALLOON_VARIABLE]
          return true
        end
        return false
      end
      #--------------------------------------------------------------------------
      # ● フキダシを更新します。
      #--------------------------------------------------------------------------
      def update_balloon
        return unless window_color_changed?
        clear_balloon
        if Saba::Gal::USE_SINGLE_WINDOW_SKIN
          self.windowskin = Cache.system("Window1")
        else
          self.windowskin = Cache.system("Window" + $game_temp.window_number.to_s)
          if openness == 255
            self.opacity = 140 unless $game_switches[Saba::Gal::CLEAR_BALLOON_SWITCH]
          end
        end
        $game_switches[Saba::Gal::CLEAR_BALLOON_SWITCH] = false
        if $game_temp.window_number != nil && $game_temp.window_number > 0
          if Saba::Gal::USE_SINGLE_WINDOW_SKIN
            balloon = Cache.system("Balloon1")
          else
            balloon = Cache.system("Balloon" + $game_temp.window_number.to_s)
          end
          w = balloon.width / 2
          h = balloon.height
          if $game_variables[Saba::Gal::BALLOON_POSITION_VARIABLE] == 2
            @balloon_sprite.bitmap.blt(Saba::Gal::BALLOON_LEFT_X, Saba::Gal::BALLOON_Y, balloon, Rect.new(w, 0, w, h))
          else
            @balloon_sprite.bitmap.blt(Saba::Gal::BALLOON_RIGHT_X, Saba::Gal::BALLOON_Y, balloon, Rect.new(0, 0, w, h))
          end
        end
      end
    
    end
    
    
    class Game_Picture
      attr_accessor:mirror_pic
      alias saba_gal_initialze initialize
      def initialize(number)
        saba_gal_initialze(number)
        @mirror_pic = false
      end
    end
    
    class Sprite_Picture < Sprite
      alias saba_gal_update update
      def update
        saba_gal_update
        if @picture_name != ""
          self.mirror = @picture.mirror_pic
        end
      end
    end
    
    class Game_Pictures
      def size
        return @data.size
      end
    end
    
    class Game_Temp
      attr_accessor :window_number
      attr_accessor :pic_actors
      alias saba_pic_initialize initialize
      def initialize
        saba_pic_initialize
        @pic_actors = []
      end
    end
    
    class Game_Interpreter
      #--------------------------------------------------------------------------
      # ● フキダシアイコンの表示
      #--------------------------------------------------------------------------
      alias saba_gal_command_213 command_213
      def command_213
        unless message_mode?
          saba_gal_command_213
          return
        end
        command = @list[@index + 1]
        if command == nil || command.code != 101
          p "イベントコマンドのフキダシアイコンの表示 の後にメッセージイベントを入れてください" 
          return
        end
    
        return if Input.press?(Saba::Gal::SKIP_BUTTON)
        params = command.parameters
        name = params[0]
        actor_id = name["actor".length..-1].to_i
        position = params[3]
        x = (picture_base_x(position) + offset_event_balloon_x(position, actor_id) + 80) / 32.0 + $game_map.display_x
        y = (picture_base_y(position) + offset_event_balloon_y(actor_id)) / 32.0 + $game_map.display_y
        balloon_char = Game_Character.new
        balloon_char.moveto(x, y)
        balloon_char.balloon_id = @params[1]
        SceneManager.scene.create_gal_event_balloon(balloon_char)
      end
      #--------------------------------------------------------------------------
      # ● 会話モードかどうかを判定します。
      #--------------------------------------------------------------------------
      def message_mode?
        return $game_switches[Saba::Gal::MESSAGE_MODE_SWITCH] == true
      end
    end
    2. Sub script #1: Hide Message Window and Access Save Screen

    Code:
    #==============================================================================
    # ■ Girl Game Message Window Expansion 4
    #   @version 0.4 11/12/27 RGSS3
    #   @author Saba Kan
    #   @translator kirinelf
    #------------------------------------------------------------------------------
    #  Adds Hide Message Window and Call Save Window from Message Window options.
    #==============================================================================
    module Saba
      module GalEx
        # Hide Message Window (R is W on the keyboard).
        # To disable, use 'nil'. 
        HIDE_BUTTON = Input::R
    
        # Save Button (L is Q on the keyboard).
        # To disable, use 'nil'. 
        SAVE_BUTTON = Input::L
      end
    end
    
    #=========================================================================
    # Do not edit anything under this line unless you know what you're doing!
    #=========================================================================
    
    class Scene_Map
      alias saba_hide_window_update update
      def update
        saba_hide_window_update
        return if @message_window.openness == 0
        if Input.trigger?(Saba::GalEx::HIDE_BUTTON)
          Sound.play_cursor
          @message_window.visible = ! @message_window.visible
        elsif Input.trigger?(Saba::GalEx::SAVE_BUTTON)
          if @message_window.is_a?(Window_MessageGal)
            Sound.play_cursor
            SceneManager.call(Scene_Save)
          end
        end
      end
    end
    
    
    
    class Window_MessageGal
      def visible=(v)
        super
        if v
          update_name_visibility
        else
          @name_sprite.visible = false
          @name_window.visible = false
        end
      end
      #--------------------------------------------------------------------------
      # ● ふきだしの表示を切り替えます。
      #--------------------------------------------------------------------------
      alias saba_hide_window_update_balloon_visibility update_balloon_visibility
      def update_balloon_visibility
        unless self.visible
          @balloon_sprite.visible = false
          return
        end
        saba_hide_window_update_balloon_visibility
      end
    end
    3. Sub script #2: Message Log

    Code:
    #==============================================================================
    # ■ Message Log 4
    #   @version 0.5 11/12/30
    #   @author Saba Kan
    #   @translator kirinelf
    #------------------------------------------------------------------------------
    #  
    #==============================================================================
    module Saba
      module MessageLog
        # Display Message Log (X is A on the keyboard).
        LOG_BUTTON = Input::X
    
        # Space in pixels between each message in the log.
        Y_SPACE = 10
    
        # Maximum number of messages to save in log. 
        # ※If too high, will result in Bitmap Overflow errors.
        MAX_HISTORY = 20
    
        # Color of the background.
        BG_COLOR = Color.new(0, 0, 0, 180)
    
        # Scrolling speed.
        SCROLL_SPEED = 5
    
        # Size of the font.
        FONT_SIZE = 20
    
        # Height in pixels of each line. 
        LINE_HEIGHT = 22
    
        # Width of the Name Column.
        NAME_WIDTH = 100
      end
    end
    
    #=========================================================================
    # Do not edit anything under this line unless you know what you're doing!
    #=========================================================================
    
    $imported = {} if $imported == nil
    $imported["MessageLog"] = true
    
    class Window_MessageLog < Window_Selectable
      #--------------------------------------------------------------------------
      # ● オブジェクト初期化
      #--------------------------------------------------------------------------
      def initialize
        super(0, 0, window_width, window_height)
        self.active = true
        self.opacity = 0
        create_back_sprite
        refresh
      end
      #--------------------------------------------------------------------------
      # ● ログに必要な高さを計算
      #--------------------------------------------------------------------------
      def calc_log_height
        return @log_height if @log_height != nil
        @log_height = 0
        for log in $game_message_log.logs
    
          log.texts.each_with_index do |text, i|
            next if i == 0 && log.talk
            @log_height += 24
          end
          @log_height += Saba::MessageLog::Y_SPACE
        end
        return @log_height
      end
      #--------------------------------------------------------------------------
      # ● 背景スプライトの作成
      #--------------------------------------------------------------------------
      def create_back_sprite
        @back_sprite = Sprite.new
        @back_sprite.bitmap = Bitmap.new(window_width, window_height)
        bg_color = Saba::MessageLog::BG_COLOR
        @back_sprite.bitmap.fill_rect(Rect.new(0, 0, window_width, window_height), bg_color)
        @back_sprite.visible = true
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウ幅の取得
      #--------------------------------------------------------------------------
      def window_width
        Graphics.width
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウ高さの取得
      #--------------------------------------------------------------------------
      def window_height
        Graphics.height
      end
      #--------------------------------------------------------------------------
      # ● リフレッシュ
      #--------------------------------------------------------------------------
      def refresh
        y = 0
        for log in $game_message_log.logs
          talk = false
          log.texts.each_with_index do |text, i|
    
            if i == 0 && log.talk
              talk = true
            end
    
            x = (talk && i == 0) ? 0 : Saba::MessageLog::NAME_WIDTH
            draw_text_ex(x-16, y, "「") if talk && i == 1
            text += "」" if talk && log.texts.size - 1 == i
            draw_text_ex(x, y, text)
            y += Saba::MessageLog::LINE_HEIGHT if ! talk || i > 0
    
          end
          y += Saba::MessageLog::Y_SPACE
        end
    
        @max_oy = [0, calc_log_height - window_height + 32].max
        self.oy = @max_oy
      end
      #--------------------------------------------------------------------------
      # ● フォント設定のリセット
      #--------------------------------------------------------------------------
      def reset_font_settings
        change_color(normal_color)
        contents.font.size = Saba::MessageLog::FONT_SIZE
        contents.font.bold = false
        contents.font.italic = false
      end
      #--------------------------------------------------------------------------
      # ● ウィンドウ内容の作成
      #--------------------------------------------------------------------------
      def create_contents
        contents.dispose
        self.contents = Bitmap.new(window_width-32, [window_height-32, calc_log_height-32].max)
      end
      def update
        super
        if Input.press?(Input::DOWN)
          self.oy += Saba::MessageLog::SCROLL_SPEED
        end
        if Input.press?(Input::UP)
          self.oy -= Saba::MessageLog::SCROLL_SPEED
        end
        self.oy = 0 if self.oy < 0
        self.oy = @max_oy if self.oy > @max_oy
      end
    end
    
    class Game_MessageLog
      attr_reader :texts
      attr_reader :talk
      def initialize(texts)
        @texts = texts
        if $imported["GalGameTalkSystem"]
          @talk = $game_switches[Saba::Gal::DISPLAY_NAME_SWITCH]
        else
          @talk = false
        end
      end
      def ==(arg)
        return arg.instance_of?(self.class) && @texts == arg.texts
      end
    end
    
    class Game_MessageLogSet
      attr_accessor:logs
    
      def initialize
        @logs = []
      end
      def push_log(texts)
        return if texts == nil || texts.size == 0
        log = Game_MessageLog.new(texts)
        return if @logs[-1] == log 
        @logs.push(log)
        @logs.shift if @logs.size > Saba::MessageLog::MAX_HISTORY
      end
    end
    
    class Scene_Map
      #--------------------------------------------------------------------------
      # ● シーン遷移に関連する更新
      #--------------------------------------------------------------------------
      alias saba_msglog_update update
      def update
        saba_msglog_update
        update_call_msg_log unless scene_changing?
      end
      #--------------------------------------------------------------------------
      # ● メッセージログ呼び出し判定
      #--------------------------------------------------------------------------
      def update_call_msg_log
        call_msglog if Input.trigger?(Saba::MessageLog::LOG_BUTTON)
      end
      def call_msglog
        Sound.play_ok
        SceneManager.call(Scene_MsgLog)
      end
    end
    
    class Scene_MsgLog < Scene_MenuBase
       #--------------------------------------------------------------------------
      # ● 開始処理
      #--------------------------------------------------------------------------
      def start
        super
        create_command_window
      end
      #--------------------------------------------------------------------------
      # ● コマンドウィンドウの作成
      #--------------------------------------------------------------------------
      def create_command_window
        @log_window = Window_MessageLog.new
        @log_window.set_handler(:cancel,    method(:return_scene))
      end
    end
    
    class Window_Message
      alias saba_msglog_process_all_text process_all_text
      def process_all_text
        $game_message_log.push_log($game_message.texts)
        saba_msglog_process_all_text
      end
    end
    
    class << DataManager
      #--------------------------------------------------------------------------
      # ● 各種ゲームオブジェクトの作成
      #--------------------------------------------------------------------------
      alias saba_msglog_create_game_objects create_game_objects
      def create_game_objects
        saba_msglog_create_game_objects
        $game_message_log          = Game_MessageLogSet.new
      end
      #--------------------------------------------------------------------------
      # ● セーブ内容の作成
      #--------------------------------------------------------------------------
      alias saba_msglog_make_save_contents make_save_contents
      def make_save_contents
        contents = saba_msglog_make_save_contents
        contents[:message_log] = $game_message_log
        contents
      end
      #--------------------------------------------------------------------------
      # ● セーブ内容の展開
      #--------------------------------------------------------------------------
      alias saba_msglog_extract_save_contents extract_save_contents
      def extract_save_contents(contents)
        saba_msglog_extract_save_contents(contents)
        $game_message_log        = contents[:message_log]
      end
    end
    The script also requires a few images that need to be placed in the Graphics/System folder. This is a link to the images required for the script to run: [Link] I have also attached them to this post for easy access. Remember that you also need a bunch of potraits that are included in the demo but which I won't add for you guys.

    The demo can be found here: [Link] This is quite a simple script IF you know what you're doing, which takes a bit of playing around. So I've included a demo to save you the trouble of accidentally ruining your current project or having to start a new project just for this. Aren't I kind?

    For those of you who can't be bothered downloading the demo, I'm including a copy of the documentation here.

    How to Use

    Place the three scripts in the order I've numbered them above Main and under Materials. 1 - This is the main script. It has the bulk of the processing stuff in it.

    2 - This is a sub script. It makes it so that you can hide the message window completely or open the save screen from within the message.

    3 - This is a sub script. It adds a message log so you can reread messages in case you missed one.

    Place all the images in the System folder into your Graphics/System folder. You also need all potraits to go into the Graphics/Pictures folder. Refer to the demo for additional details.

    One thing to note here is that since this system can be used in conjunction with the default message system, I'm going to call this a Conversation system instead of a Message system.

    This script is NOT compatible with Yanfly's Ace Message System. I haven't tried any others yet. modern algebra's ATS: Formatting doesn't work with it either, which is sad.

    *******

    Full Use

    *******

    Full use of the script includes the following elements:

    Character Potrait Positioning

    Speech Balloon

    Windowskin Color

    Namebox

    Emoticons (Balloon Icons)

    as well as

    Message Logs

    Enter Save Screen from Conversation

    Hide Conversation Window

    The latter three are from sub scripts, and the last two can be disabled individually.

    *******

    Setting Up

    *******

    To use the script to its fullest extent, you will need to turn switches on and off, as well as tinting and erasing pictures. This is easily done by setting up two common events and calling them before and after each convo, as can be seen in the demo. The first common event, which I labelled Conversation Start, turns on the switches that toggle the Conversation Mode to begin with, Name Display and Speech Balloon Graphic Display. This is also the reason why I distinguish between Conversations and Messages; there's a bloody switch that toggles between the two. These switches can be assigned from within the script; the default IDs are 132, 133 and 134.

    The second common event, which is used for ending a conversation, tints the two character potraits (Which, by default, will take up Pictures ID 10 and 12) dark, turns off the three switches you turned on, then erases them to formally end the conversation. This is all you really have to do to set up the script. This and, of course, have the pictures in your System/Pictures folder.

    You call the first common event before setting up your convo messages, and call the second common event after you're done and want to stop the conversation.

    *******

    Assigning and Using Potraits

    *******

    By default, the script uses the actor face you picked to determine the potrait you use. Refer to this grid:

    0 1 2 3

    4 5 6 7

    Each face graphic in the Graphics/Faces folder fits that grid. The script looks at the face you choose for your message, adds 1 to it, then searches your Graphics/Pictures folder for the file that matches it. This is the filename it searches for:

    (FaceFilename)_(FaceID+1).png

    So for example, you picked Ralph's face. Ralph's face belongs to the file Actor1.png in the Graphics/Faces folder, and it's in the '0' section of the grid. This means the script will look for a potrait named Actor1_1.png in the Graphics/Pictures folder. I hope that makes sense.

    This has many uses, and the most typical way this is used in the gaming industry is to have a bunch of emotions on the characters. Due to the way the system works, it's easy to organize a set of 8 different emotions for each actor you have, and it'll organize them neatly by filename in your Pictures folder. So Actor1_1 will have a neutral Ralph, Actor1_2 will have a bored Ralph, Actor1_3 will have an angry Ralph, so on and so forth.

    Also note that if you select a face ID that doesn't have a corresponding potrait in the Pictures folder (For example, Actor1_8 when you only have 7 potraits), it'll spit an error out at you saying it can't find that image.

    The last bit of configuration comes from the message positioning. If you select 'Top', the potrait appears on the right. If you select 'Bottom', the potrait appears on the left. 'Middle' crashes the game. Be warned. Oh, this does not actually affect the message position. It will ALWAYS appear at the bottom, regardless of your setting.

    *******

    Balloon Icons

    *******

    Also known as emoticons. These are easy to use. Just have an event command as usual, but with the target set to Player. They will play over the head of the next character who has a line. This may not be ideal for some (For example, having a character be startled with an exclaimation icon, but having the character who startled him speak next), but it can be dealt with by having ellipsises in that character's message (Such as by having the aforementioned startled character 'say' "...!" while having the emoticon pop up on his head).

    *******

    Speech Balloon Graphic and Windowskin Color

    *******

    The speech balloon graphics are the little pointer things over the message box that point at the person speaking so you know who's actually talking at the moment. For the most part, this is automatically handled for you. What it does is get the ID of FaceFilename and searches Graphics/System for the matching files. For example, Actor1 = Balloon1 = Window1.

    This DOES mean that your FaceFilename has to have a unique number at the end of it. For example, Eric1, Natalie2 and so on. If you have Eric1 and Natalie1, both Eric and Natalie will share the same speech balloon graphic and windowskin color.

    The speech balloon graphic is also automatically placed. If your message is positioned at the 'Top' and the character thus appears on the right, the speech balloon graphic is automatically placed so it points towards him. There's no need to worry about this one.

    You can ignore windowskin color changes by changing line 70 in the main script. This will make everyone use the one windowskin and speech balloon graphic, regardless of filename ID.

    *******

    Message Input

    *******

    Not much to say here. Messages work like any other, simply type in the message and make sure to preview it to make sure it doesn't go over the boundaries. One thing to keep in mind; if you have the Name Display switch turned on, the messagebox only has three lines for text input. The first line is for name input, and should have the actor's name written in it (Or \n[x]).

    You can also use \i[x] to put icons in the text, where 'x' is the icon ID.

    You can also simulate a system message or a message from someone out of view by turning off the Name Display and Speech Balloon Graphic Display switches temporarily, which turns the message box back to four lines as well as defaulting to the Window0 windowskin.

    *******

    End

    *******

    And there we go. Any questions, pop me a line. I might not be able to answer it, but I'll do my best and hopefully we can solve it together, or with the help of someone who knows what he's doing.

    Kirin, out.
    FAQ

    Q: Where do I put these scripts?

    A: Above Main, under Materials. You really only need the main script; the other two are just bonuses.

    Q: How do I use this script?

    A: Read the 'How to Use.txt' file included in the demo, or refer to the same section in my post above.

    Q: Help! I'm getting an 'Unable to find file: Graphics/System/<Insert filename here>' error!

    A: The hint is in the error. Download the images from either this link or from the attachment and place them in the proper folder.

    Q: Help! I'm getting an 'Unable to find file: Graphics/Pictures/<Insert filename here>' error!

    A: You have selected a face that doesn't have a corresponding potrait in the Pictures folder. Either get one or change your face.

    Credit and Thanks

    - Saba Kan, for making this script.

    - Kirin (me), for translating this.

    - Kread-Ex, for giving me pointers as to how to modify the picture base ID.

    - Enterbrain, for once again making an awesome maker.

    - Google Translate, for helping me with minor translations.

    - The makers of the Rikai-chan addon for Mozilla and the Rikai-kun extension for Chrome, for giving us an awesome Japanese translator.

    Galge Conversation.zip
     

    Attached Files:

    #1
    Romanticist, DangDut, BCj and 7 others like this.
  2. Resurrection Games

    Resurrection Games Veteran Gamer Veteran

    Messages:
    61
    Likes Received:
    1
    Location:
    Flowery Branch, GA
    First Language:
    English
    Where'd you get those portraits from?! They look awesome.
     
    #2
  3. kirinelf

    kirinelf *Stare* Veteran

    Messages:
    64
    Likes Received:
    26
    First Language:
    Hakka
    From the original Japanese demo. I don't know where they're originally from, and I'd advise against using them if at all possible.

    Although they do look like official potraits that maybe Japan got for free or something.
     
    #3
  4. Asterisk

    Asterisk アステリ (ノ ̄ー ̄)ノ♪ Veteran

    Messages:
    205
    Likes Received:
    10
    Location:
    Your Bed
    First Language:
    English
    Primarily Uses:
    RMMV
    I'm pretty sure the person drew the pictures xD He had some art under お絵かき

    Anyway this is awesome, THANKYOU~!
     
    #4
  5. kirinelf

    kirinelf *Stare* Veteran

    Messages:
    64
    Likes Received:
    26
    First Language:
    Hakka
    Yeah, now that I look at it properly, the art style does match. xD Thanks Asterisk.
     
    #5
  6. Tukang_Sapu

    Tukang_Sapu Ambassador of Eronesia Member

    Messages:
    10
    Likes Received:
    1
    Location:
    Indonesia
    First Language:
    Indonesia
    wow great !

    i have RMVX version of this script.

    thank you for translate VX-ace version
     
    #6
  7. RyuzawaEnma

    RyuzawaEnma Warper Member

    Messages:
    1
    Likes Received:
    0
    First Language:
    Indonesia
    Umm, is this compatible with Yanfly's scripts?
     
    #7
  8. Lars Ulrika

    Lars Ulrika I punch Therefore I am Harvest the land Taking the Veteran

    Messages:
    1,357
    Likes Received:
    396
    Location:
    Bengkulu Indonesia
    First Language:
    French
    Primarily Uses:
    N/A
    Wow, how this script could end up lost ? 

    Is it available for commercial use? 
     
    #8
  9. Roselise

    Roselise Warper Member

    Messages:
    1
    Likes Received:
    0
    First Language:
    English
    I keep getting the error "line 445: SyntaxError occured. unexpected tIDENTIFIER, expecting ')' ...ield until Input.trigger?:)<img src='http://forums.rpgmakerw..."

    I don't know what to do? I copied everything to the T, PLEASE HELP
     
    #9
  10. AceOfAces_Mod

    AceOfAces_Mod Engineering to infinity! Veteran

    Messages:
    1,701
    Likes Received:
    1,157
    First Language:
    Greek
    Primarily Uses:
    RMVXA
    Grab the script from the demo. It seems that he forgot to remove the refrence to the forums (I think...)
     
    #10
  11. Crimsonkun

    Crimsonkun Warper Member

    Messages:
    1
    Likes Received:
    0
    First Language:
    English
    Can someone help me? I can't seem to figure out how to mirror the picture on the right.


    I set it to true but nothing happens, but the left works fine. 


    I cannot find a solution
     
    #11
  12. BCj

    BCj Veteran Veteran

    Messages:
    1,442
    Likes Received:
    685
    Location:
    NL
    First Language:
    Dutch
    Primarily Uses:
    N/A
    Such a shame that this does not seem to work with YEA Message System :(
     
    #12

Share This Page