#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
# ** Team Scriptastic's Script Console                           [RPG Maker XP]
#    Version 1.20
#------------------------------------------------------------------------------
#  This script adds an in-game script console that allows for on-the-fly script
#  entry and debugging.
#  Requires :
#  -  Aleworks Library
#  -  Aleworks Input Module
#  -  Aleworks Keyboard Module
#  -  Aleworks Write Line
#==============================================================================
# * Version History
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#   Version 1.00 ------------------------------------------------- (2009-07-??)
#     - Initial Version
#     - Author: theory
#   Version 1.10 ------------------------------------------------- (2009-07-??)
#     - Added History
#     - Improved Layout
#     - Author: Ulqiorra (Near)
#    Version 1.20 ------------------------------------------------ (2009-08-15)
#      - Cleaned code
#      - Converted to work with XP
#      - Author: Glitchfinder
#==============================================================================
# * Instructions
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#  Place this script above Main, and below the default scripts. (I realize this
#  is obvious to most, but some people don't get it.)
#
#  Simply press the tilde key (~), located above Tab and below Esc on most US
#  keyboards, to open the script console.  From here, you can type any script
#  command to test it.  A technical note, you start at Kernal, for heiarchy.
#  A good knowledge of RGSS is expected to get the most of this utility.
#  You can call methods by their relative globals, for example,
#  $game_map.update  ;  or more useful, $game_party.gain_item(13, 1) .
#
#  At this time, for RPG Maker XP, you can only call the console screen from
#  Scene_Map.  This was a sacrifice in order to reduce the large amount of
#  aliasing that would occur in order to compensate the lack of a Scene_Base.
#
#  Note that this is a utility script for scripters (or advanced script users).
#  If you do not understand what this script does, it is probably not intended
#  for you at this point, nor would you find it useful.
#==============================================================================
# * Method List
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#  This script is plug 'n play. Therefore, no knowledge of methods is required.
#==============================================================================
# * Special Thanks
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#  Special thanks go out to Aleworks for their amazing work with the Write Line
#  script, which is the cornerstone that made this in-game script console
#  possible to develop to a releasable state.
#==============================================================================
# * Contact
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#  Glitchfinder, one of the authors of this script, may be contacted through
#  his website, found at http://www.glitchkey.com
#
#  You may also find Glitchfinder at http://www.hbgames.org
#==============================================================================
# * Usage
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#  This script may be used with the following terms and conditions:
#
#    1. This script is free to use in any noncommercial project. If you wish to
#       use this script in a commercial (paid) project, please contact
#       Glitchfinder at his website.
#    2. This script may only be hosted at the following domains:
#         http://www.glitchkey.com
#         http://www.hbgames.org
#    3. If you wish to host this script elsewhere, please contact Glitchfinder.
#    4. If you wish to translate this script, please contact Glitchfinder. He
#       will need the web address that you plan to host the script at, as well
#       as the language this script is being translated to.
#    5. This header must remain intact at all times.
#    6. Glitchfinder remains the sole owner of this code. He may modify or
#       revoke this license at any time, for any reason.
#    7. Any code derived from code within this script is owned by Glitchfinder,
#       and you must have his permission to publish, host, or distribute his
#       code.
#    8. This license applies to all code derived from the code within this
#       script.
#    9. If you use this script within your project, you must include visible
#       credit to Glitchfinder, theory, and Ulqiorra, within reason.
#
#  Note that this script utilizes the foundation set by Aleworks.  Their script
#  does not specify clear terms of service, but it is suggested that you
#  contact vgvgf regarding specifics for terms of use pertaining to their
#  script.
#
#  Aleworks' scripts contain additional credits to third parties.  While this
#  is more of a development tool than an item intended for commercial
#  application, it is advised to do a bit of homework regarding applicable
#  license information before using this script for commercial purposes.
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡

#==============================================================================
# ** Window_History
#------------------------------------------------------------------------------
#  This window displays the code input history for the Script Console.
#==============================================================================

class Window_History < Window_Base
  #--------------------------------------------------------------------------
  # * Object Initialization
  #     x      : window x-coordinate
  #     y      : window y-coordinate
  #--------------------------------------------------------------------------
  def initialize(x = 1, y = 100)
    super(x, y, 640, 426)
    self.contents = Bitmap.new(640 - 32, 426 - 32)
    @history = []
    @need_refresh = true
  end
  #--------------------------------------------------------------------------
  # * Refresh
  #--------------------------------------------------------------------------
  def refresh
    self.contents.clear
    for i in 1...10
      if ! @history[i - 1].nil?
        y = 32 * (10 - i)
        index = (i - 1) % 5
        self.contents.draw_text(0, y, 640, 32, @history[index])
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    if @need_refresh
      refresh
      @need_refresh = false
    end
    super
  end
  #--------------------------------------------------------------------------
  # * Add Line
  #--------------------------------------------------------------------------
  def add_line(code)
    @history = @history.insert(-1, code)
    until @history.size <= 15
      @history.delete_at(@history.size - 1)
    end
    @need_refresh = true
  end
  #--------------------------------------------------------------------------
  # * Return Last Line
  #--------------------------------------------------------------------------
  def last_line
    return @history[0]
  end
  #--------------------------------------------------------------------------
  # * Memorize History
  #--------------------------------------------------------------------------
  def memorize
    Memory.filling = @history
  end
  #--------------------------------------------------------------------------
  # * Restore History
  #--------------------------------------------------------------------------
  def restore
    @history = Memory.filling
  end
end

#==============================================================================
# ** Memory
#------------------------------------------------------------------------------
#  This module is used to keep track of the Script Console code history
#  between different scenes.
#==============================================================================

module Memory
  @filling = nil
  #--------------------------------------------------------------------------
  # * Return Memorized History
  #--------------------------------------------------------------------------
  def self.filling
    return @filling
  end
  #--------------------------------------------------------------------------
  # * Set Memorized History
  #--------------------------------------------------------------------------
  def self.filling=(f)
    @filling = f
    return @filling
  end
  #--------------------------------------------------------------------------
  # * Add Line
  #--------------------------------------------------------------------------
  def self.full?
    return ! @filling.nil?
  end
end


#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
#  This class performs map screen processing.
#==============================================================================

class Scene_Map
  #--------------------------------------------------------------------------
  # * Alias Methods
  #--------------------------------------------------------------------------
  alias scriptastic_script_console_scene_map_update update
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    # Call original method
    scriptastic_script_console_scene_map_update
    # Activate console if in debug mode and the ~ key is pressed
    $scene = Scene_Console.new if Input.trigger?(Keys::OEM_7) and $DEBUG
  end
end

#=============================================================================
# ** Scene_Console
#=============================================================================
#  This class performs code input processing in Debug mode.
#=============================================================================

Input::REPEAT_TIME = 3

class Scene_Console
  #--------------------------------------------------------------------------
  # * Main Processing
  #--------------------------------------------------------------------------
  def main
    start                         # Start processing
    perform_transition            # Perform transition
    Input.update                  # Update input information
    loop do
      Graphics.update             # Update game screen
      Input.update                # Update input information
      update                      # Update frame
      break if $scene != self     # When screen is switched, interrupt loop
    end
    Graphics.update
    Graphics.freeze               # Prepare transition
    terminate                     # Termination processing
  end
  #--------------------------------------------------------------------------
  # * Start processing
  #--------------------------------------------------------------------------
  def start
    create_input_window
    display_instructions
  end
  #--------------------------------------------------------------------------
  # * Execute Transition
  #--------------------------------------------------------------------------
  def perform_transition
    Graphics.transition(10)
  end
  #--------------------------------------------------------------------------
  # * Frame Update
  #--------------------------------------------------------------------------
  def update
    @window_write.update
    @history.update
    if Input.trigger?(Keys::OEM_7)
      $game_system.se_play($data_system.cancel_se)
      @history.memorize
      $scene = Scene_Map.new
    elsif Input.trigger?(Keys::RETURN)
      @console_entry = @window_write.write.pwrited
      @history.add_line(@console_entry)
      @error = "@window_write.write.clear"
      Kernel.eval(@console_entry) rescue @error
      @window_write.write.clear
      @window_write.write.update
    elsif Input.trigger?(Keys::F5)
      if @window_write.show_chr == '*'
        @window_write.show_chr = nil
      else
        @window_write.show_chr = '*'
      end
    end
  end
  #--------------------------------------------------------------------------
  # * Termination Processing
  #--------------------------------------------------------------------------
  def terminate
    dispose_input_window
    dispose_instructions
  end
  #--------------------------------------------------------------------------
  # * Create Input Window
  #--------------------------------------------------------------------------
  def create_input_window
    @window_write = Window_AWrite.new(0, 480 - 54, 500, 54)
    @window_write.write.max_pixel_width = 468
    @window_write.opacity = 0
    font = Font.new
    font.name = "Courier New"
    @window_write.write.font = font
    @history = Window_History.new(1,100)
    @history.restore if Memory.full?
    @history.opacity = 0
  end
  #--------------------------------------------------------------------------
  # * Dispose Input Window
  #--------------------------------------------------------------------------
  def dispose_input_window
    @window_write.dispose
    @history.dispose
  end
  #--------------------------------------------------------------------------
  # * Display Instructions
  #--------------------------------------------------------------------------
  def display_instructions
    @indications = Sprite.new
    @indications.y = 75
    @indications.bitmap = Bitmap.new(640, 100)
    @indications.bitmap.font.size = 12
    @indications.bitmap.font.bold = true
    @indications.bitmap.font.name = 'Courier New'
    w = ['Enter script command: (Press F5 to mask text)']
    @indications.bitmap.draw_text(0, 0, 640, nil, w, 1)
  end
  #--------------------------------------------------------------------------
  # * Dispose Instructions
  #--------------------------------------------------------------------------
  def dispose_instructions
    @indications.dispose
  end
end