The RPG Maker Resource Kit

RMRK RPG Maker Creation => RPG Maker General => General Scripting => Topic started by: Season In The Abyss on December 15, 2006, 08:13:43 PM

Title: Scrolling Message System
Post by: Season In The Abyss on December 15, 2006, 08:13:43 PM
Scrolling Message System
Version: 1.0

Last Update

December 15, 2006

Introduction

With this script the player will see just two lines of text at a time, if there are more than two, it'll be scrolled very smoothly.

Features

Screenshots

(https://rmrk.net/proxy.php?request=http%3A%2F%2Fimg92.imageshack.us%2Fimg92%2F1296%2Fscrollmessysfe9.gif&hash=d913a93fa3e86a72438c9e224dec3a9c7ce5913d)

Demo

http://www.fileul.com/view.php?file=kPuZMEm (http://www.fileul.com/view.php?file=kPuZMEm)

Script

[spoiler="Script"]#==============================================================
# ** Scrolling Message System
#------------------------------------------------------------------------------
# Slipknot (dubealex.com/asylum)
# Version 1.0
# December 15, 2006
#==============================================================

module Message
  #--------------------------------------------------------------------------
  # * Settings
  #--------------------------------------------------------------------------
  # ~ Font
  FontName = 'Tahoma'
  FontSize = 22
  # ~ Size
  Width = 480
  Height = 32
  # ~ Delay
  TextDelay = 2
  Scroll = 20
  Autoclose = 16
  #--------------------------------------------------------------------------
  # * Font
  #--------------------------------------------------------------------------
  def self.font
    Font.new(FontName, FontSize)
  end
end


class Game_Temp
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_accessor :mes_choices
end


class Spriteset_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :character_sprites
end


class Interpreter
  #--------------------------------------------------------------------------
  # * Show Text
  #--------------------------------------------------------------------------
  def command_101
    return false if (temp = $game_temp).message_text
    @message_waiting = true
    temp.message_proc = Proc.new { @message_waiting = false }
    temp.message_text = @list.at(@index).parameters.at(0) + "\n"
    loop do
      com = @list.at(@index + 1)
      if com.code == 401 || com.code == 101
        temp.message_text += com.parameters.at(0) + "\n"
      else
        if com.code == 102
          temp.choice_max = com.parameters.at(0).size
          dummy = Bitmap.new(32, 22)
          dummy.font, width = Message.font, 0
          com.parameters.at(0).each do |c|
            width = [width, dummy.text_size(c).width].max
          end
          dummy.dispose
          temp.mes_choices = [width] + com.parameters.at(0)
          temp.choice_cancel_type = com.parameters.at(1)
          current_indent = com.indent
          temp.choice_proc = Proc.new { |n| @branch[current_indent] = n }
          @index += 1
        elsif com.code == 103
          @index += 1
          temp.num_input_variable_id = com.parameters.at(0)
          temp.num_input_digits_max = com.parameters.at(1)
        end
        return true
      end
      @index += 1
    end
  end
end


class Window_Message < Window_Selectable
  #--------------------------------------------------------------------------
  # * Alias Listing
  #--------------------------------------------------------------------------
  alias slipknot_sms_init initialize
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize
    slipknot_sms_init
    self.height = Message::Height * 2 + 32
    self.back_opacity = 160
    self.windowskin.fill_rect(144, 16, 32, 32, Color.new(0, 0, 0, 0))
    @sy = @soy = 1.0
    @y = 0
  end
  #--------------------------------------------------------------------------
  # * Opacity
  #--------------------------------------------------------------------------
  def opacity=(val)
    super
    @choices.opacity = val if @choices
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    contents.font = Message.font
    @x = @y = 0
    @sy = 1.0
    return if ! (@text = temp.message_text)
    @text.gsub!(/\\\\/) { "\000" }
    @text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
    @text.gsub!('\$') { $game_party.gold.to_s }
    @text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
      $game_actors[$1.to_i] ? $game_actors[$1.to_i].name : ''
    end
    gold_win |= @text.gsub!(/\\[Gg]/, '')
    if fit |= @text[/\\[Pp]/]
      if @text.sub!(/\\[Pp]\[([-1,0-9]+)\]/, '')
        event = $1.to_i
      elsif @text.gsub!(/\\[Pp]/, '')
        event = ev_ac
      end
    end
    @text.gsub!('\$') { $game_party.gold.to_s }
    @text.gsub!(/\\[Cc]\[([0-9]+?)\]/) { "\001[#$1]" }
    @text.gsub!('\!') { "\003" }
    @text.gsub!('\.') { "\004" }
    @text.gsub!(/\\\%\[(\d+)\]/) { "\011[#$1]" }
    @text.gsub!('\%') { "\011" }
    lines_size = [0]
    save, @lines = @text.clone, 0
    while c = @text.slice!(/./m)
      if c == "\n"
        @lines += 1
        lines_size << 0
        next
      end
      lines_size[@lines] += eval_text(c, true)
    end
    @text = save
    twidth = temp.choice_max > 0 ? temp.mes_choices.at(0) + 40 : 0
    self.width = fit ? lines_size.max + 40 : Message::Width - twidth
    twidth += self.width
    self.contents = Bitmap.new(self.width - 32, @lines * Message::Height)
    contents.font = Message.font
    if ! event
      h2 = self.height / 2
      self.y = temp.in_battle ? 96 - h2 :
        case $game_system.message_position
        when 0 then 96 - h2
        when 1 then 240 - h2
        when 2 then 384 - h2
        end
      self.x = 320 - twidth / 2
    else
      c = event > 0 ? $game_map.events[event] : $game_player
      mx, my = 636 - twidth, 476 - self.height
      fx = [[c.screen_x - twidth / 2, 4].max, mx].min
      ch = [$scene.spriteset.character_sprites[event - 1].bitmap.height /
        4 + 4, 48].max
      fy = [[c.screen_y - (ch + self.height), 4].max, my].min
      self.x, self.y = fx, fy
    end
    self.opacity = $game_system.message_frame == 0 ? 255 : 0
    if gold_win
      @gold_window = Window_Gold.new
      @gold_window.x = 560 - @gold_window.width
      if temp.in_battle
        @gold_window.y = 192
      else
        @gold_window.y = self.y >= 128 ? 32 : 384
      end
      @gold_window.opacity = self.opacity
    end
    if temp.choice_max > 0
      @choices = Window_MesChoices.new(self.x + self.width, self.y)
      @choices.back_opacity = self.back_opacity
    end
  end
  #--------------------------------------------------------------------------
  # * Evaluate Text
  #--------------------------------------------------------------------------
  def eval_text(c, read = false)
    case c
    when "\000"
      c = '\\'
    when "\001"
      @text.sub!(/\[(\d+)\]/, '')
      return 0 if read
      contents.font.color = text_color($1.to_i)
      return
    when "\002"
      @text.sub!(/\[(.*?)\]/, '')
      return 24 if read
      y = Message::Height * @y
      contents.blt(@x + 4, y, RPG::Cache.icon($1.to_s), Rect.new(0, 0, 24, 24))
      @x += 24
      return
    when "\003"
      return 0 if read
      @stop = true
      return
    when "\004"
      return 0 if read
      @wait_count += 10
      return
    when "\011"
      @text.sub!(/\[(\d+)\]/, '')
      return 0 if read || temp.num_input_variable_id > 0 || temp.choice_max > 0
      @autoclose = $1 ? $1.to_i : Message::Autoclose
      return
    when "\n"
      @y += 1
      @x = 0
      return
    end
    w = contents.text_size(c).width
    return w if read
    contents.draw_text(@x + 4, Message::Height * @y, w, Message::Height, c)
    @x += w
  end
  #--------------------------------------------------------------------------
  # * Variables
  #--------------------------------------------------------------------------
  def temp() $game_temp end
  def input_number() @input_number_window end
  def ev_ac() $game_system.map_interpreter.event_id end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    if @contents_showing
      super
      if @sy < @y && @y < @lines
        @sy += 1.0 / Message::Scroll
        @soy += Message::Height / Message::Scroll.to_f
        ey = @soy - @soy.floor
        self.oy += @soy.floor
        @soy = ey
      end
      if @text
        if Input.trigger?(13) && @stop
          self.pause = @stop = false
          return
        elsif @stop
          return
        elsif @wait_count > 0
          @wait_count -= 1
          return
        end
        if c = @text.slice!(/./m)
          eval_text(c)
          if @stop
            self.pause = true
            return
          end
          @wait_count += Message::TextDelay - (Input.press?(13) ? 1 : 0)
        else
          @text = nil
        end
        return if @text || @autoclose != -1
        if temp.num_input_variable_id > 0
          digits_max = temp.num_input_digits_max
          @input_number_window = Window_InputNumber.new(digits_max)
          input_number.number = $game_variables[temp.num_input_variable_id]
          input_number.x = self.x + (self.width / 2 - input_number.width / 2)
          input_number.y = self.y + Message::Height
          @y -= 1
          @sy -= 1.0
        end
        @choices.index, @choices.active = 0, true if @choices
        return
      else
        if @autoclose > 0
          @autoclose -= 1
          return
        elsif @autoclose == 0
          terminate_message
          @autoclose = -1
          return
        end
      end
      if input_number
        input_number.update
        if Input.trigger?(13)
          $game_system.se_play($data_system.decision_se)
          $game_variables[temp.num_input_variable_id] = input_number.number
          $game_map.need_refresh = true
          input_number.dispose
          @input_number_window = nil
          terminate_message
        end
        return
      elsif @choices
        @choices.update
      end
      self.pause = true
      if Input.trigger?(12)
        if temp.choice_max > 0 && temp.choice_cancel_type > 0
          $game_system.se_play($data_system.cancel_se)
          temp.choice_proc.call(temp.choice_cancel_type - 1)
          terminate_message
        end
      end
      if Input.trigger?(13)
        if temp.choice_max > 0
          $game_system.se_play($data_system.decision_se)
          temp.choice_proc.call(@choices.index)
        end
        terminate_message
      end
      return
    end
    if ! @fade_out && temp.message_text
      @contents_showing = temp.message_window_showing = true
      if @choices
        @choices.dispose
        @choices = nil
      end
      self.oy = 0
      @stop = false
      @autoclose = -1
      refresh
      @wait_count, self.visible = 0, true
      return
    end
    return if ! visible
    @fade_out = true
    self.opacity -= 48
    if self.opacity == 0
      self.visible = @fade_out = false
      if @choices
        @choices.dispose
        @choices = nil
      end
      temp.message_window_showing = false
    end
  end
end


class Window_MesChoices < Window_Selectable
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(x, y)
    h, width = Message::Height, temp.mes_choices.shift
    super(x, y, width + 40, 2 * h + 32)
    self.opacity = $game_system.message_frame == 0 ? 255 : 0
    self.index, self.active, @item_max = -1, false, temp.choice_max
    self.contents = Bitmap.new(width + 4, @item_max * h)
    contents.font = Message.font
    temp.mes_choices.each_index do |i|
      contents.draw_text(4, i * h, width, h, temp.mes_choices.at(i))
    end
  end
  #--------------------------------------------------------------------------
  # * Game Temp
  #--------------------------------------------------------------------------
  def temp() $game_temp end
  #--------------------------------------------------------------------------
  # * Update Cursor
  #--------------------------------------------------------------------------
  def update_cursor_rect
    if @index < 0
      self.cursor_rect.empty
      return
    end
    self.oy = [[@index, @item_max].min - 1, 0].max * Message::Height
    y = @index * Message::Height - self.oy
    cursor_rect.set(0, y, width - 32, Message::Height)
  end
end


class Window_InputNumber < Window_Base
  #--------------------------------------------------------------------------
  # * Initialize
  #--------------------------------------------------------------------------
  def initialize(digits)
    @digits_max = digits
    @number = 0
    dummy = Bitmap.new(32, 32)
    dummy.font = Message.font
    @cursor_width = dummy.text_size('0').width + 8
    dummy.dispose
    super(0, 0, @cursor_width * @digits_max + 32, Message::Height + 32)
    self.contents = Bitmap.new(width - 32, height - 32)
    contents.font = Message.font
    self.z += 9999
    self.opacity = @index = 0
    refresh
    update_cursor_rect
  end
  #--------------------------------------------------------------------------
  # * Update Cursor
  #--------------------------------------------------------------------------
  def update_cursor_rect
    self.cursor_rect.set(@index * @cursor_width, 0, @cursor_width, Message::Height)
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    contents.clear
    contents.font.color = normal_color
    s = sprintf("%0*d", @digits_max, @number)
    for i in 0...@digits_max
      self.contents.draw_text(i * @cursor_width + 4, 0, 32, Message::Height, s[i, 1])
    end
  end
end


class Interpreter
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :event_id
end


class Scene_Map
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader :spriteset
end
[/spoiler]

Instructions

You need paste the code before Main.
Take a look to the demo and see how it works.
Compatibility

This script couldn't work with other message window script.

Author's Notes

Enjoy it, credit me and report any bug.
Title: Re: Scrolling Message System
Post by: Me™ on December 15, 2006, 09:04:00 PM
Okay, this is very cool  ;D

Grwat job, testing the demo out now  ;)