Advertisement
LiTTleDRAgo

[RGSS] Multiple Message Windows - Heretic86's Edit

Dec 4th, 2013
500
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 129.92 KB | None | 0 0
  1. #-----------------------------------------
  2. #-------                      ------------
  3. #---    Multiple Message Windows       ---
  4. #-------   HERETIC REVISION   ------------
  5. #-------     Version 1.55     ------------
  6. #-------                      ------------
  7. #-----------------------------------------
  8. #
  9. # NO LONGER REQUIRES SDK.  It will work fine with or without the SDK now!
  10. #
  11. # *NOTE* - This script should go ABOVE the CATERPILLAR SCRIPT
  12. #
  13. #
  14. #
  15. #==============================================================================
  16. # ** Multiple Message Windows (SDK and Non SDK Bundle!)
  17. #------------------------------------------------------------------------------
  18. # Wachunga
  19. # 1.5
  20. # 2006-11-17
  21. #==============================================================================
  22.  
  23. =begin
  24.  
  25.  
  26.   Version History: (Heretic)
  27.   1.55
  28.   - Removed SDK Dependancy
  29.   - Script will work either WITH or WITHOUT the SDK now automatically
  30.  
  31.   1.54
  32.   - Added Option for Variable Text with \v[Tn]
  33.     $game_system.mmw_text[0] = "Hello World!"
  34.     In the "Show Text..." box, put in \v[T0] to display Hello World!
  35.    
  36.   - Added Player Sticky
  37.  
  38.     This means that Event and Player Message Stickyness are now independant.
  39.     When the player moves around, I tried to reposition the Message Bubble to
  40.     maximize player visibility by placing the Message Bubble out of where I
  41.     think they are intending to go.  For example, when the player presses
  42.     Right, the Players Character faces to the Right, so in order to make sure
  43.     the Player can see where they are trying to go, the Message Bubble is
  44.     repositioned to the left of the Players Character.
  45.    
  46.     Repositioning can cause some issues with making some Messages off screen
  47.     and unable to be read.  In order to work around this, Sticky was added to
  48.     favor the Top and Bottom positions.  A Sticky Message can start anywhere,
  49.     but once it is moved, it will try to stick to the Top or the Bottom because
  50.     position on the Left and Right causes some long messages to go offscreen
  51.     and become unreadable.
  52.    
  53.     That is what Sticky means.
  54.    
  55.     - $game_player.sticky is set to FALSE by Default, and will RESET to FALSE
  56.     at the end of Event Execution.
  57.    
  58.   - Added Windowskin as a Saved Variable.  That way if you walk away from
  59.     a sign that has a different Windowskin, that Windowskin will also be
  60.     reset when you walk away from a sign before the Event complets its list
  61.     of commands to execute.
  62.    
  63.   - Fixed a Visual Bug where a Non Floating Message Window would change
  64.     the Windowskin while fading out.  Redefined Window_Base update to
  65.     fix this bug.
  66.    
  67.   - Changed set_max_dist to allow a Zero Distance.  This is useful for
  68.     Passable Events.
  69.    
  70.   - Fixed some Visual Glitches caused by other features I added becoming
  71.     read in characters in version 1.04 of the engine.  1.02 seems to
  72.     work just fine and caused me to miss these.
  73.    
  74.   - Fixed a bug with set_max_dist(N).  Cutscenes where the Player is moved
  75.     around by Event Commands would cause Event to stop executing.  Changed
  76.     to require move_during to be True and $game_player.move_route_forcing
  77.     to be False for Message Windows to automatically close.  So if you
  78.     set message.move_during = false, a Cutscene is assumed and Windows
  79.     will not be closed.
  80.    
  81.   1.53 (Heretic)
  82.  
  83.   - Added SOUNDS while text is printing out.  Think Banjo Kazooie
  84.  
  85.     What you NEED to know:  When an Event has finished its commands, or if
  86.     you walk away from it, your Sound Settings will RESET.  This is intentional.
  87.     It was implemented to save you work.  Although it is quite possible to do,
  88.     the way a non scripter would end up trying to do this would be tremendous.
  89.     Thus, I did it for you.
  90.    
  91.     There are several things you should know about SOUNDS.
  92.    
  93.     #1 - Sound does NOT play for every single character.  It plays a sound every
  94.     several characters.  Im not psychic, so I dont know what sound you will
  95.     be using, if any at all.  Because of this, the duration of that sound might
  96.     be different than some of the samples I've included.  As a result, you may
  97.     decide that it sounds better to play your sound every character or every 5
  98.     characters.  Thus, it is totally optional.  The option is called
  99.     message.sound_frequency
  100.    
  101.     #2 - It only plays sounds for Letters and Numbers, so non alphanumeric
  102.     characters do not play sounds.  This includes spaces, and special characters
  103.     used for any of the message script options.  This is just something that I
  104.     thought you should be aware of.
  105.    
  106.     #3 - The Audio File you use needs to be imported into Sound Effects, under
  107.     Materialbase -> Audio/SE (its the one at the very bottom of the list).
  108.     I ran into a couple of files that caused both the editor and the game to
  109.     crash when I tried to play them, so you may need to convert problematic
  110.     audio files to a different format.
  111.    
  112.     Several of the files I've imported I got from FlashKit.com.  Not all of
  113.     these files were compatible.  Other than that, it does have a good selection
  114.     of royalty free sound files.
  115.    
  116.     http://www.flashkit.com/soundfx/
  117.    
  118.     I considered setting up sound properties for each event and NPC, but decided
  119.     to pass on that because it caused more problems than it appeared to solve.
  120.     Also being considered are options to change the sound properties from within
  121.     the text itself.  The same way as you can make characters bold, delay, or
  122.     other features already built into the script.  If there is interest, I will
  123.     put them in, but for now, once a window starts to display its text, there
  124.     arent any options to change it until the next message window is displayed.
  125.    
  126.     -----  SOUND OPTIONS  -----
  127.    
  128.     These can be changed at any time with scripts.
  129.    
  130.     message.sound = true / false             # Enables or Disables Text Sounds  
  131.     message.sound_audio = '001-System01'     # Audio SE (in DB) to play
  132.     message.sound_volume = 80                # Text Sound Volume
  133.     message.sound_pitch = 80                 # Text Sound Pitch
  134.     message.sound_pitch_range = 20           # How Much to vary the Pitch
  135.     message.sound_vary_pitch = true          # Whether to Vary the Pitch or not
  136.     message.sound_frequency = 2              # Plays a sound this many letters
  137.    
  138.    
  139.   1.52 (Heretic)
  140.  
  141.   - Added ability to "Auto Close" Non Floating Messages based on proximity
  142.     to the triggered event.  You'll have to set a script for Every Event
  143.     you want this to occur on.
  144.     "set_max_dist(n)" where n the Distance in Steps.  One is Minimum.
  145.    
  146.     Notes:  set_max_dist will SAVE all of your MMW settings, and in the
  147.     event that the event execution is terminated early, it will restore
  148.     these settings you originally had.  This is done automatically in
  149.     order to prevent you from having to do unnecessary work.  I find
  150.     it was most useful for Signs where you might set message.floating = false
  151.     which would have resulted in you needing to put in floating = true
  152.     for every other event.  It just saves you work.  SO if you do want
  153.     to have a more permanent adjustment to your MMW settings, call them
  154.     BEFORE you call "set_max_dist(n)"
  155.    
  156.     If you expect the event to play out in its entirety, consider
  157.     using message.move_during = false.  This is intended to allow the event
  158.     to NOT COMPLETE all the entries in an event by allowing the player to
  159.     walk away and close the window.
  160.    
  161.   - Added the ability to "flip" a Message Bubble (non floating) on NPC Turn.
  162.  
  163.     This was done to allow the player to see where they are going.  When
  164.     the player moves around, they need to be able to see where they are
  165.     going, and a Message Bubble can sometimes get in their way.  I also
  166.     set it up so that once an NPC is moved (not turned), this feature
  167.     turns itself off because it assumes a Cutscene.
  168.    
  169.     This requires several things to work.
  170.     #1:  reposition_on_turn is enabled (message.reposition_on_turn = true)
  171.     #2:  NPC is set to turn_toward_player(repeat)
  172.     #3:  NPC has NOT been moved (there are ways around this)
  173.     #4:  Message Window is Auto Oriented using \$ or \%
  174.    
  175.     If you feel like re-enabling this feature after an NPC has been
  176.     moved, you can use a Move Route Script @allow_flip = true for
  177.     that NPC.
  178.    
  179.   - Added the Auto Flipping Message Windows to be "Sticky"
  180.  
  181.     What this means is that when a Message Window is repositioned, the
  182.     next window will appear in the same location as the previous window.
  183.    
  184.     Change it with message.sticky = true / false
  185.    
  186.   1.51b
  187.  
  188.   - Added \G+ and \G- to allow Gold Window to be at the Top or Bottom
  189.     of the screen.  \G can still be used.  It just positions opposite
  190.     of where the player is at.  Just a bit more control over the
  191.     position of the Gold Window.
  192.  
  193.   1.51a
  194.  
  195.   - By Request, added the \F* option to put the "Other Foot Forward"
  196.  
  197.   1.51
  198.  
  199.   - Added \* option to display next message at ANY time  
  200.  
  201.   - Added \$ and \$ options to Auto Orient Message Bubbles relative to
  202.     the direction the Speaker is facing.
  203.    
  204.   - Added "Foot Forward" commands available with \F+ and \F-
  205.  
  206.   - Added automatic features to reset a Speaking NPC to its original Stance
  207.     and make it Continue its Move Route.  
  208.  
  209.   *NOTE* - The links provided in the comments may be out of date.
  210.  
  211.   This custom message system adds numerous features on top of the default
  212.   message system, the most notable being the ability to have multiple message
  213.   windows open at once. The included features are mostly themed around turning
  214.   messages into speech (and thought) balloons, but default-style messages are
  215.   of course still possible.
  216.  
  217.   Note:
  218.   This version of the script uses the SDK, available from:
  219.   http://www.rmxp.org/forums/showthread.php?t=1802
  220.  
  221.   FEATURES
  222.  
  223.   New in 1.5:
  224.   * \C[#ffffff] for hexadecimal color
  225.   * \C for return to default color
  226.   * display name of item, weapon, armor or skill
  227.     * \N[In] = display name of item with id n (note the "I")
  228.     * \N[Wn] = display name of weapon with id n (note the "W")
  229.     * \N[An] = display name of armor with id n (note the "A")
  230.     * \N[Sn] = display name of skill with id n (note the "S")
  231.   * display icon of item, weapon, armor or skill
  232.     * \I[In] = display icon of item with id n (note the "I")
  233.     * \I[Wn] = display icon of weapon with id n (note the "W")
  234.     * \I[An] = display icon of armor with id n (note the "A")
  235.     * \I[Sn] = display icon of skill with id n (note the "S")
  236.   * display icon and name of item, weapon, armor or skill
  237.     * \I&N[In] = display icon and name of item with id n (note the "I")
  238.     * \I&N[Wn] = display icon and name of weapon with id n (note the "W")
  239.     * \I&N[An] = display icon and name of armor with id n (note the "A")
  240.     * \I&N[Sn] = display icon and name of skill with id n (note the "S")
  241.   * new windowskins available
  242.   * speech windowskin now definable separately from default windowskin
  243.   * fixed bold bug where degree sign would occasionally appear
  244.   * input number window now shares parent window's font
  245.   * changed \Var[n] back to default of \V[n]
  246.  
  247.   New in 1.1:
  248.   * message.autocenter for automatically centering text within messages
  249.   * \N[en] for displaying name of enemy with id n (note the "e")
  250.   * \MAP for displaying the name of the current map
  251.  
  252.   At a glance:
  253.   * multiple message windows
  254.   * speech balloons
  255.     * position over player/event (follows movement and scrolling)
  256.     * optional message tail (for speech or thought balloons)
  257.     * can specify location relative to player/event (up, down, left, right)
  258.   * thought balloons
  259.     * can use different windowskin, message tail and font color
  260.   * letter-by-letter mode
  261.     * variable speed (and delays)
  262.     * skippable on button press
  263.   * autoresize messages
  264.   * player movement allowed during messages
  265.     * if speaker moves offscreen, message closes (like ChronoTrigger)
  266.   * everything also works during battle
  267.   * settings configurable at anytime  
  268.  
  269.   Full list of options:
  270.  
  271.   (Note that all are case *insensitive*.)
  272.  
  273.   =============================================================================
  274.    Local (specified in message itself and resets at message end)
  275.   =============================================================================
  276.   - \L = letter-by-letter mode toggle
  277.   - \A = auto-pause mode toggle for ,.?! characters
  278.   - \S[n] = set speed at which text appears in letter-by-letter mode
  279.   - \D[n] = set delay (in frames) before next text appears
  280.   - \P[n] = position message over event with id n
  281.             * use n=0 for player
  282.             * in battle, use n=a,b,c,d for actors (e.g. \P[a] for first actor)
  283.               and n=1,...,n for enemies (e.g. \P[1] for first enemy)
  284.               where order is actually the reverse of troop order (in database)
  285.   - \P[Cn] = Tie-In with Caterpillar.  Positions Message over Cat Actor
  286.               in n Position of Caterpillar.  1 for First Cat Actor, etc...
  287.             * example: \P[C2] for 2nd Cat Actor, or 3rd Actor in Caterpillar
  288.             * n excludes Player
  289.   - \P = position message over current event (default for floating messages)
  290.   - \^ = message appears directly over its event
  291.   - \v = message appears directly below its event
  292.   - \< = message appears directly to the left of its event
  293.   - \> = message appears directly to the right of its event
  294.   - \$ = message appears above actor unless facing up, then appears below  
  295.   - \% = message appears behind actor relative to direction
  296.   - \B = bold text
  297.   - \I = italic text
  298.   - \C[#xxxxxx] = change to color specified by hexadecimal (eg. ffffff = white)
  299.   - \C = change color back to default
  300.   - \! = message autoclose
  301.   - \? = wait for user input before continuing
  302.   - \+ = make message appear at same time as preceding one
  303.          * note: must be at the start of message to work
  304.   - \* = displays the next message immediately if available
  305.          * note: next event command must be text, choice, or number input
  306.   - \@ = thought balloon
  307.   - \N[En] = display name of enemy with id n (note the "E")
  308.   - \N[In] = display name of item with id n (note the "I")
  309.   - \N[Wn] = display name of weapon with id n (note the "W")
  310.   - \N[An] = display name of armor with id n (note the "A")
  311.   - \N[Sn] = display name of skill with id n (note the "S")
  312.   - \I[In] = display icon of item with id n (note the "I")
  313.   - \I[Wn] = display icon of weapon with id n (note the "W")
  314.   - \I[An] = display icon of armor with id n (note the "A")
  315.   - \I[Sn] = display icon of skill with id n (note the "S")
  316.   - \I&N[In] = display icon and name of item with id n (note the "I")
  317.   - \I&N[Wn] = display icon and name of weapon with id n (note the "W")
  318.   - \I&N[An] = display icon and name of armor with id n (note the "A")
  319.   - \I&N[Sn] = display icon and name of skill with id n (note the "S")
  320.   - \MAP = display the name of the current map
  321.  
  322.   * Foot Forward Notes * - Sprite Sheets only have 16 total Frames of Animation
  323.     and of which, 4 are duplicates.  Foot Forward Options allow access to
  324.     ALL of the frames of animation available in Default Sprite Sheets.
  325.    
  326.   - \F+  = character puts their Foot Forward
  327.   - \F*  = character puts their Other Foot Forward
  328.   - \F-  = character resets their Foot Forward
  329.  
  330.   *NOTE* - Foot Forward Animation will RESET if the event is moved off screen.
  331.          - Change @auto_ff_reset if this feature causes you trouble with
  332.            character animations.
  333.    
  334.     It also ONLY works with the following conditions
  335.     - Direction Fix is OFF
  336.     - Move Animation is ON
  337.     - Stop Animation is OFF (technically thats Step, they typo'd)
  338.     - @auto_ff_reset is TRUE
  339.     - * These settings are the DEFAULT when a New Event is created
  340.    
  341.     You can disable the "Auto Foot Forward Off" feature by adding \no_ff
  342.     to an Event's Name.  IE: Bill\no_ff
  343.  
  344.   ---- Resets ----
  345.  
  346.   These occur when the player walks away from a Speaking NPC
  347.  
  348.   Put these strings in an Event's Name to use!
  349.            
  350.   \no_ff - If you don't want a specific event to be RESET, you can add
  351.            \no_ff to the Event's Name.  EV041\no_ff and Event will
  352.            not be affected by Foot Forward Reset when Player Walks off screen
  353.            
  354.   \no_mc - No Move Continue - In the event you dont want a specific event to
  355.            continue its Move Route from where it left off when it is moved
  356.            off-screen, put \no_mc in the Event's Name.  I.E. EV12\no_mc    
  357.  
  358.   These are, of course, in addition to the default options:
  359.   - \V[n]  = display value of variable n
  360.   - \V[Tn] = display value of text variable n
  361.   - \N[n] = display name of actor with id n
  362.   - \C[n] = change color to n
  363.   - \G  = display gold window - Screen Opposite of Player's Position
  364.   - \G+ = display gold window at the Top of the Screen
  365.   - \G- = display gold window at the Bottom of the Screen
  366.   - \\ = show the '\' character
  367.  
  368.   =============================================================================
  369.    Global (specified below or by Call Script and persist until changed)
  370.   =============================================================================
  371.   Miscellaneous:
  372.   - message.move_during = true/false
  373.     * allow/disallow player to move during messages
  374.   - message.show_pause = true/false
  375.     * show/hide "waiting for player" pause graphic
  376.   - message.autocenter = true/false
  377.     * enable/disable automatically centering text within messages
  378.   - message.auto_comma_pause = true/false
  379.     * inserts a delay before the next character after these characters ,!.?
  380.     * expects correct punctuation.  One space after a comma, the rest 2 spaces
  381.   - message.auto_comma_delay = n
  382.     * changes how long to wait after a pausable character
  383.   - message.auto_ff_reset = true/false
  384.     * resets a Foot Forward stance if a message wnidow is closed for off-screen
  385.     * set to false if it causes animation problems, or, dont use Foot Forward
  386.       on a specific NPC or Event
  387.   - message.auto_move_continue = true/false
  388.     * when moving an event off screen while speaking, resets previous move route
  389.   - message.dist_exit = true/false
  390.     * close messages if the player walks too far away
  391.   - message.dist_max = n
  392.     * the distance away from the player before windows close
  393.   - message.reposition_on_turn = true / false
  394.     * Repeat Turn Toward Player NPC's Reorient Message Windows if they Turn
  395.   - message.sticky
  396.     * If Message was Repositioned, next message will go to that Location
  397.    
  398.   Auto Repositioning Message Windows
  399.   - Cannot be Player
  400.   - NPC MUST have some form of Repeating Turn, usually toward Player
  401.   - NPC MUST NOT MOVE.  Turning is Fine, but cant MOVE
  402.  
  403.   - set_max_dist(n)
  404.     * Useful for allowing player to walk away from signs
  405.     * Saves your MMW Config in case of a Walk-Away Closure
  406.     * call from Event Editor => Scripts
  407.  
  408.   Speech/thought balloon related:
  409.   - message.resize = true/false
  410.     * enable/disable automatic resizing of messages (only as big as necessary)
  411.   - message.floating = true/false
  412.     * enable/disable positioning messages above current event by default
  413.       (i.e. equivalent to including \P in every message)
  414.   - message.location = TOP, BOTTOM, LEFT or RIGHT
  415.     * set default location for floating messages relative to their event
  416.   - message.show_tail = true/false
  417.     * show/hide message tail for speech/thought balloons
  418.  
  419.   Letter-by-letter related:
  420.   - message.letter_by_letter = true/false
  421.     * enable/disable letter-by-letter mode (globally)
  422.   - message.text_speed = 0-20
  423.     * set speed at which text appears in letter-by-letter mode (globally)
  424.   - message.skippable = true/false
  425.     * allow/disallow player to skip to end of message with button press
  426.  
  427.   Font:
  428.   - message.font_name = font
  429.     * set font to use for text, overriding all defaults
  430.       (font can be any TrueType from Windows/Fonts folder)
  431.   - message.font_size = size
  432.     * set size of text  (default 22), overriding all defaults
  433.   - message.font_color = color
  434.     * set color of text, overriding all defaults
  435.     * you can use same 0-7 as for \C[n] or "#xxxxxx" for hexadecimal
  436.    
  437.   Set Move Route:
  438.   - foot_forward_on
  439.     * Optional Parameter - frame
  440.     * foot_forward_on(0) is default, treated as just foot_forward_on
  441.     * foot_forward_on(1) puts the "Other" Foot Forward
  442.   - foot_forward_off
  443.  
  444.   Note that the default thought and shout balloon windowskins don't
  445.   stretch to four lines very well (unfortunately).
  446.    
  447.   Thanks:
  448.   XRXS code for self-close and wait for input
  449.   Slipknot for a convenient approach to altering settings in-game
  450.   SephirothSpawn for bitmap rotate method
  451.  
  452. =end
  453.  
  454. #------------------------------------------------------------------------------
  455. # * SDK Log Script
  456. #------------------------------------------------------------------------------
  457. sdk = Module.constants.include?('SDK') &&
  458.       SDK.log('Multiple Message Windows','Wachunga',1.5,'2006-11-17')
  459.  
  460. #------------------------------------------------------------------------------
  461. # * Begin SDK Enabled Check
  462. #------------------------------------------------------------------------------
  463. if !sdk || SDK.state('Multiple Message Windows') == true
  464.  
  465. #==============================================================================
  466. # Settings
  467. #==============================================================================
  468.  
  469.   #----------------------------------------------------------------------------
  470.   # Windowskins
  471.   #----------------------------------------------------------------------------
  472.   # Note: all files must be in the Graphics/Windowskins/ folder
  473.   # Tip: tails don't look right on windowskins with gradient backgrounds
  474.  
  475.   # filenames of tail and windowskin used for speech balloons
  476.   FILENAME_SPEECH_TAIL = "white-tail_speech.png"
  477.   FILENAME_SPEECH_WINDOWSKIN = "white-windowskin_speech.png"
  478.  
  479.   # filenames of tail and windowskin used for thought balloons
  480.   FILENAME_THOUGHT_TAIL = "white-tail_thought.png"
  481.   FILENAME_THOUGHT_WINDOWSKIN = "white-windowskin_thought.png"
  482.  
  483.   #----------------------------------------------------------------------------
  484.   # Fonts
  485.   #----------------------------------------------------------------------------
  486.   # Note: if floating or resize (i.e. "speech balloons") are disabled,
  487.   # Font.default_name, Font.default_size and Font.default_color are used
  488.   # (you can change these in Main)
  489.   # During gameplay, you can use message.font_name etc to override all defaults
  490.  
  491.   # defaults for speech text
  492.   SPEECH_FONT_COLOR = "#000000"
  493.   SPEECH_FONT_NAME = "Komika Slim","Comic Sans MS"
  494.   SPEECH_FONT_SIZE = 18
  495.  
  496.   # defaults for thought text
  497.   THOUGHT_FONT_COLOR = "#000000"
  498.   THOUGHT_FONT_NAME = "Komika Slick","Comic Sans MS"
  499.   THOUGHT_FONT_SIZE = 16
  500.  
  501.   # note that you can use an array of fonts for SPEECH_FONT_NAME, etc.
  502.   # e.g. ['Komika Slim', 'Arial']
  503.   # (if Verdana is not available, MS PGothic will be used instead)
  504.  
  505.   #----------------------------------------------------------------------------
  506.   # Misc
  507.   #----------------------------------------------------------------------------
  508.   # If using a specialty windowskin (e.g. the default thought balloon one),
  509.   # you can force the window width to always be a multiple of the number
  510.   # specified in this constant (even when using the resize feature).
  511.   # This allows, for example, the windowskin frame to be designed to
  512.   # repeat every 16 pixels so that the frame never looks cut off.
  513.   THOUGHT_WIDTH_MULTIPLE = 16
  514.   # (set to 0 if you're not using any such windowskins)
  515.  
  516. class Game_Message
  517.  
  518.   # Any of the below can be changed by a Call Script event during gameplay.
  519.   # E.g. turn letter-by-letter mode off with: message.letter_by_letter = false
  520.  
  521.   def initialize
  522.     # whether or not messages appear one letter at a time
  523.     @letter_by_letter = true
  524.     # note: can also change within a single message with \L
  525.  
  526.     # the default speed at which text appears in letter-by-letter mode
  527.     @text_speed = 0
  528.     # note: can also change within a single message with \S[n]
  529.    
  530.     # this is defined as a user setting that can be changed during gameplay
  531.     @text_speed_player = 0
  532.    
  533.     # Heretic's Notes:
  534.     #
  535.     # This is a placeholder for the default user setting in the event that
  536.     # a character needs to speak at a different speed without destroying
  537.     # the users preferences...
  538.     # Call by message.text_speed = message.text_speed_player
  539.     # YOU HAVE TO ENTER A NEWLINE (PRESS ENTER) BEFPRE 2ND VARIABLE
  540.     # DUE TO WRAPPING TEXT BUG WITH SCRIPTS IN EVENT SCRIPTS
  541.     # Otherwise you get errors
  542.    
  543.     # whether or not players can skip to the end of (letter-by-letter) messages
  544.     @skippable = true
  545.    
  546.     # whether or not messages are automatically resized based on the message
  547.     @resize = true
  548.    
  549.     # whether or not message windows are positioned above
  550.     # characters/events by default, i.e. without needing \P every message
  551.     # (only works if resize messages enabled -- otherwise would look very odd)
  552.     @floating = true
  553.    
  554.     # whether or not to automatically center lines within the message
  555.     @autocenter = true
  556.    
  557.     # whether or not event-positioned messages have a tail(for speech balloons)
  558.     # (only works if floating and resized messages enabled -- otherwise would
  559.     # look very odd indeed)
  560.     @show_tail = true
  561.    
  562.     # whether or not to display "waiting for user input" pause graphic
  563.     # (probably want this disabled for speech balloons)
  564.     @show_pause = false
  565.  
  566.     # whether the player is permitted to move while messages are displayed
  567.     @move_during = true
  568.    
  569.     # the default location for floating messages (relative to the event)
  570.     # note that an off-screen message will be "flipped" automatically
  571.     @location = TOP
  572.    
  573.     # font details
  574.     # overrides all defaults; leave nil to just use defaults (e.g. as above)
  575.     @font_name = nil
  576.     @font_size = nil
  577.     @font_color = nil
  578.  
  579.     # pause on these characters ,.?!
  580.     # pause for delay number of frames if this is true, toggle with \A in Text
  581.     @auto_comma_pause = true
  582.     # inserts this number of frames to ,!.? characters, nil for off    
  583.     @auto_comma_delay = 5
  584.  
  585.     # designers can allow or disallow choices, why not number windows too?
  586.     @allow_cancel_numbers = true
  587.     # speeds up text display a bit so players dont get bored waiting
  588.     @update_text_while_fading = true
  589.    
  590.     # reset foot_forwad stance on auto-close due to Event going off-screen
  591.     @auto_ff_reset = true
  592.     # continues Move Route when NPC is speaking and goes off screen
  593.     @auto_move_continue = true
  594.    
  595.     # exit if distance from speaker is too great
  596.     @dist_exit = true
  597.     # distance player can be before window closes
  598.     @dist_max = 4
  599.    
  600.     # allow message windows to float off screen instead of flipping
  601.     @allow_offscreen = true
  602.    
  603.     # reposition the message window if the speaker turns
  604.     @reposition_on_turn = true
  605.    
  606.     # if Msg Windows were Reoriented by Player Movement, sticky to that spot
  607.     @sticky = true
  608.  
  609.     # Sounds While Speaking Related
  610.     @sound = false                         # Enables or Disables Text Sounds  
  611.     @sound_audio = '001-System01'          # Audio SE (in DB) to play
  612.     @sound_volume = 80                     # Text Sound Volume
  613.     @sound_pitch = 100                      # Text Sound Pitch
  614.     @sound_pitch_range = 20                # How Much to vary the Pitch
  615.     @sound_vary_pitch = true               # Whether to Vary the Pitch or not
  616.     @sound_frequency = 3                   # Plays a sound this many letters
  617.  
  618.     # Save these settings - DONT EDIT
  619.     save_sound_settings
  620.   end
  621.  
  622.   attr_accessor :move_during                # Walk around while speaking
  623.   attr_accessor :letter_by_letter           # Display msg letter by letter
  624.   attr_accessor :text_speed                 # How fast text is displayed
  625.   attr_accessor :text_speed_player          # Saves Player Preference
  626.   attr_accessor :skippable                  # Msg can be skipped
  627.   attr_accessor :resize                     # Resizes Message Window
  628.   attr_accessor :floating                   # Messages are Speech Bubbles
  629.   attr_accessor :autocenter                 # Centers Text in Window
  630.   attr_accessor :show_tail                  # Speech Bubble Tail
  631.   attr_accessor :show_pause                 # Shows Icon to press a button
  632.   attr_accessor :location                   # Relative to Speaker Top Bottom etc
  633.   attr_accessor :font_name                  # Name of Font to be used
  634.   attr_accessor :font_size                  # Size of Font
  635.   attr_accessor :font_color                 # Color of Font
  636.   attr_accessor :auto_comma_pause           # Pauses on these characters ?,.!
  637.   attr_accessor :auto_comma_delay           # How many Frames to Delay
  638.   attr_accessor :allow_cancel_numbers       # Allows cancelling Number Input
  639.   attr_accessor :auto_ff_reset              # Foot Forward Animation reset
  640.   attr_accessor :auto_move_continue         # Continues Previous Move Route  
  641.   attr_accessor :update_text_while_fading   # Update Text while Fading In
  642.   attr_accessor :dist_exit                  # Auto Close Window if true
  643.   attr_accessor :dist_max                   # Dist Max Player from Speaker
  644.   attr_accessor :allow_offscreen            # Allows Msg Windows Off Screen
  645.   attr_accessor :reposition_on_turn         # Reposition Windows if Speaker Turn
  646.   attr_accessor :sticky                     # Msgs "Prefer" Sticky Locations
  647.   # Sound Related
  648.   attr_accessor :sound                      # Enables or Disables Text Sounds  
  649.   attr_accessor :sound_audio                # Audio SE (in DB) to play
  650.   attr_accessor :sound_volume               # Text Sound Volume
  651.   attr_accessor :sound_pitch                # Text Sound Pitch
  652.   attr_accessor :sound_pitch_range          # How Much to vary the Pitch
  653.   attr_accessor :sound_vary_pitch           # Whether to Vary the Pitch or not
  654.   attr_accessor :sound_frequency            # Plays a sound this many letters
  655.  
  656.  
  657.  
  658.   # Used for storing the Default Sound Configuration
  659.   def save_sound_settings
  660.     # Allows Saving ONCE
  661.     return if @default_sounds_audio
  662.     # Stores the Default Values
  663.     @default_sound_audio = @sound_audio
  664.     @default_sound_volume = @sound_volume
  665.     @default_sound_pitch = @sound_pitch
  666.     @default_sound_pitch_range = @sound_pitch_range
  667.     @default_sound_vary_pitch = @sound_vary_pitch
  668.     @default_sound_frequency = @sound_frequency
  669.   end
  670.  
  671.   # Loads the Default Sound Settings
  672.   def load_sound_settings
  673.     # If settings have not been saved
  674.     return if not @default_sound_audio
  675.    
  676.     # Default System Sound Configuration
  677.     @sound_audio = @default_sound_audio
  678.     @sound_volume = @default_sound_volume
  679.     @sound_pitch = @default_sound_pitch
  680.     @sound_pitch_range = @default_sound_pitch_range
  681.     @sound_vary_pitch = @default_sound_vary_pitch
  682.     @sound_frequency = @default_sound_frequency
  683.   end
  684. end
  685.  
  686. #==============================================================================
  687. # Private constants (don't edit)
  688. #==============================================================================
  689.  
  690.   # used for message.location
  691.   TOP = 8
  692.   BOTTOM = 2
  693.   LEFT = 4
  694.   RIGHT = 6
  695.  
  696. #------------------------------------------------------------------------------
  697.  
  698. class Game_Character
  699.   attr_accessor :direction               # Used for changing bubble orientation
  700.   attr_accessor :direction_fix           # Character locked facing a direction
  701.   attr_accessor :walk_anime              # Character steps when moves
  702.   attr_accessor :step_anime              # Character is Stepping
  703.   attr_accessor :erased                  # Erased Flag
  704.   attr_accessor :original_move_speed     # Characters original Move Speed
  705.   attr_accessor :original_move_frequency # Characters original Move Speed
  706.   attr_accessor :no_ff                   # Prevents Auto Foot Forward Off
  707.   attr_accessor :no_mc                   # No 'M'ove Continue
  708.   attr_accessor :dist_kill               # Closes ALL windows if Player X Dist
  709.  
  710.   unless self.method_defined?('heretic_char_mmw_initialize')
  711.     alias heretic_char_mmw_initialize initialize
  712.   end
  713.  
  714.   def initialize
  715.     # Run Original
  716.     heretic_char_mmw_initialize        
  717.     # Add New Properties
  718.     @original_move_speed = 4
  719.     @original_move_frequency = 6    
  720.     @no_ff = nil
  721.     @no_mc = nil
  722.     @dist_kill = nil
  723.     # Game Player - Sticky
  724.     if self.is_a?(Game_Player)
  725.       @sticky = false
  726.     end
  727.   end
  728. end
  729.  
  730. class Game_Event < Game_Character
  731.   unless self.method_defined?('heretic_event_mmw_initialize')
  732.     alias heretic_event_mmw_initialize initialize
  733.   end
  734.  
  735.   def initialize(map_id, event, *args)  
  736.     heretic_event_mmw_initialize(map_id, event, *args)
  737.     check_no_auto_ff(event)
  738.     check_no_mc(event)
  739.   end
  740.  
  741.   # These occur when Windows are Auto Closed for going Off Screen
  742.  
  743.   # Check for no Auto Foot Forward Off - In the event of Animation Problems...
  744.   def check_no_auto_ff(event)
  745.     event.name.gsub(/\\no_ff/i) {@no_ff = true}
  746.   end
  747.  
  748.   # Check for no MC - 'M'ove 'C'ontinue - Restores Original Move Route...
  749.   def check_no_mc(event)
  750.     event.name.gsub(/\\no_mc/i) {@no_mc = true}
  751.   end  
  752. end
  753.  
  754. class Window_Message < Window_Selectable
  755.   attr_accessor :choice_window     # Allows Multi Windows with Choice Selection
  756.  
  757. #==============================================================================
  758. # Private constants (don't edit)
  759. #==============================================================================
  760.  
  761.   # Characters that produce Text Sounds - a to z and 0 thru 9
  762.   CHARACTERS = [('a'..'z'),('0'..'9')].map{|i| i.to_a}.flatten
  763.  
  764. #------------------------------------------------------------------------------  
  765.  
  766.  
  767.   #--------------------------------------------------------------------------
  768.   # * Initialize
  769.   #--------------------------------------------------------------------------
  770.  
  771.   def initialize(msgindex = 0)
  772.     super(80, 304, 480, 160)
  773.     self.contents = Bitmap.new(width - 32, height - 32)
  774.     self.visible = false
  775.     self.z = 9000 + msgindex * 5 # permits messages to overlap legibly
  776.     @fade_in = false
  777.     @fade_out = false
  778.     @contents_showing = false
  779.     @cursor_width = 0
  780.     self.active = false
  781.     self.index = -1
  782.     @msgindex = msgindex
  783.     @tail = Sprite.new
  784.     @tail.bitmap =
  785.       if @msgindex == 0
  786.         RPG::Cache.windowskin(FILENAME_SPEECH_TAIL)
  787.       else
  788.         # don't use cached version or else all tails
  789.         # are rotated when multiple are visible at once
  790.         Bitmap.new("Graphics/Windowskins/"+FILENAME_SPEECH_TAIL)
  791.       end
  792.     # keep track of orientation of tail bitmap
  793.     if @tail.bitmap.orientation == nil
  794.       @tail.bitmap.orientation = 0
  795.     end
  796.     # make origin the center, not top left corner
  797.     @tail.ox = @tail.bitmap.width/2
  798.     @tail.oy = @tail.bitmap.height/2
  799.     # Removed due to Tail Overlap on Secondary Message Bubbles
  800.     #@tail.z = 9999
  801.     # Increase Z Index
  802.     @tail.z = self.z + 4
  803.     @tail.visible = false
  804.     if $game_system.message.floating and $game_system.message.resize
  805.       @windowskin = FILENAME_SPEECH_WINDOWSKIN
  806.     else
  807.       # use windowskin specified in database
  808.       @windowskin = $game_system.windowskin_name
  809.     end
  810.     if $game_system.message.floating and $game_system.message.resize
  811.       # if used as speech balloons, use constants
  812.       @font_name = SPEECH_FONT_NAME
  813.       @font_color = check_color(SPEECH_FONT_COLOR)
  814.       @font_size = SPEECH_FONT_SIZE
  815.     else
  816.       # use defaults
  817.       @font_name = Font.default_name
  818.       @font_color = Font.default_color
  819.       @font_size = Font.default_size
  820.     end
  821.     # override defaults if necessary
  822.     if $game_system.message.font_name != nil
  823.       @font_name = $game_system.message.font_name
  824.     end
  825.     if $game_system.message.font_color != nil
  826.       @font_color = check_color($game_system.message.font_color)
  827.     end
  828.     if $game_system.message.font_size != nil
  829.       @font_size = $game_system.message.font_size
  830.     end
  831.     @update_text = true
  832.     @letter_by_letter = $game_system.message.letter_by_letter
  833.     @text_speed = $game_system.message.text_speed
  834.     # id of character for speech balloons
  835.     @float_id = nil
  836.     # location of box relative to speaker
  837.     @location = $game_system.message.location
  838.     # insert a pause for commas, periods and other special characters
  839.     @auto_comma_pause = $game_system.message.auto_comma_pause
  840.     @auto_comma_delay = $game_system.message.auto_comma_delay
  841.     # allows number windows to be cancelled    
  842.     @allow_cancel_numbers = $game_system.message.allow_cancel_numbers
  843.     # allows windows to update text while fading in
  844.     @update_text_while_fading = $game_system.message.update_text_while_fading    
  845.     # resets foot forward animation when off screen
  846.     @auto_ff_reset = $game_system.message.auto_ff_reset
  847.     # resets foot forward animation when off screen
  848.     @auto_move_continue = $game_system.message.auto_move_continue
  849.     # allows a specific window to be flagged if choices are displayed
  850.     @choice_window = nil
  851.    
  852.     # Close a Window if distance from speaker is too great
  853.     @dist_exit = $game_system.message.dist_exit
  854.     # Maximum Distance player can be away from speaker before closing
  855.     @dist_max = $game_system.message.dist_max
  856.  
  857.     # Sounds While Speaking Related
  858.     @sound = $game_system.message.sound
  859.     @sound_audio = $game_system.message.sound_audio
  860.     @sound_volume = $game_system.message.sound_volume
  861.     @sound_pitch = $game_system.message.sound_pitch
  862.     @sound_pitch_range = $game_system.message.sound_pitch_range
  863.     @sound_vary_pitch = $game_system.message.sound_vary_pitch
  864.     @sound_frequency = $game_system.message.sound_frequency
  865.     @sound_counter = 0
  866.   end
  867.  
  868.   def dispose
  869.     terminate_message
  870.     # have to check all windows before claiming that no window is showing
  871.     if $game_temp.message_text.compact.empty?
  872.       $game_temp.message_window_showing = false
  873.     end
  874.  
  875.     if @input_number_window != nil
  876.       @input_number_window.dispose
  877.     end
  878.     super
  879.   end
  880.   #--------------------------------------------------------------------------
  881.   # * Terminate Message
  882.   #--------------------------------------------------------------------------
  883.  
  884.   def terminate_message
  885.     return if $game_temp.input_in_window == true
  886.     self.active = false
  887.     self.pause = false
  888.     self.index = -1
  889.     self.contents.clear
  890.     # Clear showing flag
  891.     @contents_showing = false
  892.  
  893.     # Clear variables related to text, choices, and number input
  894.     @tail.visible = false
  895.     # note that these variables are now indexed arrays
  896.     $game_temp.message_text[@msgindex] = nil
  897.     # Call message callback
  898.     if $game_temp.message_proc[@msgindex] != nil
  899.       # make sure no message boxes are displaying
  900.       if $game_temp.message_text.compact.empty?
  901.         $game_temp.message_proc[@msgindex].call
  902.       end
  903.       $game_temp.message_proc[@msgindex] = nil
  904.     end
  905.     self.choice_window = nil
  906.     @update_text = true
  907.     $game_temp.choice_start = 99
  908.     $game_temp.choice_max = 0
  909.     $game_temp.choice_cancel_type = 0
  910.     $game_temp.choice_proc = nil
  911.     $game_temp.num_input_start = 99
  912.     $game_temp.num_input_variable_id = 0
  913.     $game_temp.num_input_digits_max = 0
  914.     # Open gold window
  915.     if @gold_window != nil
  916.       @gold_window.dispose
  917.       @gold_window = nil
  918.     end
  919.   end
  920.  
  921.   #--------------------------------------------------------------------------
  922.   # * Refresh Message Window
  923.   #--------------------------------------------------------------------------
  924.  
  925.   def refresh
  926.     self.contents.clear
  927.     @x = @y = 0 # now instance variables
  928.     @float_id = nil
  929.     @location = $game_system.message.location
  930.     if $game_system.message.floating and $game_system.message.resize
  931.       @windowskin = FILENAME_SPEECH_WINDOWSKIN
  932.     else
  933.       # use windowskin specified in database
  934.       @windowskin = $game_system.windowskin_name
  935.     end
  936.     if $game_system.message.floating and $game_system.message.resize
  937.       # if used as speech balloons, use constants
  938.       @font_name = SPEECH_FONT_NAME
  939.       @font_color = check_color(SPEECH_FONT_COLOR)
  940.       @font_size = SPEECH_FONT_SIZE
  941.     else
  942.       # use default font
  943.       @font_name = Font.default_name
  944.       @font_color = Font.default_color
  945.       @font_size = Font.default_size
  946.     end
  947.     # override font defaults
  948.     if $game_system.message.font_name != nil
  949.       @font_name = $game_system.message.font_name
  950.     end
  951.     if $game_system.message.font_color != nil
  952.       @font_color = check_color($game_system.message.font_color)
  953.     end
  954.     if $game_system.message.font_size != nil
  955.       @font_size = $game_system.message.font_size
  956.     end
  957.     @line_widths = nil
  958.     @wait_for_input = false
  959.     @tail.bitmap =
  960.       if @msgindex == 0
  961.         RPG::Cache.windowskin(FILENAME_SPEECH_TAIL)
  962.       else
  963.         Bitmap.new("Graphics/Windowskins/"+FILENAME_SPEECH_TAIL)
  964.       end
  965.     RPG::Cache.windowskin(FILENAME_SPEECH_TAIL)
  966.     @tail.bitmap.orientation = 0 if @tail.bitmap.orientation == nil
  967.     @text_speed = $game_system.message.text_speed
  968.     @letter_by_letter = $game_system.message.letter_by_letter
  969.     @auto_comma_pause = $game_system.message.auto_comma_pause
  970.     @auto_comma_delay = $game_system.message.auto_comma_delay
  971.     @allow_cancel_numbers = $game_system.message.allow_cancel_numbers
  972.     @auto_ff_reset = $game_system.message.auto_ff_reset
  973.     @auto_move_continue = $game_system.message.auto_move_continue
  974.     @update_text_while_fading = $game_system.message.update_text_while_fading
  975.     @dist_exit = $game_system.message.dist_exit
  976.     @dist_max = $game_system.message.dist_max
  977.     @dist_max = 1 if @dist_max < 1
  978.     @auto_orient = nil
  979.     @delay = @text_speed
  980.     @player_skip = false
  981.     # Sound Related    
  982.     @sound = $game_system.message.sound
  983.     @sound_volume = $game_system.message.sound_volume
  984.     @sound_pitch = $game_system.message.sound_pitch
  985.     @sound_pitch_range = $game_system.message.sound_pitch_range
  986.     @sound_vary_pitch = $game_system.message.sound_vary_pitch
  987.     @sound_frequency = $game_system.message.sound_frequency
  988.     @sound_counter = 0    
  989.     # End Sound Related
  990.     @cursor_width = 0
  991.     # Indent if choice
  992.     if $game_temp.choice_start == 0
  993.       @x = 8
  994.     end
  995.     # If waiting for a message to be displayed
  996.     if $game_temp.message_text[@msgindex] != nil
  997.       @text = $game_temp.message_text[@msgindex] # now an instance variable
  998.       # Control text processing
  999.       begin
  1000.         last_text = @text.clone
  1001.         @text.gsub!(/\\[V]\[[T]([0-9]+)\]/i) { $game_system.mmw_text[$1.to_i] }        
  1002.         @text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
  1003.  
  1004.        
  1005.        
  1006.        
  1007.        
  1008.       end until @text == last_text
  1009.       @text.gsub!(/\\[Nn]\[([0-9]+)\]/) do
  1010.         $game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
  1011.       end
  1012.       # Change "\\\\" to "\000" for convenience
  1013.       @text.gsub!(/\\\\/) { "\000" }
  1014.       @text.gsub!(/\\[Gg][\+]/) { "\023" } # Gold Window at TOP
  1015.       @text.gsub!(/\\[Gg][\-]/) { "\024" } # Gold Window at Bottom
  1016.       @text.gsub!(/\\[Gg]/) { "\002" }  # Gold Window Auto, based on Player Loc
  1017.  
  1018.       # display icon of item, weapon, armor or skill
  1019.       @text.gsub!(/\\[Ii]\[([IiWwAaSs][0-9]+)\]/) { "\013[#{$1}]" }
  1020.       # display name of enemy, item, weapon, armor or skill
  1021.       @text.gsub!(/\\[Nn]\[([EeIiWwAaSs])([0-9]+)\]/) do
  1022.         case $1.downcase
  1023.           when "e"
  1024.             entity = $data_enemies[$2.to_i]
  1025.           when "i"
  1026.             entity = $data_items[$2.to_i]
  1027.           when "w"
  1028.             entity = $data_weapons[$2.to_i]
  1029.           when "a"
  1030.             entity = $data_armors[$2.to_i]
  1031.           when "s"
  1032.             entity = $data_skills[$2.to_i]
  1033.         end
  1034.         entity != nil ? entity.name : ""
  1035.       end
  1036.       # display icon and name of item, weapon, armor or skill
  1037.       @text.gsub!(/\\[Ii]&[Nn]\[([IiWwAaSs])([0-9]+)\]/) do
  1038.         case $1.downcase
  1039.           when "e"
  1040.             entity = $data_enemies[$2.to_i]
  1041.           when "i"
  1042.             entity = $data_items[$2.to_i]
  1043.           when "w"
  1044.             entity = $data_weapons[$2.to_i]
  1045.           when "a"
  1046.             entity = $data_armors[$2.to_i]
  1047.           when "s"
  1048.             entity = $data_skills[$2.to_i]
  1049.         end
  1050.         entity != nil ? "\013[#{$1+$2}] " + entity.name : ""
  1051.       end      
  1052.       # display name of current map
  1053.       @text.gsub!(/\\[Mm][Aa][Pp]/) { $game_map.name }
  1054.       # change font color
  1055.       @text.gsub!(/\\[Cc]\[([0-9]+|#[0-9A-Fa-f]{6,6})\]/) { "\001[#{$1}]" }
  1056.       # return to default color
  1057.       @text.gsub!(/\\[Cc]/) { "\001" }
  1058.       # toggle letter-by-letter mode
  1059.       @text.gsub!(/\\[Ll]/) { "\003" }
  1060.       # toggle auto_comma_pause mode
  1061.       @text.gsub!(/\\[Aa]/) { "\016" }
  1062.       # trigger Foot Forward Animation
  1063.       @text.gsub!(/\\[Ff]\+/) { "\020" }
  1064.       # trigger Foot Forward Animation Alter Frame
  1065.       @text.gsub!(/\\[Ff]\*/) { "\022" }        
  1066.       # trigger Reset Foot Forward Animation
  1067.       @text.gsub!(/\\[Ff]\-/) { "\021" }        
  1068.       # change text speed (for letter-by-letter)
  1069.       @text.gsub!(/\\[Ss]\[([0-9]+)\]/) { "\004[#{$1}]" }
  1070.       # insert delay
  1071.       @text.gsub!(/\\[Dd]\[([0-9]+)\]/) { "\005[#{$1}]" }
  1072.  
  1073.       # insert delays for commas, periods, questions and exclamations
  1074.       @text.gsub!(/, /) { ", \015" }    # Comma with One Space
  1075.       @text.gsub!(/!  /) { "!  \015" }  # Exclamation Point with Two Spaces
  1076.       @text.gsub!(/\?  /) { "?  \015" } # Question Mark with Two Spaces
  1077.       @text.gsub!(/\.  /) { ".  \015" } # Period with Two Spaces
  1078.      
  1079.       # self close message
  1080.       @text.gsub!(/\\[!]/) { "\006" }
  1081.       # wait for button input
  1082.       @text.gsub!(/\\[?]/) { "\007" }
  1083.       # bold
  1084.       @text.gsub!(/\\[Bb]/) { "\010" }
  1085.       # italic
  1086.       @text.gsub!(/\\[Ii]/) { "\011" }
  1087.       # add msg with \*
  1088.       @text.gsub!(/\\[*]/) { "\014" }      
  1089.       # thought balloon
  1090.       if @text.gsub!(/\\[@]/, "") != nil
  1091.         @windowskin = FILENAME_THOUGHT_WINDOWSKIN
  1092.         @font_name = THOUGHT_FONT_NAME
  1093.         @font_size = THOUGHT_FONT_SIZE
  1094.         @font_color = check_color(THOUGHT_FONT_COLOR)
  1095.         @tail.bitmap =
  1096.           if @msgindex == 0
  1097.             RPG::Cache.windowskin(FILENAME_THOUGHT_TAIL)
  1098.           else
  1099.             Bitmap.new("Graphics/Windowskins/"+FILENAME_THOUGHT_TAIL)
  1100.           end
  1101.         @tail.bitmap.orientation = 0 if @tail.bitmap.orientation == nil
  1102.       end
  1103.       # Get rid of "\+" (multiple messages)
  1104.       @text.gsub!(/\\[+]/, "")
  1105.       # Get rid of "\*" (multiple messages)
  1106.       @text.gsub!(/\\[*]/, "")      
  1107.       # Get rid of "\\^", "\\v", "\\<", "\\>" (relative message location)
  1108.       if @text.gsub!(/\\\^/, "") != nil
  1109.         @location = 8
  1110.       elsif @text.gsub!(/\\[Vv]/, "") != nil
  1111.         @location = 2
  1112.       elsif @text.gsub!(/\\[<]/, "") != nil
  1113.         @location = 4
  1114.       elsif @text.gsub!(/\\[>]/, "") != nil
  1115.         @location = 6
  1116.       end
  1117.       # Get rid of "\\P" (position window to given character)
  1118.       if @text.gsub!(/\\[Pp]\[([0-9]+)\]/, "") != nil
  1119.         @float_id = $1.to_i
  1120.       elsif @text.gsub!(/\\[Pp]\[([a-zA-Z])\]/, "") != nil and
  1121.           $game_temp.in_battle
  1122.         @float_id = $1.downcase
  1123.       # Tie-In with Caterpillar, use \P[Cn] for a Cat Actor or Follower \P[C1]
  1124.       elsif @text.gsub!(/\\[Pp]\[[Cc]([0-9]+)\]/, "") != nil and
  1125.             !$game_temp.in_battle and
  1126.             Interpreter.method_defined?('get_cat_position_id')
  1127.         # This only works with Heretic's Caterpillar
  1128.         if $1.to_i == 0
  1129.           @float_id = 0 # Player
  1130.         elsif $1.to_i > 0 and $1.to_i <= $game_system.caterpillar.actors.size
  1131.           # temporary shortuct to keep on one line
  1132.           s = $game_system.map_interpreter
  1133.           # Returns the Event ID of the Cat Actor in that position          
  1134.           @float_id = s.get_cat_position_id($1.to_i - 1)
  1135.         end        
  1136.       elsif @text.gsub!(/\\[Pp]/, "") != nil or
  1137.             ($game_system.message.floating and $game_system.message.resize) and
  1138.             !$game_temp.in_battle
  1139.         # Just assigns the Event ID of the \P[x] Event
  1140.         @float_id = $game_system.map_interpreter.event_id
  1141.       end
  1142.       # Orient to Behind Events Direction with \%
  1143.       if @text.gsub!(/\\[%]/, "") != nil and !$game_temp.in_battle    
  1144.         d = (@float_id > 0) ?
  1145.             $game_map.events[@float_id].direction : $game_player.direction
  1146.         # Allows Window to Reorient if the Speaker Turns
  1147.         @auto_orient = 1
  1148.         # If Sticky is Disabled...
  1149.         if !$game_system.message.sticky
  1150.           # Unset any possible Stickys
  1151.           $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1152.           # Game Player Sticky
  1153.           if @float_id == 0 and not $game_player.sticky
  1154.             # Reset Game Player Preferred Location
  1155.             $game_player.preferred_loc = nil
  1156.           end
  1157.         end
  1158.         if @float_id > 0 and $game_map.events[@float_id].preferred_loc and
  1159.            $game_map.events[@float_id].allow_flip
  1160.           # This just helps to keep the position the same
  1161.           @location = $game_map.events[@float_id].preferred_loc
  1162.         elsif @float_id == 0 and $game_player.preferred_loc and
  1163.               $game_player.allow_flip
  1164.           # Set Location to Players Preferred Location.
  1165.           @location = $game_player.preferred_loc
  1166.         else
  1167.           if d == 2
  1168.             @location = 8
  1169.             if @float_id == 0 and $game_player.sticky
  1170.               $game_player.preferred_loc = 8
  1171.             end
  1172.           elsif d == 4
  1173.             @location = 6
  1174.           elsif d == 6
  1175.             @location = 4
  1176.           elsif d == 8
  1177.             @location = 2
  1178.             if @float_id == 0 and $game_player.sticky
  1179.               $game_player.preferred_loc = 8
  1180.             end
  1181.           else
  1182.             @location = 8
  1183.           end
  1184.         end
  1185.       end
  1186.       # Orient Above unless facing UP, then Down
  1187.       if @text.gsub!(/\\[\$]/, "") != nil and !$game_temp.in_battle
  1188.         # This Allows Top / Bottom Flipping if the Speaker Turns
  1189.         @auto_orient = 2
  1190.         d = (@float_id > 0) ?
  1191.             $game_map.events[@float_id].direction : $game_player.direction
  1192.         # Check for "Sticky" messages
  1193.         if !$game_system.message.sticky
  1194.           # Unset any possible Stickys
  1195.           $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1196.           if @float_id == 0 and not $game_player.sticky
  1197.             $game_player.preferred_loc = nil
  1198.           end
  1199.         end
  1200.         # If the message got flipped due to Character Turning, then Prefer
  1201.         pl = (@float_id > 0) ? $game_map.events[@float_id].preferred_loc :
  1202.              (@float_id == 0) ? $game_player.preferred_loc : nil
  1203.         if ((@float_id > 0 and $game_map.events[@float_id].allow_flip) or
  1204.            (@float_id == 0 and $game_player.allow_flip)) and
  1205.            (pl == 2 or pl == 8)
  1206.            
  1207.           # Set Location to the Preferred Location.  Only works if Triggered
  1208.           # Other Events are NOT included in this "Stickyness"
  1209.           @location = pl
  1210.         else
  1211.           # Orient by Direction
  1212.           case d            
  1213.           when 8
  1214.             @location = 2
  1215.           else
  1216.             @location = 8
  1217.           end
  1218.         end
  1219.         # Set Preferred Location for Sticky
  1220.         if $game_system.message.sticky
  1221.           # Set Sticky for Player
  1222.           if @float_id == 0 and $game_player.preferred_loc == nil and
  1223.                                 $game_player.sticky
  1224.             # Set Sticky for Player, expires at end of Event Processing
  1225.             $game_player.preferred_loc = @location
  1226.           # Set Sticky for Event
  1227.           elsif @float_id > 0 and
  1228.                 $game_map.events[@float_id].preferred_loc == nil
  1229.             # Set Sticky for Event, expires at end of Event Processing
  1230.             $game_map.events[@float_id].preferred_loc = @location
  1231.           end
  1232.         end        
  1233.       end        
  1234.       if $game_system.message.resize or $game_system.message.autocenter
  1235.         # calculate length of lines
  1236.         text = @text.clone
  1237.         temp_bitmap = Bitmap.new(1,1)
  1238.         temp_bitmap.font.name = @font_name
  1239.         temp_bitmap.font.size = @font_size
  1240.         @line_widths = [0,0,0,0]
  1241.         for i in 0..3
  1242.           line = text.split(/\n/)[3-i]
  1243.           if line == nil
  1244.             next
  1245.           end
  1246.           line.gsub!(/[\001-\007](\[[#A-Fa-f0-9]+\])?/, "")          
  1247.           line.gsub!(/\013\[[IiWwAaSs][0-9]+\]/, "\013")
  1248.           line.chomp.split(//).each do |c|
  1249.            
  1250.            
  1251.             # C for Characters in Size of Message Bubble
  1252.            
  1253.             case c
  1254.               when "\000"
  1255.                 c = "\\"
  1256.               when "\010"
  1257.                 # bold
  1258.                 temp_bitmap.font.bold = !temp_bitmap.font.bold
  1259.                 next
  1260.               when "\011"
  1261.                 # italics
  1262.                 temp_bitmap.font.italic = !temp_bitmap.font.italic
  1263.                 next
  1264.               when "\013"
  1265.                 # icon
  1266.                 @line_widths[3-i] += 24
  1267.                 next
  1268.               when "\014","\015","\016","\020","\021","\022","\023","\024"
  1269.                 # Featres Heretic added, causes garbage to appear
  1270.                 next
  1271.             end
  1272.             @line_widths[3-i] += temp_bitmap.text_size(c).width
  1273.           end
  1274.           if (3-i) >= $game_temp.choice_start
  1275.             # account for indenting
  1276.             @line_widths[3-i] += 8 unless $game_system.message.autocenter
  1277.           end
  1278.         end
  1279.         if $game_temp.num_input_variable_id > 0
  1280.           # determine cursor_width as in Window_InputNumber
  1281.           # (can't get from @input_number_window because it doesn't exist yet)
  1282.           cursor_width = temp_bitmap.text_size("0").width + 8
  1283.           # use this width to calculate line width (+8 for indent)
  1284.           input_number_width = cursor_width*$game_temp.num_input_digits_max
  1285.           input_number_width += 8 unless $game_system.message.autocenter
  1286.           @line_widths[$game_temp.num_input_start] = input_number_width
  1287.         end
  1288.         temp_bitmap.dispose
  1289.       end
  1290.       resize
  1291.       reposition if @float_id != nil
  1292.       self.contents.font.name = @font_name
  1293.       self.contents.font.size = @font_size
  1294.       self.contents.font.color = @font_color
  1295.       self.windowskin = RPG::Cache.windowskin(@windowskin)
  1296.       # autocenter first line if enabled
  1297.       # (subsequent lines are done as "\n" is encountered)
  1298.       if $game_system.message.autocenter and @text != ""
  1299.         @x = (self.width-40)/2 - @line_widths[0]/2
  1300.       end
  1301.     end
  1302.   end
  1303.  
  1304.   #--------------------------------------------------------------------------
  1305.   # * Resize Window
  1306.   #--------------------------------------------------------------------------
  1307.   def resize
  1308.     if !$game_system.message.resize
  1309.       # reset to defaults
  1310.       self.width = 480
  1311.       self.height = 160
  1312.       self.contents = Bitmap.new(width - 32, height - 32)
  1313.       self.x = 80 # undo any centering
  1314.       return
  1315.     end
  1316.     max_x = @line_widths.max
  1317.     max_y = 4
  1318.     @line_widths.each do |line|
  1319.       max_y -= 1 if line == 0 and max_y > 1
  1320.     end
  1321.     if $game_temp.choice_max  > 0
  1322.       # account for indenting
  1323.       max_x += 8 unless $game_system.message.autocenter
  1324.     end
  1325.     new_width = max_x + 40
  1326.     if @windowskin == FILENAME_THOUGHT_WINDOWSKIN and THOUGHT_WIDTH_MULTIPLE >0
  1327.       # force window width to be a multiple of THOUGHT_WIDTH_MULTIPLE
  1328.       # so that specialty windowskins (e.g. thought balloon) look right
  1329.       if new_width % THOUGHT_WIDTH_MULTIPLE != 0
  1330.         new_width += THOUGHT_WIDTH_MULTIPLE-(new_width%THOUGHT_WIDTH_MULTIPLE)
  1331.       end
  1332.     end
  1333.     self.width = new_width
  1334.     self.height = max_y * 32 + 32
  1335.     self.contents = Bitmap.new(width - 32, height - 32)
  1336.     self.x = 320 - (self.width/2) # center
  1337.   end
  1338.  
  1339.   def triggered_id?(event_id)
  1340.     return false if not $scene.is_a?(Scene_Map)
  1341.     # If the Event Speaking is the one that was Triggered in max_dist_id
  1342.     return true if $game_system.map_interpreter.max_dist_id ==
  1343.                    $game_system.map_interpreter.event_id
  1344.   end
  1345.  
  1346.   #--------------------------------------------------------------------------
  1347.   # * Reposition Window
  1348.   #--------------------------------------------------------------------------
  1349.   def reposition
  1350.     if $game_temp.in_battle
  1351.       if "abcd".include?(@float_id) # must be between a and d
  1352.         @float_id = @float_id[0] - 97 # a = 0, b = 1, c = 2, d = 3
  1353.         if $scene.spriteset.actor_sprites[@float_id] == nil
  1354.           @tail.visible = false
  1355.           return
  1356.         end
  1357.         sprite = $scene.spriteset.actor_sprites[@float_id]
  1358.       else
  1359.         @float_id -= 1 # account for, e.g., player entering 1 for index 0
  1360.         if $scene.spriteset.enemy_sprites[@float_id] == nil
  1361.           @tail.visible = false
  1362.           return
  1363.         end
  1364.         sprite = $scene.spriteset.enemy_sprites[@float_id]
  1365.       end
  1366.  
  1367.       if sprite.height != nil
  1368.         char_height = sprite.height
  1369.         char_width = sprite.width
  1370.         char_x = sprite.x
  1371.         char_y = sprite.y - char_height/2
  1372.       else
  1373.         # This prevents GAME CRASH Enemy doesnt exist
  1374.         return
  1375.       end
  1376.      
  1377.     else # not in battle...
  1378.       char = (@float_id == 0 ? $game_player : $game_map.events[@float_id])
  1379.       if char == nil
  1380.         # no such character
  1381.         @float_id = nil
  1382.         return
  1383.       end
  1384.       # close message (and stop event processing) if speaker is off-screen
  1385.       # or the window itself is completely off-screen
  1386.       if char.screen_x <= 0 or char.screen_x >= 640 or
  1387.          char.screen_y <= 0 or char.screen_y > 480 or
  1388.          ($game_system.message.move_during and
  1389.           not triggered_id?(char.id) and
  1390.           @dist_exit and char.allow_flip and  
  1391.            @float_id > 0 and not char.within_range?(@dist_max, @float_id)) or
  1392.            ($game_system.message.allow_offscreen and !$game_temp.in_battle and
  1393.            (self.height - self.y > 480 or self.height + self.y < 0 or
  1394.             self.width - self.x > 640 or self.width + self.x < 0))
  1395.         # Moved Off Screen or out of range so close Window
  1396.         terminate_message
  1397.         # 115 Breaks Event Processing
  1398.         $game_system.map_interpreter.command_115
  1399.         # reset foot forward on speak stance
  1400.         if @auto_ff_reset and not char.no_ff
  1401.           char.foot_forward_off
  1402.         end
  1403.         # reset 'M'ove 'C'ontinue
  1404.         if @auto_move_continue and not char.no_mc
  1405.           char.event_move_continue(@float_id, true)
  1406.         end
  1407.         # Instanced for this Msg Window, prevents calling Resets multiple times
  1408.         @auto_ff_reset = false
  1409.         # Turn off the Triggered Flag
  1410.         char.allow_flip = false
  1411.         char.preferred_loc = nil
  1412.         # Load the Default Sound Settings because Player walked away
  1413.         $game_system.message.load_sound_settings
  1414.         return
  1415.       end
  1416.       char_height = RPG::Cache.character(char.character_name,0).height / 4
  1417.       char_width = RPG::Cache.character(char.character_name,0).width / 4
  1418.       # record coords of character's center
  1419.       char_x = char.screen_x
  1420.       char_y = char.screen_y - char_height/2
  1421.     end
  1422.     params = [char_height, char_width, char_x, char_y]
  1423.     # position window and message tail
  1424.     vars = new_position(params)
  1425.     x = vars[0]
  1426.     y = vars[1]
  1427.  
  1428.     # check if need to flip because of Speaker Direction
  1429.     flip = need_flip?(@float_id, @location, x, y, params)
  1430.    
  1431.     # check if any window locations need to be "flipped"
  1432.     # because of Window Location
  1433.     if @location == 4 and
  1434.        ((x < 0 and
  1435.        (!$game_system.message.allow_offscreen or $game_temp.in_battle)) or
  1436.        flip)
  1437.       # if the msg is an Auto Oriented Msg and it needs to be flipped
  1438.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1439.         @location = put_behind(@float_id, 6)
  1440.       else      
  1441.         # switch to right
  1442.         @location = 6
  1443.       end
  1444.       vars = new_position(params)
  1445.       x = vars[0]
  1446.       if x + self.width > 640 and
  1447.          (!$game_system.message.allow_offscreen or $game_temp.in_battle)
  1448.         # right is no good either...
  1449.         if y >= 0
  1450.           # switch to top
  1451.           @location = 8
  1452.           vars = new_position(params)
  1453.         else
  1454.           # switch to bottom
  1455.           @location = 2
  1456.           vars = new_position(params)
  1457.         end
  1458.       end
  1459.       if $game_system.message.sticky
  1460.         $game_map.events[@float_id].preferred_loc = @location if @float_id > 0
  1461.         if @float_id == 0 and [2,8].include?(@location)
  1462.           if $game_player.allow_flip and $game_player.sticky
  1463.             $game_player.preferred_loc = @location
  1464.           else
  1465.             $game_player.preferred_loc = nil
  1466.           end
  1467.         end
  1468.       else
  1469.         $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1470.       end
  1471.     elsif @location == 6 and
  1472.           ((x + self.width > 640 and
  1473.           (!$game_system.message.allow_offscreen or $game_temp.in_battle)) or
  1474.           flip)
  1475.       # if the msg is an Auto Oriented Msg and it needs to be flipped
  1476.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1477.         @location = put_behind(@float_id, 4)
  1478.       else          
  1479.         # switch to left
  1480.         @location = 4
  1481.       end
  1482.       vars = new_position(params)
  1483.       x = vars[0]
  1484.       if x < 0 and
  1485.          (!$game_system.message.allow_offscreen or $game_temp.in_battle)
  1486.         # left is no good either...
  1487.         if y >= 0
  1488.           # switch to top
  1489.           @location = 8
  1490.           vars = new_position(params)
  1491.         else
  1492.           # switch to bottom
  1493.           @location = 2
  1494.           vars = new_position(params)
  1495.         end
  1496.       end
  1497.       if $game_system.message.sticky
  1498.         $game_map.events[@float_id].preferred_loc = @location if @float_id > 0
  1499.         if @float_id == 0 and [2,8].include?(@location)
  1500.           if $game_player.allow_flip and $game_player.sticky
  1501.             $game_player.preferred_loc = @location
  1502.           else
  1503.             $game_player.preferred_loc = nil
  1504.           end
  1505.         end
  1506.       else
  1507.         $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1508.       end
  1509.     elsif @location == 8 and
  1510.           ((y < 0 and
  1511.           (!$game_system.message.allow_offscreen or $game_temp.in_battle)) or
  1512.           flip)
  1513.       # if the msg is an Auto Oriented Msg and it needs to be flipped
  1514.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1515.         @location = put_behind(@float_id, 2)
  1516.       else
  1517.         # switch to bottom
  1518.         @location = 2
  1519.       end
  1520.       vars = new_position(params)
  1521.       y = vars[1]
  1522.  
  1523.       if y + self.height > 480 and
  1524.          (!$game_system.message.allow_offscreen or $game_temp.in_battle)
  1525.         # bottom is no good either...
  1526.         # note: this will probably never occur given only 3 lines of text
  1527.         # note: heretic - yeah right.  Wait till I get ahold of your code!
  1528.         x = vars[0]
  1529.         if x >= 0
  1530.           # switch to left
  1531.           @location = 4
  1532.           vars = new_position(params)
  1533.         else
  1534.           # switch to right
  1535.           @location = 6
  1536.           vars = new_position(params)
  1537.         end
  1538.       end
  1539.       if not $game_temp.in_battle
  1540.         if $game_system.message.sticky
  1541.           $game_map.events[@float_id].preferred_loc = @location if @float_id > 0
  1542.           if @float_id == 0 and [2,8].include?(@location)
  1543.             if $game_player.allow_flip and $game_player.sticky
  1544.               $game_player.preferred_loc = @location
  1545.             else
  1546.               $game_player.preferred_loc = nil
  1547.             end
  1548.           end
  1549.         else
  1550.           $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1551.         end
  1552.       end
  1553.     elsif @location == 2 and
  1554.           ((y + self.height > 480 and
  1555.           (!$game_system.message.allow_offscreen or $game_temp.in_battle)) or
  1556.           flip)
  1557.       # if the msg is an Auto Oriented Msg and it needs to be flipped
  1558.       if @auto_orient == 1 and need_flip?(@float_id, @location, x, y)
  1559.         @location = put_behind(@float_id, 8)
  1560.       else
  1561.         # switch to top
  1562.         @location = 8
  1563.       end
  1564.       vars = new_position(params)
  1565.       y = vars[1]
  1566.       if y < 0 and
  1567.          (!$game_system.message.allow_offscreen or $game_temp.in_battle)
  1568.         # top is no good either...
  1569.         # note: this will probably never occur given only 3 lines of text
  1570.         # note: heretic - yeah right.  Wait till I get ahold of your code!        
  1571.         x = vars[0]
  1572.         if x >= 0
  1573.           # switch to left
  1574.           @location = 4
  1575.           vars = new_position(params)
  1576.         else
  1577.           # switch to right
  1578.           @location = 6
  1579.           vars = new_position(params)
  1580.         end
  1581.       end
  1582.       if not $game_temp.in_battle
  1583.         if $game_system.message.sticky
  1584.           $game_map.events[@float_id].preferred_loc = @location if @float_id > 0
  1585.           if @float_id == 0 and [2,8].include?(@location)
  1586.             if $game_player.allow_flip and $game_player.sticky
  1587.               $game_player.preferred_loc = @location
  1588.             else
  1589.               $game_player.preferred_loc = nil
  1590.             end
  1591.           end
  1592.         else
  1593.           $game_map.events[@float_id].preferred_loc = nil if @float_id > 0
  1594.         end
  1595.       end
  1596.     end
  1597.     x = vars[0]
  1598.     y = vars[1]
  1599.     tail_x = vars[2]
  1600.     tail_y = vars[3]    
  1601.     # adjust windows if near edge of screen
  1602.     if not $game_system.message.allow_offscreen or $game_temp.in_battle
  1603.       if x < 0
  1604.         x = 0
  1605.       elsif (x + self.width) > 640
  1606.         x = 640 - self.width
  1607.       end
  1608.       if y < 0
  1609.         y = 0
  1610.       elsif (y + self.height) > 480
  1611.         y = 480 - self.height
  1612.       elsif $game_temp.in_battle and @location == 2 and (y > (320 - self.height))
  1613.         # when in battle, prevent enemy messages from overlapping battle status
  1614.         # (note that it could still happen from actor messages, though)
  1615.         y = 320 - self.height
  1616.         tail_y = y
  1617.       end
  1618.     end
  1619.     # finalize positions
  1620.     self.x = x
  1621.     self.y = y
  1622.     @tail.x = tail_x
  1623.     @tail.y = tail_y
  1624.   end
  1625.  
  1626.   #--------------------------------------------------------------------------
  1627.   # * Need Flip? - Prevent Player from walking under Message Bubbles
  1628.   #--------------------------------------------------------------------------
  1629.   def need_flip?(event_id, loc, x, y, params = nil)
  1630.     return false if !@auto_orient or
  1631.                     @fade_out or
  1632.                     event_id.nil? or
  1633.                     (event_id != 0 and
  1634.                     $game_map.events[event_id].erased) or
  1635.                     $game_temp.in_battle or
  1636.                     !$game_system.message.reposition_on_turn or
  1637.                     !$game_system.message.move_during
  1638.     # vars for speaker
  1639.     event = (event_id > 0) ? $game_map.events[event_id] : $game_player
  1640.     dir = event.direction
  1641.    
  1642.     # if an argument is passed called params and not allowed offscreen  
  1643.     if params and not $game_system.message.allow_offscreen
  1644.       case loc
  1645.         when 2
  1646.           new_loc = 8
  1647.         when 4
  1648.           new_loc = 6
  1649.         when 6
  1650.           new_loc = 4
  1651.         when 8
  1652.           new_loc = 2
  1653.       end
  1654.       # check what the new coordinates of a repositioned window will be  
  1655.       new_vars = new_position(params, new_loc, no_rotate = true)
  1656.       new_x = new_vars[0]
  1657.       new_y = new_vars[1]
  1658.       # return false if not allowed off screen and new position is off screen
  1659.       if (new_x < 0 and new_loc == 4) or
  1660.          (new_x + self.width > 640) or
  1661.          (new_y < 0) or
  1662.          (new_y + self.height > 480)
  1663.         # if not allowed offscreen and trying to flip offscreen
  1664.         return false
  1665.       end
  1666.     end
  1667.  
  1668.     # default result
  1669.     result = false
  1670.     result = true if @auto_orient == 2 and
  1671.                      event.allow_flip and
  1672.                      dir == loc
  1673.  
  1674.     if @auto_orient == 1
  1675.       if event_id > 1
  1676.         # If Auto Orient Any Direction, try to put preference on top / bottom
  1677.         # Top / Bottom Preference was made for readability of Msgs
  1678.         # because it is easier to go off screen left and right
  1679.         if dir == loc or
  1680.            ((dir == 2 or dir == 8) and (loc == 4 or loc == 6))
  1681.           result = true
  1682.         end
  1683.       elsif event_id == 0 and $game_player.allow_flip
  1684.  
  1685.         # if Game Player Message is Sticky
  1686.         if $game_player.sticky and
  1687.            ((dir == 2 and loc != 8) or
  1688.            (dir == 8 and loc != 2) or
  1689.            (
  1690.              (not $game_player.preferred_loc) and
  1691.              ((dir == 4 and loc != 6) or (dir == 6 and loc != 4))
  1692.             )
  1693.            )
  1694.           # Return that Message needs to be Flipped
  1695.           result = true
  1696.         # If Game Player Non Sticky Message not behind Player  
  1697.         elsif not $game_player.sticky and
  1698.            ((dir == 2 and loc != 8) or
  1699.            (dir == 4 and loc != 6) or
  1700.            (dir == 6 and loc != 4) or
  1701.            (dir == 8 and loc != 2))
  1702.           # Return that Message needs to be Flipped
  1703.           result = true
  1704.         end
  1705.       end
  1706.     end
  1707.     return result
  1708.   end
  1709.  
  1710.   #--------------------------------------------------------------------------
  1711.   # Place Message Bubble behind Speaker
  1712.   #--------------------------------------------------------------------------
  1713.   def put_behind(event_id, default_loc)
  1714.     return default_loc if event_id.nil? or $game_temp.in_battle
  1715.     dir = (event_id > 0 ) ? $game_map.events[event_id].direction :
  1716.           $game_player.direction
  1717.     return 2 if dir == 8
  1718.     return 4 if dir == 6
  1719.     return 6 if dir == 4
  1720.     return 8 if dir == 2
  1721.     return default_loc
  1722.   end  
  1723.  
  1724.   #--------------------------------------------------------------------------
  1725.   # * Determine New Window Position
  1726.   #--------------------------------------------------------------------------  
  1727.   def new_position(params, location = @location, no_rotate = nil)
  1728.     char_height = params[0]
  1729.     char_width = params[1]
  1730.     char_x = params[2]
  1731.     char_y = params[3]
  1732.     if location == 8
  1733.       # top
  1734.       x = char_x - self.width/2
  1735.       y = char_y - char_height/2 - self.height - @tail.bitmap.height/2
  1736.       @tail.bitmap.rotation(0) if not no_rotate
  1737.       tail_x = x + self.width/2
  1738.       tail_y = y + self.height
  1739.     elsif location == 2
  1740.       # bottom
  1741.       x = char_x - self.width/2
  1742.       y = char_y + char_height/2 + @tail.bitmap.height/2
  1743.       @tail.bitmap.rotation(180) if not no_rotate
  1744.       tail_x = x + self.width/2
  1745.       tail_y = y
  1746.     elsif location == 4
  1747.       # left
  1748.       x = char_x - char_width/2 - self.width - @tail.bitmap.width/2
  1749.       y = char_y - self.height/2
  1750.       @tail.bitmap.rotation(270) if not no_rotate
  1751.       tail_x = x + self.width
  1752.       tail_y = y + self.height/2
  1753.     elsif location == 6
  1754.       # right
  1755.       x = char_x + char_width/2 + @tail.bitmap.width/2
  1756.       y = char_y - self.height/2
  1757.       @tail.bitmap.rotation(90) if not no_rotate
  1758.       tail_x = x
  1759.       tail_y = y + self.height/2
  1760.     end
  1761.     return [x,y,tail_x,tail_y]
  1762.   end
  1763.  
  1764.   #--------------------------------------------------------------------------
  1765.   # * Text Sound
  1766.   #--------------------------------------------------------------------------  
  1767.  
  1768.   def play_text_sound(char)
  1769.     sound = "Audio/SE/" + $game_system.message.sound_audio
  1770.     volume = @sound_volume
  1771.    
  1772.     if @sound_vary_pitch and @sound_pitch
  1773.       # Prevent Negative Numbers...
  1774.       sound_pitch_range = (@sound_pitch_range > @sound_pitch) ?
  1775.           @sound_pitch : @sound_pitch_range      
  1776.       # If we want to Randomize the Sounds
  1777.       if @sound_vary_pitch == "random"
  1778.         # Random within the Range
  1779.         pitch = rand(sound_pitch_range * 2) + @sound_pitch - sound_pitch_range
  1780.       # Vary Sound Pitch to be based on Letter Sounds
  1781.       else
  1782.  
  1783.         # Note to Self - Reorganize based on actual Letter Sounds, not so Random
  1784.         if ['l','m','n','q','u','w','2'].include?(char)
  1785.           pitch = @sound_pitch - sound_pitch_range
  1786.         elsif ['a','f','h','j','k','o','r','x','1','4','7','8'].include?(char)
  1787.           pitch = @sound_pitch - sound_pitch_range / 2
  1788.         elsif ['b','c','d','e','g','p','t','v','z','0','3','6'].to_a.include?(char)
  1789.           pitch = @sound_pitch
  1790.         elsif ['s','7'].to_a.include?(char)
  1791.           pitch = @sound_pitch + sound_pitch_range / 2
  1792.         elsif ['i','y','5','9'].to_a.include?(char)
  1793.           pitch = @sound_pitch + sound_pitch_range
  1794.         else
  1795.           pitch = rand(@sound_pitch_range * 2) + @sound_pitch
  1796.         end
  1797.       end
  1798.     else
  1799.       pitch=(@sound_pitch and @sound_pitch.is_a?(Numeric)) ? @sound_pitch : 100
  1800.     end
  1801.  
  1802.     # Play the Sound
  1803.     Audio.se_play(sound, volume, pitch)
  1804.   end
  1805.      
  1806.   #--------------------------------------------------------------------------
  1807.   # * Update Text
  1808.   #--------------------------------------------------------------------------  
  1809.   def update_text
  1810.     if @text != nil
  1811.       # Get 1 text character in c (loop until unable to get text)
  1812.       while ((c = @text.slice!(/./m)) != nil)
  1813.         # Plays Sounds for each Letter, Numbers and Spaces Excluded
  1814.         if @sound and @letter_by_letter and !@player_skip and
  1815.            CHARACTERS.include?(c.downcase)
  1816.           # Increment for each Letter Sound Played
  1817.           @sound_counter += 1
  1818.           # Prevents Division by Zero, allows 0 to play a sound every letter
  1819.           frequency = (@sound_frequency == 0) ?
  1820.                       @sound_counter : @sound_frequency
  1821.           # Play Sound for each New Word or if Remainder is 0
  1822.           if @sound_counter == 1 or @sound_counter % frequency == 0
  1823.             # Play correct sound for each letter
  1824.             play_text_sound(c.downcase)
  1825.           end
  1826.         else
  1827.           @sound_counter = 0
  1828.         end        
  1829.         # If \\
  1830.         if c == "\000"
  1831.           # Return to original text
  1832.           c = "\\"
  1833.         end
  1834.         # If \C[n] or \C[#xxxxxx] or \C
  1835.         if c == "\001"
  1836.           # Change text color
  1837.           @text.sub!(/\[([0-9]+|#[0-9A-Fa-f]{6,6})\]/, "")
  1838.           if $1 != nil
  1839.             self.contents.font.color = check_color($1)
  1840.           else
  1841.             # return to default color
  1842.             if $game_system.message.font_color != nil
  1843.               color = check_color($game_system.message.font_color)
  1844.             elsif $game_system.message.floating and $game_system.message.resize
  1845.               color = check_color(SPEECH_FONT_COLOR)
  1846.             else
  1847.               # use defaults
  1848.               color = Font.default_color
  1849.             end
  1850.             self.contents.font.color = color
  1851.           end
  1852.           # go to next text
  1853.           next
  1854.         end
  1855.         # If \G+ (Gold Window at the Top)
  1856.         if c == "\023"
  1857.           # Make gold window
  1858.           if @gold_window == nil
  1859.             @gold_window = Window_Gold.new
  1860.             @gold_window.x = 560 - @gold_window.width
  1861.             if $game_temp.in_battle
  1862.               @gold_window.y = 192
  1863.             else
  1864.               @gold_window.y = 32
  1865.             end
  1866.             @gold_window.opacity = self.opacity
  1867.             @gold_window.back_opacity = self.back_opacity
  1868.           end
  1869.           # Dont take up space in window, next character
  1870.           next
  1871.         end
  1872.         # If \G- (Gold Window at the Bottom)
  1873.         if c == "\024"
  1874.           # Make gold window
  1875.           if @gold_window == nil
  1876.             @gold_window = Window_Gold.new
  1877.             @gold_window.x = 560 - @gold_window.width
  1878.             if $game_temp.in_battle
  1879.               @gold_window.y = 192
  1880.             else
  1881.               @gold_window.y = 384
  1882.             end
  1883.             @gold_window.opacity = self.opacity
  1884.             @gold_window.back_opacity = self.back_opacity
  1885.           end
  1886.           # Dont take up space in window, next character
  1887.           next
  1888.         end
  1889.         # If \G
  1890.         if c == "\002"
  1891.           # Make gold window
  1892.           if @gold_window == nil
  1893.             @gold_window = Window_Gold.new
  1894.             @gold_window.x = 560 - @gold_window.width
  1895.             if $game_temp.in_battle
  1896.               @gold_window.y = 192
  1897.             else
  1898.               @gold_window.y = self.y >= 128 ? 32 : 384
  1899.             end
  1900.             @gold_window.opacity = self.opacity
  1901.             @gold_window.back_opacity = self.back_opacity
  1902.           end
  1903.           # go to next text
  1904.           next
  1905.         end
  1906.         # If \L
  1907.         if c == "\003"
  1908.           # toggle letter-by-letter mode
  1909.           @letter_by_letter = !@letter_by_letter
  1910.           # go to next text
  1911.           next
  1912.         end
  1913.         # If \S[n]
  1914.         if c == "\004"
  1915.           @text.sub!(/\[([0-9]+)\]/, "")
  1916.           speed = $1.to_i
  1917.           if speed >= 0
  1918.             @text_speed = speed
  1919.             # reset player skip after text speed change
  1920.             @player_skip = false            
  1921.           end
  1922.           return
  1923.         end
  1924.         # If \D[n]
  1925.         if c == "\005"
  1926.           @text.sub!(/\[([0-9]+)\]/, "")
  1927.           delay = $1.to_i
  1928.           if delay >= 0
  1929.             @delay += delay
  1930.             # reset player skip after delay
  1931.             @player_skip = false
  1932.           end
  1933.           return
  1934.         end  
  1935.         # If \!
  1936.         if c == "\006"
  1937.           # close message and return from method
  1938.           terminate_message
  1939.           return
  1940.         end
  1941.         # If \?
  1942.         if c == "\007"
  1943.           @wait_for_input = true
  1944.           return
  1945.         end
  1946.         # If \B or \b
  1947.         if c == "\010"
  1948.           # bold
  1949.           self.contents.font.bold = !self.contents.font.bold
  1950.           return
  1951.         end
  1952.         # If \I or \i
  1953.         if c == "\011"
  1954.           # italics
  1955.           self.contents.font.italic = !self.contents.font.italic
  1956.           return
  1957.         end
  1958.         if c == "\013"
  1959.           # display icon of item, weapon, armor or skill
  1960.           @text.sub!(/\[([IiWwAaSs])([0-9]+)\]/, "")
  1961.           case $1.downcase
  1962.             when "i"
  1963.               item = $data_items[$2.to_i]
  1964.             when "w"
  1965.               item = $data_weapons[$2.to_i]
  1966.             when "a"
  1967.               item = $data_armors[$2.to_i]
  1968.             when "s"
  1969.               item = $data_skills[$2.to_i]
  1970.           end
  1971.           if item == nil
  1972.             return
  1973.           end
  1974.           bitmap = RPG::Cache.icon(item.icon_name)
  1975.           self.contents.blt(4+@x, 32*@y+4, bitmap, Rect.new(0, 0, 24, 24))
  1976.           @x += 24
  1977.           #self.contents.draw_text(x + 28, y, 212, 32, item.name)
  1978.           return
  1979.         end
  1980.         # if \*
  1981.         if c == "\014"
  1982.           if $scene.is_a?(Scene_Battle)
  1983.             # Set Variables in the Battle Interpreter to display Next Window
  1984.             $game_system.battle_interpreter.set_multi
  1985.           elsif $scene.is_a?(Scene_Map)
  1986.             # Set Variables in the Map Interpreter to display Next Window
  1987.             $game_system.map_interpreter.set_multi
  1988.           end
  1989.           return
  1990.         end
  1991.         # if ", " or ".  " or "!  " or "?  " characters with spaces
  1992.         if c == "\015"
  1993.           if @auto_comma_pause and @letter_by_letter
  1994.             delay = @text_speed + @auto_comma_delay
  1995.             if delay >= 0
  1996.               @delay += delay
  1997.               # reset player skip after delay
  1998.               @player_skip = false
  1999.             end
  2000.           end
  2001.           return          
  2002.         end
  2003.         # if \A (Auto Pause for Commas, Periods, Exclamation and Question Marks)
  2004.         if c == "\016"
  2005.           # toggle auto comma pause
  2006.           @auto_comma_pause = !@auto_comma_pause
  2007.           return
  2008.         end
  2009.         # if \F+ (Foot Forward Animation On)
  2010.         if c == "\020" and @float_id
  2011.           speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  2012.           speaker.foot_forward_on
  2013.           # Dont take up space in window, next character
  2014.           next
  2015.         end
  2016.         # if \F- (Foot Forward Animation Off)  
  2017.         if c == "\021" and @float_id
  2018.           speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  2019.           speaker.foot_forward_off
  2020.           # Dont take up space in window, next character
  2021.           next
  2022.         end
  2023.         # if \F* (Foot Forward Animation On "Other" Foot)
  2024.         if c == "\022" and @float_id
  2025.           speaker = (@float_id > 0) ? $game_map.events[@float_id] : $game_player
  2026.           speaker.foot_forward_on(frame = 1)
  2027.           # Dont take up space in window, next character
  2028.           next
  2029.         end          
  2030.         # If new line text
  2031.         if c == "\n"
  2032.           # Update cursor width if choice
  2033.           if @y >= $game_temp.choice_start
  2034.             width = $game_system.message.autocenter ? @line_widths[@y]+8 : @x
  2035.             @cursor_width = [@cursor_width, width].max
  2036.           end
  2037.           # Add 1 to y
  2038.           @y += 1
  2039.           if $game_system.message.autocenter and @text != ""
  2040.             @x = (self.width-40)/2 - @line_widths[@y]/2
  2041.           else
  2042.             @x = 0
  2043.             # Indent if choice
  2044.             if @y >= $game_temp.choice_start
  2045.               @x = 8
  2046.             end
  2047.           end
  2048.           # go to next text
  2049.           next
  2050.         end
  2051.         # Draw text
  2052.         self.contents.draw_text(4 + @x, 32 * @y, 40, 32, c)
  2053.         # Add x to drawn text width
  2054.         @x += self.contents.text_size( c ).width
  2055.         # add text speed to time to display next character
  2056.         @delay += @text_speed unless !@letter_by_letter or @player_skip
  2057.         return if @letter_by_letter and !@player_skip
  2058.       end
  2059.     end
  2060.     # If choice and window has choices set to be displayed
  2061.     if $game_temp.choice_max > 0 and @choice_window
  2062.       @item_max = $game_temp.choice_max
  2063.       self.active = true
  2064.       if $choice_index and $choice_index.is_a?(Integer) and
  2065.          $choice_index < $game_temp.choice_max
  2066.         self.index = $choice_index
  2067.       else
  2068.         self.index = 0
  2069.       end
  2070.     end
  2071.     # If number input and this window shows choices and no number window exists
  2072.     if $game_temp.num_input_variable_id > 0 and @choice_window and
  2073.        not @input_number_window
  2074.       digits_max = $game_temp.num_input_digits_max
  2075.       number = $game_variables[$game_temp.num_input_variable_id]
  2076.       @input_number_window = Window_InputNumber.new(digits_max)
  2077.       @input_number_window.set_font(@font_name, @font_size, @font_color)
  2078.       @input_number_window.number = number
  2079.       @input_number_window.x =
  2080.         if $game_system.message.autocenter
  2081.           offset = (self.width-40)/2-@line_widths[$game_temp.num_input_start]/2
  2082.           self.x + offset + 4
  2083.         else
  2084.           self.x + 8
  2085.         end
  2086.       @input_number_window.y = self.y + $game_temp.num_input_start * 32
  2087.     end
  2088.     @update_text = false
  2089.   end
  2090.  
  2091.   def reset_window
  2092.     if $game_temp.in_battle
  2093.       self.y = 16
  2094.     else
  2095.       case $game_system.message_position
  2096.       when 0  # up
  2097.         self.y = 16
  2098.       when 1  # middle
  2099.         self.y = 160
  2100.       when 2  # down
  2101.         self.y = 304
  2102.       end
  2103.     end
  2104.     if $game_system.message_frame == 0
  2105.       self.opacity = 255
  2106.     else
  2107.       self.opacity = 0
  2108.     end
  2109.     # transparent speech balloons don't look right, so keep opacity at 255
  2110.     # self.back_opacity = 160
  2111.     @tail.opacity = 255
  2112.   end
  2113.  
  2114.   def update
  2115.     super
  2116.     # Terminate ANY Messages if Player too far away, useful for signs
  2117.     if $scene.is_a?(Scene_Map)
  2118.       if $game_system.map_interpreter.event_id != 0
  2119.         e_id = $game_system.map_interpreter.event_id
  2120.         ev = $game_map.events[e_id]
  2121.         if ev and $game_map.events[e_id].dist_kill
  2122.           if not ev.within_range?(ev.dist_kill, e_id) and
  2123.              not $game_player.move_route_forcing and
  2124.              $game_system.message.move_during
  2125.             # Player moved too far away so kill windows and event processing
  2126.             if @input_number_window != nil
  2127.               # Dispose of number input window
  2128.               @input_number_window.dispose
  2129.               @input_number_window = nil  
  2130.             end
  2131.             # Terminate This Msg - Leave Others so each handles their @float_id
  2132.             terminate_message
  2133.             # 115 Breaks Event Processing
  2134.             $game_system.map_interpreter.command_115
  2135.            
  2136.             # If there is someone speaking        
  2137.             if @float_id
  2138.               # Player
  2139.               # Note: No Move Continue because moving away
  2140.               # is a Player initiated Action
  2141.               if @float_id == 0
  2142.                 # reset foot forward on speak stance
  2143.                 if @auto_ff_reset and not $game_player.no_ff
  2144.                   # Command to turn Foot Forward Poses Off
  2145.                   $game_player.foot_forward_off
  2146.                 end
  2147.                 $game_player.allow_flip = false
  2148.                 $game_player.preferred_loc = nil
  2149.               elsif @float_id > 0
  2150.                 # reset foot forward on speak stance
  2151.                 if @auto_ff_reset and not $game_map.events[@float_id].no_ff
  2152.                   # Command to turn Foot Forward Poses Off
  2153.                   $game_map.events[@float_id].foot_forward_off
  2154.                 end
  2155.                 # reset 'M'ove 'C'ontinue
  2156.                 if @auto_move_continue and not $game_map.events[@float_id].no_mc
  2157.                   # Continue doing what it was doing before
  2158.                   event_to_reset = $game_map.events[@float_id]
  2159.                   event_to_reset.event_move_continue(@float_id, true, 1)
  2160.                 end
  2161.                 $game_map.events[@float_id].allow_flip = false
  2162.                 $game_map.events[@float_id].preferred_loc = nil
  2163.               end
  2164.             end
  2165.             # Instanced for this Msg Window, prevents calling Resets multiple times
  2166.             @auto_ff_reset = false
  2167.             # Turn off the Triggered Flag
  2168.             ev.allow_flip = false
  2169.             ev.preferred_loc = nil
  2170.  
  2171.             if $game_temp.message_text.compact.empty?
  2172.               ev.dist_kill = nil
  2173.               $game_system.map_interpreter.restore_mmw_vars
  2174.               #$game_map.need_refresh = true
  2175.               if not $game_map.events[e_id].no_mc
  2176.                 $game_map.events[e_id].event_move_continue(e_id, true, 1)
  2177.                 $game_system.map_interpreter.max_dist_id = nil
  2178.               end
  2179.             end
  2180.           # Load the Default Sound Settings because Player walked away
  2181.           $game_system.message.load_sound_settings
  2182.           end
  2183.         end
  2184.       end
  2185.     end
  2186.    
  2187.     # If fade in
  2188.     if @fade_in
  2189.       self.contents_opacity += 24
  2190.       if @input_number_window != nil
  2191.         @input_number_window.contents_opacity += 24
  2192.       end
  2193.       if self.contents_opacity == 255
  2194.         @fade_in = false
  2195.       end
  2196.       # allow text to be updated while window is fading in
  2197.       return if not $game_system.message.update_text_while_fading
  2198.     end
  2199.     # If inputting number
  2200.     if @input_number_window != nil
  2201.       @input_number_window.update
  2202.       # Confirm
  2203.       if Input.trigger?(Input::C)
  2204.         # Allows windows to be closed
  2205.         $game_temp.input_in_window = false
  2206.         # play sound effect
  2207.         $game_system.se_play($data_system.decision_se)
  2208.         # Set Variable to identify the Number Window was Cancelled
  2209.         $game_system.number_cancelled = false        
  2210.         # if variable_id was lost, refer to backup
  2211.         if $game_temp.num_input_variable_id == 0
  2212.           $game_variables[$game_temp.num_input_variable_id_backup] =
  2213.             @input_number_window.number
  2214.         else
  2215.           $game_variables[$game_temp.num_input_variable_id] =
  2216.             @input_number_window.number
  2217.         end
  2218.         $game_map.need_refresh = true
  2219.         # Dispose of number input window
  2220.         @input_number_window.dispose
  2221.         @input_number_window = nil  
  2222.         if $scene.message_window.size > 1
  2223.           for msg in $scene.message_window
  2224.             msg.terminate_message
  2225.           end
  2226.         else
  2227.           terminate_message
  2228.         end
  2229.       # Cancel, if allowed
  2230.       # *NOTE* - use "number_cancelled?" to checks if Cancel Button was pushed
  2231.       elsif Input.trigger?(Input::B) and
  2232.             $game_system.message.allow_cancel_numbers
  2233.         # play cancel sound effect
  2234.         $game_system.se_play($data_system.cancel_se)
  2235.         # Allows windows to be closed
  2236.         $game_temp.input_in_window = false
  2237.         # Set Variable to identify the Number Window was Cancelled
  2238.         $game_system.number_cancelled = true
  2239.         # Dispose of number input window
  2240.         @input_number_window.dispose
  2241.         @input_number_window = nil        
  2242.         if $scene.message_window.size > 1
  2243.           for msg in $scene.message_window
  2244.             msg.terminate_message
  2245.           end
  2246.         else
  2247.           terminate_message
  2248.         end
  2249.       end
  2250.       # prevent terminating windows and destroying variables
  2251.       return
  2252.     end
  2253.     # If message is being displayed
  2254.     if @contents_showing
  2255.       # Confirm or cancel finishes waiting for input or message
  2256.       if Input.trigger?(Input::C) or Input.trigger?(Input::B)
  2257.         if @wait_for_input
  2258.           @wait_for_input = false
  2259.           self.pause = false
  2260.         elsif $game_system.message.skippable
  2261.           @player_skip = true
  2262.         end
  2263.         # Dont close the window if waiting for choices to be displayed
  2264.         if $game_temp.input_in_window and
  2265.            $game_temp.message_text.compact.size > 1 and
  2266.            not $input_window_wait
  2267.           # wait until next input to confirm any choices
  2268.           $input_window_wait = true
  2269.           return
  2270.         else
  2271.           $input_window_wait = false          
  2272.         end
  2273.       end      
  2274.       if need_reposition?
  2275.         reposition # update message position for character/screen movement
  2276.         if @contents_showing == false
  2277.           # i.e. if char moved off screen
  2278.           return
  2279.         end
  2280.       end
  2281.       if @update_text and !@wait_for_input
  2282.         if @delay == 0
  2283.           update_text
  2284.         else
  2285.           @delay -= 1
  2286.         end
  2287.         return
  2288.       end
  2289.  
  2290.       # If choice isn't being displayed, show pause sign
  2291.       if !self.pause and ($game_temp.choice_max == 0 or @wait_for_input)
  2292.         self.pause = true unless !$game_system.message.show_pause
  2293.       end
  2294.       # Cancel
  2295.       if Input.trigger?(Input::B)
  2296.         if $game_temp.choice_max > 0 and $game_temp.choice_cancel_type > 0
  2297.           # Allow ALL windows to be closed
  2298.           $game_temp.input_in_window = false
  2299.           # Play Sound Effect
  2300.           $game_system.se_play($data_system.cancel_se)
  2301.           # Process the Choice
  2302.           $game_temp.choice_proc.call($game_temp.choice_cancel_type - 1)
  2303.           # If multi window cancel choice
  2304.           if $scene.message_window.size > 1
  2305.             for msg in $scene.message_window
  2306.               msg.terminate_message
  2307.             end
  2308.           else
  2309.             terminate_message
  2310.           end
  2311.         end
  2312.         # personal preference: cancel button should also continue
  2313.         terminate_message
  2314.       end
  2315.       # Confirm
  2316.       if Input.trigger?(Input::C)
  2317.         # Allow ALL windows to be closed
  2318.         $game_temp.input_in_window = false
  2319.         # if choice is displayed in one of multiple windows        
  2320.         if $game_temp.choice_max > 0
  2321.           if $scene.message_window.size > 1
  2322.             for i in 0...$scene.message_window.size
  2323.               if $scene.message_window[i].choice_window
  2324.                 # return selection position by index of the choice window
  2325.                 @index = $scene.message_window[i].index
  2326.               end
  2327.             end
  2328.           end          
  2329.           $game_system.se_play($data_system.decision_se)
  2330.           $game_temp.choice_proc.call(self.index)
  2331.         end
  2332.         # If Preceeding Window not closed because choice displayed
  2333.         if $scene.message_window.size > 1
  2334.           choice = false
  2335.           for i in 0...$scene.message_window.size
  2336.             if $scene.message_window[i].choice_window
  2337.               choice = true
  2338.               break
  2339.             end
  2340.           end
  2341.           # If window is a choice window and other windows held open
  2342.           if choice
  2343.             # close all the message windows
  2344.             for msg in $scene.message_window
  2345.               msg.terminate_message
  2346.             end
  2347.           else
  2348.             # close the single message window            
  2349.             terminate_message
  2350.           end
  2351.         else
  2352.           if $game_temp.choice_max > 0
  2353.             $game_system.se_play($data_system.decision_se)
  2354.             $game_temp.choice_proc.call(self.index)
  2355.           end
  2356.           terminate_message
  2357.           end
  2358.         end
  2359.       return      
  2360.     end
  2361.     # If display wait message or choice exists when not fading out
  2362.     if @fade_out == false and $game_temp.message_text[@msgindex] != nil
  2363.       @contents_showing = true
  2364.       $game_temp.message_window_showing = true
  2365.       reset_window
  2366.       refresh
  2367.       Graphics.frame_reset
  2368.       self.visible = true
  2369.       if show_message_tail?
  2370.         @tail.visible = true
  2371.       elsif @tail.visible
  2372.         @tail.visible = false
  2373.       end
  2374.       self.contents_opacity = 0
  2375.       if @input_number_window != nil
  2376.         @input_number_window.contents_opacity = 0
  2377.       end
  2378.       @fade_in = true
  2379.       return
  2380.     end
  2381.     # If message which should be displayed is not shown, but window is visible
  2382.     if self.visible
  2383.       @fade_out = true
  2384.       self.opacity -= 96
  2385.       @tail.opacity -= 96 if @tail.opacity > 0
  2386.       if need_reposition?
  2387.         # update message position for character/screen movement        
  2388.         reposition
  2389.       end
  2390.       if self.opacity == 0
  2391.         self.visible = false
  2392.         @fade_out = false
  2393.         @tail.visible = false if @tail.visible
  2394.         # have to check all windows before claiming that no window is showing
  2395.         if $game_temp.message_text.compact.empty?
  2396.           $game_temp.message_window_showing = false  
  2397.         end
  2398.       end
  2399.       return
  2400.     end
  2401.   end
  2402.  
  2403.   #--------------------------------------------------------------------------
  2404.   # * Repositioning Determination
  2405.   #--------------------------------------------------------------------------
  2406.   def need_reposition?
  2407.     if !$game_temp.in_battle and $game_system.message.floating and
  2408.         $game_system.message.resize and @float_id != nil
  2409.       if $game_system.message.move_during and @float_id == 0 and
  2410.           (($game_player.last_real_x != $game_player.real_x) or
  2411.           ($game_player.last_real_y != $game_player.real_y))
  2412.           # player with floating message moved
  2413.           # (note that relying on moving? leads to "jumpy" message boxes)
  2414.           return true
  2415.       elsif ($game_map.last_display_y != $game_map.display_y) or
  2416.          ($game_map.last_display_x != $game_map.display_x)
  2417.         # player movement or scroll event caused the screen to scroll
  2418.         return true
  2419.       else
  2420.         char = $game_map.events[@float_id]
  2421.         if char != nil and
  2422.           ((char.last_real_x != char.real_x) or
  2423.           (char.last_real_y != char.real_y))
  2424.           # character moved
  2425.           return true
  2426.         end
  2427.       end    
  2428.     end
  2429.     return false
  2430.   end
  2431.  
  2432.   #--------------------------------------------------------------------------
  2433.   # * Show Message Tail Determination
  2434.   #--------------------------------------------------------------------------
  2435.   def show_message_tail?
  2436.     if $game_system.message.show_tail and $game_system.message.floating and
  2437.       $game_system.message.resize and $game_system.message_frame == 0 and
  2438.       @float_id != nil
  2439.       return true
  2440.     end
  2441.     return false
  2442.   end
  2443.  
  2444.   def update_cursor_rect
  2445.     if @index >= 0
  2446.       n = $game_temp.choice_start + @index
  2447.       if $game_system.message.autocenter
  2448.         x = 4 + (self.width-40)/2 - @cursor_width/2
  2449.       else
  2450.         x = 8
  2451.       end
  2452.       self.cursor_rect.set(x, n * 32, @cursor_width, 32)
  2453.     else
  2454.       self.cursor_rect.empty
  2455.     end
  2456.   end
  2457.  
  2458. end
  2459.  
  2460. #------------------------------------------------------------------------------
  2461.  
  2462. class Game_Character
  2463.   attr_reader   :last_real_x         # last map x-coordinate
  2464.   attr_reader   :last_real_y         # last map y-coordinate
  2465.   attr_accessor :move_frequency      # allows resetting if interrupted
  2466.   attr_accessor :allow_flip          # if event was triggered by player
  2467.   attr_accessor :preferred_loc       # triggered after Msg Reposition
  2468.  
  2469.   alias heretic_game_ch_mmw_initialize initialize
  2470.   def initialize
  2471.     # Original
  2472.     heretic_game_ch_mmw_initialize
  2473.     # Used with Flip and Sticky Options...
  2474.     @preferred_loc = nil
  2475.   end
  2476.  
  2477.   alias wachunga_game_char_update update
  2478.   def update
  2479.     @last_real_x = @real_x
  2480.     @last_real_y = @real_y
  2481.     wachunga_game_char_update
  2482.   end
  2483.  
  2484.   def within_range?(range = 4, id = @event_id)
  2485.     e = $game_map.events[id]
  2486.     radius = (Math.hypot((e.x - $game_player.x), (e.y - $game_player.y))).abs
  2487.     #BAWLZ
  2488.     return (range >= radius)
  2489.   end  
  2490.  
  2491.   #----------------------------------------------------------------------------
  2492.   # * Allows Animation Change regardless of Direction
  2493.   #----------------------------------------------------------------------------
  2494.  
  2495.   unless self.method_defined?('foot_forward_on')  
  2496.     def foot_forward_on(frame = 0)
  2497.       return if @direction_fix or !@walk_anime or @step_anime or
  2498.                 $game_temp.in_battle
  2499.       if frame == 0
  2500.         case @direction
  2501.         when 2
  2502.           @pattern = 3
  2503.         when 4, 6, 8
  2504.           @pattern = 1
  2505.         else
  2506.           @pattern = 0
  2507.         end
  2508.         @original_pattern = @pattern
  2509.         refresh
  2510.       elsif frame == 1
  2511.         case @direction
  2512.         when 2
  2513.           @pattern = 1
  2514.           when 4, 6, 8
  2515.           @pattern = 3
  2516.         else
  2517.           @pattern = 0
  2518.         end
  2519.         @original_pattern = @pattern
  2520.         refresh
  2521.       end
  2522.     end
  2523.  
  2524.     def foot_forward_off
  2525.       # If called by walking off screen, dont affect a Sign or Stepping Actor
  2526.       return if $game_temp.in_battle or @direction_fix or !@walk_anime or @no_ff
  2527.       @pattern, @original_pattern = 0, 0
  2528.     end
  2529.   end
  2530.    
  2531.   # Call from Event Editor => Scripts
  2532.   # DO NOT call from Set Move Route => Scripts
  2533.   def event_move_continue(event_id, valid = false, alt = false)
  2534.     # return if Event has a No 'M'ove 'C'ontinue flag
  2535.     return if @no_mc
  2536.     # Restore Original Move Route if Event went off the screen while talking
  2537.     # This may be buggy if multiple event pages are used
  2538.     if @ff_original_move_route != nil and valid
  2539.       # Release forced move route
  2540.       @move_route_forcing = false
  2541.       # Restore original values        
  2542.       @move_speed = @ff_original_move_speed
  2543.       @move_frequency = @ff_original_move_frequency
  2544.       @move_route = @ff_original_move_route
  2545.       @move_route_index = @ff_original_move_route_index
  2546.       # Release storing variables
  2547.       @ff_original_move_index = nil
  2548.       @ff_original_move_speed = nil
  2549.       @ff_original_move_frequency = nil
  2550.       @ff_original_move_route = nil
  2551.       @original_move_route = nil
  2552.       @original_move_route_index = nil
  2553.     elsif @original_move_route != nil and valid and alt
  2554.       # Release forced move route
  2555.       @move_route_forcing = false      
  2556.       @move_route = @original_move_route
  2557.       @move_route_index = @original_move_route_index
  2558.       @original_move_route = nil
  2559.       @original_move_route_index = nil      
  2560.     end
  2561.   end
  2562.  
  2563.   unless self.method_defined?('heretic_mmw_lock')
  2564.     alias heretic_mmw_lock lock
  2565.     alias heretic_mmw_unlock unlock
  2566.   end    
  2567.    
  2568.   def lock
  2569.     # Call Original
  2570.     heretic_mmw_lock
  2571.     # Store Movement Variables in case player walks away
  2572.     @ff_original_move_route_index = @move_route_index
  2573.     @ff_original_move_speed = @move_speed
  2574.     @ff_original_move_frequency = @move_frequency
  2575.     @ff_original_move_route = @move_route
  2576.     # Store Variable that Event was Triggered by Player
  2577.     @allow_flip = true
  2578.   end
  2579.    
  2580.   def unlock
  2581.     # Call Original
  2582.     heretic_mmw_unlock
  2583.     # Unset Variable that Event was Triggered by Player
  2584.     @allow_flip = false
  2585.     @preferred_loc = nil
  2586.     # Reset Player as well...
  2587.     $game_player.allow_flip = false
  2588.     $game_player.preferred_loc = nil
  2589.     $game_player.sticky = false
  2590.    
  2591.     # Unset any possible dist kill flags
  2592.     if $game_temp.message_text.compact.empty?
  2593.       $game_map.events[@id].dist_kill = nil if @id
  2594.       $game_system.map_interpreter.max_dist_id = nil
  2595.     end
  2596.  
  2597.     # Reset Choice Index
  2598.     $choice_index = 0    
  2599.    
  2600.     # Loads the Default Sound Settings at the End of Event Interaction
  2601.     $game_system.message.load_sound_settings if $game_system.message.sound
  2602.   end
  2603.  
  2604. end
  2605.  
  2606. #------------------------------------------------------------------------------
  2607.  
  2608. class Game_Player < Game_Character
  2609.  
  2610.   attr_accessor :sticky  # Used for Positioning Msg Bubbles
  2611.  
  2612.   alias wachunga_mmw_game_player_update update
  2613.   def update
  2614.    # The conditions are changed so the player can move around while messages
  2615.    # are showing (if move_during is true), but not if user is making a
  2616.    # choice or inputting a number
  2617.    # Note that this check overrides the default one (later in the method)
  2618.    # because it is more general
  2619.     unless moving? or
  2620.       @move_route_forcing or
  2621.       ($game_system.map_interpreter.running? and
  2622.       !$game_temp.message_window_showing) or
  2623.       ($game_temp.message_window_showing and
  2624.       !$game_system.message.move_during) or
  2625.       ($game_temp.choice_max > 0 or $game_temp.num_input_digits_max > 0)
  2626.       update_player_movement
  2627.     end
  2628.     wachunga_mmw_game_player_update    
  2629.   end
  2630.  
  2631. end
  2632.  
  2633. #------------------------------------------------------------------------------
  2634.  
  2635. class Game_Temp
  2636.   alias wachunga_mmw_game_temp_initialize initialize
  2637.   def initialize
  2638.     wachunga_mmw_game_temp_initialize
  2639.     @message_text = []
  2640.     @message_proc = []
  2641.   end
  2642. end
  2643.  
  2644. #------------------------------------------------------------------------------
  2645.  
  2646. class Sprite_Battler < RPG::Sprite
  2647.   # necessary for positioning messages relative to battlers
  2648.   attr_reader :height
  2649.   attr_reader :width
  2650. end
  2651.  
  2652. #------------------------------------------------------------------------------
  2653.  
  2654. class Scene_Battle
  2655.   # necessary for accessing actor/enemy sprites in battle
  2656.   attr_reader :spriteset
  2657. end
  2658.  
  2659. #------------------------------------------------------------------------------
  2660.  
  2661. class Spriteset_Battle
  2662.   # necessary for accessing actor/enemy sprites in battle
  2663.   attr_reader :actor_sprites
  2664.   attr_reader :enemy_sprites
  2665. end
  2666.  
  2667. #------------------------------------------------------------------------------
  2668.  
  2669. class Scene_Map
  2670.   attr_reader :message_window
  2671.   #--------------------------------------------------------------------------
  2672.   # * Scene_Map - New Message Window Addition
  2673.   #--------------------------------------------------------------------------
  2674.   def new_message_window(index)
  2675.     if @message_window[index] != nil
  2676.       # clear message windows at and after this index
  2677.       last_index = @message_window.size - 1
  2678.       last_index.downto(index) do |i|
  2679.         if @message_window[i] != nil
  2680.           @message_window[i].dispose
  2681.           @message_window[i] = nil
  2682.         end
  2683.       end
  2684.       @message_window.compact!
  2685.     end
  2686.     new_message = Window_Message.new(index)
  2687.     @message_window.push(new_message)
  2688.   end
  2689.  
  2690. end
  2691.  
  2692. #------------------------------------------------------------------------------
  2693.  
  2694. class Scene_Battle
  2695.   attr_reader :message_window  
  2696.   #--------------------------------------------------------------------------
  2697.   # * Scene_Battle - New Message Window Addition
  2698.   #--------------------------------------------------------------------------
  2699.   def new_message_window(index)
  2700.     if @message_window[index] != nil
  2701.       # clear message windows at and after this index
  2702.       last_index = @message_window.size - 1
  2703.       last_index.downto(index) do |i|
  2704.         if @message_window[i] != nil
  2705.           @message_window[i].dispose
  2706.           @message_window[i] = nil
  2707.         end
  2708.       end
  2709.       @message_window.compact!
  2710.     end
  2711.     @message_window.push(Window_Message.new(index))
  2712.   end
  2713.  
  2714. end
  2715.  
  2716. #------------------------------------------------------------------------------
  2717.  
  2718. class Game_System
  2719.   attr_accessor  :number_cancelled   # Allows detection if a Number Input Cancel
  2720.   attr_accessor  :mmw_text           # Holds Strings to show in Msgs \v[Tn]
  2721.   attr_reader    :message            # Shortcut, allows message without $game_
  2722.  
  2723.   alias wachunga_mmw_game_system_init initialize
  2724.   def initialize
  2725.     wachunga_mmw_game_system_init
  2726.     @message = Game_Message.new
  2727.     # allows detection if a Number Input was Cancelled
  2728.     @number_cancelled = false
  2729.     # Holds Strings to show in Msgs
  2730.     @mmw_text = []
  2731.   end
  2732. end
  2733.  
  2734. #------------------------------------------------------------------------------
  2735.  
  2736. class Interpreter
  2737.   attr_reader   :event_id
  2738.   attr_reader   :list
  2739.   attr_accessor :index
  2740.   attr_accessor :max_dist_id
  2741.  
  2742.   alias wachunga_mmw_interp_setup setup
  2743.   def setup(list, event_id)
  2744.     wachunga_mmw_interp_setup(list, event_id)
  2745.     # index of window for the message
  2746.     @msgindex = 0
  2747.     # whether multiple messages are displaying
  2748.     @multi_message = false
  2749.     # Id of Event that is using set_max_dist
  2750.     @max_dist_id = nil
  2751.   end
  2752.  
  2753.   def setup_choices(parameters)
  2754.     # Set Select Window to Active
  2755.     $scene.message_window[@msgindex].active = true
  2756.     # Set choice item count to choice_max
  2757.     $game_temp.choice_max = parameters[0].size
  2758.     # Set choice to message_text
  2759.     for text in parameters[0]
  2760.       # just add index for array
  2761.       $game_temp.message_text[@msgindex] += text + "\n"
  2762.     end
  2763.     # Set cancel processing
  2764.     $game_temp.choice_cancel_type = parameters[1]
  2765.     # Set callback
  2766.     current_indent = @list[@index].indent
  2767.     $game_temp.choice_proc = Proc.new { |n| @branch[current_indent] = n }
  2768.   end
  2769.  
  2770.   # Not sure if this will be useful, leaving undocumented for now
  2771.   def event_move_continue(event_id)
  2772.     $game_map.events[event_id].event_move_continue(event_id, true)
  2773.   end  
  2774.  
  2775.   def number_cancelled?
  2776.     return $game_system.number_cancelled
  2777.   end
  2778.  
  2779.   def set_multi
  2780.     # Setting these two variables causes the Next Message to be displayed.
  2781.     @multi_message = true
  2782.     @message_waiting = false
  2783.   end
  2784.  
  2785.   #--------------------------------------------------------------------------
  2786.   # * Show Text
  2787.   #--------------------------------------------------------------------------
  2788.   def command_101
  2789.     # If other text has been set to message_text
  2790.     if $game_temp.message_text[@msgindex] != nil
  2791.       if @multi_message
  2792.         @msgindex += 1
  2793.         $scene.new_message_window(@msgindex)
  2794.       else
  2795.         # End
  2796.         return false
  2797.       end
  2798.     end
  2799.     @msgindex = 0 if !@multi_message
  2800.     @multi_message = false
  2801.     # Set message end waiting flag and callback
  2802.     @message_waiting = true
  2803.     # just adding indexes
  2804.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  2805.     # Set message text on first line
  2806.     $game_temp.message_text[@msgindex] = @list[@index].parameters[0] + "\n"
  2807.     # Start Message on Line 1
  2808.     line_count = 1
  2809.     # Loop
  2810.     loop do
  2811.       # If next event command text is on the second line or after
  2812.       if @list[@index+1].code == 401
  2813.         # Add the second line or after to message_text
  2814.         # just adding index
  2815.         $game_temp.message_text[@msgindex]+=@list[@index+1].parameters[0]+"\n"
  2816.         line_count += 1
  2817.       # If event command is not on the second line or after
  2818.       else
  2819.         # If next event command is show choices
  2820.         if @list[@index+1].code == 102
  2821.           # If choices fit on screen
  2822.           if @list[@index+1].parameters[0].size <= 4 - line_count
  2823.             # Prevent the closure of a single window with multiple windows
  2824.             $game_temp.input_in_window = true            
  2825.             # Flag this window as having choices displayed for multi
  2826.             $scene.message_window[@msgindex].choice_window = @msgindex
  2827.             # Advance index
  2828.             @index += 1
  2829.             # Choices setup
  2830.             $game_temp.choice_start = line_count
  2831.             setup_choices(@list[@index].parameters)
  2832.           end
  2833.         # If next event command is input number
  2834.         elsif @list[@index+1].code == 103
  2835.           # If number input window fits on screen
  2836.           if line_count < 4
  2837.             # Prevent the closure of a single window with multiple windows
  2838.             $game_temp.input_in_window = true
  2839.             # Flag this window as having choices displayed
  2840.             $scene.message_window[@msgindex].choice_window = @msgindex
  2841.             # Advance index
  2842.             @index += 1
  2843.             # Number input setup
  2844.             $game_temp.num_input_start = line_count
  2845.             $game_temp.num_input_variable_id = @list[@index].parameters[0]
  2846.             $game_temp.num_input_digits_max = @list[@index].parameters[1]
  2847.             $game_temp.num_input_variable_id_backup =
  2848.               @list[@index].parameters[0]
  2849.           end
  2850.         # start multimessage if next line is "Show Text" starting with "\+"
  2851.         elsif @list[@index+1].code == 101
  2852.           if @list[@index+1].parameters[0][0..1]=="\\+"
  2853.             @multi_message = true
  2854.             @message_waiting = false
  2855.           end
  2856.         end
  2857.         # Continue
  2858.         return true
  2859.       end
  2860.       # Advance index
  2861.       @index += 1
  2862.     end
  2863.   end
  2864.  
  2865.   #--------------------------------------------------------------------------
  2866.   # * Show Choices
  2867.   #--------------------------------------------------------------------------
  2868.   def command_102
  2869.     # Prevent the closure of a single window with multiple windows
  2870.     $game_temp.input_in_window = true
  2871.     # Flag this window as having choices displayed for multi
  2872.     $scene.message_window[@msgindex].choice_window = @msgindex    
  2873.     # If text has been set to message_text
  2874.     # just adding index
  2875.     if $game_temp.message_text[@msgindex] != nil
  2876.       # End
  2877.       return false
  2878.     end
  2879.     # Set message end waiting flag and callback
  2880.     @message_waiting = true
  2881.     # adding more indexes
  2882.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  2883.     # Choices setup
  2884.     $game_temp.message_text[@msgindex] = ""
  2885.     $game_temp.choice_start = 0
  2886.     setup_choices(@parameters)
  2887.     # Continue
  2888.     return true
  2889.   end
  2890.  
  2891.   #--------------------------------------------------------------------------
  2892.   # * Input Number
  2893.   #--------------------------------------------------------------------------
  2894.   def command_103
  2895.     # Prevent the closure of a single window with multiple windows
  2896.     $game_temp.input_in_window = true
  2897.     # Flag this window as having choices displayed
  2898.     $scene.message_window[@msgindex].choice_window = @msgindex    
  2899.     # If text has been set to message_text
  2900.     # just adding index
  2901.     if $game_temp.message_text[@msgindex] != nil
  2902.       # End
  2903.       return false
  2904.     end
  2905.     # Set message end waiting flag and callback
  2906.     @message_waiting = true
  2907.     # adding more indexes
  2908.     $game_temp.message_proc[@msgindex] = Proc.new { @message_waiting = false }
  2909.     # Number input setup
  2910.     $game_temp.message_text[@msgindex] = ""
  2911.     $game_temp.num_input_start = 0
  2912.     $game_temp.num_input_variable_id = @parameters[0]
  2913.     $game_temp.num_input_digits_max = @parameters[1]
  2914.     $game_temp.num_input_variable_id_backup = @list[@index].parameters[0]
  2915.     # Continue
  2916.     return true
  2917.   end
  2918.  
  2919.   #--------------------------------------------------------------------------
  2920.   # * Script
  2921.   #--------------------------------------------------------------------------
  2922.   # Fix for RMXP bug: call script boxes that return false hang the game
  2923.   # See, e.g., http://rmxp.org/forums/showthread.php?p=106639  
  2924.   #--------------------------------------------------------------------------
  2925.   def command_355
  2926.     # Set first line to script
  2927.     script = @list[@index].parameters[0] + "\n"
  2928.     # Loop
  2929.     loop do
  2930.       # If next event command is second line of script or after
  2931.       if @list[@index+1].code == 655
  2932.         # Add second line or after to script
  2933.         script += @list[@index+1].parameters[0] + "\n"
  2934.       # If event command is not second line or after
  2935.       else
  2936.         # Abort loop
  2937.         break
  2938.       end
  2939.       # Advance index
  2940.       @index += 1
  2941.     end
  2942.     # Evaluation
  2943.     result = eval(script)
  2944.     # If return value is false
  2945.     if result == false
  2946.       # End
  2947.       #return false
  2948.     end
  2949.     # Continue
  2950.     return true
  2951.   end
  2952.  
  2953.   def message
  2954.     $game_system.message
  2955.   end
  2956.  
  2957.   def within_range?(range = 4, id = @event_id)
  2958.     e = $game_map.events[id]
  2959.     radius = (Math.hypot((e.x - $game_player.x), (e.y - $game_player.y))).abs
  2960.     return (radius <= range)
  2961.   end
  2962.  
  2963.   unless self.method_defined?('heretic_mmw_command_209')
  2964.     alias heretic_mmw_command_202 command_202
  2965.     alias heretic_mmw_command_209 command_209
  2966.   end
  2967.  
  2968.   #--------------------------------------------------------------------------
  2969.   # * Set Event Location
  2970.   #--------------------------------------------------------------------------
  2971.   def command_202
  2972.     # Run the Original
  2973.     heretic_mmw_command_202
  2974.     # Get character
  2975.     character = get_character(@parameters[0])
  2976.     # If no character exists, Player is still checked...
  2977.     if character == nil
  2978.       # Continue
  2979.       return true
  2980.     end
  2981.     if @event_id != 0
  2982.       $game_map.events[@event_id].allow_flip = false
  2983.       $game_map.events[@event_id].preferred_loc = nil
  2984.     end
  2985.     # Return that the command has run...
  2986.     return true
  2987.   end
  2988.   #--------------------------------------------------------------------------
  2989.   # * Set Move Route
  2990.   #--------------------------------------------------------------------------
  2991.   def command_209
  2992.     # Run the Original
  2993.     heretic_mmw_command_209
  2994.     # Get character
  2995.     character = get_character(@parameters[0])
  2996.     # If no character exists, Player is still checked...
  2997.     if character == nil
  2998.       # Continue
  2999.       return true
  3000.     end
  3001.     if @parameters[1]
  3002.       # Any Movement Related Commands, Turn Commands and Others are Ignored
  3003.       codes = *[1..14]
  3004.       # Scripts from Caterpillar that cause Movement in NPC's
  3005.       commands = ['move_toward_event','move_away_from_event']
  3006.       # Check the List of Move Commands to see if they are Movement Related...
  3007.       for command in @parameters[1].list
  3008.         if codes.include?(command.code) and @event_id != 0
  3009.           $game_map.events[@event_id].allow_flip = false
  3010.           $game_map.events[@event_id].preferred_loc = nil          
  3011.           # quit iterating
  3012.           return true
  3013.         elsif command.code == 45
  3014.           script = command.parameters[0]
  3015.           for string in commands
  3016.             found = false
  3017.             script.sub(string) {found = true}
  3018.             if found and @event_id != 0
  3019.               $game_map.events[@event_id].allow_flip = false if found
  3020.               $game_map.events[@event_id].preferred_loc = nil if found
  3021.               # quit iterating
  3022.               return true
  3023.             end
  3024.           end
  3025.         end
  3026.       end
  3027.     end
  3028.   end    
  3029.  
  3030.   def set_max_dist(dist)
  3031.     return if not $scene.is_a?(Scene_Map)
  3032.     $game_map.events[@event_id].dist_kill = dist if dist.is_a?(Numeric)
  3033.     # If Max Distance is 0 and Location is NOT Passable when triggered
  3034.     if $game_map.events[@event_id].dist_kill == 0 and
  3035.        (!$game_map.passable?($game_map.events[@event_id].x,
  3036.                            $game_map.events[@event_id].y,
  3037.                            0) or
  3038.        ($game_map.events[@event_id].character_name != "" and
  3039.        !$game_map.events[@event_id].through))
  3040.       # Bump it up to 1 because 0 doesnt work for non passable triggers
  3041.       $game_map.events[@event_id].dist_kill = 1
  3042.     end
  3043.    
  3044.     # Prevent closing at a distance for other NPC's that might be speaking...
  3045.     @max_dist_id = event_id
  3046.     # Save MMW Configuration in case of a Walk Away...
  3047.     save_mmw_vars
  3048.   end
  3049.  
  3050.   def save_mmw_vars
  3051.     # Window Skin
  3052.     @windowskin_name_save = $game_system.windowskin_name
  3053.     # MMW Variables
  3054.     @mmw_vars_saved = true
  3055.     @mmw_letter_by_letter = $game_system.message.letter_by_letter
  3056.     @mmw_text_speed = $game_system.message.text_speed
  3057.     @mmw_text_speed_player = $game_system.message.text_speed_player
  3058.     @mmw_skippable = $game_system.message.skippable
  3059.     @mmw_resize = $game_system.message.resize
  3060.     @mmw_floating = $game_system.message.floating
  3061.     @mmw_autocenter = $game_system.message.autocenter
  3062.     @mmw_show_tail = $game_system.message.show_tail
  3063.     @mmw_show_pause = $game_system.message.show_pause
  3064.     @mmw_move_during = $game_system.message.move_during
  3065.     @mmw_location = $game_system.message.location
  3066.     @mmw_font_name = $game_system.message.font_name
  3067.     @mmw_font_size = $game_system.message.font_size
  3068.     @mmw_font_color = $game_system.message.font_color
  3069.     @mmw_auto_comma_pause = $game_system.message.auto_comma_pause
  3070.     @mmw_auto_comma_delay = $game_system.message.auto_comma_delay
  3071.     @mmw_allow_cancel_numbers = $game_system.message.allow_cancel_numbers
  3072.     @mmw_update_text_while_fading=$game_system.message.update_text_while_fading
  3073.     @mmw_auto_ff_reset = $game_system.message.auto_ff_reset
  3074.     @mmw_auto_move_continue = $game_system.message.auto_move_continue
  3075.     @mmw_dist_exit = $game_system.message.dist_exit
  3076.     @mmw_dist_max = $game_system.message.dist_max
  3077.     @mmw_allow_offscreen = $game_system.message.allow_offscreen
  3078.     @mmw_reposition_on_turn = $game_system.message.reposition_on_turn
  3079.     @mmw_sticky = $game_system.message.sticky
  3080.     # Sound Stuff
  3081.     @mmw_sound = $game_system.message.sound
  3082.     @mmw_sound_volume = $game_system.message.sound_volume
  3083.     @mmw_sound_pitch = $game_system.message.sound_pitch
  3084.     @mmw_sound_pitch_range = $game_system.message.sound_pitch_range
  3085.     @mmw_sound_vary_pitch = $game_system.message.sound_vary_pitch
  3086.     @mmw_sound_frequency = $game_system.message.sound_frequency    
  3087.   end
  3088.  
  3089.   def restore_mmw_vars
  3090.     if @mmw_vars_saved
  3091.      # Windowskin - Used with Different Backgrounds on Signs
  3092.      $game_system.windowskin_name = @windowskin_name_save
  3093.      # MMW Variables
  3094.      $game_system.message.letter_by_letter = @mmw_letter_by_letter
  3095.      $game_system.message.text_speed = @mmw_text_speed
  3096.      $game_system.message.text_speed_player = @mmw_text_speed_player
  3097.      $game_system.message.skippable = @mmw_skippable
  3098.      $game_system.message.resize = @mmw_resize
  3099.      $game_system.message.floating = @mmw_floating
  3100.      $game_system.message.autocenter = @mmw_autocenter
  3101.      $game_system.message.show_tail = @mmw_show_tail
  3102.      $game_system.message.show_pause = @mmw_show_pause
  3103.      $game_system.message.move_during = @mmw_move_during
  3104.      $game_system.message.location = @mmw_location
  3105.      $game_system.message.font_name = @mmw_font_name
  3106.      $game_system.message.font_size = @mmw_font_size
  3107.      $game_system.message.font_color = @mmw_font_color
  3108.      $game_system.message.auto_comma_pause = @mmw_auto_comma_pause
  3109.      $game_system.message.auto_comma_delay = @mmw_auto_comma_delay
  3110.      $game_system.message.allow_cancel_numbers = @mmw_allow_cancel_numbers
  3111.      $game_system.message.update_text_while_fading=@mmw_update_text_while_fading
  3112.      $game_system.message.auto_ff_reset = @mmw_auto_ff_reset
  3113.      $game_system.message.auto_move_continue = @mmw_auto_move_continue
  3114.      $game_system.message.dist_exit = @mmw_dist_exit
  3115.      $game_system.message.dist_max = @mmw_dist_max
  3116.      $game_system.message.allow_offscreen = @mmw_allow_offscreen
  3117.      $game_system.message.reposition_on_turn  = @mmw_reposition_on_turn
  3118.      $game_system.message.sticky = @mmw_sticky
  3119.      # Sound Stuff
  3120.      $game_system.message.sound = @mmw_sound
  3121.      $game_system.message.sound_volume = @mmw_sound_volume
  3122.      $game_system.message.sound_pitch = @mmw_sound_pitch
  3123.      $game_system.message.sound_pitch_range = @mmw_sound_pitch_range
  3124.      $game_system.message.sound_vary_pitch=@mmw_sound_vary_pitch
  3125.      $game_system.message.sound_frequency = @mmw_sound_frequency
  3126.     end
  3127.   end  
  3128. end
  3129.  
  3130. #------------------------------------------------------------------------------
  3131.  
  3132. class Game_Map
  3133.   attr_accessor :last_display_x                # last display x-coord * 128
  3134.   attr_accessor :last_display_y                # last display y-coord * 128
  3135.  
  3136.   alias wachunga_mmw_game_map_update update
  3137.   def update
  3138.     @last_display_x = @display_x
  3139.     @last_display_y = @display_y
  3140.     wachunga_mmw_game_map_update
  3141.   end
  3142.  
  3143.   # This was removed because it requires the SDK
  3144.  
  3145.   #def name
  3146.   #  return load_data('Data/MapInfos.rxdata')[@map_id].name
  3147.   #end
  3148.  
  3149.   # Removes some of the need for the SDK
  3150.  
  3151.   # NOTE:  This is also defined in Caterpillar, which doesnt require the SDK
  3152.  
  3153.   #----------------
  3154.   # * Name
  3155.   #----------------
  3156.   @@map_info = load_data("Data/MapInfos.rxdata")
  3157.  
  3158.   def name(id = @map_id)
  3159.     return @@map_info[id].name
  3160.   end
  3161.  
  3162. end
  3163.  
  3164. #------------------------------------------------------------------------------
  3165.  
  3166. # Note:  I know this is a crappy way to do it, but I cant figure out another
  3167. #  way to prevent the loss of data when showing a number input with multiple
  3168. #  windows being displayed.  It destroys the data before it can call the data
  3169. #  so just creating a backup of that data.  It works, thats all I care.
  3170.  
  3171. class Game_Temp
  3172.   attr_accessor :num_input_variable_id_backup  # prevents variable loss
  3173.   attr_accessor :input_in_window               # prevents window closures
  3174.  
  3175.   #--------------------------------------------------------------------------
  3176.   # * Object Initialization
  3177.   #--------------------------------------------------------------------------
  3178.   unless self.method_defined?('heretic_number_window_backup_initialize')
  3179.     alias heretic_number_window_backup_initialize initialize
  3180.   end
  3181.  
  3182.   def initialize
  3183.     # Call Original
  3184.     heretic_number_window_backup_initialize
  3185.     @num_input_variable_id_backup = 0
  3186.     @input_in_window = false
  3187.   end
  3188. end
  3189.  
  3190. #------------------------------------------------------------------------------
  3191.  
  3192. class Bitmap
  3193.  
  3194.   attr_accessor :orientation
  3195.  
  3196.   #--------------------------------------------------------------------------
  3197.   # * Rotation Calculation
  3198.   #--------------------------------------------------------------------------
  3199.   def rotation(target)
  3200.     return if not [0, 90, 180, 270].include?(target) # invalid orientation
  3201.     if @rotation != target
  3202.       degrees = target - @orientation
  3203.       if degrees < 0
  3204.         degrees += 360
  3205.       end
  3206.       rotate(degrees)
  3207.     end    
  3208.   end
  3209.  
  3210.   #--------------------------------------------------------------------------
  3211.   # * Rotate Square (Clockwise)
  3212.   #--------------------------------------------------------------------------
  3213.   def rotate(degrees = 90)
  3214.     # method originally by SephirothSpawn
  3215.     # would just use Sprite.angle but its rotation is buggy
  3216.     # (see http://www.rmxp.org/forums/showthread.php?t=12044)
  3217.     return if not [90, 180, 270].include?(degrees)
  3218.     copy = self.clone
  3219.     if degrees == 90
  3220.       # Passes Through all Pixels on Dummy Bitmap
  3221.       for i in 0...self.height
  3222.         for j in 0...self.width
  3223.           self.set_pixel(width - i - 1, j, copy.get_pixel(j, i))
  3224.         end
  3225.       end
  3226.     elsif degrees == 180
  3227.       for i in 0...self.height
  3228.         for j in 0...self.width
  3229.           self.set_pixel(width - j - 1, height - i - 1, copy.get_pixel(j, i))
  3230.         end
  3231.       end      
  3232.     elsif degrees == 270
  3233.       for i in 0...self.height
  3234.         for j in 0...self.width
  3235.           self.set_pixel(i, height - j - 1, copy.get_pixel(j, i))
  3236.         end
  3237.       end
  3238.     end
  3239.     @orientation = (@orientation + degrees) % 360
  3240.   end
  3241.  
  3242. end
  3243.  
  3244. #------------------------------------------------------------------------------
  3245.  
  3246. class Window_Base
  3247.  
  3248.   #--------------------------------------------------------------------------
  3249.   # * Check Color
  3250.   #     color : color to check
  3251.   #--------------------------------------------------------------------------
  3252.   def check_color(color)
  3253.     if color.type == Color
  3254.       # already a Color object
  3255.       return color
  3256.     elsif color[0].chr == "#"
  3257.       # specified as hexadecimal
  3258.       r = color[1..2].hex
  3259.       g = color[3..4].hex
  3260.       b = color[5..6].hex
  3261.       return Color.new(r,g,b)
  3262.     else
  3263.       # specified as integer (0-7)
  3264.       color = color.to_i
  3265.       if color >= 0 and color <= 7
  3266.         return text_color(color)
  3267.       end
  3268.     end
  3269.     return normal_color
  3270.   end
  3271.  
  3272. end
  3273.  
  3274. #------------------------------------------------------------------------------
  3275.  
  3276. class Window_InputNumber < Window_Base
  3277.  
  3278.   def set_font(fname, fsize, fcolor)
  3279.     return if fname == nil and fsize == nil and fcolor == nil
  3280.     # Calculate cursor width from number width
  3281.     dummy_bitmap = Bitmap.new(32, 32)
  3282.     dummy_bitmap.font.name = fname
  3283.     dummy_bitmap.font.size = fsize
  3284.     @cursor_width = dummy_bitmap.text_size("0").width + 8
  3285.     dummy_bitmap.dispose
  3286.     self.width = @cursor_width * @digits_max + 32
  3287.     self.contents = Bitmap.new(width - 32, height - 32)
  3288.     self.contents.font.name = fname
  3289.     self.contents.font.size = fsize
  3290.     self.contents.font.color = check_color(fcolor)
  3291.     refresh
  3292.     update_cursor_rect
  3293.   end
  3294.  
  3295.   def refresh
  3296.     self.contents.clear
  3297.     #self.contents.font.color = normal_color
  3298.     s = sprintf("%0*d", @digits_max, @number)
  3299.     for i in 0...@digits_max
  3300.       self.contents.draw_text(i * @cursor_width + 4, 0, 32, 32, s[i,1])
  3301.     end
  3302.   end
  3303.  
  3304. end
  3305.  
  3306. #==============================================================================
  3307. # ** Window_Base
  3308. #------------------------------------------------------------------------------
  3309. #  This class is for all in-game windows.
  3310. #==============================================================================
  3311.  
  3312. class Window_Base < Window
  3313.   #--------------------------------------------------------------------------
  3314.   # * Frame Update - Redefinition - Added Aug 31st, 2013
  3315.   #
  3316.   #   This fixes a Visual Bug where a Windowskin will change on you when
  3317.   #   a Non Floating Message Window is Fading Out.  The NEXT Message will
  3318.   #   have the newly set Windowskin applied.
  3319.   #--------------------------------------------------------------------------
  3320.   def update
  3321.     super
  3322.     # Reset if windowskin was changed
  3323.     if $game_system.windowskin_name != @windowskin_name
  3324.       # Prevents changing Message Windowskin until Next Message
  3325.       if not self.is_a?(Window_Message)
  3326.         @windowskin_name = $game_system.windowskin_name
  3327.         self.windowskin = RPG::Cache.windowskin(@windowskin_name)
  3328.       end
  3329.     end
  3330.   end
  3331. end
  3332.  
  3333. #=============================================================================
  3334. # ** Game_Multi_Message
  3335. #-----------------------------------------------------------------------------
  3336. #  This class handles the actor array. Refer to "$game_actors" for each
  3337. #  instance of this class.
  3338. #=============================================================================
  3339.  
  3340. class Game_Multi_Message
  3341.   #--------------------------------------------------------------------------
  3342.   # * Data
  3343.   #--------------------------------------------------------------------------
  3344.   def initialize()  @data = []         end
  3345.   def [](id)        @data[id]          end
  3346.   def []=(id,val)   @data[id] = val    end
  3347.   def update()      @data.each {|s| s.respond_to?(:update) && s.update }   end
  3348.   def dispose()     @data.each {|s| s.respond_to?(:dispose) && s.dispose } end
  3349.   #--------------------------------------------------------------------------
  3350.   # ● Method Missing
  3351.   #--------------------------------------------------------------------------
  3352.   def method_missing(val,*args,&block)
  3353.     return @data.send(val.to_s,*args,&block) if @data.respond_to?(val.to_sym)
  3354.     text = "Undefined method #{val} at #{self.inspect}"
  3355.     raise(NoMethodError, text, caller(1))              
  3356.   end
  3357. end
  3358.  
  3359. #=============================================================================
  3360. # ** Scene_Map
  3361. #-----------------------------------------------------------------------------
  3362. #  This class performs map screen processing.
  3363. #=============================================================================
  3364. class Scene_Map
  3365.   #--------------------------------------------------------------------------
  3366.   # ● Alias Listing
  3367.   #--------------------------------------------------------------------------
  3368.   $@ || alias_method(:mmw_sdk_patch_update, :update)
  3369.   #--------------------------------------------------------------------------
  3370.   # ● Frame Update
  3371.   #--------------------------------------------------------------------------
  3372.   def update(*args)
  3373.     unless @message_window.is_a?(Game_Multi_Message)
  3374.       @message_window.respond_to?(:dispose) && @message_window.dispose
  3375.       @message_window = Game_Multi_Message.new
  3376.       @message_window[0] = Window_Message.new(0)
  3377.     end
  3378.     mmw_sdk_patch_update(*args)
  3379.   end
  3380. end
  3381.  
  3382. #=============================================================================
  3383. # ** Scene_Battle
  3384. #-----------------------------------------------------------------------------
  3385. #  This class performs battle screen processing.
  3386. #=============================================================================
  3387. class Scene_Battle
  3388.   #--------------------------------------------------------------------------
  3389.   # ● Alias Listing
  3390.   #--------------------------------------------------------------------------
  3391.   $@ || alias_method(:mmw_sdk_patch_update, :update)
  3392.   #--------------------------------------------------------------------------
  3393.   # ● Frame Update
  3394.   #--------------------------------------------------------------------------
  3395.   def update(*args)
  3396.     unless @message_window.is_a?(Game_Multi_Message)
  3397.       @message_window.respond_to?(:dispose) && @message_window.dispose
  3398.       @message_window = Game_Multi_Message.new
  3399.       @message_window[0] = Window_Message.new(0)
  3400.     end
  3401.     mmw_sdk_patch_update(*args)
  3402.   end
  3403. end
  3404.  
  3405. #=============================================================================
  3406. # ** Game_Player
  3407. #-----------------------------------------------------------------------------
  3408. #  This class handles the player. Its functions include event starting
  3409. #  determinants and map scrolling. Refer to "$game_player" for the one
  3410. #  instance of this class.
  3411. #=============================================================================
  3412. class Game_Player
  3413.   #--------------------------------------------------------------------------
  3414.   # * Player Movement Update
  3415.   #--------------------------------------------------------------------------
  3416.   unless method_defined?(:update_player_movement)
  3417.     def update_player_movement
  3418.       case Input.dir4
  3419.       when 2 then move_down
  3420.       when 4 then move_left
  3421.       when 6 then move_right
  3422.       when 8 then move_up
  3423.       end
  3424.     end
  3425.   end
  3426. end
  3427. #------------------------------------------------------------------------------
  3428. # * End SDK Enable Test
  3429. #------------------------------------------------------------------------------
  3430. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement