Advertisement
LiTTleDRAgo

[RGSS] Multiple Message Windows Ex 1.6d

Aug 21st, 2016
442
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 148.09 KB | None | 0 0
  1. #==============================================================================
  2. # ** Multiple Message Windows Ex 1.6d                                 2016-08-21
  3. #------------------------------------------------------------------------------
  4. # Originally written by Wachunga
  5. # Optimized and De-SDK'ed by ForeverZer0
  6. # Ex Version by LiTTleDRAgo
  7. #==============================================================================
  8. =begin
  9.  
  10. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  11.  
  12.   ForeverZer0's Notes
  13.  
  14. - Credit for the original script is 100% Wachunga. Original map and events
  15.   are also Wachunga's original.
  16. - Edits have been made by ForeverZer0 to eliminate the SDK requirement
  17.   and improve coding and performance
  18. - I have added a compatibility switch for Blizzard's simple shaded text if you
  19.   are you using that, because it doesn't look right with message text. The
  20.   switch will disable it whenever a message is showing, but otherwise will
  21.   shade everything else.
  22. - This script must be placed below Blizzard's Tons-of-Add-ons if you are
  23.   using it. If you don't you will get an error. It has something to do with
  24.   the Lagless HUD script. Some bug I couldn't isolate... If you find it, let
  25.   me know, else just keep it under Tons.
  26.  
  27. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  28. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  29.  
  30.   LiTTleDRAgo's Notes
  31.  
  32. - This script is edited and remodeled a bit by me to make it compatible with
  33.   Blizz ABS (and pst... H Mode 7)
  34. - Although this version is de-SDK-ed by F0, This version should be 80%
  35.   compatible with SDK
  36. - Some features were added to enchanche this script functionality
  37.  
  38. ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  39.  
  40.   This custom message system adds numerous features on top of the default
  41.   message system, the most notable being the ability to have multiple message
  42.   windows open at once. The included features are mostly themed around turning
  43.   messages into speech (and thought) balloons, but default-style messages are
  44.   of course still possible.
  45.  
  46.   The original version of the script uses the SDK, seems to be lost
  47.  
  48.   FEATURES
  49.   New in 1.6 (feature by ThallionDarkshine)
  50.       \ani[TYPE]
  51.          TYPE - Which type of animation the text should have
  52.            0  - Turn off Animation
  53.            1  - Grow             4  - Shake
  54.            2  - Rock             5  - Float
  55.            3  - Shrink           6  - Color Rotate
  56.            
  57.            7  - Bounce           10 - Letter Grow (2)
  58.            8  - Fade             11 - Letter Swivel
  59.            9  - Letter Grow (1)  12 - Letter Colorize
  60.            
  61.            13 - Letter Fade (1)   16 - Letter Shrink (2)
  62.            14 - Letter Fade (2)   17 - Letter Bounce
  63.            15 - Letter Shrink (1) 18 - Letter Float
  64.            
  65.   New in 1.5x
  66.  
  67.   * \f[face_image] = display faceset image
  68.                    image must be placed in folder pictures and the size
  69.                    is 80x80
  70.   * \a[name]       = display message name
  71.   * \r[string]     = display furigana text
  72.   * \F+  = character puts their Foot Forward
  73.   * \F*  = character puts their Other Foot Forward
  74.   * \F-  = character resets their Foot Forward
  75.  
  76.   * \font[fontname,fontsize] = change font name and font size
  77.   * \z[value]      = change z value from message  
  78.  
  79.   - message.auto_comma_pause = true/false
  80.   - message.auto_comma_delay = n
  81.   - message.opacity = (0-255)
  82.   - message.sound = true / false
  83.   - message.sound_audio = '001-System01'
  84.   - message.sound_volume = n
  85.   - message.sound_pitch = n
  86.   - message.sound_pitch_range = n
  87.   - message.sound_frequency = n
  88.   - message.sound_vary_pitch = true / false / 'random'
  89.   - message.shortcut[:(shortcut)] = 'Message'
  90.   - message.speech_windowskin  = [windowskin_name,tail_windowskin_name]
  91.   - message.thought_windowskin = [windowskin_name,tail_windowskin_name]
  92.   - message.message_log = true / false
  93.  
  94.   * fixed face sprite bug
  95.   * added message log  
  96.  
  97.   New in 1.5:
  98.   * \C[#ffffff] for hexadecimal color
  99.   * \C for return to default color
  100.   * display name of item, weapon, armor or skill
  101.     * \N[In] = display name of item with id n (note the "I")
  102.     * \N[Wn] = display name of weapon with id n (note the "W")
  103.     * \N[An] = display name of armor with id n (note the "A")
  104.     * \N[Sn] = display name of skill with id n (note the "S")
  105.   * display icon of item, weapon, armor or skill
  106.     * \I[In] = display icon of item with id n (note the "I")
  107.     * \I[Wn] = display icon of weapon with id n (note the "W")
  108.     * \I[An] = display icon of armor with id n (note the "A")
  109.     * \I[Sn] = display icon of skill with id n (note the "S")
  110.   * display icon and name of item, weapon, armor or skill
  111.     * \I&N[In] = display icon and name of item with id n (note the "I")
  112.     * \I&N[Wn] = display icon and name of weapon with id n (note the "W")
  113.     * \I&N[An] = display icon and name of armor with id n (note the "A")
  114.     * \I&N[Sn] = display icon and name of skill with id n (note the "S")
  115.   * new windowskins available
  116.   * speech windowskin now definable separately from default windowskin
  117.   * fixed bold bug where degree sign would occasionally appear
  118.   * input number window now shares parent window's font
  119.   * changed \Var[n] back to default of \V[n]
  120.  
  121.   New in 1.1:
  122.   * message.autocenter for automatically centering text within messages
  123.   * \N[en] for displaying name of enemy with id n (note the "e")
  124.   * \MAP for displaying the name of the current map
  125.  
  126.   At a glance:
  127.   * multiple message windows
  128.   * speech balloons
  129.     * position over player/event (follows movement and scrolling)
  130.     * optional message tail (for speech or thought balloons)
  131.     * can specify location relative to player/event (up, down, left, right)
  132.   * thought balloons
  133.     * can use different windowskin, message tail and font color
  134.   * letter-by-letter mode
  135.     * variable speed (and delays)
  136.     * skippable on button press
  137.   * autoresize messages
  138.   * player movement allowed during messages
  139.     * if speaker moves offscreen, message closes (like ChronoTrigger)
  140.   * everything also works during battle
  141.   * settings configurable at anytime  
  142.  
  143.   Full list of options:
  144.  
  145.   (Note that all are case *insensitive*.)
  146.  
  147.   =============================================================================
  148.    Local (specified in message itself and resets at message end)
  149.   =============================================================================
  150.   - \L = letter-by-letter mode toggle
  151.   - \S[n] = set speed at which text appears in letter-by-letter mode
  152.   - \D[n] = set delay (in frames) before next text appears
  153.   - \P[n] = position message over event with id n
  154.             * use n=0 for player
  155.             * in battle, use n=a,b,c,d for actors (e.g. \P[a] for first actor)
  156.               and n=1,...,n for enemies (e.g. \P[1] for first enemy)
  157.               where order is actually the reverse of troop order (in database)
  158.   - \P = position message over current event (default for floating messages)
  159.   - \^ = message appears directly over its event
  160.   - \v = message appears directly below its event
  161.   - \< = message appears directly to the left of its event
  162.   - \> = message appears directly to the right of its event
  163.   - \B = bold text
  164.   - \I = italic text
  165.   - \C[#xxxxxx] = change to color specified by hexadecimal (eg. ffffff = white)
  166.   - \C = change color back to default
  167.   - \! = message autoclose
  168.   - \? = wait for user input before continuing
  169.   - \+ = make message appear at same time as preceding one
  170.          * note: must be at the start of message to work
  171.   - \# = insert the last message with line text the preceding one      
  172.   - \@ = thought balloon
  173.   - \N[En] = display name of enemy with id n (note the "E")
  174.   - \N[Pn] = display name of event with id n (note the "P")
  175.   - \N[In] = display name of item with id n (note the "I")
  176.   - \N[Wn] = display name of weapon with id n (note the "W")
  177.   - \N[An] = display name of armor with id n (note the "A")
  178.   - \N[Sn] = display name of skill with id n (note the "S")
  179.   - \I[In] = display icon of item with id n (note the "I")
  180.   - \I[Wn] = display icon of weapon with id n (note the "W")
  181.   - \I[An] = display icon of armor with id n (note the "A")
  182.   - \I[Sn] = display icon of skill with id n (note the "S")
  183.   - \I&N[In] = display icon and name of item with id n (note the "I")
  184.   - \I&N[Wn] = display icon and name of weapon with id n (note the "W")
  185.   - \I&N[An] = display icon and name of armor with id n (note the "A")
  186.   - \I&N[Sn] = display icon and name of skill with id n (note the "S")
  187.   - \MAP = display the name of the current map
  188.  
  189.   These are, of course, in addition to the default options:
  190.   - \V[n] = display value of variable n
  191.   - \N[n] = display name of actor with id n
  192.   - \C[n] = change color to n
  193.   - \G = display gold window
  194.   - \\ = show the '\' character
  195.  
  196.   * Foot Forward Notes * - Sprite Sheets only have 16 total Frames of Animation
  197.     and of which, 4 are duplicates.  Foot Forward Options allow access to
  198.     ALL of the frames of animation available in Default Sprite Sheets.
  199.    
  200.   - \F+  = character puts their Foot Forward
  201.   - \F*  = character puts their Other Foot Forward
  202.   - \F-  = character resets their Foot Forward
  203.  
  204.   *NOTE* - Foot Forward Animation will RESET if the event is moved off screen.
  205.          - Change @auto_ff_reset if this feature causes you trouble with
  206.            character animations.
  207.    
  208.     It also ONLY works with the following conditions
  209.     - Direction Fix is OFF
  210.     - Move Animation is ON
  211.     - Stop Animation is OFF (technically thats Step, they typo'd)
  212.     - @auto_ff_reset is TRUE
  213.     - * These settings are the DEFAULT when a New Event is created
  214.    
  215.   =============================================================================
  216.    Global (specified below or by Call Script and persist until changed)
  217.   =============================================================================
  218.  
  219.   Zer0 Note:
  220.   If you use any of these in another script, etc. and not a script call, you
  221.   will need to place "$game_system." before each command.
  222.  
  223.   Miscellaneous:
  224.   - message.move_during = true/false
  225.     * allow/disallow player to move during messages
  226.   - message.show_pause = true/false
  227.     * show/hide "waiting for player" pause graphic
  228.   - message.autocenter = true/false
  229.     * enable/disable automatically centering text within messages
  230.   - message.auto_comma_pause = true/false
  231.     * inserts a delay before the next character after these characters ,!.?
  232.     * expects correct punctuation.  One space after a comma, the rest 2 spaces
  233.   - message.auto_comma_delay = n
  234.     * changes how long to wait after a pausable character
  235.   - message.auto_shrink = true/false
  236.     * shrink the balloon message to one liner, but enlarge after
  237.       exceeding one line
  238.   - message.opacity = (0-255)
  239.     * change opacity for every message
  240.   - message.speech_windowskin = [windowskin_name,tail_windowskin_name]
  241.   - message.thought_windowskin = [windowskin_name,tail_windowskin_name]
  242.  
  243.   Speech/thought balloon related:
  244.   - message.resize = true/false
  245.     * enable/disable automatic resizing of messages (only as big as necessary)
  246.   - message.floating = true/false
  247.     * enable/disable positioning messages above current event by default
  248.       (i.e. equivalent to including \P in every message)
  249.   - message.location = TOP, BOTTOM, LEFT or RIGHT
  250.     * set default location for floating messages relative to their event
  251.   - message.show_tail = true/false
  252.     * show/hide message tail for speech/thought balloons
  253.  
  254.   Letter-by-letter related:
  255.   - message.letter_by_letter = true/false
  256.     * enable/disable letter-by-letter mode (globally)
  257.   - message.text_speed = 0-20
  258.     * set speed at which text appears in letter-by-letter mode (globally)
  259.   - message.skippable = true/false
  260.     * allow/disallow player to skip to end of message with button press
  261.  
  262.   Font:
  263.   - message.font_name = font
  264.     * set font to use for text, overriding all defaults
  265.       (font can be any TrueType from Windows/Fonts folder)
  266.   - message.font_size = size
  267.     * set size of text  (default 22), overriding all defaults
  268.   - message.font_color = color
  269.     * set color of text, overriding all defaults
  270.     * you can use same 0-7 as for \C[n] or "#xxxxxx" for hexadecimal
  271.    
  272.   Sound related:
  273.  
  274.   - message.sound = true / false
  275.     * Enables or Disables Text Sounds  
  276.   - message.sound_audio = '001-System01'    
  277.     * Audio SE (in DB) to play
  278.   - message.sound_volume = n
  279.     * Text Sound Volume (0 - 100)
  280.   - message.sound_pitch = n
  281.     * Text Sound Pitch (100 is default)
  282.   - message.sound_pitch_range = n
  283.     * How Much to vary the Pitch (10 = pitch of 90 to 110 with base 100)
  284.   - message.sound_frequency = n
  285.     * Plays a sound this many letters  
  286.   - message.sound_vary_pitch = true / false / 'random'    
  287.     *  Whether to Vary the Pitch or not, or totally randomize
  288.     ** If random, use quotes and lower case: 'random'    
  289.  
  290.   Note that the default thought and shout balloon windowskins don't
  291.   stretch to four lines very well (unfortunately).
  292.    
  293.   Thanks:
  294.   XRXS code for self-close and wait for input
  295.   Slipknot for a convenient approach to altering settings in-game
  296.   SephirothSpawn for bitmap rotate method
  297.   Heretic86 for Sound related method, auto comma delay and fixed choice bug
  298.   ThallionDarkshine for Animated Letter
  299.  
  300. =end
  301.  
  302. #==============================================================================
  303. # Settings
  304. #==============================================================================
  305.  
  306.   # Zer0 Edit. Blizzard's Simple Shaded Text just looks kinda funny when used
  307.   # on black text (which is default for MMS). If you are using Shaded Text and
  308.   # do not want it to display for the message windows, set this to true. It will
  309.   # still show for everything else.
  310.  
  311.   Blizzard_Shaded_Text_Fix = true
  312.  
  313.   #----------------------------------------------------------------------------
  314.   # Windowskins
  315.   #----------------------------------------------------------------------------
  316.   # Note: all files must be in the Graphics/Windowskins/ folder
  317.   # Tip: tails don't look right on windowskins with gradient backgrounds
  318.  
  319.   # filenames of tail and windowskin used for speech balloons
  320.   FILENAME_SPEECH_TAIL        = 'white-tail_speech.png'
  321.   FILENAME_SPEECH_WINDOWSKIN  = 'white-windowskin_speech.png'
  322.  
  323.   # filenames of tail and windowskin used for thought balloons
  324.   FILENAME_THOUGHT_TAIL       = 'white-tail_thought.png'
  325.   FILENAME_THOUGHT_WINDOWSKIN = 'white-windowskin_thought.png'
  326.  
  327.   #----------------------------------------------------------------------------
  328.   # MESSAGE LOG
  329.   #----------------------------------------------------------------------------
  330.   # this will used for message log
  331.   MESSAGE_LOG_TEXT            = 'MESSAGE LOG'
  332.   MESSAGE_LOG_FONT            = [Font.default_name, 'Arial', 30]
  333.   MESSAGE_LOG_WINDOWSKIN      = '001-Blue01'
  334.   MESSAGE_LOG_OPACITY         = 180
  335.   #----------------------------------------------------------------------------
  336.   # Fonts
  337.   #----------------------------------------------------------------------------
  338.   # Note: if floating or resize (i.e. 'speech balloons') are disabled,
  339.   # Font.default_name, Font.default_size and Font.default_color are used
  340.   # (you can change these in Main)
  341.   # During gameplay, you can use message.font_name etc to override all defaults
  342.  
  343.   # defaults for speech text
  344.   SPEECH_FONT_COLOR   = "#000000"
  345.   SPEECH_FONT_NAME    = ['Comic Sans MS', 'Arial']
  346.   SPEECH_FONT_SIZE    = 20
  347.  
  348.   # defaults for thought text
  349.   THOUGHT_FONT_COLOR  = "#000000"
  350.   THOUGHT_FONT_NAME   = ['Comic Sans MS', 'Arial']
  351.   THOUGHT_FONT_SIZE   = 20
  352.  
  353.   # note that you can use an array of fonts for SPEECH_FONT_NAME, etc.
  354.   # e.g. ['Verdana', 'MS PGothic']
  355.   # (if Verdana is not available, MS PGothic will be used instead)
  356.  
  357.   #----------------------------------------------------------------------------
  358.   # Misc
  359.   #----------------------------------------------------------------------------
  360.   # If using a specialty windowskin (e.g. the default thought balloon one),
  361.   # you can force the window width to always be a multiple of the number
  362.   # specified in this constant (even when using the resize feature).
  363.   # This allows, for example, the windowskin frame to be designed to
  364.   # repeat every 16 pixels so that the frame never looks cut off.
  365.   THOUGHT_WIDTH_MULTIPLE = 16
  366.   # (set to 0 if you're not using any such windowskins)
  367.  
  368. class Game_Message
  369.  
  370.   # Any of the below can be changed by a Call Script event during gameplay.
  371.   # E.g. turn letter-by-letter mode off with: message.letter_by_letter = false
  372.  
  373.   attr_accessor :speech_windowskin
  374.   attr_accessor :thought_windowskin
  375.   attr_accessor :message_log
  376.   attr_accessor :move_during
  377.   attr_accessor :letter_by_letter
  378.   attr_accessor :text_speed
  379.   attr_accessor :skippable
  380.   attr_accessor :resize
  381.   attr_accessor :floating
  382.   attr_accessor :autocenter
  383.   attr_accessor :show_tail
  384.   attr_accessor :show_pause
  385.   attr_accessor :location
  386.   attr_accessor :font_name
  387.   attr_accessor :font_size
  388.   attr_accessor :font_color
  389.   attr_accessor :auto_shrink
  390.   attr_accessor :opacity
  391.   attr_accessor :auto_comma_pause
  392.   attr_accessor :auto_comma_delay
  393.   attr_accessor :allow_cancel_numbers
  394.   attr_accessor :sound            
  395.   attr_accessor :sound_audio
  396.   attr_accessor :sound_volume
  397.   attr_accessor :sound_pitch
  398.   attr_accessor :sound_pitch_range
  399.   attr_accessor :sound_vary_pitch
  400.   attr_accessor :sound_frequency  
  401.   attr_accessor :shortcut  
  402.   attr_accessor :auto_ff_reset
  403.   attr_accessor :cinema
  404.   attr_accessor :cinema_z
  405.   attr_accessor :reposition_on_turn
  406.   attr_accessor :allow_offscreen
  407.   attr_accessor :dist_exit
  408.   attr_accessor :dist_max
  409.  
  410.   def default_setting
  411.     # change windowskin at message
  412.     @speech_windowskin  = [FILENAME_SPEECH_WINDOWSKIN,  FILENAME_SPEECH_TAIL ]
  413.     @thought_windowskin = [FILENAME_THOUGHT_WINDOWSKIN, FILENAME_THOUGHT_TAIL]
  414.    
  415.     # enable/disable message log
  416.     @message_log = true
  417.  
  418.     # whether or not messages appear one letter at a time
  419.     @letter_by_letter = true
  420.     # note: can also change within a single message with \L
  421.  
  422.     # the default speed at which text appears in letter-by-letter mode
  423.     @text_speed = 1
  424.     # note: can also change within a single message with \S[n]
  425.    
  426.     # whether or not players can skip to the end of (letter-by-letter) messages
  427.     @skippable = true
  428.    
  429.     # whether or not messages are automatically resized based on the message
  430.     @resize = true
  431.    
  432.     # whether or not message windows are positioned above
  433.     # characters/events by default, i.e. without needing \P every message
  434.     # (only works if resize messages enabled -- otherwise would look very odd)
  435.     @floating = true
  436.    
  437.     # whether or not to automatically center lines within the message
  438.     @autocenter = true
  439.    
  440.     # whether or not event-positioned messages have a tail(for speech balloons)
  441.     # (only works if floating and resized messages enabled -- otherwise would
  442.     # look very odd indeed)
  443.     @show_tail = true
  444.    
  445.     # whether or not to display "waiting for user input" pause graphic
  446.     # (probably want this disabled for speech balloons)
  447.     @show_pause = false
  448.  
  449.     # whether the player is permitted to move while messages are displayed
  450.     @move_during = true
  451.    
  452.     # the default location for floating messages (relative to the event)
  453.     # note that an off-screen message will be "flipped" automatically
  454.     @location = TOP
  455.    
  456.     # font details
  457.     # overrides all defaults; leave nil to just use defaults (e.g. as above)
  458.     @font_name = nil
  459.     @font_size = nil
  460.     @font_color = nil
  461.    
  462.     # auto shrink (buggy)
  463.     @auto_shrink = false
  464.    
  465.     # message opacity, insert 0-255
  466.     @opacity = 180
  467.    
  468.    
  469.     # pause on these characters ,.?!
  470.     # pause for delay number of frames if this is true, toggle with \A in Text
  471.     @auto_comma_pause = true
  472.     # inserts this number of frames to ,!.? characters, nil for off    
  473.     @auto_comma_delay = 10
  474.    
  475.     # designers can allow or disallow choices, why not number windows too?
  476.     @allow_cancel_numbers = false
  477.    
  478.     # Sounds While Speaking Related
  479.     @sound = false                          # Enables or Disables Text Sounds  
  480.     @sound_audio = '001-System01'          # Audio SE (in DB) to play
  481.     @sound_volume = 80                     # Text Sound Volume
  482.     @sound_pitch = 100                     # Text Sound Pitch
  483.     @sound_pitch_range = 20                # How Much to vary the Pitch
  484.     @sound_vary_pitch = true               # Whether to Vary the Pitch or not
  485.     @sound_frequency = 3                   # Plays a sound this many letters
  486.    
  487.     # reset foot_forward stance on auto-close due to Event going off-screen
  488.     @auto_ff_reset = true
  489.    
  490.     # For shortcut reference
  491.     @shortcut = {
  492.        :A => 'This is for shortcut purposes',
  493.        :Wdyt => 'What do you think?',
  494.     }
  495.    
  496.     @cinema = false # Cinema movie flag (don't change it)
  497.     @cinema_z = 900 # Screen z for cinema movie mode
  498.    
  499.     # reposition the message window if the speaker turns
  500.     @reposition_on_turn = true
  501.     @allow_offscreen = false
  502.    
  503.     # exit if distance from speaker is too great
  504.     @dist_exit = true
  505.     # distance player can be before window closes
  506.     @dist_max = 4
  507.   end
  508.  
  509. #==============================================================================
  510. # Private constants (don't edit)
  511. #==============================================================================
  512.  
  513.   # used for message.location
  514.   TOP    = 8
  515.   BOTTOM = 2
  516.   LEFT   = 4
  517.   RIGHT  = 6
  518.  
  519. end
  520. #==============================================================================
  521. # ? SG::Skin
  522. #==============================================================================
  523.  
  524. class Skin_Windowskin
  525.   #--------------------------------------------------------------------------
  526.   # ? instances settings
  527.   #--------------------------------------------------------------------------
  528.   attr_accessor  :margin, :bitmap
  529.   #--------------------------------------------------------------------------
  530.   # ? initialize
  531.   #--------------------------------------------------------------------------
  532.   def initialize
  533.     @bitmap = nil
  534.     @values = {}
  535.     @values['bg'] = Rect.new(0, 0, 128, 128)
  536.     @values['pause0'] = Rect.new(160, 64, 16, 16)
  537.     @values['pause1'] = Rect.new(176, 64, 16, 16)
  538.     @values['pause2'] = Rect.new(160, 80, 16, 16)
  539.     @values['pause3'] = Rect.new(176, 80, 16, 16)
  540.     @values['arrow_up'] = Rect.new(152, 16, 16, 8)
  541.     @values['arrow_down'] = Rect.new(152, 40, 16, 8)
  542.     @values['arrow_left'] = Rect.new(144, 24, 8, 16)
  543.     @values['arrow_right'] = Rect.new(168, 24, 8, 16)
  544.     self.margin = 16
  545.   end
  546.   #--------------------------------------------------------------------------
  547.   # ? width
  548.   #--------------------------------------------------------------------------
  549.   def margin=(width)
  550.     @margin = width
  551.     set_values
  552.   end
  553.   #--------------------------------------------------------------------------
  554.   # ? set_values
  555.   #--------------------------------------------------------------------------
  556.   def set_values
  557.     w = @margin
  558.     @values['ul_corner'] = Rect.new(128, 0, w, w)
  559.     @values['ur_corner'] = Rect.new(192-w, 0, w, w)
  560.     @values['dl_corner'] = Rect.new(128, 64-w, w, w)
  561.     @values['dr_corner'] = Rect.new(192-w, 64-w, w, w)
  562.     @values['up'] = Rect.new(128+w, 0, (64-2*w), w)
  563.     @values['down'] = Rect.new(128+w, 64-w, (64-2*w), w)
  564.     @values['left'] = Rect.new(128, w, w, (64-2*w))
  565.     @values['right'] = Rect.new(192-w, w, w, (64-2*w))
  566.   end
  567.   #--------------------------------------------------------------------------
  568.   # ? []
  569.   #--------------------------------------------------------------------------
  570.   def [](value) @values[value] end
  571. end
  572.  
  573. #==============================================================================
  574. # ** Window_Message
  575. #------------------------------------------------------------------------------
  576. #  This message window is used to display text.
  577. #==============================================================================
  578. class Window_Message < Window_Selectable
  579.   #--------------------------------------------------------------------------
  580.   # * Public Instance Variables
  581.   #--------------------------------------------------------------------------
  582.   attr_accessor :choice_window, :event_id
  583.   # Characters that produce Text Sounds - a to z and 0 thru 9
  584.   CHARACTERS = [('a'..'z'),('0'..'9')].map{|i| i.to_a}.flatten
  585.   #--------------------------------------------------------------------------
  586.   # * Initialize
  587.   #--------------------------------------------------------------------------
  588.   def initialize(msgindex=0)
  589.     super(80, 304, 480, 160)
  590.     self.contents = Bitmap.new(width - 32, height - 32)
  591.     self.visible = false
  592.     self.z = 1000 + msgindex * 10 # permits messages to overlap legibly
  593.     $game_system.update if !$game_system.message
  594.     message_eval('message.default_setting if !message.text_speed')
  595.     @fade_in = @fade_out = @contents_showing = false
  596.     @cursor_width = 0
  597.     self.active = false
  598.     self.index = -1
  599.     @msgindex = msgindex
  600.     @tail = Sprite.new
  601.     create_bitmap_tail
  602.     # make origin the center, not top left corner
  603.     @tail.ox = @tail.bitmap.width/2
  604.     @tail.oy = @tail.bitmap.height/2
  605.     @tail.z = self.z + 10
  606.     @tail.visible = false
  607.     create_bitmap_windowskin
  608.     refresh_font
  609.     @update_text = true
  610.     @letter_by_letter = $game_system.message.letter_by_letter
  611.     @text_speed       = $game_system.message.text_speed
  612.     # id of character for speech balloons
  613.     @float_id = nil
  614.     # location of box relative to speaker
  615.     @location         = $game_system.message.location
  616.     @auto_ff_reset    = $game_system.message.auto_ff_reset
  617.     @fwindowskin      = Sprite.new
  618.     @fwindowskin.bitmap = Bitmap.new(640,480)
  619.   end
  620.   #--------------------------------------------------------------------------
  621.   # * create_bitmap_tail
  622.   #--------------------------------------------------------------------------
  623.   def create_bitmap_tail
  624.     @tail.bitmap = if @speech_windowskin && @speech_windowskin.is_a?(Array) &&
  625.       FileTest.exist?('Graphics/Windowskins/'+@speech_windowskin[1])
  626.         if @msgindex == 0
  627.           RPG::Cache.windowskin(@speech_windowskin[1])
  628.         else
  629.           # don't use cached version or else all tails
  630.           # are rotated when multiple are visible at once
  631.           Bitmap.new('Graphics/Windowskins/'+@speech_windowskin[1])
  632.         end
  633.       else
  634.         RPG::Cache.windowskin('')
  635.       end
  636.     # keep track of orientation of tail bitmap
  637.     @tail.bitmap.orientation = 0 if @tail.bitmap.orientation == nil
  638.   end
  639.   #--------------------------------------------------------------------------
  640.   # * create_bitmap_windowskin
  641.   #--------------------------------------------------------------------------
  642.   def create_bitmap_windowskin
  643.     @windowskin = if $game_system.message.floating && @speech_windowskin &&
  644.         $game_system.message.resize &&  @speech_windowskin.is_a?(Array) &&
  645.          FileTest.exist?('Graphics/Windowskins/'+@speech_windowskin[0])
  646.         @speech_windowskin[0]
  647.       else
  648.         # use windowskin specified in database
  649.         $game_system.windowskin_name
  650.       end
  651.   end
  652.   #--------------------------------------------------------------------------
  653.   # * refresh font
  654.   #--------------------------------------------------------------------------
  655.   def refresh_font
  656.     if $game_system.message.floating && $game_system.message.resize
  657.       # if used as speech balloons, use constants
  658.       @font_name  = ($game_system.message.font_name || SPEECH_FONT_NAME)
  659.       @font_size  = ($game_system.message.font_size || SPEECH_FONT_SIZE)
  660.       @font_color = check_color(($game_system.message.font_color ||
  661.                     SPEECH_FONT_COLOR))
  662.     else
  663.       # use default font
  664.       @font_name  = Font.default_name
  665.       @font_size  = Font.default_size
  666.       @font_color = Font.default_color
  667.     end
  668.   end
  669.   #--------------------------------------------------------------------------
  670.   # * Dispose
  671.   #--------------------------------------------------------------------------
  672.   def dispose
  673.     terminate_message
  674.     # have to check all windows before claiming that no window is showing
  675.     if $game_temp.message_text.compact.empty?
  676.       $game_temp.message_window_showing = false
  677.     end
  678.     @fwindowskin.dispose if !@fwindowskin.disposed?
  679.     @input_number_window.dispose if @input_number_window != nil
  680.     super
  681.   end
  682.   #--------------------------------------------------------------------------
  683.   # * Terminate Message
  684.   #--------------------------------------------------------------------------
  685.   def terminate_message
  686.     return if $game_temp.input_in_window
  687.     self.active = false
  688.     self.pause = false
  689.     self.index = -1
  690.     self.contents.clear
  691.     @fwindowskin.bitmap.clear if @fwindowskin && !@fwindowskin.disposed?
  692.     # Clear showing flag
  693.     @contents_showing = false
  694.     # Clear variables related to text, choices, and number input
  695.     @tail.visible = false
  696.     # note that these variables are now indexed arrays
  697.     $game_temp.message_text = [] if !$game_temp.message_text.is_a?(Array)
  698.     $game_temp.message_proc = [] if !$game_temp.message_proc.is_a?(Array)
  699.     $game_temp.message_text[@msgindex] = nil
  700.     # Call message callback
  701.     if $game_temp.message_proc[@msgindex] != nil
  702.       # make sure no message boxes are displaying
  703.       if $game_temp.message_text.compact.empty?
  704.         $game_temp.message_proc[@msgindex].call
  705.         message_interpreter.class.send(:attr_accessor,:message_waiting)
  706.         #message_interpreter.class.send(:attr_accessor,:wait_count)
  707.         #message_interpreter.wait_count += 2
  708.         $game_temp.message_window_showing = false  
  709.         message_interpreter.message_waiting = false
  710.       end
  711.       $game_temp.message_proc[@msgindex] = nil
  712.     end
  713.     @update_text = true
  714.     $game_temp.choice_start = 99
  715.     $game_temp.choice_max = 0
  716.     $game_temp.choice_cancel_type = 0
  717.     $game_temp.choice_proc = nil
  718.     $game_temp.num_input_start = 99
  719.     $game_temp.num_input_variable_id = 0
  720.     $game_temp.num_input_digits_max = 0
  721.     # Open gold window
  722.     if @gold_window != nil
  723.       @gold_window.dispose
  724.       @gold_window = nil
  725.     end
  726.   end
  727.   #--------------------------------------------------------------------------
  728.   # * replace_basic_code
  729.   #--------------------------------------------------------------------------
  730.   def replace_basic_code
  731.     # Change "\\\\" to "\000" for convenience
  732.     @text.gsub!(/\\\\/) { "\000" }
  733.     @text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
  734.     @text.gsub!('\$') { $game_party.gold.to_s }
  735.     @text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
  736.        $game_actors[$1.to_i] ? $game_actors[$1.to_i].name : ''
  737.     end
  738.   end
  739.  
  740.   #--------------------------------------------------------------------------
  741.   # * Alias Listing
  742.   #--------------------------------------------------------------------------
  743.   $@ || alias_method(:replace_basic_code_addition, :replace_basic_code)
  744.   #--------------------------------------------------------------------------
  745.   # * replace_basic_code
  746.   #--------------------------------------------------------------------------
  747.   def replace_basic_code
  748.     @text.gsub!(/\\[Nn][Aa][Mm][Ee]\[([0-9]+)\]/) {  "\\n[#{$1}]" }
  749.     replace_basic_code_addition
  750.     @text.gsub!(/\\[Gg]/) { "\002" }
  751.     # display icon of item, weapon, armor or skill
  752.     @text.gsub!(/\\[Ii]\[([IiWwAaSs][0-9]+)\]/) { "\013[#{$1}]" }
  753.     # display name of enemy, item, weapon, armor or skill
  754.     @text.gsub!(/\\[Nn]\[([EeIiWwAaSsPp])([0-9]+)\]/) {
  755.       entity = case $1.downcase
  756.         when 'e' then $data_enemies[$2.to_i]
  757.         when 'i' then $data_items[$2.to_i]
  758.         when 'w' then $data_weapons[$2.to_i]
  759.         when 'a' then $data_armors[$2.to_i]
  760.         when 's' then $data_skills[$2.to_i]
  761.         when 'p' then $game_map.events[$2.to_i]
  762.       end
  763.       entity != nil ? entity.name : ''   }
  764.     # display icon and name of item, weapon, armor or skill
  765.     @text.gsub!(/\\[Ii]&[Nn]\[([IiWwAaSs])([0-9]+)\]/) {
  766.       entity = case $1.downcase
  767.         when 'e' then $data_enemies[$2.to_i]
  768.         when 'i' then $data_items[$2.to_i]
  769.         when 'w' then $data_weapons[$2.to_i]
  770.         when 'a' then $data_armors[$2.to_i]
  771.         when 's' then $data_skills[$2.to_i]
  772.       end
  773.       entity != nil ? "\013[#{$1+$2}] " + entity.name : ''  }      
  774.     # display name of current map
  775.     @text.gsub!(/\\[Mm][Aa][Pp]/) { $game_map.name }
  776.     # change font color
  777.     @text.gsub!(/\\[Cc]\[([0-9]+|#[0-9A-Fa-f]{6,6})\]/) { "\001[#{$1}]" }
  778.     # return to default color
  779.     @text.gsub!(/\\[Cc]/) { "\001" }
  780.     # toggle letter-by-letter mode
  781.     @text.gsub!(/\\[Ll]/) { "\003" }
  782.     # change text speed (for letter-by-letter)
  783.     @text.gsub!(/\\[Ss]\[([0-9]+)\]/) { "\004[#{$1}]" }
  784.     # insert delay
  785.     @text.gsub!(/\\[Dd]\[([0-9]+)\]/) { "\005[#{$1}]" }      
  786.     # change z
  787.     @text.gsub!(/\\[Zz]\[([0-9]+)\]/) { "\024[#{$1}]" }      
  788.    
  789.    
  790.     # self close message
  791.     @text.gsub!(/\\[!]/) { "\006" }
  792.     # wait for button input
  793.     @text.gsub!(/\\[?]/) { "\007" }
  794.     # bold
  795.     @text.gsub!(/\\[Bb]/) { "\010" }
  796.     # italic
  797.     @text.gsub!(/\\[Ii]/) { "\011" }
  798.     # new line
  799.     @text.gsub!(/\\[n]/) { "\n" }
  800.     # name
  801.     @text.gsub!(/\\[Ff][Oo][Nn][Tt]\[(.+?),([0-9]+)\]/) { "\023[#{$1},#{$2}]" }
  802.     @text.gsub!(/\\[Ff]\+/) { "\020" }
  803.     @text.gsub!(/\\[Ff]\-/) { "\021" }      
  804.     @text.gsub!(/\\[Ff]\*/) { "\022" }        
  805.     @text.gsub!(/\\[Ff]\[(.+?)(?:,(\d+))?\]/) { "\014[#{$1}]" }
  806.     @text.gsub!(/\\[Aa]\[([0-9]+),([0-9]+)\]/) { "\015[#{$1},#{$2}]" }
  807.     @text.gsub!(/\\[Aa]\[(.+?)(?:(\d+))?\]/) { "\016[#{$1}]" }
  808.     @text.gsub!(/\\[Rr]\[(.+?)\]/) { "\017[#{$1}]" }
  809.     # insert delays for commas, periods, questions and exclamations
  810.     @text.gsub!(/, /) { ", \017[#d]" }    # Comma with One Space
  811.     @text.gsub!(/!  /) { "!  \017[#d]" }  # Exclamation Point with Two Spaces
  812.     @text.gsub!(/\?  /) { "?  \017[#d]"} # Question Mark with Two Spaces
  813.     @text.gsub!(/\.  /) { ".  \017[#d]" } # Period with Two Spaces
  814.    
  815.     @text.gsub!(/\\[*]/, '<!@multi_message, @message_waiting = true, false>')
  816.     @text.gsub!(/\\[Mm][Oo][Vv]/) { '<!message.cinema = !message.cinema>' }
  817.     @text.gsub!(/\\[Dd][Ii][Ss][Tt]\[([0-9]+)\]/) { "<@@dist = #{$1}>" }
  818.     @text.gsub!(/[<][!](.+?)[>]/) { "\017[#si#{$1}]" }
  819.     @text.gsub!(/[<][@](.+?)[>]/) { "\017[#ss#{$1}]" }
  820.   end
  821.   #--------------------------------------------------------------------------
  822.   # * replace_technical_code
  823.   #--------------------------------------------------------------------------
  824.   def replace_technical_code
  825.     if @text.gsub!(/\\[Ee]\[([0-9]+),([0-9]+)\]/, '') != nil
  826.       @float_id = $1.to_i
  827.       @location = case $2.to_i
  828.         when 1..2 then 2
  829.         when 3..4 then 4
  830.         when 5..6 then 6
  831.         else 8
  832.       end
  833.     end
  834.     # thought balloon
  835.     if @text.gsub!(/\\[@]/, '') != nil
  836.       @windowskin = @thought_windowskin && @thought_windowskin.is_a?(Array) &&
  837.           FileTest.exist?('Graphics/Windowskins/'+@thought_windowskin[0]) ?
  838.           @thought_windowskin[0] : $game_system.windowskin_name
  839.       @font_name = THOUGHT_FONT_NAME
  840.       @font_size = THOUGHT_FONT_SIZE
  841.       @font_color = check_color(THOUGHT_FONT_COLOR)
  842.       @tail.bitmap = if @thought_windowskin &&
  843.         @thought_windowskin.is_a?(Array) &&
  844.         FileTest.exist?('Graphics/Windowskins/'+@thought_windowskin[1])
  845.           if @msgindex == 0
  846.             RPG::Cache.windowskin(@thought_windowskin[1])
  847.           else
  848.             Bitmap.new('Graphics/Windowskins/'+@thought_windowskin[1])
  849.           end
  850.         else
  851.           RPG::Cache.windowskin('')
  852.         end
  853.       @tail.bitmap.orientation ||= 0
  854.     end
  855.     # Get rid of "\\+" (multiple messages)
  856.     @text.gsub!(/\\[+]/, '')
  857.     @text.gsub!(/\\[#]/, '')
  858.     # Get rid of "\\P" (position window to given character)
  859.     if @text.gsub!(/\\[Pp]\[([0-9]+),([0-9]+)\]/, '') != nil
  860.       @float_id = [$1.to_i,$2.to_i]
  861.     elsif @text.gsub!(/\\[Pp]\[([0-9]+)\]/, '') != nil
  862.       @float_id = $1.to_i
  863.     elsif @text.gsub!(/\\[Pp]\[([a-zA-Z])\]/, '') != nil &&
  864.         $game_temp.in_battle
  865.       @float_id = $1.downcase
  866.     elsif @text.gsub!(/\\[Pp]/, '') != nil ||
  867.       ($game_system.message.floating && $game_system.message.resize) &&
  868.       (!$game_temp.in_battle)
  869.       message_interpreter.class.send(:attr_reader, :event_id)
  870.       @float_id = message_interpreter.event_id
  871.     end
  872.    
  873.     # Get rid of "\\^", "\\v", "\\<", "\\>" (relative message location)
  874.     if @text.gsub!(/\\\^/, '') != nil
  875.       @location = 8
  876.     elsif @text.gsub!(/\\[Vv]/, '') != nil
  877.       @location = 2
  878.     elsif @text.gsub!(/\\[<]/, '') != nil
  879.       @location = 4
  880.     elsif @text.gsub!(/\\[>]/, '') != nil
  881.       @location = 6
  882.     elsif @text.gsub!(/\\[%]/, '') != nil && !$game_temp.in_battle    
  883.       e = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  884.       @auto_orient = 1    
  885.       @location = case e.direction
  886.       when 8 then 2
  887.       when 2 then 8
  888.       when 6 then 4
  889.       when 4 then 6
  890.       end
  891.     end
  892.   end
  893.   #--------------------------------------------------------------------------
  894.   # * Refresh
  895.   #--------------------------------------------------------------------------
  896.   def refresh
  897.     self.contents.clear
  898.     @fwindowskin.bitmap.clear if @fwindowskin && !@fwindowskin.disposed?
  899.     @x = @y = 0 # now instance variables
  900.     @float_id = nil
  901.     @location = $game_system.message.location
  902.     @speech_windowskin  = $game_system.message.speech_windowskin
  903.     @thought_windowskin = $game_system.message.thought_windowskin
  904.     refresh_font
  905.     # override font defaults
  906.     @line_widths = nil
  907.     @wait_for_input = false
  908.     create_bitmap_windowskin
  909.     create_bitmap_tail
  910.     @dist_exit = $game_system.message.dist_exit
  911.     @dist_max = $game_system.message.dist_max
  912.     @text_speed = $game_system.message.text_speed
  913.     @letter_by_letter = $game_system.message.letter_by_letter
  914.     @delay = @text_speed
  915.     @player_skip = false
  916.     @cursor_width = 0
  917.     # Indent if choice
  918.     if $game_temp.choice_start == 0
  919.       @x = 8
  920.     end
  921.     # If waiting for a message to be displayed
  922.     if $game_temp.message_text[@msgindex] != nil
  923.       @text = $game_temp.message_text[@msgindex] # now an instance variable
  924.       # Control text processing
  925.       begin
  926.         last_text = @text.clone
  927.         @text.gsub!(/\[:(.+?)\]/) { $game_system.message.shortcut[$1.to_sym] }
  928.         @text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
  929.       end until @text == last_text      
  930.       replace_basic_code
  931.       replace_technical_code
  932.       ufmt = @text.clone
  933.       ufmt.gsub!(/[\001-\007](\[[#A-Fa-f0-9]+\])?/, '')
  934.       ufmt.gsub!(/\013\[(.+?)\]/, '\013')
  935.       ufmt.gsub!(/[\014-\017](\[(.+?)(?:(\d+))?\])?/, '')
  936.       ufmt.gsub!(/\016\[(.+?),(.+?)\]/, '')
  937.       ufmt.gsub!(/[\020-\025]\[(.+?),([0-9]+)\]?/, '')
  938.       @text.gsub!(/\\[Aa][Nn][Ii](?:\[([0-9]+)\])?/, '')
  939.       if $game_system.message.resize || $game_system.message.autocenter
  940.         # calculate length of lines
  941.         text = ufmt.clone
  942.         temp_bitmap = Bitmap.new(1,1)
  943.         temp_bitmap.font.name = @font_name
  944.         temp_bitmap.font.size = @font_size
  945.         @linerenew = false
  946.         @line_widths = [0,0,0,0,0,0,0,0]
  947.         #(0..@line_widths.size-1).each  do |i|
  948.         @line_widths.each_with_index  do |a,i|
  949.           line = text.split(/\n/)[@line_widths.size-1-i]
  950.           next if line.nil?
  951.           line.gsub!(/\\[Aa][Nn][Ii](?:\[([0-9]+)\])?/, '')
  952.           line.chomp.split(//).each do |c|
  953.             case c
  954.             when "\000"
  955.               c = "\\"
  956.             when "\010"
  957.               # bold
  958.               temp_bitmap.font.bold = !temp_bitmap.font.bold
  959.               next
  960.             when "\011"
  961.               # italics
  962.               temp_bitmap.font.italic = !temp_bitmap.font.italic
  963.               next
  964.             when "\013"
  965.               # icon
  966.               @line_widths[@line_widths.size-1-i] += 24
  967.               next
  968.             end
  969.             @line_widths[@line_widths.size-1-i] += temp_bitmap.text_size(c).width
  970.           end
  971.           if (@line_widths.size-1-i) >= $game_temp.choice_start
  972.             # account for indenting
  973.             @line_widths[@line_widths.size-1-i] += 8 unless $game_system.message.autocenter
  974.           end
  975.         end
  976.         if $game_temp.num_input_variable_id > 0
  977.           # determine cursor_width as in Window_InputNumber
  978.           # (can't get from @input_number_window because it doesn't exist yet)
  979.           cursor_width = temp_bitmap.text_size('0').width + 8
  980.           # use this width to calculate line width (+8 for indent)
  981.           input_number_width = cursor_width*$game_temp.num_input_digits_max
  982.           input_number_width += 8 unless $game_system.message.autocenter
  983.           @line_widths[$game_temp.num_input_start] = input_number_width
  984.         end
  985.         temp_bitmap.dispose
  986.       end
  987.       resize
  988.       @float_id && reposition
  989.       self.contents.font.name = @font_name
  990.       self.contents.font.size = @font_size
  991.       self.contents.font.color = @font_color
  992.       self.windowskin = RPG::Cache.windowskin(@windowskin)
  993.       # autocenter first line if enabled
  994.       # (subsequent lines are done as '\n' is encountered)
  995.       if $game_system.message.autocenter && @text != ''
  996.         @x = (self.width-40)/2 - @line_widths[0]/2
  997.       end
  998.       @animations && @animations.each { |ani|
  999.         ani.disposed? ||  [ani.bitmap.dispose, ani.dispose]
  1000.       }
  1001.       @letter_animations && @letter_animations.each { |ani| ani.dispose }
  1002.       @animations, @letter_animations = [], []
  1003.       temp_bitmap = Bitmap.new(1,1)
  1004.       temp_bitmap.font.name = @font_name
  1005.       temp_bitmap.font.size = @font_size
  1006.       animation = [0, []]
  1007.       lanimation = [0, []]
  1008.       x, y = 0, 0
  1009.       center = $game_system.message.autocenter
  1010.       if (center && x == (self.width-40)/2 - @line_widths[0]/2)  ||
  1011.          (!center && x == 0)
  1012.          x = center ? ((self.width-40)/2 - @line_widths[0]/2) : 0
  1013.       end
  1014.       # Update cursor width if choice
  1015.       if $game_temp.choice_start == 0
  1016.         width = $game_system.message.autocenter ? @line_widths[y]+8 : x
  1017.       end
  1018.       ufmt.gsub!(/\\[Aa][Nn][Ii]/) { "\001" }
  1019.       if $game_system.message.autocenter && ufmt != ''
  1020.         x = (self.width-40)/2 - @line_widths[y]/2 if @line_widths[y]
  1021.       else
  1022.         x = 0
  1023.         # Indent if choice
  1024.         x = 8 if $game_temp.choice_start == 0
  1025.       end
  1026.       while ((c = ufmt.slice!(/./m)) != nil)
  1027.         case c
  1028.         when "\000"
  1029.           c = "\\"
  1030.         when "\010"
  1031.           temp_bitmap.font.bold = !temp_bitmap.font.bold
  1032.           next
  1033.         when "\011"
  1034.           temp_bitmap.font.italic = !temp_bitmap.font.italic
  1035.           next
  1036.         when "\001"
  1037.           if animation[0] != 0
  1038.             animation[1][-1].width = x + 4 - animation[1][-1].x
  1039.             @animations.push(animation)
  1040.           elsif lanimation[0] != 0
  1041.             @letter_animations.push(lanimation)
  1042.           end
  1043.           animation = [0, []]
  1044.           lanimation = [0, []]
  1045.           if ufmt.index(/\[(\d+)\]/) == 0
  1046.             ufmt.sub!(/\[(\d+)\]/, '')
  1047.             type = $1.to_i
  1048.             if type == 0
  1049.               animation[1] = []
  1050.             elsif type <= 8
  1051.               animation[0] = $1.to_i
  1052.               animation[1].push(Rect.new(4 + x, 32 * y, 0, 32))
  1053.             else
  1054.               lanimation[0] = $1.to_i - 8
  1055.             end
  1056.           else
  1057.             animation[0] = 0
  1058.             lanimation[0] = 0
  1059.           end
  1060.           next
  1061.         when "\n"
  1062.           if animation[0] != 0
  1063.             animation[1][-1].width = x + 4 - animation[1][-1].x
  1064.           end
  1065.           center = $game_system.message.autocenter
  1066.           if (center && x == (self.width-40)/2 - @line_widths[y]/2)  ||
  1067.              (!center && x == 0)
  1068.              x = center ? ((self.width-40)/2 - @line_widths[y]/2) : 0
  1069.           end
  1070.           # Update cursor width if choice
  1071.           if y >= $game_temp.choice_start
  1072.             width = $game_system.message.autocenter ? @line_widths[y]+8 : x
  1073.           end
  1074.           # Add 1 to y
  1075.           y += 1
  1076.           if $game_system.message.autocenter && ufmt != ''
  1077.             x = (self.width-40)/2 - @line_widths[y]/2 if @line_widths[y]
  1078.           else
  1079.             x = 0
  1080.             # Indent if choice
  1081.             x = 8 if y >= $game_temp.choice_start
  1082.           end
  1083.           if animation[0] != 0
  1084.             animation[1].push(Rect.new(x + 4, y * 32, 0, 32))
  1085.           end
  1086.           # go to next text
  1087.           next
  1088.         end
  1089.         size = contents.text_size(c)
  1090.         if lanimation[0] != 0
  1091.           lanimation[1].push(Rect.new(x + 4, y * 32, size.width, 32))
  1092.         end
  1093.         x += size.width
  1094.       end
  1095.       if animation[0] != 0
  1096.         animation[1][-1].width = x + 4 - animation[1][-1].x
  1097.         @animations.push(animation)
  1098.       elsif lanimation[0] != 0
  1099.         @letter_animations.push(lanimation)
  1100.       end
  1101.     end
  1102.   end
  1103.   #--------------------------------------------------------------------------
  1104.   # * Resize Window
  1105.   #--------------------------------------------------------------------------
  1106.   def resize
  1107.     if !$game_system.message.resize
  1108.       # reset to defaults
  1109.       self.width = 480
  1110.       self.height = 160
  1111.       self.contents = Bitmap.new(width - 32, height - 32)
  1112.       self.x = 80 # undo any centering
  1113.       return
  1114.     end
  1115.     max_x = @line_widths.max
  1116.     max_y = 8
  1117.     @line_widths.each {|line| max_y -= 1 if line == 0 && max_y > 1}
  1118.     if $game_temp.choice_max  > 0
  1119.       # account for indenting
  1120.       max_x += 8 unless $game_system.message.autocenter
  1121.     end
  1122.     new_width = max_x + 40
  1123.     t = @thought_windowskin && @thought_windowskin.is_a?(Array)
  1124.     if t && @windowskin == @thought_windowskin[0] && THOUGHT_WIDTH_MULTIPLE >0
  1125.       # force window width to be a multiple of THOUGHT_WIDTH_MULTIPLE
  1126.       # so that specialty windowskins (e.g. thought balloon) look right
  1127.       if new_width % THOUGHT_WIDTH_MULTIPLE != 0
  1128.         new_width += THOUGHT_WIDTH_MULTIPLE-(new_width%THOUGHT_WIDTH_MULTIPLE)
  1129.       end
  1130.     end
  1131.     self.width = new_width
  1132.     new_height = max_y * 32 + 32
  1133.     self.height = $game_system.message.auto_shrink ? 1 * 32 + 32 : new_height    
  1134.     self.contents = Bitmap.new(width - 32, new_height - 32)
  1135.     self.x = 320 - (self.width/2) # center
  1136.   end
  1137.   #--------------------------------------------------------------------------
  1138.   # * Reposition Window
  1139.   #--------------------------------------------------------------------------
  1140.   def reposition
  1141.     if @float_id.is_a?(Array)
  1142.       char_height = 1
  1143.       char_width = 1
  1144.       char_x = @float_id[0]
  1145.       char_y = @float_id[1]
  1146.     elsif $game_temp.in_battle
  1147.       if 'abcd'.include?(@float_id) # must be between a and d
  1148.         @float_id = @float_id[0] - 97 # a = 0, b = 1, c = 2, d = 3
  1149.         return if $scene.spriteset.actor_sprites[@float_id] == nil
  1150.         sprite = $scene.spriteset.actor_sprites[@float_id]
  1151.       else
  1152.         @float_id -= 1 # account for, e.g., player entering 1 for index 0
  1153.         return if $scene.spriteset.enemy_sprites[@float_id] == nil
  1154.         sprite = $scene.spriteset.enemy_sprites[@float_id]
  1155.       end
  1156.       char_height = sprite.height
  1157.       char_width = sprite.width
  1158.       char_x = sprite.x
  1159.       char_y = sprite.y - char_height/2
  1160.     else # not in battle...
  1161.       char = (@float_id == 0 ? $game_player : $game_map.events[@float_id])
  1162.       if char == nil
  1163.         # no such character
  1164.         @float_id = nil
  1165.         return
  1166.       end
  1167.       # close message (and stop event processing) if speaker is off-screen
  1168.       if speaker_offscreen(char) ||  
  1169.         ($game_system.message.allow_offscreen && !$game_temp.in_battle &&
  1170.         (self.height - self.y > 480 || self.height + self.y < 0 ||
  1171.           self.width - self.x > 640 || self.width + self.x < 0)) ||
  1172.          ($game_system.message.move_during &&  @dist_exit &&
  1173.            @float_id > 0 && !char.within_range?(@dist_max, @float_id) &&
  1174.            @float_id == @event_id )
  1175.         terminate_message
  1176.         message_interpreter.command_115
  1177.         if !@fwindowskin.nil? && !@fwindowskin.disposed?
  1178.           @fwindowskin.visible = false
  1179.           @fwindowskin.bitmap.dispose if !@fwindowskin.bitmap.disposed?
  1180.           @fwindowskin.dispose
  1181.           @fwindowskin = nil
  1182.         end
  1183.         char.foot_forward_off  if @auto_ff_reset && !char.no_ff
  1184.         @auto_ff_reset = false
  1185.         return
  1186.       end
  1187.       if char.character_name =~ /[8]/i
  1188.         char_height = RPG::Cache.character(char.character_name,0).height / 8
  1189.       else
  1190.         char_height = RPG::Cache.character(char.character_name,0).height / 4
  1191.       end
  1192.       if char.character_name =~ /[s]/i
  1193.         char_width = RPG::Cache.character(char.character_name,0).width / 8
  1194.       else
  1195.         char_width = RPG::Cache.character(char.character_name,0).width / 4
  1196.       end
  1197.       # record coords of character's center
  1198.       char_x = record_screen_xy(char)[0]
  1199.       char_y = record_screen_xy(char)[1] - char_height/2
  1200.     end
  1201.     params = [char_height, char_width, char_x, char_y]
  1202.     # position window and message tail
  1203.     vars = new_position(params)
  1204.     x,y = vars[0], vars[1]
  1205.     # check if any window locations need to be 'flipped'
  1206.     offsc = (!$game_system.message.allow_offscreen || $game_temp.in_battle)
  1207.     flip = need_flip?(@float_id, @location, x, y, params)
  1208.     loc4 = ((x < 0 && !@face) || (x < 90 && @face)) && offsc
  1209.     if @location == 4 && (loc4 || flip)
  1210.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1211.         @location = put_behind(@float_id, 6)
  1212.       else  # switch to right
  1213.         @location = 6
  1214.       end
  1215.       vars = new_position(params)
  1216.       x = vars[0]
  1217.       if (x + self.width) > 640 && offsc
  1218.         # right is no good either...
  1219.         if y >= 0
  1220.           # switch to top
  1221.           @location = 8
  1222.           vars = new_position(params)
  1223.         else
  1224.           # switch to bottom
  1225.           @location = 2
  1226.           vars = new_position(params)
  1227.         end
  1228.       end
  1229.     elsif @location == 6 && (((x + self.width) > 640 && offsc) || flip)
  1230.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1231.         @location = put_behind(@float_id, 4)
  1232.       else     # switch to left
  1233.         @location = 4
  1234.       end
  1235.       vars = new_position(params)
  1236.       x = vars[0]
  1237.       if x < 0 && offsc
  1238.         # left is no good either...
  1239.         if y >= 0
  1240.           # switch to top
  1241.           @location = 8
  1242.           vars = new_position(params)
  1243.         else
  1244.           # switch to bottom
  1245.           @location = 2
  1246.           vars = new_position(params)
  1247.         end
  1248.       end
  1249.     elsif @location == 8 && ((y < 0 && offsc) || flip)
  1250.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1251.         @location = put_behind(@float_id, 2)
  1252.       else     # switch to bottom
  1253.         @location = 2
  1254.       end
  1255.       vars = new_position(params)
  1256.       y = vars[1]
  1257.       if (y + self.height) > 480 && offsc
  1258.         # bottom is no good either...
  1259.         # note: this will probably never occur given only 3 lines of text
  1260.         x = vars[0]
  1261.         if x >= 0
  1262.           # switch to left
  1263.           @location = 4
  1264.           vars = new_position(params)
  1265.         else
  1266.           # switch to right
  1267.           @location = 6
  1268.           vars = new_position(params)
  1269.         end
  1270.       end
  1271.     elsif @location == 2 && (((y + self.height) > 480 && offsc) || flip)
  1272.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1273.         @location = put_behind(@float_id, 8)
  1274.       else   # switch to top
  1275.         @location = 8
  1276.       end
  1277.       vars = new_position(params)
  1278.       y = vars[1]
  1279.       if y < 0 && offsc
  1280.         # top is no good either...
  1281.         # note: this will probably never occur given only 3 lines of text
  1282.         x = vars[0]
  1283.         if x >= 0
  1284.           # switch to left
  1285.           @location = 4
  1286.           vars = new_position(params)
  1287.         else
  1288.           # switch to right
  1289.           @location = 6
  1290.           vars = new_position(params)
  1291.         end
  1292.       end
  1293.     end
  1294.     x = vars[0]
  1295.     y = vars[1]
  1296.     tail_x = vars[2]
  1297.     tail_y = vars[3]    
  1298.     # adjust windows if near edge of screen
  1299.     if offsc
  1300.       if x < 0 && !@face
  1301.         x = 0
  1302.       elsif x < 90 && @face
  1303.         x = 90
  1304.       elsif (x + self.width) > 640
  1305.         x = 640 - self.width
  1306.       end
  1307.       if y < 0
  1308.         y = [y, 0].max
  1309.       elsif (y + self.height) > 480
  1310.         y = 480 - self.height
  1311.       elsif $game_temp.in_battle && @location == 2 && (y > (320 - self.height))
  1312.         # when in battle, prevent enemy messages from overlapping battle status
  1313.         # (note that it could still happen from actor messages, though)
  1314.         y = 320 - self.height
  1315.         tail_y = y
  1316.       end
  1317.     end
  1318.     # finalize positions
  1319.     self.x = x
  1320.     self.y = y
  1321.     @tail.x = tail_x
  1322.     @tail.y = tail_y
  1323.     v = case @location
  1324.     when 2, 6 then -15
  1325.     when 4, 8 then -17
  1326.     end
  1327.     if @contents_showing  #!$game_temp.message_text.compact.empty?
  1328.       draw_window
  1329.       @fwindowskin.dispose if !@fwindowskin.nil? && !@fwindowskin.disposed?
  1330.       @fwindowskin = Sprite.new
  1331.       @fwindowskin.z = self.z - 10
  1332.       @fwindowskin.bitmap = Bitmap.new(640,480)
  1333.       @fwindowskin.bitmap.blt(x,y,@frame.bitmap,@frame.bitmap.rect)
  1334.       @fwindowskin.bitmap.blt(tail_x+v,tail_y+v,@tail.bitmap,
  1335.                  @tail.bitmap.rect) if show_message_tail?
  1336.       @fwindowskin.opacity = $game_system.message.opacity
  1337.       if @face && self.height > 64
  1338.         a = 80
  1339.         while a >= -10
  1340.           @fwindowskin.bitmap.blt(@face.x+a,y,@frame.bitmap,
  1341.             Rect.new(0,0,@face.bitmap.width-45,@frame.bitmap.height))
  1342.           a = (a == 5) ? 15 : a - 25
  1343.         end
  1344.       end
  1345.       self.opacity = @tail.opacity = 0
  1346.       @frame.dispose
  1347.     end
  1348.     bit = @tail.bitmap
  1349.   end
  1350.   #--------------------------------------------------------------------------
  1351.   # Prevent Player from walking under Message Bubbles
  1352.   #--------------------------------------------------------------------------
  1353.   def need_flip?(event_id, loc, x, y, params = nil)
  1354.     return false if !@auto_orient || @fade_out ||  event_id.nil? ||
  1355.                     (event_id != 0 && $game_map.events[event_id].erased) ||
  1356.                     $game_temp.in_battle ||
  1357.                     !$game_system.message.reposition_on_turn ||
  1358.                     !$game_system.message.move_during
  1359.     # vars for speaker
  1360.     event = (event_id > 0) ? $game_map.events[event_id] : $game_player
  1361.     dir = event.direction
  1362.     # if an argument is passed called params and not allowed offscreen  
  1363.     if params and not $game_system.message.allow_offscreen
  1364.       case loc
  1365.         when 2 then new_loc = 8
  1366.         when 4 then new_loc = 6
  1367.         when 6 then new_loc = 4
  1368.         when 8 then new_loc = 2
  1369.       end
  1370.       # check what the new coordinates of a repositioned window will be  
  1371.       new_vars = new_position(params, new_loc, no_rotate = true)
  1372.       new_x = new_vars[0]
  1373.       new_y = new_vars[1]
  1374.       # return false if not allowed off screen and new position is off screen
  1375.       if (new_x < 0 && new_loc == 4) ||    (new_x + self.width > 640) ||
  1376.          (new_y < 0) ||    (new_y + self.height > 480)
  1377.         # if not allowed offscreen and trying to flip offscreen
  1378.         return false
  1379.       end
  1380.     end
  1381.     # default result
  1382.     result = false
  1383.     result = true if @auto_orient == 2 &&  dir == loc
  1384.     if @auto_orient == 1
  1385.       if event_id > 1
  1386.         # If Auto Orient Any Direction, try to put preference on top / bottom
  1387.         # Top / Bottom Preference was made for readability of Msgs
  1388.         # because it is easier to go off screen left and right
  1389.         if dir == loc ||  ((dir == 2 || dir == 8) && (loc == 4 || loc == 6))
  1390.           result = true
  1391.         end
  1392.       elsif event_id == 0
  1393.         if ((dir == 2 && loc != 8) || (dir == 4 && loc != 6) ||
  1394.            (dir == 6 && loc != 4) ||  (dir == 8 && loc != 2))
  1395.           result = true
  1396.         end
  1397.       end
  1398.     end
  1399.     return result
  1400.   end
  1401.   #--------------------------------------------------------------------------
  1402.   # Place Message Bubble behind Speaker
  1403.   #--------------------------------------------------------------------------
  1404.   def put_behind(event_id, default_loc)
  1405.     return default_loc if event_id.nil? or $game_temp.in_battle
  1406.     dir = (event_id > 0 ) ? $game_map.events[event_id].direction :
  1407.           $game_player.direction
  1408.     return 2 if dir == 8
  1409.     return 4 if dir == 6
  1410.     return 6 if dir == 4
  1411.     return 8 if dir == 2
  1412.     return default_loc
  1413.   end  
  1414.   #--------------------------------------------------------------------------
  1415.   # ? speaker_offscreen
  1416.   #--------------------------------------------------------------------------
  1417.   def speaker_offscreen(char)
  1418.     return record_screen_xy(char)[0] <= 0 || record_screen_xy(char)[0] >= 640 ||
  1419.            record_screen_xy(char)[1] <= 0 || record_screen_xy(char)[1] > 480
  1420.   end
  1421.   #--------------------------------------------------------------------------
  1422.   # ? record_screen_xy
  1423.   #--------------------------------------------------------------------------
  1424.   def record_screen_xy(char)
  1425.     return char.rev_scr_xy || [char.screen_x,char.screen_y]
  1426.   end
  1427.   #--------------------------------------------------------------------------
  1428.   # ? draw_window
  1429.   #--------------------------------------------------------------------------
  1430.   def draw_window(width = self.width, height = self.height,win = @windowskin )
  1431.     @skin = Skin_Windowskin.new
  1432.     @skin.bitmap = RPG::Cache.windowskin(win)
  1433.     @frame,@bg   = Sprite.new, Sprite.new()
  1434.     @width,@height = width, height
  1435.     return if @skin.bitmap == nil
  1436.     return if @width == 0 or @height == 0
  1437.     m = @skin.margin
  1438.     decrement = 2
  1439.     @frame.bitmap ||= Bitmap.new(@width, @height)
  1440.     @bg.bitmap    ||= Bitmap.new(@width-(decrement*2), @height-(decrement*2))
  1441.     @frame.bitmap.clear
  1442.     @bg.bitmap.clear
  1443.     dest_rect = Rect.new(0, 0, @width-(decrement*2), @height-(decrement*2))
  1444.     #dest_rect = Rect.new(0, 0, @width, @height)
  1445.     @bg.bitmap.stretch_blt(dest_rect, @skin.bitmap, @skin['bg'])
  1446.     bx = Integer((@width - m*2) / @skin['up'].width) + 1
  1447.     by = Integer((@height - m*2) / @skin['left'].height) + 1
  1448.     (0..bx).each { |x|
  1449.       w = @skin['up'].width
  1450.       @frame.bitmap.blt(x * w + m, 0, @skin.bitmap, @skin['up'])
  1451.       @frame.bitmap.blt(x * w + m, @height - m, @skin.bitmap, @skin['down'])}
  1452.     @frame.bitmap.stretch_blt(Rect.new(decrement, decrement,
  1453.          @frame.bitmap.width-(decrement*2),
  1454.          @frame.bitmap.height-(decrement*2)), @bg.bitmap, @bg.bitmap.rect)
  1455.     (0..by).each { |y|
  1456.       h = @skin['left'].height
  1457.       @frame.bitmap.blt(0, y * h + m, @skin.bitmap, @skin['left'])
  1458.       @frame.bitmap.blt(@width - m, y * h + m, @skin.bitmap, @skin['right'])}
  1459.     @frame.bitmap.erase(@width - m, 0, m, m)
  1460.     @frame.bitmap.erase(0, @height - m, m, m)
  1461.     @frame.bitmap.erase(@width - m, @height - m, m, m)
  1462.     @frame.bitmap.stretch_blt(Rect.new(decrement, decrement,
  1463.          @frame.bitmap.width-(decrement*2),
  1464.          @frame.bitmap.height-(decrement*2)), @bg.bitmap, @bg.bitmap.rect)
  1465.     @frame.bitmap.blt(0, 0, @skin.bitmap, @skin['ul_corner'])
  1466.     @frame.bitmap.blt(@width - m, 0, @skin.bitmap, @skin['ur_corner'])
  1467.     @frame.bitmap.blt(0, @height - m, @skin.bitmap, @skin['dl_corner'])
  1468.     @frame.bitmap.blt(@width - m, @height - m, @skin.bitmap, @skin['dr_corner'])
  1469.     @frame.bitmap.blt(@width - m, @height - m, @skin.bitmap, @skin['dr_corner'])
  1470.     @bg.dispose
  1471.   end
  1472.   #--------------------------------------------------------------------------
  1473.   # * Determine New Window Position
  1474.   #--------------------------------------------------------------------------  
  1475.   def new_position(params, location = @location, no_rotate = nil)
  1476.     char_height, char_width, char_x, char_y = params
  1477.     if location == 8
  1478.       # top
  1479.       x = char_x - self.width/2
  1480.       y = char_y - char_height/2 - self.height - @tail.bitmap.height/2
  1481.       @tail.bitmap.rotation(0)  unless no_rotate
  1482.       tail_x = x + self.width/2
  1483.       tail_y = y + self.height
  1484.     elsif location == 2
  1485.       # bottom
  1486.       x = char_x - self.width/2
  1487.       y = char_y + char_height/2 + @tail.bitmap.height/2
  1488.       @tail.bitmap.rotation(180) unless no_rotate
  1489.       tail_x = x + self.width/2
  1490.       tail_y = y
  1491.     elsif location == 4
  1492.       # left
  1493.       x = char_x - char_width/2 - self.width - @tail.bitmap.width/2
  1494.       y = char_y - self.height/2
  1495.       @tail.bitmap.rotation(270) unless no_rotate
  1496.       tail_x = x + self.width
  1497.       tail_y = y + self.height/2
  1498.     elsif location == 6
  1499.       # right
  1500.       x = char_x + char_width/2 + @tail.bitmap.width/2
  1501.       y = char_y - self.height/2
  1502.       @tail.bitmap.rotation(90) unless no_rotate
  1503.       tail_x = x
  1504.       tail_y = y + self.height/2
  1505.     end
  1506.     return [x,y,tail_x,tail_y]
  1507.   end  
  1508.   #--------------------------------------------------------------------------
  1509.   # * eval_text
  1510.   #--------------------------------------------------------------------------
  1511.   def eval_text(bitmap)
  1512.     # If \\
  1513.     if @c == "\000"
  1514.       # Return to original text
  1515.       @c = "\\"
  1516.     end
  1517.     # If \C[n] or \C[#xxxxxx] or \C
  1518.     if @c == "\001"
  1519.       # Change text color
  1520.       @text.sub!(/\[([0-9]+|#[0-9A-Fa-f]{6,6})\]/, '')
  1521.       if $1 != nil
  1522.         bitmap.font.color = check_color($1)
  1523.       else
  1524.         # return to default color
  1525.         if $game_system.message.font_color != nil
  1526.           color = check_color($game_system.message.font_color)
  1527.         elsif $game_system.message.floating && $game_system.message.resize
  1528.           color = check_color(SPEECH_FONT_COLOR)
  1529.         else
  1530.           # use defaults
  1531.           color = Font.default_color
  1532.         end
  1533.         bitmap.font.color = color
  1534.       end
  1535.       # go to next text
  1536.       return 1
  1537.     end
  1538.     # If \G
  1539.     if @c == "\002"
  1540.       # Make gold window
  1541.       if @gold_window == nil
  1542.         @gold_window = Window_Gold.new
  1543.         @gold_window.x = 560 - @gold_window.width
  1544.         if $game_temp.in_battle
  1545.           @gold_window.y = 192
  1546.         else
  1547.           @gold_window.y = self.y >= 128 ? 32 : 384
  1548.         end
  1549.         @gold_window.opacity = $game_system.message.opacity
  1550.         @gold_window.back_opacity = self.back_opacity
  1551.       end
  1552.       # go to next text
  1553.       return 1
  1554.     end
  1555.     # If \L
  1556.     if @c == "\003"
  1557.       # toggle letter-by-letter mode
  1558.       @letter_by_letter = !@letter_by_letter
  1559.       # go to next text
  1560.       return 1
  1561.     end
  1562.     # If \S[n]
  1563.     if @c == "\004"
  1564.       @text.sub!(/\[([0-9]+)\]/, '')
  1565.       speed = $1.to_i
  1566.       if speed >= 0
  1567.         @text_speed = speed
  1568.         # reset player skip after text speed change
  1569.         @player_skip = false            
  1570.       end
  1571.       return 0
  1572.     end
  1573.     # If \D[n]
  1574.     if @c == "\005"
  1575.       @text.sub!(/\[([0-9]+)\]/, '')
  1576.       delay = $1.to_i
  1577.       if delay >= 0
  1578.         @delay += delay
  1579.         # reset player skip after delay
  1580.         @player_skip = false
  1581.       end
  1582.       return 0
  1583.     end  
  1584.     # If \!
  1585.     if @c == "\006"
  1586.       # close message and return from method
  1587.       terminate_message
  1588.       return 0
  1589.     end
  1590.     # If \?
  1591.     if @c == "\007"
  1592.       @wait_for_input = true
  1593.       return 0
  1594.     end
  1595.     if @c == "\010"
  1596.       # bold
  1597.       bitmap.font.bold = !bitmap.font.bold
  1598.       return 0
  1599.     end
  1600.     if @c == "\023"
  1601.       # change font
  1602.       @text.sub!(/\[(.+?),([0-9]+)\]/,  '')
  1603.       bitmap.font.name = $1
  1604.       bitmap.font.size = $2.to_i
  1605.       return 0
  1606.     end
  1607.     if @c == "\011"
  1608.       # italics
  1609.       bitmap.font.italic = !bitmap.font.italic
  1610.       return 0
  1611.     end
  1612.     if @c == "\013"
  1613.       # display icon of item, weapon, armor or skill
  1614.       @text.sub!(/\[([IiWwAaSs])([0-9]+)\]/, '')
  1615.       return 0 if $1.nil?
  1616.       item = case $1.downcase
  1617.       when 'i' then $data_items[$2.to_i]
  1618.       when 'w' then $data_weapons[$2.to_i]
  1619.       when 'a' then $data_armors[$2.to_i]
  1620.       when 's' then $data_skills[$2.to_i]
  1621.       end
  1622.       if item == nil
  1623.         return 0
  1624.       end
  1625.       icon = RPG::Cache.icon(item.icon_name)
  1626.       bitmap.blt(4+@x, 32*@y+4, icon, Rect.new(0, 0, 24, 24))
  1627.       @x += 24
  1628.       #bitmap.draw_text(x + 28, y, 212, 32, item.name)
  1629.       return 0
  1630.     end
  1631.     if @c == "\014"
  1632.       @text.sub!(/\[(.+?)(?:,(\d+))?\]/, '')
  1633.       face = $1.to_s
  1634.       if  face != '' && face['|']
  1635.         face = face.split('|')
  1636.         create_portrait(face)
  1637.         return 0
  1638.       end
  1639.       create_face_sprite(face) if face != ''  
  1640.       return 0
  1641.     end
  1642.     if @c == "\015" || @c == "\016"
  1643.       if @c == "\015"
  1644.         @text.sub!(/\[([0-9]+),([0-9]+)\]/, '')
  1645.         name = $game_actors[$1.to_i].name.dup
  1646.         face = case $1.to_i
  1647.         when 1 then sprintf("zdc-%02d", $2.to_i)
  1648.         when 2 then sprintf("spc-%02d", $2.to_i)
  1649.         when 3 then sprintf("freya-%02d", $2.to_i)
  1650.         when 4 then sprintf("chris-%02d", $2.to_i)
  1651.         end
  1652.       elsif @c == "\016"
  1653.         @text.sub!(/\[(.+?)(?:(\d+))?\]/, '')
  1654.         name = $1.to_s
  1655.       end
  1656.       create_name_sprite(name) if name != ''
  1657.       create_face_sprite(face)
  1658.     end
  1659.     if @c == "\017"
  1660.       @text.sub!(/\[(.+?)\]/, '')
  1661.       text = [$1.to_s]
  1662.       if text[0] == "#d"
  1663.         if $game_system.message.auto_comma_pause && @letter_by_letter
  1664.           delay = @text_speed + $game_system.message.auto_comma_delay
  1665.           if delay >= 0
  1666.             @delay += delay
  1667.             # reset player skip after delay
  1668.             @player_skip = false
  1669.           end
  1670.         end
  1671.         return 0    
  1672.       elsif text[0].sub!(/#si/, '') != nil
  1673.         text[0].gsub!('(!', '[')
  1674.         text[0].gsub!('!)', ']')
  1675.         message_eval(text[0])
  1676.       elsif text[0].sub!(/#ss/, '') != nil
  1677.         text[0].gsub!('(!', '[')
  1678.         text[0].gsub!('!)', ']')
  1679.         eval(text[0])
  1680.       else
  1681.         bitmap.font.size -= 4
  1682.         text[1] = bitmap.text_size( text[0]  ).width
  1683.         bitmap.draw_text(4 + @x, 32 * @y-10, 10*text[1], 32,text[0] )
  1684.         bitmap.font.size += 4
  1685.       end
  1686.     end
  1687.     # if \F+ (Foot Forward Animation On)
  1688.     if @c == "\020" && @float_id && !@float_id.is_a?(Array)
  1689.       speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  1690.       speaker.foot_forward_on
  1691.       return 0
  1692.     end
  1693.     # if \F- (Foot Forward Animation Off)  
  1694.     if @c == "\021" && @float_id && !@float_id.is_a?(Array)
  1695.       speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  1696.       speaker.foot_forward_off
  1697.       return 0
  1698.     end
  1699.     # if \F* (Foot Forward Animation On "Other" Foot)
  1700.     if @c == "\022" && @float_id && !@float_id.is_a?(Array)
  1701.       speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  1702.       speaker.foot_forward_on(frame = 1)
  1703.       return 0
  1704.     end          
  1705.     # If \Z[n]
  1706.     if @c == "\024"
  1707.       @text.sub!(/\[([0-9]+)\]/, '')
  1708.       self.z = $1.to_i
  1709.       @tail.z = self.z + 10
  1710.       @face.z = self.z  if @face
  1711.       @fwindowskin.z = self.z if @fwindowskin
  1712.       @name_sprite.z = self.z + 101 if @name_sprite
  1713.       return 0
  1714.     end        
  1715.     extra = eval_extra(bitmap)
  1716.     return extra if extra
  1717.     # If new line text
  1718.     if @c == "\n"
  1719.       center = $game_system.message.autocenter
  1720.       if (center && @x == (self.width-40)/2 - @line_widths[@y]/2)  ||
  1721.           (!center && @x == 0)  
  1722.         @line_widths[@y] = nil
  1723.         @line_widths.compact!
  1724.         @x = center ? ((self.width-40)/2 - @line_widths[@y]/2) : 0
  1725.         return 0
  1726.       end
  1727.       # Update cursor width if choice
  1728.       if @y >= $game_temp.choice_start
  1729.         width = $game_system.message.autocenter ? @line_widths[@y]+8 : @x
  1730.         @cursor_width = [@cursor_width, width].max
  1731.       end
  1732.       # Add 1 to y
  1733.       @y += 1
  1734.       if $game_system.message.auto_shrink
  1735.         while self.height < @y * 32 + 32
  1736.           Graphics.update
  1737.           self.height += 1
  1738.           reposition
  1739.         end
  1740.         face_position
  1741.         self.height = @y * 32 + 32
  1742.       end
  1743.       if $game_system.message.autocenter && @text != ''
  1744.         @x = (self.width-40)/2 - @line_widths[@y]/2 if @line_widths[@y]
  1745.       else
  1746.         @x = 0
  1747.         # Indent if choice
  1748.         @x = 8 if @y >= $game_temp.choice_start
  1749.       end
  1750.       # go to next text
  1751.       return 1
  1752.     end
  1753.   end
  1754.   #--------------------------------------------------------------------------
  1755.   # * eval_extra
  1756.   #--------------------------------------------------------------------------
  1757.   def eval_extra(bitmap) return false end
  1758.   #--------------------------------------------------------------------------
  1759.   # * Play Sound
  1760.   #--------------------------------------------------------------------------
  1761.   def play_sound
  1762.     if $game_system.message.sound && @letter_by_letter && !@player_skip &&
  1763.         CHARACTERS.include?(@c.downcase)
  1764.       # Increment for each Letter Sound Played
  1765.       @sound_counter = (@sound_counter || 0) + 1
  1766.       # Prevents Division by Zero, allows 0 to play a sound every letter
  1767.       frequency = $game_system.message.sound_frequency
  1768.       frequency = (frequency == 0) ? @sound_counter : frequency
  1769.       # Play Sound for each New Word or if Remainder is 0
  1770.       if @sound_counter == 1 or @sound_counter % frequency == 0
  1771.         # Play correct sound for each letter
  1772.         play_text_sound(@c.downcase)
  1773.       end
  1774.     else
  1775.       @sound_counter = 0
  1776.     end      
  1777.   end
  1778.   #--------------------------------------------------------------------------
  1779.   # * Update Text
  1780.   #--------------------------------------------------------------------------  
  1781.   def update_text
  1782.     if @text != nil
  1783.      
  1784.       # Get 1 text character in c (loop until unable to get text)
  1785.       while ((@c = @text.slice!(/./m)) != nil)
  1786.         # Plays Sounds for each Letter, Numbers and Spaces Excluded
  1787.         play_sound
  1788.         case eval_text(self.contents)
  1789.         when 0 then return
  1790.         when 1 then next
  1791.         end
  1792.         # Draw text
  1793.         self.contents.draw_text(4 + @x, 32 * @y, 40, 32, @c)
  1794.         # Add x to drawn text width
  1795.         @x += self.contents.text_size( @c ).width
  1796.         # add text speed to time to display next character
  1797.         @delay += @text_speed unless !@letter_by_letter || @player_skip
  1798.         return if @letter_by_letter && !@player_skip
  1799.       end
  1800.       height = self.contents.height+10
  1801.       height = [height, @face.bitmap.height+20].max if @face
  1802.       saved_bitmap = Bitmap.new(640,height)
  1803.       saved_bitmap.blt(100,10,self.contents,self.contents.rect)
  1804.       saved_bitmap.blt(@face.x-self.x+100,@face.y-self.y+10,
  1805.                     @face.bitmap,@face.bitmap.rect) if @face
  1806.       saved_bitmap.blt(@name_sprite.x-self.x+100,@name_sprite.y-self.y+10,
  1807.                 @name_sprite.bitmap,@name_sprite.bitmap.rect) if @name_sprite
  1808.       save_message_bitmap(saved_bitmap)
  1809.       @animations = @animations.map { |ani|
  1810.              AnimationSprite.new(ani[0], self.x + 16,
  1811.              self.y + 16, self.z + 1, ani[1], self.contents) }
  1812.       @letter_animations = @letter_animations.map { |ani|
  1813.                 AnimationLetters.new(ani[0], self.x + 16,
  1814.                 self.y + 16, self.z + 1, ani[1], self.contents) }
  1815.       @animations.each { |i| i.opacity = self.contents_opacity }
  1816.       @letter_animations.each { |i| i.opacity = self.contents_opacity }
  1817.     end
  1818.     # If choice
  1819.     if $game_temp.choice_max > 0 && @choice_window
  1820.       @item_max = $game_temp.choice_max
  1821.       self.active = true
  1822.       if $choice_index && $choice_index.is_a?(Integer) &&
  1823.          $choice_index < $game_temp.choice_max
  1824.         self.index = $choice_index
  1825.       else
  1826.         self.index = 0
  1827.       end
  1828.     end
  1829.     # If number input
  1830.     if $game_temp.num_input_variable_id > 0 && @choice_window  
  1831.       digits_max = $game_temp.num_input_digits_max
  1832.       number = $game_variables[$game_temp.num_input_variable_id]
  1833.       @input_number_window = Window_InputNumber.new(digits_max)
  1834.       @input_number_window.set_font(@font_name, @font_size, @font_color)
  1835.       @input_number_window.number = number
  1836.       @input_number_window.x =
  1837.         if $game_system.message.autocenter
  1838.           offset = (self.width-40)/2-@line_widths[$game_temp.num_input_start]/2
  1839.           self.x + offset + 4
  1840.         else
  1841.           self.x + 8
  1842.         end
  1843.       @input_number_window.y = self.y + $game_temp.num_input_start * 32
  1844.     end
  1845.     @update_text = false
  1846.   end
  1847.   #--------------------------------------------------------------------------
  1848.   # * save_message_bitmap
  1849.   #--------------------------------------------------------------------------
  1850.   def save_message_bitmap(saved_bitmap)
  1851.     d =  $multiple_message_windows['saved']
  1852.     $multiple_message_windows['saved'] = [] unless d && d.is_a?(Array)  
  1853.     $multiple_message_windows['saved'].push(saved_bitmap)
  1854.     if d && d.size + 1 > 20
  1855.       bitmap = $multiple_message_windows['saved'].shift
  1856.       bitmap.dispose
  1857.     end
  1858.   end
  1859.   #--------------------------------------------------------------------------
  1860.   # * Message_Eval
  1861.   #--------------------------------------------------------------------------
  1862.   def message_eval(v)
  1863.     message_interpreter.send(:eval,v)
  1864.   end
  1865.   #--------------------------------------------------------------------------
  1866.   # * Message_Interpreter
  1867.   #--------------------------------------------------------------------------
  1868.   def message_interpreter
  1869.     if $scene.is_a?(Scene_Map)
  1870.       $game_system.map_interpreter
  1871.     elsif $scene.is_a?(Scene_Battle)
  1872.       $game_system.battle_interpreter
  1873.     else
  1874.       Interpreter.new
  1875.     end
  1876.   end
  1877.   #--------------------------------------------------------------------------
  1878.   # * Reset Window
  1879.   #--------------------------------------------------------------------------
  1880.   def reset_window
  1881.     case $game_system.message_position
  1882.     when 0 then self.y = 16  # up
  1883.     when 1 then self.y = 160 # middle
  1884.     when 2 then self.y = 304 # down
  1885.     end
  1886.     self.y =16  if $game_temp.in_battle
  1887.     self.y =394 if $game_system.message.cinema && $game_system.message_frame > 0
  1888.     $game_system.message.opacity ||= 255
  1889.     self.opacity = $game_system.message_frame == 0 ?
  1890.       $game_system.message.opacity.to_i : 0
  1891.     @tail.opacity = $game_system.message.opacity.to_i
  1892.   end
  1893.   #--------------------------------------------------------------------------
  1894.   # * Frame Update
  1895.   #--------------------------------------------------------------------------
  1896.   def update
  1897.     super
  1898.     if @animations && !@fade_out &&
  1899.         @animations.all? { |ani|  ani.is_a?(AnimationSprite) } &&
  1900.         @letter_animations.all? { |ani| ani.is_a?(AnimationLetters) }
  1901.       @animations.each { |ani| ani.update(self.x + 16, self.y + 16) }
  1902.       @letter_animations.each { |ani| ani.update(self.x + 16, self.y + 16) }
  1903.     end
  1904.     # If fade in
  1905.     if @fade_in
  1906.       self.contents_opacity += 24
  1907.       if @input_number_window != nil
  1908.         @input_number_window.contents_opacity += 24
  1909.       end
  1910.       if !@animations.nil? &&  !@fade_out &&
  1911.           @animations.all? { |ani| ani.is_a?(AnimationSprite) } &&
  1912.           @letter_animations.all? { |ani| ani.is_a?(AnimationLetters) }
  1913.         @animations.each { |ani| ani.opacity = self.contents_opacity }
  1914.         @letter_animations.each { |ani| ani.opacity = self.contents_opacity }
  1915.       end
  1916.       if self.contents_opacity == 255
  1917.         @fade_in = false
  1918.       end
  1919.     end
  1920.     # If inputting number
  1921.     if @input_number_window != nil
  1922.       @input_number_window.update
  1923.       # Confirm
  1924.       if Input.trigger?(Input::C)
  1925.         # Allows windows to be closed
  1926.         $game_temp.input_in_window = false
  1927.         $game_system.se_play($data_system.decision_se)
  1928.         $game_variables[$game_temp.num_input_variable_id] =
  1929.           @input_number_window.number
  1930.         $game_system.number_cancelled = false        
  1931.         $game_map.need_refresh = true
  1932.        
  1933.         s = $multiple_message_windows['saved']
  1934.         if s.is_a?(Array)
  1935.           bitmap = s[-1]
  1936.           if bitmap.is_a?(Bitmap)
  1937.             input_contents = @input_number_window.contents
  1938.             if $game_system.message.autocenter
  1939.               pos_x = (self.contents.width - input_contents.width) / 2
  1940.             else
  1941.               pos_x = 0
  1942.             end
  1943.             bitmap.blt(100 + pos_x,(bitmap.height - input_contents.height),
  1944.               input_contents,input_contents.rect)
  1945.           end
  1946.         end
  1947.         # Dispose of number input window
  1948.         @input_number_window.dispose
  1949.         @input_number_window = nil
  1950.         terminate_message
  1951.         return
  1952.       elsif Input.trigger?(Input::B) and
  1953.             $game_system.message.allow_cancel_numbers
  1954.         # play cancel sound effect
  1955.         $game_system.se_play($data_system.cancel_se)
  1956.         # Allows windows to be closed
  1957.         $game_temp.input_in_window = false
  1958.         # Set Variable to identify the Number Window was Cancelled
  1959.         $game_system.number_cancelled = true
  1960.         # Dispose of number input window
  1961.         @input_number_window.dispose
  1962.         @input_number_window = nil        
  1963.         if $scene.multi_message_window.compact.size > 1
  1964.           $scene.multi_message_window.each {|msg| msg.terminate_message }
  1965.         else
  1966.           terminate_message
  1967.         end
  1968.       end
  1969.     end
  1970.     # If message is being displayed
  1971.     if @contents_showing
  1972.       # Confirm or cancel finishes waiting for input or message
  1973.       if Input.trigger?(Input::C) || Input.trigger?(Input::B)
  1974.         if @wait_for_input
  1975.           @wait_for_input = false
  1976.           self.pause = false
  1977.         elsif $game_system.message.skippable
  1978.           @player_skip = true
  1979.         end
  1980.         # Dont close the window if waiting for choices to be displayed
  1981.         if $game_temp.input_in_window &&
  1982.            $game_temp.message_text.compact.size > 1 &&
  1983.            !$input_window_wait
  1984.           # wait until next input to confirm any choices
  1985.           $input_window_wait = true
  1986.           return
  1987.         else
  1988.           $input_window_wait = false          
  1989.         end
  1990.       end
  1991.       if need_reposition?
  1992.         reposition # update message position for character/screen movement
  1993.         if @contents_showing == false
  1994.           # i.e. if char moved off screen
  1995.           return
  1996.         end
  1997.       end
  1998.       if @update_text && !@wait_for_input
  1999.         if @delay == 0
  2000.           update_text
  2001.         else
  2002.           @delay -= 1
  2003.         end
  2004.         return
  2005.       end
  2006.       # If choice isn't being displayed, show pause sign
  2007.       if !self.pause && ($game_temp.choice_max == 0 || @wait_for_input)
  2008.         self.pause = true if $game_system.message.show_pause
  2009.       end
  2010.       # Cancel
  2011.       if Input.trigger?(Input::B)
  2012.         if $game_temp.choice_max > 0 && $game_temp.choice_cancel_type > 0
  2013.           # Allow ALL windows to be closed
  2014.           $game_temp.input_in_window = false
  2015.           $game_system.se_play($data_system.cancel_se)
  2016.           $game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
  2017.           # If multi window cancel choice
  2018.           if $scene.multi_message_window.compact.size > 1
  2019.             $scene.multi_message_window.each {|msg| msg.terminate_message }
  2020.           else
  2021.             terminate_message
  2022.           end
  2023.         end
  2024.         # personal preference: cancel button should also continue
  2025.         terminate_message
  2026.       end
  2027.       # Confirm
  2028.       if Input.trigger?(Input::C)
  2029.         if $game_temp.choice_max > 0
  2030.           $game_temp.input_in_window = false
  2031.           if $scene.multi_message_window.compact.size > 1
  2032.             $scene.multi_message_window.compact.each { |window|
  2033.               if window.choice_window
  2034.                 # return selection position by index of the choice window
  2035.                 @index = window.index
  2036.               end    }
  2037.           end          
  2038.           $game_system.se_play($data_system.decision_se)
  2039.           $game_temp.choice_proc.call(self.index)
  2040.         end
  2041.         # If Preceeding Window not closed because choice displayed
  2042.         if $scene.multi_message_window.compact.size > 1
  2043.           choice = false
  2044.           $scene.multi_message_window.compact.each { |window|
  2045.             if window.choice_window
  2046.               choice = true
  2047.               break
  2048.             end }
  2049.           # If window is a choice window and other windows held open
  2050.           if choice
  2051.             # close all the message windows
  2052.             $scene.multi_message_window.each {|msg|  msg.terminate_message }
  2053.           else
  2054.             # close the single message window            
  2055.             terminate_message
  2056.           end
  2057.         else
  2058.           if $game_temp.choice_max > 0
  2059.             $game_system.se_play($data_system.decision_se)
  2060.             $game_temp.choice_proc.call(self.index)
  2061.           end
  2062.           terminate_message
  2063.         end
  2064.       end
  2065.         return
  2066.     end
  2067.     # If display wait message or choice exists when not fading out
  2068.     $game_temp.message_text = [] if !$game_temp.message_text.is_a?(Array)
  2069.     $game_temp.message_proc = [] if !$game_temp.message_proc.is_a?(Array)
  2070.     if @fade_out == false && $game_temp.message_text[@msgindex] != nil
  2071.       @contents_showing = true
  2072.       $game_temp.message_window_showing = true
  2073.       reset_window
  2074.       refresh
  2075.       Graphics.frame_reset
  2076.       self.visible = true
  2077.       if show_message_tail?
  2078.         @tail.visible = true
  2079.       elsif @tail.visible
  2080.         @tail.visible = false
  2081.       end
  2082.       self.contents_opacity = 0
  2083.       if !@animations.nil?  && !@fade_out &&
  2084.           @animations.all? { |ani| ani.is_a?(AnimationSprite) } &&
  2085.           @letter_animations.all? { |ani| ani.is_a?(AnimationLetters) }
  2086.         @animations.each { |ani| ani.opacity = self.contents_opacity }
  2087.         @letter_animations.each { |ani| ani.opacity = self.contents_opacity }
  2088.       end
  2089.       if @input_number_window != nil
  2090.         @input_number_window.contents_opacity = 0
  2091.       end
  2092.       @fade_in = true
  2093.       return
  2094.     end
  2095.     # If message which should be displayed is not shown, but window is visible
  2096.     if self.visible
  2097.       @fade_out = true
  2098.       self.opacity -= 96
  2099.       @tail.opacity -= 96 if @tail.opacity > 0
  2100.       if !@animations.nil?  && !@fade_out &&
  2101.         @animations.all? { |ani| ani.is_a?(AnimationSprite) } &&
  2102.         @letter_animations.all? { |ani| ani.is_a?(AnimationLetters) }
  2103.         @animations.each { |ani| ani.opacity =
  2104.                  self.opacity * self.contents_opacity / 255 }
  2105.         @letter_animations.each { |ani| ani.opacity =
  2106.                  self.opacity * self.contents_opacity / 255 }
  2107.       end
  2108.       if need_reposition?
  2109.         reposition # update message position for character/screen movement
  2110.       end
  2111.       if self.opacity == 0 #@fwindowskin.opacity == 0
  2112.         self.visible = false
  2113.         unless @animations.nil? || @animations.any? { |i| i.is_a?(Array) } ||
  2114.           @letter_animations.any? { |i| i.is_a?(Array) }
  2115.           @animations.each { |ani| ani.bitmap.dispose;ani.dispose }
  2116.           @letter_animations.each { |ani| ani.dispose }
  2117.         else
  2118.           @animations = @letter_animations = []
  2119.         end
  2120.       @fade_out = false
  2121.         @tail.visible = false if @tail.visible
  2122.         # have to check all windows before claiming that no window is showing
  2123.         if $game_temp.message_text.compact.empty?
  2124.           $game_temp.message_window_showing = false  
  2125.         end
  2126.       end
  2127.       return
  2128.     end
  2129.   end
  2130.   #--------------------------------------------------------------------------
  2131.   # * Repositioning Determination
  2132.   #--------------------------------------------------------------------------
  2133.   def need_reposition?
  2134.     if (!$game_temp.in_battle) && $game_system.message.floating &&
  2135.         $game_system.message.resize && @float_id != nil
  2136.       char = (@float_id == 0 ? $game_player : $game_map.events[@float_id])
  2137.       if !char.nil? && @screen_xy != record_screen_xy(char)
  2138.         @screen_xy = record_screen_xy(char)
  2139.         return true
  2140.       elsif $game_system.message.move_during && @float_id == 0 &&
  2141.           (($game_player.last_real_xy[0] != $game_player.real_x) ||
  2142.           ($game_player.last_real_xy[1] != $game_player.real_y))
  2143.           # player with floating message moved
  2144.           # (note that relying on moving? leads to "jumpy" message boxes)
  2145.           return true
  2146.       elsif ($game_map.last_disp_xy[1] != $game_map.display_y) ||
  2147.          ($game_map.last_disp_xy[0] != $game_map.display_x)
  2148.         # player movement or scroll event caused the screen to scroll
  2149.         return true
  2150.       else
  2151.         char = $game_map.events[@float_id]
  2152.         if char != nil &&
  2153.           ((char.last_real_xy[0] != char.real_x) ||
  2154.           (char.last_real_xy[1] != char.real_y))
  2155.           # character moved
  2156.           return true
  2157.         end
  2158.       end    
  2159.     end
  2160.     return false
  2161.   end
  2162.   #--------------------------------------------------------------------------
  2163.   # * Show Message Tail Determination
  2164.   #--------------------------------------------------------------------------
  2165.   def show_message_tail?
  2166.     if $game_system.message.show_tail && $game_system.message.floating &&
  2167.       $game_system.message.resize && $game_system.message_frame == 0 &&
  2168.       @float_id != nil
  2169.       return true
  2170.     end
  2171.     return false
  2172.   end
  2173.   #--------------------------------------------------------------------------
  2174.   # * update_cursor_rect
  2175.   #--------------------------------------------------------------------------
  2176.   def update_cursor_rect
  2177.     if @index >= 0
  2178.       n = $game_temp.choice_start + @index
  2179.       if $game_system.message.autocenter
  2180.         x = 4 + (self.width-40)/2 - @cursor_width/2
  2181.       else
  2182.         x = 8
  2183.       end
  2184.       self.cursor_rect.set(x, n * 32, @cursor_width, 32)
  2185.     else
  2186.       self.cursor_rect.empty
  2187.     end
  2188.   end
  2189.   #--------------------------------------------------------------------------
  2190.   # * Alias Listing
  2191.   #--------------------------------------------------------------------------
  2192.   alias drg128_term terminate_message unless method_defined?(:drg128_term)
  2193.   alias drg128_upd update unless method_defined?(:drg128_upd)
  2194.   alias drg128_rep reposition unless method_defined?(:drg128_rep)
  2195.   #--------------------------------------------------------------------------
  2196.   # * Create Face_Sprite
  2197.   #--------------------------------------------------------------------------
  2198.   def create_face_sprite(face='')
  2199.     terminate_face rescue return
  2200.     return if face.nil? || face == ' '
  2201.     dir = 'Graphics/Faces'
  2202.     Dir.mkdir(dir) unless File.directory?(dir)
  2203.     face = Bitmap.new("#{dir}/#{face}")
  2204.     bitmap = Bitmap.new(80,80)
  2205.     bitmap.stretch_blt(bitmap.rect, face, face.rect)
  2206.     create_face_cont(bitmap)
  2207.   end
  2208.   #--------------------------------------------------------------------------
  2209.   # * Create Face_Sprite
  2210.   #--------------------------------------------------------------------------
  2211.   def create_face_cont(bitmap)
  2212.     @face = Sprite.new
  2213.     @face.bitmap = bitmap
  2214.     @face.opacity = $game_system.message.opacity
  2215.     face_position rescue return
  2216.     reposition
  2217.   end
  2218.   #--------------------------------------------------------------------------
  2219.   # * Create Name_Sprite
  2220.   #--------------------------------------------------------------------------
  2221.   def create_name_sprite(name='')
  2222.     terminate_name_sprite
  2223.     bitmap = Bitmap.new(name.length*10, 32)
  2224.     bitmap.font = self.contents.font
  2225.     bitmap.font.size += 4
  2226.     bitmap.font.color = normal_color
  2227.       (0...2).each {|i|
  2228.         bitmap.draw_text(-i, i, name.length*10, 32, name)
  2229.         bitmap.draw_text(i, -i, name.length*10, 32, name)
  2230.         bitmap.draw_text(-i, -i, name.length*10, 32, name)
  2231.         bitmap.draw_text(i, i, name.length*10, 32, name)  }
  2232.     bitmap.font.color = self.contents.font.color
  2233.       (0...1).each {|i|
  2234.         bitmap.draw_text(-i, i, name.length*10, 32, name)
  2235.         bitmap.draw_text(i, -i, name.length*10, 32, name)
  2236.         bitmap.draw_text(-i, -i, name.length*10, 32, name)
  2237.         bitmap.draw_text(i, i, name.length*10, 32, name)   }
  2238.     @name_sprite = Sprite.new
  2239.     @name_sprite.bitmap = bitmap
  2240.     name_sprite_position
  2241.   end
  2242.   #--------------------------------------------------------------------------
  2243.   # * Face Position
  2244.   #--------------------------------------------------------------------------
  2245.   def face_position
  2246.     return if !@face || @face.disposed?  
  2247.     if $game_system.message.floating
  2248.       @face.x = self.x - (@face.bitmap.width * @face.zoom_x + 2)
  2249.       @face.y = self.y  + 20 * ([64-64, 0].max/32).floor
  2250.       @face.y -= [(10 - (self.height - 64)), -6].max
  2251.     else
  2252.       @face.zoom_x = 1.2
  2253.       @face.zoom_y = 1.2
  2254.       @face.x = self.x + (self.width - (@face.bitmap.width * @face.zoom_x + 8))
  2255.       @face.y = self.y + 10
  2256.     end
  2257.     @face.z = self.z
  2258.   end
  2259.   #--------------------------------------------------------------------------
  2260.   # * Name_Sprite Position
  2261.   #--------------------------------------------------------------------------
  2262.   def name_sprite_position
  2263.     return if !@name_sprite || @name_sprite.disposed?
  2264.     @name_sprite.y = self.y - 15
  2265.     @name_sprite.x = self.x + 10
  2266.     @name_sprite.z = self.z + 101
  2267.   end
  2268.   #--------------------------------------------------------------------------
  2269.   # * Terminate Face
  2270.   #--------------------------------------------------------------------------
  2271.   def terminate_face()  eval ('@face.dispose; @face = nil') if @face   end
  2272.   #--------------------------------------------------------------------------
  2273.   # * Terminate Name_Sprite
  2274.   #--------------------------------------------------------------------------
  2275.   def terminate_name_sprite()
  2276.     eval('@name_sprite.dispose; @name_sprite = nil')if @name_sprite
  2277.   end
  2278.   #--------------------------------------------------------------------------
  2279.   # * Terminate Message
  2280.   #--------------------------------------------------------------------------
  2281.   def terminate_message
  2282.     @fwindowskin.bitmap.clear if !@fwindowskin.nil? && !@fwindowskin.disposed?
  2283.     terminate_face
  2284.     terminate_name_sprite
  2285.     drg128_term
  2286.   end
  2287.   #--------------------------------------------------------------------------
  2288.   # * Update Frame
  2289.   #--------------------------------------------------------------------------
  2290.   def update
  2291.     temp = $game_temp.in_battle
  2292.     $game_temp.in_battle = $scene.is_a?(Scene_Battle)
  2293.     drg128_upd
  2294.     $game_temp.in_battle = temp
  2295.   end
  2296.   #--------------------------------------------------------------------------
  2297.   # * Reposition Window
  2298.   #--------------------------------------------------------------------------
  2299.   def reposition
  2300.     drg128_rep
  2301.     face_position
  2302.     name_sprite_position
  2303.   end
  2304.   #--------------------------------------------------------------------------
  2305.   # * Text Sound
  2306.   #--------------------------------------------------------------------------  
  2307.   def play_text_sound(char)
  2308.     sound = 'Audio/SE/' + $game_system.message.sound_audio
  2309.     volume = $game_system.message.sound_volume
  2310.     @sound_pitch =       $game_system.message.sound_pitch
  2311.    
  2312.     if $game_system.message.sound_vary_pitch and @sound_pitch
  2313.       @sound_pitch_range = $game_system.message.sound_pitch_range
  2314.       # Prevent Negative Numbers...
  2315.       sound_pitch_range = (@sound_pitch_range > @sound_pitch) ?
  2316.           @sound_pitch : @sound_pitch_range      
  2317.       # If we want to Randomize the Sounds
  2318.       if @sound_vary_pitch == 'random'
  2319.         # Random within the Range
  2320.         pitch = rand(sound_pitch_range * 2) + @sound_pitch - sound_pitch_range
  2321.       # Vary Sound Pitch to be based on Letter Sounds
  2322.       else
  2323.         # Note to Self - Reorganize based on actual Letter Sounds, not so Random
  2324.         if ['l','m','n','q','u','w','2'].include?(char)
  2325.           pitch = @sound_pitch - sound_pitch_range
  2326.         elsif ['a','f','h','j','k','o','r','x','1','4','7','8'].include?(char)
  2327.           pitch = @sound_pitch - sound_pitch_range / 2
  2328.         elsif ['b','c','d','e','g','p','t','v','z','0','3','6'].to_a.include?(char)
  2329.           pitch = @sound_pitch
  2330.         elsif ['s','7'].to_a.include?(char)
  2331.           pitch = @sound_pitch + sound_pitch_range / 2
  2332.         elsif ['i','y','5','9'].to_a.include?(char)
  2333.           pitch = @sound_pitch + sound_pitch_range
  2334.         else
  2335.           pitch = rand(@sound_pitch_range * 2) + @sound_pitch
  2336.         end
  2337.       end
  2338.     else
  2339.       pitch=(@sound_pitch and @sound_pitch.is_a?(Numeric)) ? @sound_pitch : 100
  2340.     end
  2341.     # Play the Sound
  2342.     Audio.se_play(sound, volume, pitch)
  2343.   end
  2344.   #--------------------------------------------------------------------------
  2345.   # * Alias Listing
  2346.   #--------------------------------------------------------------------------
  2347.   alias upd_mess_log update unless method_defined?(:upd_mess_log)
  2348.   alias dis_mess_log dispose unless method_defined?(:dis_mess_log)
  2349.   #--------------------------------------------------------------------------
  2350.   # * Create Message Log
  2351.   #--------------------------------------------------------------------------
  2352.   def create_message_log(win = MESSAGE_LOG_WINDOWSKIN)
  2353.     log_opacity = MESSAGE_LOG_OPACITY
  2354.     @message_log_sprite = [@message_log = Sprite.new,
  2355.                           @message_log_text = Sprite.new]
  2356.     @message_log.bitmap = Bitmap.new(600,460)
  2357.     @message_log_text.bitmap = @message_log.bitmap.dup
  2358.     @message_log.bitmap.clear
  2359.     @message_log_text.bitmap.clear
  2360.     @message_log.x, @message_log.y = 20, 10
  2361.     @message_log.z = self.z * 2
  2362.     @message_log.opacity = 200
  2363.     @message_log_text.opacity = 255
  2364.     @message_log_text.z = @message_log.z + 10
  2365.     draw_window(@message_log.bitmap.width, @message_log.bitmap.height, win)
  2366.     frame, mess = @frame.bitmap, @message_log.bitmap
  2367.     cls = [Color.new(0,0,0,0), Color.new(255,255,255,255)]
  2368.     @message_log.bitmap.blt(0,0,frame,frame.rect, log_opacity)
  2369.     @message_log_height = 0
  2370.     $multiple_message_windows['saved'].reverse.each_with_index do |i,s|
  2371.       next if s < @message_log_index
  2372.       @message_log_height +=(i.height+20)
  2373.       v = mess.height - @message_log_height
  2374.       @message_log_text.bitmap.blt(20 ,v ,i, i.rect)
  2375.       @message_log.bitmap.fill_rect( Rect.new(30,v-15,mess.width-60,2),cls[0])
  2376.     end
  2377.     @message_log.bitmap.blt(0,0,frame, Rect.new(0,0,frame.width,50),log_opacity)
  2378.     @message_log.bitmap.fill_rect( Rect.new(10,40, mess.width-20,2), cls[1])
  2379.     @message_log_text.bitmap.fill_rect( Rect.new(0,0,frame.width,55), cls[0])
  2380.     @message_log.bitmap.font.name = MESSAGE_LOG_FONT.flatten
  2381.     @message_log.bitmap.font.size = [MESSAGE_LOG_FONT[-1].to_i, 12].max
  2382.     @message_log.bitmap.draw_text(10,0,mess.width,  45,MESSAGE_LOG_TEXT)
  2383.     [@frame].each {|i| i.dispose}
  2384.   end
  2385.   #--------------------------------------------------------------------------
  2386.   # * Update Frame
  2387.   #--------------------------------------------------------------------------
  2388.   def update
  2389.     message_log_input if $game_system.message.message_log
  2390.     upd_mess_log unless @message_log
  2391.   end
  2392.   #--------------------------------------------------------------------------
  2393.   # * message_log_input
  2394.   #--------------------------------------------------------------------------
  2395.   def message_log_input
  2396.     if (saved_image = $multiple_message_windows['saved']) &&
  2397.       !saved_image.empty? && !@message_log && @msgindex == 0
  2398.       if input_message_log(sc = mouse_scroll) || @force_message_log == 1
  2399.         @message_log_move = [$game_system.message.move_during,
  2400.                             $game_temp.message_window_showing]
  2401.         $game_temp.message_window_showing = true
  2402.         $game_system.message.move_during = false
  2403.         $game_system.se_play($data_system.decision_se)
  2404.         @message_log_index = @force_message_log = 0
  2405.         return create_message_log
  2406.       end
  2407.     elsif @message_log && @msgindex == 0
  2408.       if cansel_mesage_log
  2409.         $game_system.message.move_during = @message_log_move[0]
  2410.         $game_temp.message_window_showing = @message_log_move[1]
  2411.         $game_system.se_play($data_system.cancel_se)
  2412.         @message_log_sprite.compact.each {|i| i.dispose}
  2413.         @message_log = nil
  2414.       elsif elmessage_log(sc = mouse_scroll)
  2415.         @message_log_index = [(s=@message_log_index)+1,saved_image.size-1].min
  2416.         $game_system.se_play($data_system.cursor_se) if s != @message_log_index
  2417.         @message_log_sprite.compact.each {|i| i.dispose}
  2418.         create_message_log
  2419.       elsif ermessage_log(sc)
  2420.         @message_log_index = [(s=@message_log_index)-1,0].max
  2421.         $game_system.se_play($data_system.cursor_se) if s != @message_log_index
  2422.         @message_log_sprite.compact.each {|i| i.dispose}
  2423.         create_message_log
  2424.       end
  2425.     end
  2426.   end
  2427.   #--------------------------------------------------------------------------
  2428.   # * Forcefully Show Message Log
  2429.   #--------------------------------------------------------------------------
  2430.   def show_message_log
  2431.     @force_message_log = 1
  2432.   end
  2433.   #--------------------------------------------------------------------------
  2434.   # * input_message_log
  2435.   #--------------------------------------------------------------------------
  2436.   def input_message_log(sc = 0)
  2437.     return true if Input.trigger?(Input::F8)
  2438.     return true if sc > 0
  2439.     return false
  2440.   end
  2441.   #--------------------------------------------------------------------------
  2442.   # * Cancel Message Log
  2443.   #--------------------------------------------------------------------------
  2444.   def cansel_mesage_log
  2445.     begin
  2446.       return true if Input.trigger?(Input::F8)
  2447.       return true if Input.trigger?(Input::B)
  2448.       if $mouse_controller || $BlizzABS
  2449.         return true if Input.trigger?(Input::Key['Mouse Right'])
  2450.       elsif (($imported ||= {})[:drg_custom_input] || 0) >= 2.00
  2451.         return true if Mouse.press?(Mouse::SECONDARY)
  2452.       end
  2453.     rescue
  2454.       false
  2455.     end
  2456.     return false
  2457.   end
  2458.   #--------------------------------------------------------------------------
  2459.   # * elmessage_log
  2460.   #--------------------------------------------------------------------------
  2461.   def elmessage_log(sc = 0)
  2462.     return true if Input.trigger?(Input::L)
  2463.     return true if Input.repeat?(Input::UP)
  2464.     return true if sc > 0
  2465.     return false
  2466.   end
  2467.   #--------------------------------------------------------------------------
  2468.   # * ermessage_log
  2469.   #--------------------------------------------------------------------------
  2470.   def ermessage_log(sc = 0)
  2471.     return true if Input.trigger?(Input::R)
  2472.     return true if Input.repeat?(Input::DOWN)
  2473.     return true if sc < 0
  2474.     return false
  2475.   end
  2476.   #--------------------------------------------------------------------------
  2477.   # * mouse_scroll
  2478.   #--------------------------------------------------------------------------
  2479.   def mouse_scroll
  2480.     @scroll_count = (@scroll_count || 0) + 1
  2481.     return 0 if @scroll_count < 5
  2482.     @scroll_count = 0
  2483.     if Input.respond_to?(:scroll?)
  2484.       return 1  if Input.scroll_up?
  2485.       return -1 if Input.scroll_down?
  2486.     end
  2487.     if (($imported ||= {})[:drg_custom_input] || 0) >= 2.00
  2488.       return 1  if Mouse.scroll_up?
  2489.       return -1 if Mouse.scroll_down?
  2490.     end
  2491.     return 0
  2492.   end
  2493.   #--------------------------------------------------------------------------
  2494.   # * Dispose
  2495.   #--------------------------------------------------------------------------
  2496.   def dispose
  2497.     dis_mess_log
  2498.     @message_log_sprite.compact.each {|i| i.dispose} if @message_log_sprite
  2499.   end
  2500.   #--------------------------------------------------------------------------
  2501.   # * Alias Listing
  2502.   #--------------------------------------------------------------------------
  2503.   alias upd_portrait update unless method_defined?(:upd_portrait)
  2504.   alias term_face_por terminate_face unless method_defined?(:term_face_por)
  2505.   #--------------------------------------------------------------------------
  2506.   # * create_portrait
  2507.   #--------------------------------------------------------------------------
  2508.   def create_portrait(face)
  2509.     terminate_face rescue return
  2510.     return if face.nil? || face == ' ' #\f [portrait,face,coord,color,xy]
  2511.     dir, a, b = 'Graphics/Portrait', [204+5,28,204,204], [0,0]
  2512.     Dir.mkdir(dir) unless File.directory?(dir)
  2513.     a = face[2].split(',').map {|x| x.to_i } if face[2] && face[2] != ' '
  2514.     b = face[4].split(',').map {|x| x.to_i } if face[4] && face[4] != ' '
  2515.     c = face[3]
  2516.     d = Bitmap.new("#{dir}/#{face[0]}")
  2517.     e = Bitmap.new("#{dir}/#{face[1]}")  if face[1] && face[1][0].chr != ' '
  2518.     f = Bitmap.new(80,80)
  2519.     @portrait = Sprite.new
  2520.     @portrait.bitmap, @portrait.opacity = d, 0
  2521.     @portrait.x, @portrait.y = b[0], b[1]
  2522.     @portrait.bitmap.blt(0, 0, e || Bitmap.new(1,1),
  2523.         Rect.new(0,0,@portrait.bitmap.width,a[1]+a[3]))
  2524.     unless  c == ' '    
  2525.       f.fill_rect(Rect.new(0,0,80,80),check_color(0)) if c
  2526.       f.stretch_blt(f.rect, @portrait.bitmap, Rect.new(*a)) if face[1] != ' '
  2527.       f.fill_rect(Rect.new(0,0,80,2),check_color(c))  if c
  2528.       f.fill_rect(Rect.new(0,78,80,2),check_color(c)) if c
  2529.       f.fill_rect(Rect.new(0,0,2,80),check_color(c))  if c
  2530.       f.fill_rect(Rect.new(78,0,2,80),check_color(c)) if c
  2531.     end
  2532.     create_face_cont(f)
  2533.   end
  2534.   #--------------------------------------------------------------------------
  2535.   # * Update Frame
  2536.   #--------------------------------------------------------------------------
  2537.   def update
  2538.     @portrait.opacity = [@portrait.opacity+15, 255].min if @portrait
  2539.     upd_portrait
  2540.   end
  2541.   #--------------------------------------------------------------------------
  2542.   # * terminate_face
  2543.   #--------------------------------------------------------------------------
  2544.   def terminate_face
  2545.     term_face_por
  2546.     eval '@portrait.dispose;  @portrait = nil' if @portrait
  2547.   end
  2548.   #--------------------------------------------------------------------------
  2549.   # * Alias Listing
  2550.   #--------------------------------------------------------------------------
  2551.   alias drg3x4dkc2dy_repbcod replace_basic_code
  2552.   #--------------------------------------------------------------------------
  2553.   # * Replace Basic Code
  2554.   #--------------------------------------------------------------------------
  2555.   def replace_basic_code
  2556.     @text.gsub!(/\\[Ii][Ff]\[(.*?),(.*?)\]/) do
  2557.       cond, result = "#$1", "#$2"
  2558.       message_eval(cond.gsub!("(!","[").gsub!("!)","]")) ? result : ""
  2559.     end
  2560.     @text.gsub!(/\\[Uu][Nn][Ll][Ee][Ss][Ss]\[(.*?),(.*?)\]/) do
  2561.       cond, result = "#$1", "#$2"
  2562.       message_eval(cond.gsub!("(!","[").gsub!("!)","]")) ?  "" : result
  2563.     end
  2564.     drg3x4dkc2dy_repbcod
  2565.   end
  2566. end
  2567. #==============================================================================
  2568. # ** Game_Character
  2569. #------------------------------------------------------------------------------
  2570. #  This class deals with characters. It's used as a superclass for the
  2571. #  Game_Player and Game_Event classes.
  2572. #==============================================================================
  2573.  
  2574. class Game_Character
  2575.   #--------------------------------------------------------------------------
  2576.   # * Public Instance Variables
  2577.   #--------------------------------------------------------------------------
  2578.   attr_accessor   :no_ff, :rev_scr_xy
  2579.   attr_reader     :erased
  2580.   #--------------------------------------------------------------------------
  2581.   # * Name
  2582.   #---------------------------------------------------------------------------
  2583.   def name() self.is_a?(Game_Event) ? @event.name : $game_party.actors[0].name end
  2584.   #--------------------------------------------------------------------------
  2585.   # * last_real_xy
  2586.   #--------------------------------------------------------------------------
  2587.   def last_real_xy() [@real_x, @real_y] end
  2588.   #----------------------------------------------------------------------------
  2589.   # * Allows Animation Change regardless of Direction
  2590.   #----------------------------------------------------------------------------
  2591.   unless self.method_defined?('foot_forward_on')  
  2592.     def foot_forward_on(frame = 0)
  2593.       return if @direction_fix || !@walk_anime || @step_anime ||
  2594.                 $game_temp.in_battle
  2595.       @pattern = case @direction
  2596.       when 2       then frame == 0 ? 3 : 1
  2597.       when 4, 6, 8 then frame == 0 ? 1 : 3
  2598.       end || 0
  2599.       @original_pattern = @pattern
  2600.       refresh
  2601.     end
  2602.     def foot_forward_off
  2603.       # If called by walking off screen, dont affect a Sign or Stepping Actor
  2604.       return if $game_temp.in_battle || @direction_fix || !@walk_anime || @no_ff
  2605.       @pattern, @original_pattern = 0, 0
  2606.     end
  2607.   end
  2608.   #----------------------------------------------------------------------------
  2609.   # * within_range?
  2610.   #----------------------------------------------------------------------------
  2611.   def within_range?(range = 4, id = @event_id)
  2612.     e = $game_map.events[id]
  2613.     # using real_x and real_y to support BlizzABS pixel movement
  2614.     e = (Math.hypot((e.x-$game_player.real_x/128),
  2615.         (e.y-$game_player.real_y/128))).abs if e
  2616.     return (e <= range) if e
  2617.   end  
  2618. end
  2619.  
  2620. #==============================================================================
  2621. # ** Sprite_Battler
  2622. #------------------------------------------------------------------------------
  2623. #  This sprite is used to display the battler.It observes the Game_Character
  2624. #  class and automatically changes sprite conditions.
  2625. #==============================================================================
  2626. ['Sprite_Battler','Spriteset_Battle'].each {|i| eval "
  2627. class #{i}
  2628.  #--------------------------------------------------------------------------
  2629.  # * Public Instance Variables
  2630.  #--------------------------------------------------------------------------
  2631.  # necessary for positioning messages relative to battlers
  2632.  attr_reader :height, :width, :actor_sprites, :enemy_sprites
  2633. end#"}
  2634.  
  2635. #==============================================================================
  2636. # ** Game_Temp
  2637. #------------------------------------------------------------------------------
  2638. #  This class handles temporary data that is not included with save data.
  2639. #  Refer to "$game_temp" for the instance of this class.
  2640. #==============================================================================
  2641. class Game_Temp
  2642.   attr_accessor :num_input_variable_id_backup, :input_in_window
  2643.   attr_accessor :input_type
  2644. end
  2645.  
  2646. #==============================================================================
  2647. # ** Scene_Map
  2648. #------------------------------------------------------------------------------
  2649. #  This class performs map screen processing.
  2650. #==============================================================================
  2651. ['Scene_Map','Scene_Battle'].each_with_index {|klass,i| eval "
  2652. class #{klass}
  2653.  #--------------------------------------------------------------------------
  2654.  # * Public Instance Variables
  2655.  #--------------------------------------------------------------------------
  2656.  # necessary for accessing actor/enemy sprites in battle
  2657.  attr_accessor :spriteset, :multi_message_window, :message_window
  2658.  #--------------------------------------------------------------------------
  2659.  # * Alias Listing
  2660.  #--------------------------------------------------------------------------
  2661.  alias drg128_upd update unless method_defined?(:drg128_upd)
  2662.  alias drg128_main main unless method_defined?(:drg128_main)
  2663.  #--------------------------------------------------------------------------
  2664.  # * drg152_main
  2665.  #--------------------------------------------------------------------------
  2666.  def drg152_main
  2667.    drg128_main  
  2668.    dispose_mmw_variable(@multi_message_window + @cinemasks)
  2669.  end
  2670.  #--------------------------------------------------------------------------
  2671.  # * dispose_multi_message_window
  2672.  #--------------------------------------------------------------------------
  2673.  def dispose_mmw_variable(var = [])
  2674.    var.each {|mw| mw.disposed? || mw.dispose}  
  2675.  end
  2676.  #--------------------------------------------------------------------------
  2677.  # * Main Processing
  2678.  #--------------------------------------------------------------------------
  2679.  def main()  drg152_main end
  2680.  #--------------------------------------------------------------------------
  2681.  # * New Message Window Addition
  2682.  #--------------------------------------------------------------------------
  2683.  def new_message_window(index)
  2684.    if @multi_message_window[index] != nil
  2685.      # clear message windows at and after this index
  2686.      (@multi_message_window.size - 1).downto(index) { |i|
  2687.        next if @multi_message_window[i] == nil
  2688.        @multi_message_window[i].dispose
  2689.        @multi_message_window[i] = nil }
  2690.      @multi_message_window.compact!
  2691.    end
  2692.    @multi_message_window.push(Window_Message.new(index))
  2693.  end
  2694.  #--------------------------------------------------------------------------
  2695.  # * Cinemaskie
  2696.  #--------------------------------------------------------------------------
  2697.  def create_cinema(a=640,b=48,x=0,y=0,z=nil,o= nil)
  2698.    mask,@cinema_fadecount = Sprite.new, 24
  2699.    mask.bitmap = Bitmap.new(a,b)
  2700.    mask.bitmap.fill_rect(0,0,a,b, Color.new(0,0,0,255))
  2701.    mask.x, mask.y, mask.opacity = [x,y,o||255]
  2702.    mask.z = z || $game_system.message.cinema_z
  2703.    return mask
  2704.  end
  2705.  #--------------------------------------------------------------------------
  2706.  # Update Cinema
  2707.  #--------------------------------------------------------------------------
  2708.  def update_cinema
  2709.    cii = $game_system.message.cinema
  2710.    @cinemasks ||= []
  2711.    @cinema_fadecount ||= 24
  2712.    if (cii && @cinema_fadecount >  0) || (!cii && @cinema_fadecount < 24)
  2713.      if @cinemasks.empty?
  2714.        @cinemasks << create_cinema(640,48,0,-48)
  2715.        @cinemasks << create_cinema(640,72,0,480)
  2716.        @cinemasks << create_cinema(640,480,0,0,199,0)
  2717.      end            
  2718.      @cinema_fadecount = (@cinema_fadecount || 24) + (cii ? -1 : 1)
  2719.      @cinemasks[0].y =   0 -  6 *       @cinema_fadecount  / 3
  2720.      @cinemasks[1].y = 480 -  9 * (24 - @cinema_fadecount) / 3
  2721.      @cinemasks[2].opacity =  4 * (24 - @cinema_fadecount)
  2722.    elsif !@cinemasks.empty? && @cinemasks[0].y <= -48
  2723.      dispose_mmw_variable(@cinemasks)
  2724.      @cinemasks = []
  2725.    end      
  2726.  end
  2727.  #--------------------------------------------------------------------------
  2728.  # * update_scene_cinema
  2729.  #--------------------------------------------------------------------------
  2730.  def update_scene_cinema
  2731.    @multi_message_window ||= [@message_window]  
  2732.    @multi_message_window.each_with_index {|mw,i| mw.disposed? || i == 0 || mw.update}    
  2733.    update_cinema
  2734.  end
  2735.  #--------------------------------------------------------------------------
  2736.  # * Frame Update
  2737.  #--------------------------------------------------------------------------
  2738.  def update
  2739.    update_scene_cinema
  2740.    drg128_upd
  2741.  end
  2742. end#"}
  2743. #==============================================================================
  2744. # ** Game_Player
  2745. #------------------------------------------------------------------------------
  2746. #  This class handles the player. Its functions include event starting
  2747. #  determinants and map scrolling. Refer to "$game_player" for the one
  2748. #  instance of this class.
  2749. #==============================================================================
  2750.  
  2751. class Game_Player
  2752.   #--------------------------------------------------------------------------
  2753.   # * Alias Listing
  2754.   #--------------------------------------------------------------------------
  2755.   alias drg128_upd update unless method_defined?(:drg128_upd)
  2756.   #--------------------------------------------------------------------------
  2757.   # * Frame Update
  2758.   #--------------------------------------------------------------------------
  2759.   def update
  2760.     update_mmw_moving
  2761.     drg128_upd
  2762.   end
  2763.   #--------------------------------------------------------------------------
  2764.   # * update_mmw_moving
  2765.   #--------------------------------------------------------------------------
  2766.   def update_mmw_moving
  2767.     message_showing = $game_temp.message_window_showing
  2768.     unless moving? || @move_route_forcing ||
  2769.       ($game_system.map_interpreter.running? && !message_showing) ||
  2770.       (message_showing && !$game_system.message.move_during) ||
  2771.       ($game_temp.choice_max > 0 || $game_temp.num_input_digits_max > 0)
  2772.       if (input = Input.dir4)
  2773.         case input
  2774.         when 2 then move_down
  2775.         when 4 then move_left
  2776.         when 6 then move_right
  2777.         when 8 then move_up
  2778.         end
  2779.       end
  2780.     end
  2781.   end
  2782.   #--------------------------------------------------------------------------
  2783.   # * Touch Event Starting Determinant
  2784.   #--------------------------------------------------------------------------
  2785.   # This is a fix if Blizzard's Optimized default scripts are being used
  2786.   if method_defined?(:check_event_trigger_touch)
  2787.     alias_method(:check_event_trigger_fix, :check_event_trigger_touch)
  2788.     def check_event_trigger_touch(*args)
  2789.       return false if $game_system.map_interpreter.running?
  2790.       return check_event_trigger_fix(*args)
  2791.     end
  2792.   end
  2793. end
  2794. #==============================================================================
  2795. # ** Game_System
  2796. #------------------------------------------------------------------------------
  2797. #  This class handles data surrounding the system. Backround music, etc.
  2798. #  is managed here as well. Refer to "$game_system" for the instance of
  2799. #  this class.
  2800. #==============================================================================
  2801.  
  2802. class Game_System
  2803.   #--------------------------------------------------------------------------
  2804.   # * Public Instance Variables
  2805.   #--------------------------------------------------------------------------
  2806.   attr_accessor :number_cancelled
  2807.   #--------------------------------------------------------------------------
  2808.   # * Alias Listing
  2809.   #--------------------------------------------------------------------------
  2810.   alias drg128_upd update unless method_defined?(:drg128_upd)
  2811.   #--------------------------------------------------------------------------
  2812.   # * Frame Update
  2813.   #--------------------------------------------------------------------------
  2814.   def update
  2815.     update_shaded_fix
  2816.     drg128_upd
  2817.   end
  2818.   #--------------------------------------------------------------------------
  2819.   # * Frame Update
  2820.   #--------------------------------------------------------------------------
  2821.   def message()  @message ||= Game_Message.new  end
  2822.   #--------------------------------------------------------------------------
  2823.   # * Frame Update
  2824.   #--------------------------------------------------------------------------
  2825.   def update_shaded_fix
  2826.     if message && @SHADED_TEXT != nil && Blizzard_Shaded_Text_Fix == true
  2827.       if $game_temp.message_window_showing
  2828.         @SHADED_TEXT = false
  2829.       else
  2830.         @SHADED_TEXT = true
  2831.       end
  2832.     end
  2833.   end
  2834.   #--------------------------------------------------------------------------
  2835.   # Can Move?
  2836.   #--------------------------------------------------------------------------
  2837.   def blizzabs_can_move?(type=0)
  2838.     player = $BlizzABS.actors[0]
  2839.     message_showing = $game_temp.message_window_showing
  2840.     interpreter = $game_system.map_interpreter.running?
  2841.     return type == 0 ? (((player.ai.act.defend? && player.attacked == 0) ||
  2842.           $game_system.turn_button && Input.press?(Input::Turn)) &&
  2843.           !player.moving? && !player.move_route_forcing &&
  2844.           (!interpreter || message_showing) &&
  2845.           (!message_showing || $game_system.message.move_during) &&
  2846.           $game_temp.choice_max <= 0 && $game_temp.num_input_digits_max <= 0) :
  2847.           (player.move_route_forcing ||  (interpreter && !message_showing) ||
  2848.           (message_showing && !$game_system.message.move_during) ||
  2849.           ($game_temp.choice_max > 0 || $game_temp.num_input_digits_max > 0))
  2850.   end
  2851. end
  2852.  
  2853. #==============================================================================
  2854. # ** Interpreter
  2855. #------------------------------------------------------------------------------
  2856. #  This interpreter runs event commands. This class is used within the
  2857. #  Game_System class and the Game_Event class.
  2858. #==============================================================================
  2859. class Interpreter
  2860.   #--------------------------------------------------------------------------
  2861.   # * Alias Listing
  2862.   #--------------------------------------------------------------------------
  2863.   alias drg128_setup setup unless method_defined?(:drg128_setup)
  2864.   alias drg128_upd update unless method_defined?(:drg128_upd)
  2865.   #--------------------------------------------------------------------------
  2866.   # * Setup
  2867.   #--------------------------------------------------------------------------
  2868.   def setup(*args)
  2869.     drg128_setup(*args)
  2870.     # index of window for the message
  2871.     @msgindex = 0
  2872.     $game_temp.message_text, $game_temp.message_proc = [],[]
  2873.     if @list.size > 1
  2874.       templist = @list.pop
  2875.       @list << RPG::EventCommand.new(106,0,[1]) << templist
  2876.     end
  2877.     # whether multiple messages are displaying
  2878.     @multi_message = false
  2879.   end
  2880.   #--------------------------------------------------------------------------
  2881.   # * Update
  2882.   #--------------------------------------------------------------------------
  2883.   def update(*args)
  2884.     @message_waiting = $game_temp.message_window_showing
  2885.     drg128_upd(*args)
  2886.   end
  2887.   #--------------------------------------------------------------------------
  2888.   # * Message
  2889.   #--------------------------------------------------------------------------
  2890.   def message() $game_system.message end
  2891.   #--------------------------------------------------------------------------
  2892.   # * Setup Choices
  2893.   #--------------------------------------------------------------------------
  2894.   def setup_choices(parameters)
  2895.     # Set choice item count to choice_max
  2896.     $game_temp.choice_max = parameters[0].size
  2897.     # Set choice to message_text
  2898.     parameters[0].each {|text| $game_temp.message_text[@msgindex] += text + "\n"}
  2899.     # Set cancel processing
  2900.     $game_temp.choice_cancel_type = parameters[1]
  2901.     # Set callback
  2902.     current_indent = @list[@index].indent
  2903.     $game_temp.choice_proc = Proc.new { |n| @branch[current_indent] = n }
  2904.   end
  2905.   #--------------------------------------------------------------------------
  2906.   # * Show Text
  2907.   #--------------------------------------------------------------------------
  2908.   def command_101
  2909.     # If other text has been set to message_text
  2910.     if $game_temp.message_text[@msgindex] != nil
  2911.       if @multi_message
  2912.         @msgindex += 1
  2913.         $scene.new_message_window(@msgindex)
  2914.       else
  2915.         # End
  2916.         return false
  2917.       end
  2918.     end
  2919.     @msgindex = 0 if !@multi_message
  2920.     @multi_message = false
  2921.     # Set message end waiting flag and callback
  2922.     @message_waiting = true
  2923.     # just adding indexes
  2924.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  2925.     # Set message text on first line
  2926.     $game_temp.message_text[@msgindex] = @list[@index].parameters[0] + "\n"
  2927.     $scene.multi_message_window[@msgindex].event_id = @event_id
  2928.     line_count = 1
  2929.     # Loop
  2930.     loop do
  2931.       # If next event command text is on the second line or after
  2932.       if @list[@index+1].code == 401 || @list[@index+1].code == 101 &&
  2933.           @list[@index+1].parameters[0][0..1] == '\\#'
  2934.         # just adding index
  2935.         $game_temp.message_text[@msgindex] += @list[@index+1].parameters[0]+"\n"
  2936.         line_count += 1
  2937.       # If event command is not on the second line or after
  2938.       else
  2939.         # If next event command is show choices
  2940.         if @list[@index+1].code == 102
  2941.           # If choices fit on screen
  2942.           if @list[@index+1].parameters[0].size <= 4 - line_count
  2943.             # Prevent the closure of a single window with multiple windows
  2944.             $game_temp.input_in_window = true            
  2945.             # Flag this window as having choices displayed for multi
  2946.             $scene.multi_message_window[@msgindex].choice_window = @msgindex
  2947.             # Advance index
  2948.             @index += 1
  2949.             # Choices setup
  2950.             $game_temp.choice_start = line_count
  2951.             setup_choices(@list[@index].parameters)
  2952.           end
  2953.         # If next event command is input number
  2954.         elsif @list[@index+1].code == 103
  2955.           # If number input window fits on screen
  2956.           if line_count < 4
  2957.             # Prevent the closure of a single window with multiple windows
  2958.             $game_temp.input_in_window = true
  2959.             # Flag this window as having choices displayed
  2960.             $scene.multi_message_window[@msgindex].choice_window = @msgindex
  2961.             # Advance index
  2962.             @index += 1
  2963.             # Number input setup
  2964.             $game_temp.num_input_start = line_count
  2965.             $game_temp.num_input_variable_id = @list[@index].parameters[0]
  2966.             $game_temp.num_input_digits_max = @list[@index].parameters[1]
  2967.             $game_temp.num_input_variable_id_backup =
  2968.               @list[@index].parameters[0]
  2969.           end
  2970.         # start multimessage if next line is "Show Text" starting with "\\+"
  2971.         elsif @list[@index+1].code == 101
  2972.           if @list[@index+1].parameters[0][0..1]=='\\+'
  2973.             @multi_message,@message_waiting = true, false
  2974.           end
  2975.         end
  2976.         # Continue
  2977.         return true
  2978.       end
  2979.       # Advance index
  2980.       @index += 1
  2981.     end
  2982.   end
  2983.   #--------------------------------------------------------------------------
  2984.   # * Show Choices
  2985.   #--------------------------------------------------------------------------
  2986.   def command_102
  2987.     # Prevent the closure of a single window with multiple windows
  2988.     $game_temp.input_in_window = true
  2989.     # Flag this window as having choices displayed for multi
  2990.     $scene.multi_message_window[@msgindex].choice_window = @msgindex  
  2991.     # If text has been set to message_text
  2992.     # just adding index
  2993.     return false if $game_temp.message_text[@msgindex] != nil
  2994.     # Set message end waiting flag and callback
  2995.     @message_waiting = true
  2996.     # adding more indexes
  2997.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  2998.     # Choices setup
  2999.     $game_temp.message_text[@msgindex] = ''
  3000.     $game_temp.choice_start = 0
  3001.     setup_choices(@parameters)
  3002.     # Continue
  3003.     return true
  3004.   end
  3005.   #--------------------------------------------------------------------------
  3006.   # * Input Number
  3007.   #--------------------------------------------------------------------------
  3008.   def command_103
  3009.     # Prevent the closure of a single window with multiple windows
  3010.     $game_temp.input_in_window = true
  3011.     # Flag this window as having choices displayed for multi
  3012.     $scene.multi_message_window[@msgindex].choice_window = @msgindex  
  3013.     # If text has been set to message_text
  3014.     # just adding index
  3015.     return false if $game_temp.message_text[@msgindex] != nil
  3016.     # Set message end waiting flag and callback
  3017.     @message_waiting = true
  3018.     # adding more indexes
  3019.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  3020.     # Number input setup
  3021.     $game_temp.message_text[@msgindex] = ''
  3022.     $game_temp.num_input_start = 0
  3023.     $game_temp.num_input_variable_id = @parameters[0]
  3024.     $game_temp.num_input_digits_max = @parameters[1]
  3025.     $game_temp.num_input_variable_id_backup = @list[@index].parameters[0]
  3026.     # Continue
  3027.     return true
  3028.   end
  3029.   #--------------------------------------------------------------------------
  3030.   # ● Redefined method: same_map?, next_event_code
  3031.   #--------------------------------------------------------------------------
  3032.   def same_map?()        @map_id == $game_map.map_id    end
  3033.   def next_event_code()  @list[@index + 1].code         end
  3034.   SCRIPT_WAIT_RESULTS = [:wait, FalseClass]
  3035.   #--------------------------------------------------------------------------
  3036.   # * Script
  3037.   #--------------------------------------------------------------------------
  3038.   # Fix for RMXP bug: call script boxes that return false hang the game
  3039.   # See, e.g., http://rmxp.org/forums/showthread.php?p=106639  
  3040.   #--------------------------------------------------------------------------
  3041.   def command_355
  3042.     script = @list[index = @index].parameters[0] + "\n"
  3043.     while [655, 355].include?(next_event_code) do
  3044.       script += @list[@index+=1].parameters[0] + "\n"
  3045.     end
  3046.     wait = SCRIPT_WAIT_RESULTS.include?(eval(script))
  3047.     return wait ? !(@index = index) : true
  3048.   end  
  3049. end
  3050. #==============================================================================
  3051. # ** Game_Map
  3052. #------------------------------------------------------------------------------
  3053. #  This class handles the map. It includes scrolling and passable determining
  3054. #  functions. Refer to "$game_map" for the instance of this class.
  3055. #==============================================================================
  3056. class Game_Map
  3057.   #--------------------------------------------------------------------------
  3058.   # * Define Method
  3059.   #--------------------------------------------------------------------------
  3060.   define_method(:last_disp_xy) { [@display_x, @display_y] }
  3061.   define_method(:name) { load_data('Data/MapInfos.rxdata')[@map_id].name  }
  3062. end
  3063. #==============================================================================
  3064. # ** Bitmap
  3065. #------------------------------------------------------------------------------
  3066. #  This class is for all in-game bitmap.
  3067. #==============================================================================
  3068. class Bitmap
  3069.   #--------------------------------------------------------------------------
  3070.   # * Public Instance Variables
  3071.   #--------------------------------------------------------------------------
  3072.   attr_accessor :orientation
  3073.   #--------------------------------------------------------------------------
  3074.   # * Rotation Calculation
  3075.   #--------------------------------------------------------------------------
  3076.   def rotation(t)
  3077.     return if not [0, 90, 180, 270].include?(t) # invalid orientation
  3078.     rotate(t - @orientation + (t-@orientation < 0 ? 360 : 0)) if @rotation != t
  3079.   end
  3080.   #--------------------------------------------------------------------------
  3081.   # * Rotate Square (Clockwise)
  3082.   #--------------------------------------------------------------------------
  3083.   def rotate(degrees = 90)
  3084.     # method originally by SephirothSpawn
  3085.     # would just use Sprite.angle but its rotation is buggy
  3086.     return if not [90, 180, 270].include?(degrees)
  3087.     copy = self.clone
  3088.     if degrees == 90
  3089.       # Passes Through all Pixels on Dummy Bitmap
  3090.       (0...self.height).each {|i| (0...self.width).each {|j|
  3091.           self.set_pixel(width - i - 1, j, copy.get_pixel(j, i))}}
  3092.     elsif degrees == 180
  3093.       (0...self.height).each {|i| (0...self.width).each {|j|
  3094.           self.set_pixel(width - j - 1, height - i - 1, copy.get_pixel(j, i))} }      
  3095.     elsif degrees == 270
  3096.       (0...self.height).each {|i| (0...self.width).each {|j|
  3097.           self.set_pixel(i, height - j - 1, copy.get_pixel(j, i)) } }
  3098.     end
  3099.     @orientation = (@orientation + degrees) % 360
  3100.   end
  3101.   #--------------------------------------------------------------------------
  3102.   # ? erase
  3103.   #--------------------------------------------------------------------------
  3104.   def erase(*args)
  3105.     case args.size
  3106.     when 1 then fill_rect( args[0], Color.new(0, 0, 0, 0))
  3107.     when 4 then fill_rect(Rect.new(*args), Color.new(0, 0, 0, 0))
  3108.     end
  3109.   end
  3110. end
  3111. #==============================================================================
  3112. # ** Window_Base
  3113. #------------------------------------------------------------------------------
  3114. #  This class is for all in-game windows.
  3115. #==============================================================================
  3116. class Window_Base
  3117.   #--------------------------------------------------------------------------
  3118.   # * Check Color
  3119.   #     color : color to check
  3120.   #--------------------------------------------------------------------------
  3121.   def check_color(color)
  3122.     if color.type == Color
  3123.       # already a Color object
  3124.       return color
  3125.     elsif color[0].chr == "#"
  3126.       # specified as hexadecimal
  3127.       r = color[1..2].hex
  3128.       g = color[3..4].hex
  3129.       b = color[5..6].hex
  3130.       return Color.new(r,g,b)
  3131.     else
  3132.       # specified as integer (0-7)
  3133.       color = color.to_i if color
  3134.       if color && color >= 0 && color <= 7
  3135.         return text_color(color)
  3136.       end
  3137.     end
  3138.     return normal_color
  3139.   end
  3140. end
  3141. #==============================================================================
  3142. # ** Window_InputNumber
  3143. #------------------------------------------------------------------------------
  3144. #  This window is for inputting numbers, and is used within the
  3145. #  message window.
  3146. #==============================================================================
  3147. class Window_InputNumber < Window_Base
  3148.   #--------------------------------------------------------------------------
  3149.   # * Object Initialization
  3150.   #     digits_max : digit count
  3151.   #--------------------------------------------------------------------------
  3152.   def initialize(digits_max)
  3153.     @character_array = get_characters
  3154.     @digits_max = digits_max
  3155.     @letter_array = [0] * @digits_max
  3156.     super(0, 0, cursor_width * @digits_max + 32, 64)
  3157.     self.contents = Bitmap.new(width - 32, height - 32)
  3158.     self.z += 9999
  3159.     self.opacity = 0
  3160.     @index = 0
  3161.     refresh
  3162.     update_cursor_rect
  3163.   end
  3164.   #--------------------------------------------------------------------------
  3165.   # * Get Characters
  3166.   #--------------------------------------------------------------------------
  3167.   def get_characters
  3168.     character_array = case $game_temp.input_type.to_s.downcase
  3169.     when 'default',''       then ('0'..'9').to_a
  3170.     when 'binary'           then ["0","1"]
  3171.     when 'hexa'             then [('0'..'9'),('A'..'F')].collect! {|i| i.to_a}
  3172.     when 'upcase_letters'   then [('A'..'Z')," "].collect! {|i| i.to_a}
  3173.     when 'downcase_letters' then [('a'..'z')," "].collect! {|i| i.to_a}
  3174.     when 'all_letters'      then [('A'..'Z'),('a'..'z')," "].map! {|i| i.to_a}
  3175.     when 'all_characters'   then [('A'..'Z'),('a'..'z'),('0'..'9'),
  3176.                                   "+","-","*","/","!","#","$","%","&",
  3177.                                   "@",".",",","-"," "].collect! {|i| i.to_a}
  3178.     # when...
  3179.     end
  3180.     return (character_array || ['-']).flatten
  3181.   end
  3182.   #--------------------------------------------------------------------------
  3183.   # * Set cursor_width
  3184.   #--------------------------------------------------------------------------
  3185.   def cursor_width
  3186.     unless @cursor_width
  3187.       dummy_bitmap = Bitmap.new(32, 32)
  3188.       for i in 0...@character_array.size
  3189.         letter_size = dummy_bitmap.text_size(@character_array[i]).width + 8
  3190.         @cursor_width = [@cursor_width, letter_size].max
  3191.       end
  3192.       dummy_bitmap.dispose
  3193.     end
  3194.     @cursor_width
  3195.   end
  3196.   #--------------------------------------------------------------------------
  3197.   # * Get Letter
  3198.   #--------------------------------------------------------------------------
  3199.   def letter(index)
  3200.     return @character_array[@letter_array[index]]
  3201.   end
  3202.   #--------------------------------------------------------------------------
  3203.   # * Increase Letter Array
  3204.   #--------------------------------------------------------------------------
  3205.   def increase_letter_array(index)
  3206.     @letter_array[index] = (@letter_array[index] + 1) % @character_array.size
  3207.   end
  3208.   #--------------------------------------------------------------------------
  3209.   # * Decrease Letter Array
  3210.   #--------------------------------------------------------------------------
  3211.   def decrease_letter_array(index)
  3212.     @letter_array[index] = (@letter_array[index] - 1) % @character_array.size
  3213.   end
  3214.   #--------------------------------------------------------------------------
  3215.   # * Cursor Rectangle Update
  3216.   #--------------------------------------------------------------------------
  3217.   def update_cursor_rect
  3218.     self.cursor_rect.set(@index * @cursor_width, 0, @cursor_width, 32)
  3219.   end  
  3220.   #--------------------------------------------------------------------------
  3221.   # * Get Number
  3222.   #--------------------------------------------------------------------------
  3223.   def number
  3224.     string  = (0...@digits_max).collect {|i| letter(i)}.join
  3225.     integer = string.to_i
  3226.     @number = sprintf('%0*d',@digits_max,integer) == string ? integer : string
  3227.   end
  3228.   #--------------------------------------------------------------------------
  3229.   # * Set Number
  3230.   #     number : new number
  3231.   #--------------------------------------------------------------------------
  3232.   def number=(number)
  3233.     if (array = number.to_s.scan(/./)).size < @digits_max
  3234.       array.unshift(@character_array[0]) until array.size == @digits_max
  3235.     end
  3236.     @digits_max.times do |i|
  3237.       (@character_array.size + 1).times do |j|
  3238.         array[i] == @character_array[j] && @letter_array[i] = j
  3239.       end
  3240.     end
  3241.     refresh
  3242.   end
  3243.   #--------------------------------------------------------------------------
  3244.   # * Frame Update
  3245.   #--------------------------------------------------------------------------
  3246.   def update
  3247.     super
  3248.     if Input.repeat?(Input::UP) or Input.repeat?(Input::DOWN)
  3249.       $game_system.se_play($data_system.cursor_se)
  3250.       increase_letter_array(@index) if Input.repeat?(Input::UP)
  3251.       decrease_letter_array(@index) if Input.repeat?(Input::DOWN)
  3252.       refresh
  3253.     end
  3254.     if Input.repeat?(Input::RIGHT) or Input.repeat?(Input::LEFT)
  3255.       if @digits_max >= 2
  3256.         $game_system.se_play($data_system.cursor_se)
  3257.         @index = (@index + 1) % @digits_max if Input.repeat?(Input::RIGHT)
  3258.         @index = (@index - 1) % @digits_max if Input.repeat?(Input::LEFT)
  3259.       end
  3260.     end
  3261.     if Input.trigger?(Input::B)
  3262.       (@letter_array[@index] = 0) &&  refresh
  3263.     end
  3264.     update_cursor_rect
  3265.   end
  3266.   #--------------------------------------------------------------------------
  3267.   # * Set Font
  3268.   #--------------------------------------------------------------------------
  3269.   def set_font(fname, fsize, fcolor)
  3270.     return if fname == nil && fsize == nil && fcolor == nil
  3271.     # Calculate cursor width from number width
  3272.     dummy_bitmap = Bitmap.new(32, 32)
  3273.     dummy_bitmap.font.name = fname
  3274.     dummy_bitmap.font.size = fsize
  3275.     @cursor_width = dummy_bitmap.text_size('0').width + 8
  3276.     dummy_bitmap.dispose
  3277.     self.width = @cursor_width * @digits_max + 32
  3278.     self.contents = Bitmap.new(width - 32, height - 32)
  3279.     self.contents.font.name  = fname
  3280.     self.contents.font.size  = fsize
  3281.     self.contents.font.color = check_color(fcolor)
  3282.     refresh
  3283.     update_cursor_rect
  3284.   end
  3285.   #--------------------------------------------------------------------------
  3286.   # * Refresh
  3287.   #--------------------------------------------------------------------------
  3288.   def refresh
  3289.     contents.clear
  3290.     #self.contents.font.color = normal_color
  3291.     @digits_max.times do |i|
  3292.       contents.draw_text(i*@cursor_width,0,@cursor_width,32,letter(i),1)
  3293.     end
  3294.   end
  3295. end
  3296.  
  3297. #==============================================================================
  3298. # ** AnimationSprite
  3299. #------------------------------------------------------------------------------
  3300. # Created by ThallionDarkshine
  3301. #  
  3302. #==============================================================================
  3303. class AnimationSprite < Sprite
  3304.   #--------------------------------------------------------------------------
  3305.   # * Object Initialization
  3306.   #--------------------------------------------------------------------------
  3307.   def initialize(type, x, y, z, rects, src_bitmap)
  3308.     super()
  3309.     @old_x, @old_y = x, y
  3310.     @type = type
  3311.     rects.compact!
  3312.     rects.delete_if { |rect| rect.width == 0 or rect.height == 0 }
  3313.     ry = rects.min { |i, e| i.y <=> e.y }.y
  3314.     rx = rects.min { |i, e| i.x <=> e.x }.x
  3315.     h = rects.max { |i, e| i.y + i.height <=> e.y + e.height }
  3316.     h = h.y + h.height - ry
  3317.     w = rects.max { |i, e| i.x + i.width <=> e.x + e.width }
  3318.     w = w.x + w.width - rx
  3319.     self.x, self.y, self.z = x + rx, y + ry, z
  3320.     self.ox, self.oy = w / 2, h / 2
  3321.     self.x += ox
  3322.     self.y += oy
  3323.     self.bitmap = Bitmap.new(w, h)
  3324.     self.bitmap.font.name  = src_bitmap.font.name
  3325.     self.bitmap.font.size  = src_bitmap.font.size
  3326.     self.bitmap.font.color = src_bitmap.font.color
  3327.     rects.each { |rect|
  3328.       bitmap.blt(rect.x - rx, rect.y - ry, src_bitmap, rect)
  3329.       src_bitmap.fill_rect(rect, Color.new(0, 0, 0, 0)) }
  3330.     @frames = 0
  3331.     @fplus = 1
  3332.     case @type
  3333.     when 4:
  3334.       @shake = [0, 0]
  3335.       @shaked = 1
  3336.     when 6:
  3337.       @frames = -40
  3338.     when 7:
  3339.       @frames = 2
  3340.     end
  3341.   end
  3342.   #--------------------------------------------------------------------------
  3343.   # * Frame Update
  3344.   #--------------------------------------------------------------------------
  3345.   def update(x, y)
  3346.     return if self.disposed?
  3347.     if x != @old_x or y != @old_y
  3348.       repos(x, y)
  3349.     end
  3350.     @frames += @fplus
  3351.     case @type
  3352.     when 1:
  3353.       z = 1.0 + @frames * 0.1 / 20
  3354.       @fplus = -1 if @frames == 20
  3355.       @fplus = 1 if @frames == 0
  3356.       self.zoom_x = z
  3357.       self.zoom_y = z
  3358.     when 2:
  3359.       a = @frames * 5.0 / 12
  3360.       @fplus = -1 if @frames == 12
  3361.       @fplus = 1 if @frames == -12
  3362.       self.angle = a
  3363.     when 3:
  3364.       z = 1.0 - @frames * 0.1 / 20
  3365.       @fplus = -1 if @frames == 20
  3366.       @fplus = 1 if @frames == 0
  3367.       self.zoom_x = z
  3368.       self.zoom_y = z
  3369.     when 4:
  3370.       shake_power = 1
  3371.       shake_speed = 10
  3372.       delta = (shake_power * shake_speed * @fplus) / 15.0 + rand(3) - 1
  3373.       @shake[0] += delta
  3374.       if @shake[0] > shake_power
  3375.         @fplus = -1
  3376.       end
  3377.       if @shake[0] < - shake_power
  3378.         @fplus = 1
  3379.       end
  3380.       delta = (shake_power * shake_speed * @shaked) / 15.0 + rand(3) - 1
  3381.       @shake[1] += delta
  3382.       if @shake[1] > shake_power
  3383.         @shaked = -1
  3384.       end
  3385.       if @shake[1] < - shake_power
  3386.         @shaked = 1
  3387.       end
  3388.       self.ox = self.bitmap.width / 2 + @shake[0]
  3389.       self.oy = self.bitmap.height / 2 + @shake[1]
  3390.     when 5:
  3391.       amnt = 5
  3392.       amnt *= Math.sin(Math::PI * @frames / 30.0)
  3393.       self.oy = self.bitmap.height / 2 + amnt
  3394.     when 6:
  3395.       if @frames < 0
  3396.         a = 255 + @frames * 255 / 40
  3397.         self.color.set(255, 0, 0, a)
  3398.         return
  3399.       end
  3400.       r = g = b = 0
  3401.       tmp = (@frames % 360) * 255 / 360
  3402.       while tmp < 0
  3403.         tmp += 255
  3404.       end
  3405.       if tmp < 85
  3406.         g = tmp * 3
  3407.         r = (85 - tmp) * 3
  3408.       elsif tmp < 170
  3409.         b = (tmp - 85) * 3
  3410.         g = (170 - tmp) * 3
  3411.       else
  3412.         r = (tmp - 170) * 3
  3413.         b = (255 - tmp) * 3
  3414.       end
  3415.       self.color.set(r, g, b)
  3416.     when 7:
  3417.       amnt = 10
  3418.       amnt *= Math.sin(Math::PI * @frames / 30.0).abs
  3419.       self.oy = self.bitmap.height / 2 + amnt - 5
  3420.     when 8:
  3421.       self.opacity = 255 - 170 * @frames / 20
  3422.       @fplus = -1 if @frames == 20
  3423.       @fplus = 1 if @frames == 0
  3424.     end
  3425.   end
  3426.   #--------------------------------------------------------------------------
  3427.   # * Repos
  3428.   #--------------------------------------------------------------------------
  3429.   def repos(x, y)
  3430.     self.x += x - @old_x
  3431.     self.y += y - @old_y
  3432.     @old_x, @old_y = x, y
  3433.   end
  3434. end
  3435.  
  3436. #==============================================================================
  3437. # ** AnimationLetters
  3438. #------------------------------------------------------------------------------
  3439. #  Created by ThallionDarkshine
  3440. #  
  3441. #==============================================================================
  3442. class AnimationLetters
  3443.   #--------------------------------------------------------------------------
  3444.   # * Define Method
  3445.   #--------------------------------------------------------------------------
  3446.   define_method(:dispose) {@sprites.each {|i|[i.bitmap,i].each{|j|j.dispose}}}
  3447.   #--------------------------------------------------------------------------
  3448.   # * Object Initialization
  3449.   #--------------------------------------------------------------------------
  3450.   def initialize(type, x, y, z, rects, src_bitmap)
  3451.     @old_x, @old_y = x, y
  3452.     @type = type
  3453.     @sprites = []
  3454.     @data = []
  3455.     tmp_data = get_tmp_data(type, rects.length)
  3456.     rects.each { |rect|
  3457.       sprite = Sprite.new
  3458.       sprite.x, sprite.y, sprite.z = x + rect.x, y + rect.y, z
  3459.       sprite.bitmap = Bitmap.new(rect.width, rect.height)
  3460.    
  3461.       sprite.bitmap.font.name  = src_bitmap.font.name
  3462.       sprite.bitmap.font.size  = src_bitmap.font.size
  3463.       sprite.bitmap.font.color = src_bitmap.font.color
  3464.    
  3465.       sprite.bitmap.blt(0, 0, src_bitmap, rect)
  3466.       sprite.ox, sprite.oy = rect.width / 2, rect.height / 2
  3467.       sprite.x += sprite.ox
  3468.       sprite.y += sprite.oy
  3469.       src_bitmap.fill_rect(rect, Color.new(0, 0, 0, 0))
  3470.       @sprites.push(sprite)
  3471.       @data.push(get_data(type, tmp_data)) }
  3472.     case @type
  3473.     when 4:
  3474.       @frames = -40
  3475.     else
  3476.       @frames = 0
  3477.     end
  3478.     @fplus = 1
  3479.   end
  3480.   #--------------------------------------------------------------------------
  3481.   # * Get Temporary Data
  3482.   #--------------------------------------------------------------------------
  3483.   def get_tmp_data(type, length)
  3484.     case type
  3485.     when 1, 5, 7:
  3486.       data = Array.new(length) { |i| i }
  3487.       @duration = length * 31
  3488.       @no_end = true
  3489.     when 2, 6, 8:
  3490.       len = (length / 2.0).floor
  3491.       data = Array.new(len) { |i| i }
  3492.       data = data.concat(data.clone)
  3493.       if len % 2 == 1
  3494.         data.push(rand(len))
  3495.       end
  3496.       @duration = len * 31
  3497.       @no_end = true
  3498.     when 9, 10:
  3499.       data = Array.new(length) { |i| i }
  3500.     when 11, 12:
  3501.       tmp = Array.new(length) { |i| i }
  3502.       data = []
  3503.       length.times {
  3504.         ind = rand(tmp.length)
  3505.         data.push(tmp[ind])
  3506.         tmp.delete_at(ind)  }
  3507.     else
  3508.       data = []
  3509.     end
  3510.     data
  3511.   end
  3512.   #--------------------------------------------------------------------------
  3513.   # * Get Data
  3514.   #--------------------------------------------------------------------------
  3515.   def get_data(type, tmp_data)
  3516.     data = {}
  3517.     case type
  3518.     when 1, 2, 5, 6, 7, 8:
  3519.       tmp = rand(tmp_data.length)
  3520.       data[:start] = (tmp_data[tmp] || 0) * 31 + rand(11) - 5
  3521.       data[:middle] = data[:start] + 15
  3522.       while data[:start] < 0
  3523.         data[:start] += @duration
  3524.       end
  3525.       data[:end] = (data[:middle] + 15) % @duration
  3526.       tmp_data.delete_at(tmp)
  3527.     when 4:
  3528.       data[:hue] = rand(255)
  3529.       data[:mod] = rand(5) - 2
  3530.       while data[:mod] == 0
  3531.         data[:mod] = rand(5) - 2
  3532.       end
  3533.     when 9, 10, 11, 12:
  3534.       data[:end] = false
  3535.       len = tmp_data.length
  3536.       ind = tmp_data.shift
  3537.       len += ind
  3538.       data[:offset] = -ind * Math::PI / len
  3539.     end
  3540.     data
  3541.   end
  3542.   #--------------------------------------------------------------------------
  3543.   # * Update Frame
  3544.   #--------------------------------------------------------------------------
  3545.   def update(x, y)
  3546.     return if @sprites.any? { |i| i.disposed? }
  3547.     repos(x, y) if x != @old_x or y != @old_y
  3548.     @frames += @fplus
  3549.     case @type
  3550.     when 1, 2:
  3551.       @frames %= @duration
  3552.       @sprites.each_with_index { |sprite, i|
  3553.         data = @data[i]
  3554.         cur_frames = @frames
  3555.         start = data[:start]
  3556.         middle = data[:middle]
  3557.         endf = data[:end]
  3558.         while endf < start
  3559.           endf += @duration
  3560.         end
  3561.         while middle < start
  3562.           middle += @duration
  3563.         end
  3564.         while cur_frames < start
  3565.           cur_frames += @duration
  3566.         end
  3567.         while cur_frames > endf
  3568.           cur_frames -= @duration
  3569.         end
  3570.         while (cur_frames - start) > @duration
  3571.           cur_frames -= @duration
  3572.         end
  3573.         while (start - cur_frames) > @duration
  3574.           cur_frames += @duration
  3575.         end
  3576.         if cur_frames.between?(start, middle)
  3577.           @no_end = false
  3578.           z = 1.0 + (cur_frames - start) * 0.5 / (middle - start)
  3579.           sprite.zoom_x = sprite.zoom_y = z
  3580.         elsif cur_frames.between?(middle, endf) and !@no_end
  3581.           z = 1.0 + (endf - cur_frames) * 0.5 / (endf - middle)
  3582.           sprite.zoom_x = sprite.zoom_y = z
  3583.         else
  3584.           sprite.zoom_x = sprite.zoom_y = 1.0
  3585.         end
  3586.         mod = rand(5) - 2
  3587.         @data[i][:start] += mod
  3588.         @data[i][:middle] += mod
  3589.         @data[i][:end] += mod }
  3590.     when 3:
  3591.       a = @frames * 10.0 / 12
  3592.       @fplus = -1 if @frames == 30
  3593.       @fplus = 1 if @frames == -30
  3594.       @sprites.each { |i| i.angle = a }
  3595.     when 4:
  3596.       if @frames < 0
  3597.         a = 255 + @frames * 255 / 40
  3598.         @sprites.each_with_index { |sprite, i|
  3599.           @data[i][:hue] += @data[i][:mod]
  3600.           color = get_color(@data[i][:hue])
  3601.           color.alpha = a
  3602.           sprite.color = color   }
  3603.         return
  3604.       end
  3605.       @sprites.each_with_index { |sprite, i|
  3606.         @data[i][:hue] += @data[i][:mod]
  3607.         color = get_color(@data[i][:hue])
  3608.         sprite.color = color  }
  3609.     when 5, 6:
  3610.       @frames %= @duration
  3611.       @sprites.each_with_index { |sprite, i|
  3612.         data = @data[i]
  3613.         cur_frames = @frames
  3614.         start = data[:start]
  3615.         middle = data[:middle]
  3616.         endf = data[:end]
  3617.         while endf < start
  3618.           endf += @duration
  3619.         end
  3620.         while middle < start
  3621.           middle += @duration
  3622.         end
  3623.         while cur_frames < start
  3624.           cur_frames += @duration
  3625.         end
  3626.         while cur_frames > endf
  3627.           cur_frames -= @duration
  3628.         end
  3629.         while (cur_frames - start) > @duration
  3630.           cur_frames -= @duration
  3631.         end
  3632.         while (start - cur_frames) > @duration
  3633.           cur_frames += @duration
  3634.         end
  3635.         if cur_frames.between?(start, middle)
  3636.           @no_end = false
  3637.           sprite.opacity = 255 - (cur_frames - start) * 170 / (middle - start)
  3638.         elsif cur_frames.between?(middle, endf) and !@no_end
  3639.           sprite.opacity = 255 - (endf - cur_frames) * 170 / (endf - middle)
  3640.         else
  3641.           sprite.opacity = 255
  3642.         end
  3643.         mod = rand(5) - 2
  3644.         @data[i][:start] += mod
  3645.         @data[i][:middle] += mod
  3646.         @data[i][:end] += mod  }
  3647.     when 7, 8:
  3648.       @frames %= @duration
  3649.       @sprites.each_with_index { |sprite, i|
  3650.         data = @data[i]
  3651.         cur_frames = @frames
  3652.         start = data[:start]
  3653.         middle = data[:middle]
  3654.         endf = data[:end]
  3655.         while endf < start
  3656.           endf += @duration
  3657.         end
  3658.         while middle < start
  3659.           middle += @duration
  3660.         end
  3661.         while cur_frames < start
  3662.           cur_frames += @duration
  3663.         end
  3664.         while cur_frames > endf
  3665.           cur_frames -= @duration
  3666.         end
  3667.         while (cur_frames - start) > @duration
  3668.           cur_frames -= @duration
  3669.         end
  3670.         while (start - cur_frames) > @duration
  3671.           cur_frames += @duration
  3672.         end
  3673.         if cur_frames.between?(start, middle)
  3674.           @no_end = false
  3675.           z = 1.0 - (cur_frames - start) * 0.5 / (middle - start)
  3676.           sprite.zoom_x = sprite.zoom_y = z
  3677.         elsif cur_frames.between?(middle, endf) and !@no_end
  3678.           z = 1.0 - (endf - cur_frames) * 0.5 / (endf - middle)
  3679.           sprite.zoom_x = sprite.zoom_y = z
  3680.         else
  3681.           sprite.zoom_x = sprite.zoom_y = 1.0
  3682.         end
  3683.         mod = rand(5) - 2
  3684.         @data[i][:start] += mod
  3685.         @data[i][:middle] += mod
  3686.         @data[i][:end] += mod   }
  3687.     when 9, 11:
  3688.       @sprites.each_with_index { |sprite, i|
  3689.         data = @data[i]
  3690.         mod = 10 * Math.sin(Math::PI * @frames / 45.0 + data[:offset]).abs - 5
  3691.         mod2 = 10 * Math.sin(Math::PI * (@frames + 1) / 45.0 + data[:offset]).abs - 5
  3692.         if mod > 0 and mod <= 10 * Math.sin(Math::PI * 6 / 30.0).abs - 5 and mod2 > 0
  3693.           @data[i][:end] = true
  3694.         else
  3695.           next unless @data[i][:end]
  3696.         end
  3697.         sprite.oy = sprite.bitmap.height / 2 + mod  }
  3698.     when 10, 12:
  3699.       @sprites.each_with_index { |sprite, i|
  3700.         data = @data[i]
  3701.         mod = 5 * Math.sin(Math::PI * @frames / 30.0 + data[:offset])
  3702.         mod2 = 5 * Math.sin(Math::PI * (@frames + 1) / 30.0 + data[:offset])
  3703.         #p 10 * Math.sin(Math::PI * 2 * 3 / 30.0) - 5
  3704.         #p mod
  3705.         if mod > 0 and mod <= 5 * Math.sin(Math::PI * 6 / 30.0) and mod2 > 0
  3706.           @data[i][:end] = true
  3707.         else
  3708.           next unless @data[i][:end]
  3709.         end
  3710.         sprite.oy = sprite.bitmap.height / 2 + mod  }
  3711.     end
  3712.   end
  3713.   #--------------------------------------------------------------------------
  3714.   # * Get Color
  3715.   #--------------------------------------------------------------------------
  3716.   def get_color(hue)
  3717.     r = g = b = 0
  3718.     tmp = hue % 255
  3719.     while tmp < 0
  3720.       tmp += 255
  3721.     end
  3722.     if tmp < 85
  3723.       g = tmp * 3
  3724.       r = (85 - tmp) * 3
  3725.     elsif tmp < 170
  3726.       b = (tmp - 85) * 3
  3727.       g = (170 - tmp) * 3
  3728.     else
  3729.       r = (tmp - 170) * 3
  3730.       b = (255 - tmp) * 3
  3731.     end
  3732.     return Color.new(r, g, b)
  3733.   end
  3734.   #--------------------------------------------------------------------------
  3735.   # * Opacity
  3736.   #--------------------------------------------------------------------------
  3737.   def opacity=(v) @sprites.each { |i| i.disposed? || i.opacity = v }  end  
  3738.   #--------------------------------------------------------------------------
  3739.   # * Repos
  3740.   #--------------------------------------------------------------------------
  3741.   def repos(x, y)
  3742.     @sprites.reject! { |i| i.disposed? }
  3743.     @sprites.each { |i| (i.x += x - @old_x)  && (i.y += y - @old_y) }
  3744.     @old_x, @old_y = x, y
  3745.   end
  3746. end
  3747.  
  3748. $multiple_message_windows = {}
  3749. $multiple_message_windows['ver'] = 1.6
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement