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