Glitchfinder
Staff
By: Glitchfinder
Introduction
Glitchfinder's Script Console is an advanced scripting tool that provides access to a fully functional script console from any point in RPG Maker XP or RPG Maker VX. As a note, I've had this script sitting around for months, because I didn't want to finish the massive help method that I had been working on. (and that has been purged from this version) That being said, the console is fully functional and extremely useful.
Features
- Multiregional key input
- Fully functional console
- Advanced debugging
- Command memory
- Allows you to save commands to reload later
- Allows you to save console logs to reload later
Screenshots

Script
RMXP Version
Code:
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
# ** Glitchfinder's Script Console [RPG Maker XP]
# Version 1.10
#------------------------------------------------------------------------------
# This script helps game designers debug their projects by giving them access
# to a fully fubnctional script console in-game.
#==============================================================================
# * Version History
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Version 1.00 ------------------------------------------------- (2010-08-21)
# - Initial version
# - Author: Glitchfinder
# Version 1.10 ------------------------------------------------ (2011-04-15)
# - Fixed crash on F12
# - Fixed version count on startup
# - Modified for RMXP
# - 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.)
#
# This script requires Glitchfinder's Key Input Module (at least version 1.10)
# and Glitchfinder's Mouse Input Module.
#
# This script is designed in such a way that it is highly recommended that you
# remove it before releasing your game. This is because there is no way to
# keep the player from activating it, if they wish to. For example, players
# can access the default debug menu if they create a shortcut to your game
# that adds the correct instructions to the end of the call, and thus opens
# the game in debug mode.
#
# To activate this script, simply press the ~ key. Since this reads the actual
# text character instead of the key, shift may be required. You may use the
# same key to exit the console.
#
# To set the console to give verbose error output, set the variable
# @backtrace_errors to true. You can undo tghis by setting it to false.
#
# You can bind the console to another object, and operate from within that
# object. To do so, you call @binding = [object_name].set_binding, where
# [object_name] is the name of the object. (For example, calling
# @binding = $scene.set_binding would result in you operating from within the
# current scene's class.) To undo this, you must call
# Script_Console.reset_binding.
#
# This console is designed not to crash, and all errors should give debug
# output. However, if you edit something that would cause the game to crash
# while running, like deleting the command window in Scene_Title, it will
# still crash when you exit the console.
#==============================================================================
# * Glitchfinder's Advice
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# This script is meant for people with at least a basic level of scripting
# knowledge and ability. If you are unsure of your abilities, or don't know
# how to script, then it would be a good idea to avoid this script.
#==============================================================================
# * Contact
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Glitchfinder, the author of this script, may be contacted through his
# website, found at [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]
#
# You may also find Glitchfinder at [url=http://www.hbgames.org]http://www.hbgames.org[/url]
#==============================================================================
# * 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:
# [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]
# [url=http://www.hbgames.org]http://www.hbgames.org[/url]
# 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 and theory, within reason.
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
#==============================================================================
# ** Object
#------------------------------------------------------------------------------
# Object is the parent class of all classes in Ruby. Its methods are
# therefore available to all objects unless explicitly overridden.
#==============================================================================
class Object
#--------------------------------------------------------------------------
# * Set Binding
#--------------------------------------------------------------------------
def set_binding
# Create a new process
Proc.new {}
end
end
#==============================================================================
# ** Script_Console
#------------------------------------------------------------------------------
# This is a container for the Script Console data
#==============================================================================
module Script_Console
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
begin
@commands = [] # Commands used
@current_command = [] # Command currently being typed
@backup_command = [] # Backup of the current command
@copyright = [] # Copyright information displayed at the top
@lines = [] # Lines displayed
@current_lines = [] # Current lines
@text_index = 0 # Current index of text cursor
@command_index = 0 # Index of the command repeater
@lines_size = 0 # Backup of the current line length
@scroll_line = 0 # Current scroll position
@font_size = 12 # Console font size
@line_spacing = 2 # Console vertical line spacing
@insert_on = false # Insert flag
@active = false # Active flag
@deactivated = false # Recently deactivated flag
@drawn = false # Console drawn flag
@slider_drag = false # Scroll bar slider drag state
@backtrace_errors = false # Flag to backtrace error messages
@binding = nil # Set to bind to a class
@keystate = Win32API.new('user32.dll', 'GetKeyState', 'I', 'I')
end
#--------------------------------------------------------------------------
# * Get Commands
#--------------------------------------------------------------------------
def self.commands(*args)
# If no arguments were given
if args.empty?
# Return the full commands array
return @commands
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific command in the Script "
message += "Console\nif you feed the commands method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified command
return @commands[args[0].join]
end
end
end
#--------------------------------------------------------------------------
# * Get Lines
#--------------------------------------------------------------------------
def self.lines(*args)
# If no arguments were given
if args.empty?
# Return the full lines array
return @lines
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific line in the Script "
message += "Console\nif you feed the lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified line
return @lines[args[0]]
end
end
end
#--------------------------------------------------------------------------
# * Get Current Lines
#--------------------------------------------------------------------------
def self.current_lines(*args)
# If no arguments were given
if args.empty?
# Return the full current lines array
return @current_lines
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific line in the Script "
message += "Console\nif you feed the lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified line
return @current_lines[args[0]]
end
end
end
#--------------------------------------------------------------------------
# * Get Total Lines
#--------------------------------------------------------------------------
def self.total_lines
# Return the total line count
return (@lines.size + @current_lines.size + @copyright.size)
end
#--------------------------------------------------------------------------
# * Get Text Index
#--------------------------------------------------------------------------
def self.text_index
# Return the command index
return @text_index
end
#--------------------------------------------------------------------------
# * Get Command Index
#--------------------------------------------------------------------------
def self.command_index
# Return the command index
return @command_index
end
#--------------------------------------------------------------------------
# * Get Number of Lines to Print
#--------------------------------------------------------------------------
def self.lines_size
# Return the number of lines set to print
return @lines_size
end
#--------------------------------------------------------------------------
# * Get Current Scroll Line
#--------------------------------------------------------------------------
def self.scroll_line
# Return the number of the line at the top of the screen
return @scroll_line
end
#--------------------------------------------------------------------------
# * Get Console Font Size
#--------------------------------------------------------------------------
def self.font_size
# Return the font size
return @font_size
end
#--------------------------------------------------------------------------
# * Get Console Vertical Line Spacing
#--------------------------------------------------------------------------
def self.line_spacing
# Return the number of pixels between lines of text
return @line_spacing
end
#--------------------------------------------------------------------------
# * Get Console Line Height
#--------------------------------------------------------------------------
def self.line_height
# Return the height of a line of text, in pixels
return (@font_size + @line_spacing)
end
#--------------------------------------------------------------------------
# * Get Console Line Count Per Sprite
#--------------------------------------------------------------------------
def self.line_count
# Return the number of lioines in a line sprite
return (@line_bitmap_height / line_height)
end
#--------------------------------------------------------------------------
# * Get Current Command
#--------------------------------------------------------------------------
def self.current_command
# Return the current command
return @current_command.join
end
#--------------------------------------------------------------------------
# * Get Backup Command
#--------------------------------------------------------------------------
def self.backup_command
# Return the backup of the current command
return @backup_command
end
#--------------------------------------------------------------------------
# * Get Insert Flag
#--------------------------------------------------------------------------
def self.insert_on?
# Return insert flag
return @insert_on
end
#--------------------------------------------------------------------------
# * Get Active Flag
#--------------------------------------------------------------------------
def self.active?
# Return active flag
return @active
end
#--------------------------------------------------------------------------
# * Get Drawn Flag
#--------------------------------------------------------------------------
def self.deactivated?
# If the console has just been deactivated
if @deactivated == true
# Set deactivated flag to false and return true
@deactivated = false
return true
end
# Return false
return false
end
#--------------------------------------------------------------------------
# * Get Drawn Flag
#--------------------------------------------------------------------------
def self.drawn?
# Return drawn flag
return @drawn
end
#--------------------------------------------------------------------------
# * Get Slider Dragging Flag
#--------------------------------------------------------------------------
def self.slider_drag?
# Return slider dragging flag
return @slider_drag
end
#--------------------------------------------------------------------------
# * Get Error Backtrace Flag
#--------------------------------------------------------------------------
def self.backtrace_errors?
# Return UK English flag
return @backtrace_errors
end
#--------------------------------------------------------------------------
# * Get Binding
#--------------------------------------------------------------------------
def self.binding
# Return eval binding
return @binding
end
#--------------------------------------------------------------------------
# * Set Commands
#--------------------------------------------------------------------------
def self.set_commands(*args)
# If one argument was given
if args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Array)
# Print an error message
message = "You cannot set the arguments array of the Script "
message += "Console\nif you feed the set_commands method a "
message += args[0].class.to_s + "\ninstead of an Array."
raise(ArgumentError, message)
end
# Set the arguments array
@arguments = args[0]
# If the argument was a Fixnum
elsif args.size == 2
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot set a specific argument in the Script "
message += "Console\nif you feed the set_arguments method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
elsif !args[1].instance_of?(String)
# Print an error message
message = "You cannot set a specific argument in the Script "
message += "Console\nif you feed the set_arguments method a "
message += args[0].class.to_s + "\ninstead of a String."
raise(ArgumentError, message)
end
# Set the specified command
@commands[args[0]] = args[1].split(//)
end
end
#--------------------------------------------------------------------------
# * Set Lines
#--------------------------------------------------------------------------
def self.set_lines(*args)
# If one argument was given
if args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Array)
# Print an error message
message = "You cannot set the lines array of the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of an Array."
raise(ArgumentError, message)
end
# Set the lines array
@lines = args[0]
# Dispose the console
dispose if @drawn
# Redraw the console
draw_initial if !@drawn
# If the argument was a Fixnum
elsif args.size == 2
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot set a specific line in the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
elsif !args[1].instance_of?(String)
# Print an error message
message = "You cannot set a specific line in the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of a String."
raise(ArgumentError, message)
end
# Set the specified line
@lines[args[0]] = args[1]
# Redraw the line
redraw_line(args[1])
end
end
#--------------------------------------------------------------------------
# * Set Text Index
#--------------------------------------------------------------------------
def self.text_index=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the text index in the Script Console\n"
message += "if you feed the text_index=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = @current_command.size if new_value > @current_command.size
# Set the current text index
@text_index = new_value
end
#--------------------------------------------------------------------------
# * Set Command Index
#--------------------------------------------------------------------------
def self.command_index=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the command index in the Script Console\n"
message += "if you feed the command_index=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = @commands.size if new_value > @commands.size
# Set the current command index
@command_index = new_value
end
#--------------------------------------------------------------------------
# * Set Scroll Line
#--------------------------------------------------------------------------
def self.scroll_line=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the scroll line in the Script Console\n"
message += "if you feed the scroll_line=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = scroll_limit if new_value > scroll_limit
# Set the current command index
@scroll_line = new_value
end
#--------------------------------------------------------------------------
# * Set Current Command
#--------------------------------------------------------------------------
def self.current_command=(new_value)
# If the input is not a String
if !new_value.instance_of?(String)
# Print an error message
message = "You cannot set the current command in the Script Console\n"
message += "if you feed the current_command=(String) method a\n"
message += new_value.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# Set the current command index
@current_command = new_value.split(//)
# Update the cursor index
@text_index = @current_command.size if @command_index == @commands.size
# Update current line
update_current_line if @command_index == @commands.size
# Update Console Text
update_console_text if @command_index == @commands.size
end
#--------------------------------------------------------------------------
# * Set Backup Command
#--------------------------------------------------------------------------
def self.backup_command=(new_value)
# If the input is not a String
if !new_value.instance_of?(String)
# Print an error message
message = "You cannot set the backup command in the Script Console\n"
message += "if you feed the backup_command=(String) method a\n"
message += new_value.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# Set the current command index
@backup_command = new_value.split(//)
end
#--------------------------------------------------------------------------
# * Set Insert Flag
#--------------------------------------------------------------------------
def self.insert_on=(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the insert flag in the Script Console\n"
message += "if you feed the insert_on=(boolean) method a\n"
message += new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@insert_on = new_value
# If insert is now on
if @insert_on
# Set the text cursor bitmap
@cursor_sprite.bitmap = @insert_bitmap
# If insert if now off
else
# Set the text cursor bitmap
@cursor_sprite.bitmap = @cursor_bitmap
end
end
#--------------------------------------------------------------------------
# * Set Active Flag
#--------------------------------------------------------------------------
def self.active=(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the active flag in the Script Console\n"
message += "if you feed the active=(boolean) method a\n"
message += new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@active = new_value
# If the console is now active
if @active
# Make the console visible
@console_viewport.visible = true
@scroll_viewport.visible = true
# If the console is now inactive
else
# Hide the console
@console_viewport.visible = false
@scroll_viewport.visible = false
# Set the console to recently deactivated status
@deactivated = true
end
end
#--------------------------------------------------------------------------
# * Set Error Backtrace Flag
#--------------------------------------------------------------------------
def self.backtrace_errors(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the error backtrace flag in the Script "
message += "Console\n if you feed the backtrace_errors=(boolean) method"
message += " a\n" + new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@backtrace_errors = new_value
end
#--------------------------------------------------------------------------
# * Set Binding
#--------------------------------------------------------------------------
def self.set_binding(object)
# Set the binding scope to that of the specified object
@binding = object.binding
end
#--------------------------------------------------------------------------
# * Reset Binding
#--------------------------------------------------------------------------
def self.reset_binding
# Reset the binding
@binding = nil
end
#--------------------------------------------------------------------------
# * Dump Log to Text
#--------------------------------------------------------------------------
def self.dump_log(name = nil)
# If the input is not a String
if !name.instance_of?(String) && name != nil
# Print an error message
message = "You cannot dump a log of the Script Console text\n"
message += "if you feed the dump_log(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If no name was specified
if name == nil
# Get the current time
time = Time.new
# Generate a generic filename
name = 'log_' + time.year.to_s + '_' + time.mon.to_s + '_'
name += time.mday.to_s + '_' + time.hour.to_s + '_' + time.min.to_s
name += '_' + time.sec.to_s + '.txt'
# If the filename is not for a .txt file
elsif name[-4, 4] != '.txt'
# Append the filetype to the end of the filename
name += '.txt'
end
# Create an array of all lines
lines = @lines + @current_lines
# Create a string containing the lines
text = lines.join("\n")
# Create the log file
log = File.new(name, "w")
# Write to the log
log.write(text)
# Close the log file
log.close
end
#--------------------------------------------------------------------------
# * Save Command List
#--------------------------------------------------------------------------
def self.save_commands(name)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot save the commands of the Script Console\n"
message += "if you feed the save_commands(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# Create the command file
file = File.new(name, "wb")
# Write to the file
Marshal.dump(@commands, file)
# Close the file
file.close
end
#--------------------------------------------------------------------------
# * Save Line List
#--------------------------------------------------------------------------
def self.save_output(name)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot save the output of the Script Console\n"
message += "if you feed the save_output(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# Create the output file
file = File.new(name, "wb")
# Write to the file
Marshal.dump(@lines, file)
# Close the file
file.close
end
#--------------------------------------------------------------------------
# * Load Command List
#--------------------------------------------------------------------------
def self.load_commands(name, after = true)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot load the commands of the Script Console\n"
message += "if you feed the load_commands(String, Boolean) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the input is not a boolean
if !(after.instance_of?(TrueClass) || after.instance_of?(FalseClass))
# Print an error message
message = "You cannot load the commands of the Script Console\n"
message += "if you feed the load_commands(String, Boolean) method a\n"
message += after.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# If the file does not exist
if !FileTest.exist?(name)
# Print an error message
message = 'Cannot find the file ' + name + '.'
raise(ENOENT, message)
end
# Load the command file
file = File.open(name, "rb")
# Write to the file
new_commands = Marshal.load(file)
# Close the file
file.close
# If not set to load the old commands before the new ones
if after == false
# Set a temporary variable to the command list size
size = new_commands.size
# Iterate through the list of old commands
for i in 0...size
# Set the current command index
index = (size - 1) - i
# If the new command already exists
if @commands.include?(new_commands[index])
# Delete the command
new_commands.delete_at(index)
end
end
# Add the old commands to the new command array
new_commands += @commands
# Reset the command array
@commands = new_commands
# If set to load the old commands after the new ones
else
# Set a temporary variable to the command list size
size = @commands.size
# Iterate through the list of old commands
for i in 0...size
# Set the current command index
index = (size - 1) - i
# If the new command already exists
if new_commands.include?(@commands[index])
# Delete the command
@commands.delete_at(index)
end
end
# Add the new commands to the old command list
@commands += new_commands
end
# Reset the command index
@command_index = @commands.size
end
#--------------------------------------------------------------------------
# * Load Line List
#--------------------------------------------------------------------------
def self.load_output(name, after = true)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot load the output of the Script Console\n"
message += "if you feed the load_output(String, Boolean) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the input is not a boolean
if !(after.instance_of?(TrueClass) || after.instance_of?(FalseClass))
# Print an error message
message = "You cannot load the output of the Script Console\n"
message += "if you feed the load_output(String, Boolean) method a\n"
message += after.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# If the file does not exist
if !FileTest.exist?(name)
# Print an error message
message = 'Cannot find the file ' + name + '.'
raise(ENOENT, message)
end
# Load the output file
file = File.open(name, "rb")
# Write to the file
new_lines = Marshal.load(file)
# Close the file
file.close
# If not set to load the old lines before the new ones
if after == false
# Add the old commands to the new command array
new_lines += @lines
# Reset the command array
@lines = new_lines
# Freeze the graphics
Graphics.freeze
# Dispose the Script Console
dispose
# Redraw the console
draw_initial
# Set the console to active
self.active = true
# Reload the graphics
Graphics.transition(1)
# If set to load the old lines after the new ones
else
# Add the new commands to the old command list
@lines += new_lines
# Clear the @lines_size variable
#@lines_size = 0
# Set the number of lines to print
@lines_size += new_lines.size
# Update the console text
update_text
end
end
#--------------------------------------------------------------------------
# * Clear Output
#--------------------------------------------------------------------------
def self.clear
# Delete output lines
@lines = []
# Freeze the graphics
Graphics.freeze
# Dispose the Script Console
dispose
# Redraw the console
draw_initial
# Set the console to active
self.active = true
# Set the scroll line to 0
@scroll_line = 0
# Reload the graphics
Graphics.transition(1)
end
#--------------------------------------------------------------------------
# * Input Non-Executed Text
#--------------------------------------------------------------------------
def self.input_text
# Update the current line of text
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
end
#--------------------------------------------------------------------------
# * Set Up Console Screen
#--------------------------------------------------------------------------
def self.draw_initial
# Create colors
@black = Color.new(0, 0, 0, 255)
@white = Color.new(255, 255, 255, 255)
# Create the console's viewport
@console_viewport = Viewport.new(0, 0, 640 - 20, 480)
@console_viewport.z = 1000
# Hide the console's viewport
@console_viewport.visible = false
# Create the background bitmap for the console
console_background = Bitmap.new(32, 32)
console_background.fill_rect(0, 0, 32, 32, @black)
# Create the console bacground
@console_background = Plane.new(@console_viewport)
# Set the console background bitmap
@console_background.bitmap = console_background
# Create the console scroll bar viewport
@scroll_viewport = Viewport.new(640 - 20, 0, 20, 480)
@scroll_viewport.z = 1000
# Hide the console scroll bar viewport
@scroll_viewport.visible = false
# Create the scroll bar background bitmap
scroll_bar_background_bmp = Bitmap.new(20, 480 - 40)
scroll_bar_background_bmp.fill_rect(0, 0, 20, 480 - 40, @black)
scroll_bar_background_bmp.fill_rect(0, 0, 1, 480 - 40, @white)
scroll_bar_background_bmp.fill_rect(19, 0, 1,480 - 40, @white)
# Create the scroll bar slider bitmap
@scroll_bar_bmp = Bitmap.new(20, 20)
@scroll_bar_bmp.blt(0, 0, scroll_bar_background_bmp, Rect.new(0, 0, 20, 20))
@scroll_bar_bmp.fill_rect(0, 0, 20, 1, @white)
@scroll_bar_bmp.fill_rect(0, 19, 20, 1, @white)
# Creare the top scroll bar button bitmap
@scroll_bar_button_top_bmp = @scroll_bar_bmp.clone
@scroll_bar_button_top_bmp.fill_rect(6, 11, 8, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(7, 10, 6, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(8, 9, 4, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(9, 8, 2, 1, @white)
# Creare the bottom scroll bar button bitmap
@scroll_bar_button_bottom_bmp = @scroll_bar_bmp.clone
@scroll_bar_button_bottom_bmp.fill_rect(6, 8, 8, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(7, 9, 6, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(8, 10, 4, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(9, 11, 2, 1, @white)
# Create the highlighted scroll bar slider bitmap
@h_scroll_bar_bmp = Bitmap.new(20, 20)
@h_scroll_bar_bmp.fill_rect(0, 0, 20, 20, @white)
# Creare the highlighted top scroll bar button bitmap
@h_scroll_bar_button_top_bmp = @h_scroll_bar_bmp.clone
@h_scroll_bar_button_top_bmp.fill_rect(6, 11, 8, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(7, 10, 6, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(8, 9, 4, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(9, 8, 2, 1, @black)
# Creare the highlighted bottom scroll bar button bitmap
@h_scroll_bar_button_bottom_bmp = @h_scroll_bar_bmp.clone
@h_scroll_bar_button_bottom_bmp.fill_rect(6, 8, 8, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(7, 9, 6, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(8, 10, 4, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(9, 11, 2, 1, @black)
# Create the scroll bar background
@scroll_bar_background = Sprite.new(@scroll_viewport)
@scroll_bar_background.y = 20
@scroll_bar_background.bitmap = scroll_bar_background_bmp
# Create the scroll bar slider
@scroll_bar = Sprite.new(@scroll_viewport)
@scroll_bar.y = 20
@scroll_bar.z = 10
@scroll_bar.bitmap = @scroll_bar_bmp
# Create the top scroll bar button
@scroll_bar_button_top = Sprite.new(@scroll_viewport)
@scroll_bar_button_top.y = 0
@scroll_bar_button_top.bitmap = @scroll_bar_button_top_bmp
# Create the bottom scroll bar button
@scroll_bar_button_bottom = Sprite.new(@scroll_viewport)
@scroll_bar_button_bottom.y = 480 - 20
@scroll_bar_button_bottom.bitmap = @scroll_bar_button_bottom_bmp
# Set console text properties
@console_font = Font.new("Lucida Console", @font_size)
@console_font.color = @white
# Create array to store line sprites
@line_sprites = []
# Create blank line sprite bitmap
@line_bitmap_height = ((480 / line_height) * line_height)
@line_bitmap = Bitmap.new(640 - 20, @line_bitmap_height)
@line_bitmap.font = @console_font
# Create first line sprite
sprite = Sprite.new(@console_viewport)
sprite.bitmap = @line_bitmap.clone
sprite.z = 100
@line_sprites[0] = sprite
# Create an array that merges the old lines and the current line
lines = @copyright + @lines + @current_lines
# Iterate through lines array
for i in 0...lines.size
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# Calculate line sprite index
sprite_index = (i / line_count)
# If the sprite in question does not exist
if @line_sprites[sprite_index] == nil
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Determine line properties
y = ((i % (@line_bitmap_height / line_height)) * line_height)
width = 640 - 20
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[i])
end
# Create the text cursor bitmaps
@cursor_bitmap = Bitmap.new(7, line_height)
@insert_bitmap = @cursor_bitmap.clone
@cursor_bitmap.fill_rect(0, 0, 1, line_height, @white)
@insert_bitmap.fill_rect(0, 12, 7, 2, @white)
# Create the cursor sprite
@cursor_sprite = Sprite.new(@console_viewport)
@cursor_sprite.x = (@text_index *
@line_sprites[0].bitmap.text_size('O').width)
if ((@cursor_sprite.x + @line_sprites[0].bitmap.text_size('O').width) >
@line_sprites[0].src_rect.width)
@cursor_sprite.x = 0
end
@cursor_sprite.y = lines.size * line_height
@cursor_sprite.y -= line_height unless @current_lines.empty?
@cursor_sprite.bitmap = @cursor_bitmap
# Set the cursor sprite timer
@cursor_timer = Graphics.frame_rate / 2
# Set the console drawn flag to true
@drawn = true
end
#--------------------------------------------------------------------------
# * Dispose Console Screen
#--------------------------------------------------------------------------
def self.dispose
# Dispose the console background
@console_background.bitmap.dispose
@console_background.dispose
# Dispose the scroll bar background
@scroll_bar_background.bitmap.dispose
@scroll_bar_background.dispose
# Dispose the scroll bar slider
@scroll_bar_bmp.dispose
@h_scroll_bar_bmp.dispose
@scroll_bar.dispose
# Dispose the top scroll bar button
@scroll_bar_button_top_bmp.dispose
@h_scroll_bar_button_top_bmp.dispose
@scroll_bar_button_top.dispose
# Dispose the bottom scroll bar button
@scroll_bar_button_bottom_bmp.dispose
@h_scroll_bar_button_bottom_bmp.dispose
@scroll_bar_button_bottom.dispose
# Iterate through the line sprite array
for sprite in @line_sprites
# Skip if not a sprite
next unless sprite.instance_of?(Sprite)
# Dispose the sprite's bitmap
sprite.bitmap.dispose
# Dispose the sprite
sprite.dispose
end
# Dispose the default line sprite bitmap
@line_bitmap.dispose
# Dispose the cursor
@cursor_bitmap.dispose
@insert_bitmap.dispose
@cursor_sprite.dispose
# Set the console drawn flag to false
@drawn = false
end
#--------------------------------------------------------------------------
# * Redraw Line
#--------------------------------------------------------------------------
def self.redraw_line(index)
# Return if the line is out of bounds
return if index < 0 || index >= @lines.size + @copyright.size
# Set a temporary variable to sprite 0
sprite_index = 0
# Iterate through the lines
until index < line_count
# Subtract the number of lines in a sprite
line -= line_count
# Increment the sprite index
sprite_index += 1
end
# If the line sprite exists
if @line_sprites[sprite_index] != nil
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
# If the sprite does not exist
else
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Set the line's y position to 0
y = 0
# Set the line's width
width = 640 - 20
# Set the index to the beginning of the sprite
index = sprite_index * line_height
# Iterate through the lines on the sprite
for i in 0...line_count
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[index])
# Increment the line index
index += 1
# Increment the y position
y += line_height
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def self.update
# Reset the line size
@lines_size = 0
# Set a temporary variable to false
graphics_update = false
# Set the temporary variable to true if control input was detected
graphics_update = true if update_control_input
# If text input was detected
if update_text_input || graphics_update
# If the current command was not the selected one
if @command_index != @commands.size
# Set the current command to the newly selected command
@current_command = @commands[@command_index].clone
# Reset the current command if it is equal to nil
@current_command = [] if @current_command == nil
# Set the command index to the newly selected command
@command_index = @commands.size
# Set the text index to the end of the new command if it is too small
@text_index = @current_command.size if (@text_index >
@current_command.size)
# Update the text input with the new command
update_text_input
end
# Increment the text index unless a control character was called
@text_index += 1 unless graphics_update
# If insert is on, and the text index is not at the end of the line
if @insert_on && @text_index < @current_command.size
# Delete the currently selected character
@current_command.delete_at(@text_index)
end
# Set the temporary variable to true
graphics_update = true
end
# Update the cursor
update_cursor
# If input was detected
if graphics_update
# Update the current line
update_current_line
# Update the text view
update_text
end
# Update the console's scroll position
update_scroll
end
#--------------------------------------------------------------------------
# * Update Control Input
#--------------------------------------------------------------------------
def self.update_control_input
# If the Escape key is being pressed
if Keys.trigger?(Keys::ESCAPE)
# Set the console to inactive
self.active = false
# Return that no character input was given
return false
# If the Tab key is being pressed
elsif Keys.trigger?(Keys::TAB)
# Add two spaces to the current command
@current_command.insert(@text_index, ' ')
@current_command.insert(@text_index, ' ')
# Increment the text index
@text_index += 2
# Return true
return true
# If the Backspace key is being pressed
elsif Keys.repeat?(Keys::BACKSPACE)
# If there are no characters to remove
if @text_index == 0
# Return false
return false
end
# Remove a character from the command
@current_command.delete_at(@text_index - 1)
# Decrement the text index
@text_index -= 1
# Return true
return true
# If the Delete key is being pressed
elsif (Keys.repeat?(Keys::DELETE) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.repeat?(Keys::DECIMAL)))
# If there are no characters to remove
if @text_index >= @current_command.size
# Return false
return false
end
# Remove a character from the command
@current_command.delete_at(@text_index)
# Return true
return true
# If the Insert key is being pressed
elsif (Keys.trigger?(Keys::INSERT) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.trigger?(Keys::NUMPAD0)))
# Change the insert key state
@insert_on = ((@insert_on == true) ? false : true)
# If insert is now on
if @insert_on
# Set the text cursor bitmap
@cursor_sprite.bitmap = @insert_bitmap
# If insert if now off
else
# Set the text cursor bitmap
@cursor_sprite.bitmap = @cursor_bitmap
end
# Return false
return false
# If the Left key is being pressed
elsif (Keys.repeat?(Keys::LEFT) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD4)))
# If the text index is 0
if @text_index <= 0
# Return false
return false
end
# Decrement the text index
@text_index -= 1
# Return false
return false
# If the Right key is being pressed
elsif (Keys.repeat?(Keys::RIGHT) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.repeat?(Keys::NUMPAD6)))
# If the text index is at the end of the line
if @text_index >= @current_command.size
# Return false
return false
end
# Increment the text index
@text_index += 1
# Return false
return false
# If the Up key is being pressed
elsif (Keys.repeat?(Keys::UP) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD8)))
# If the command index is 0
if @command_index <= 0
# Return false
return false
end
# If the command index is set to the current command
if @command_index == @commands.size
# Set the backup command to the current command
@backup_command = @current_command
end
# Decrement the text index
@command_index -= 1
# If the new commend is not nil
if @commands[@command_index] != nil
# Set the text index to the end of the new line
@text_index = @commands[@command_index].size
# If the command does not exist
else
# Set the text index to 0
@text_index = 0
end
# Return true
return true
# If the Down key is being pressed
elsif (Keys.repeat?(Keys::DOWN) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD2)))
# If the command index is at the latest command
if @command_index >= @commands.size
# Return false
return false
end
# Increment the command index
@command_index += 1
# If the new commend is not nil
if @commands[@command_index] != nil
# Set the text index to the end of the new line
@text_index = @commands[@command_index].size
# If the new command is set to the current command
elsif @command_index == @commands.size
# Set the current command to the backup command
@current_command = @backup_command
# Set the tezxt index to the currently selected command
@text_index = @current_command.size
# If the command does not exist
else
# Set the current command to an empty line
@current_command = []
# Set the text index to 0
@text_index = 0
end
# Return true
return true
# If the Enter key is being pressed
elsif Keys.trigger?(Keys::RETURN)
# Interpret the command
interpret_command
# Return true
return true
end
end
#--------------------------------------------------------------------------
# * Update Text Input
#--------------------------------------------------------------------------
def self.update_text_input
# Get the currently pressed character
character = Keys.character_repeat
# Return false if no chracter was returned
return false if !character
# If the character was a ~
if character[0] == 126
# Set the console to inactive
self.active = false
# Return false to prevent input
return false
end
# Insert the returned character
@current_command.insert(@text_index, character.strip)
# If the stripped character is an empty string
if character.strip == ''
# Insert a space into the command array
@current_command.insert(@text_index, ' ')
end
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Set the slider to idle, if being dragged
@slider_drag = false
# If scrolling is possible
if scroll_limit > 0
# Set the scroll line to the bottom
@scroll_line = scroll_limit
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = 480 - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
end
# Return true if a character was inserted
return true
end
#--------------------------------------------------------------------------
# * Interpret Command
#--------------------------------------------------------------------------
def self.interpret_command
# If the command index is not set to the current command
if @command_index != @commands.size
# Set the current command to the one selected
@current_command = @commands[@command_index].clone
# Set the current command to an empty string if it is nil
@current_command = [] if @current_command == nil
end
# If the current command has already been entered
if @commands.include?(@current_command)
# Delete the existing command
@commands.delete_at(@commands.index(@current_command))
end
# Add the current command to the commands array
@commands.push(@current_command)
# Set the command index to the latest command
@command_index = @commands.size
# Add the current lines to the lines array
@lines += @current_lines
# Backup current line length
@lines_size = @current_lines.size
# Clear the current line array
@current_lines = []
# Set the text cursor index to 0
@text_index = 0
# Set up a block for debugging purposes
begin
# If a binding is set
if @binding != nil
# Evaluate the currently selected command
eval @current_command.join, @binding.binding
# If a binding is not set
else
# Evaluate the currently selected command
eval @current_command.join
end
# If there was a syntax error
rescue SyntaxError => exception
# Print the error
print_error(exception)
# If there was an error
rescue => exception
# Print the error
print_error(exception)
# If a binding error was detected
if exception.message.include?("private method `binding' called for")
# Reset method binding
@binding = nil
end
end
# Reset the current command
@current_command = []
# Reset the text index
@text_index = 0
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Set the slider to idle, if being dragged
@slider_drag = false
# If scrolling is possible
if scroll_limit > 0
# Set the scroll line to the bottom
@scroll_line = scroll_limit
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = 480 - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
end
end
#--------------------------------------------------------------------------
# * Update Cursor Position
#--------------------------------------------------------------------------
def self.print_error(exception)
# Add the exception class to the current line array
@current_command = exception.class.to_s.split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
# Add the exception message to the current line array
@current_command = exception.message.split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
# Return if not set to backtrace errors
return if !@backtrace_errors
# Add the exception backtrace to the current line array
for i in 0...exception.backtrace.size
@current_command = exception.backtrace[i].split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
end
end
#--------------------------------------------------------------------------
# * Update Cursor Position
#--------------------------------------------------------------------------
def self.update_cursor
# If the cursor timer has run out
if @cursor_timer <= 0
# Set the cursor's visibility
@cursor_sprite.visible = (@cursor_sprite.visible == true ? false : true)
# Set the curosr timer to half a second
@cursor_timer = Graphics.frame_rate / 2
# If the cursor timer is still running
else
# Decrement the cursor timer
@cursor_timer -= 1
end
# set a temporary variable to the width of a character
character_width = @line_sprites[0].bitmap.text_size('O').width
# set a temporary variable to the width of a line, in characters
line_width = ((@line_sprites[0].src_rect.width / character_width) *
character_width)
# set the cursor sprite's x position
@cursor_sprite.x = (@text_index * character_width) % line_width
# Set blank y offset
y_offset = 0
# If there is more than one line in the current command
if @current_lines.size > 1
# Calculate the text index, from the end of the last line
text_index = @current_command.size - @text_index
# If the last line is not full
if @current_lines[-1].split(//).size != (line_width / character_width)
# Remove any incomplete lines from the new index
text_index -= @current_lines[-1].split(//).size
# Increment the line offset unless at the beginning of a line
y_offset += 1 unless @cursor_sprite.x == 0
end
# Calculate the line offset
y_offset += ((text_index * character_width) / line_width)
# Modify offset to reflect y positioning
y_offset *= line_height
end
# Calculate the curosr sprite's y position
cursor_y = total_lines * line_height
# If the current line is not empty
if !@current_lines.empty?
# If the cursor is not at the beginning of a new line
unless ((@cursor_sprite.x == 0) &&
(@current_command.size - @text_index == 0))
# Move the cursor up a line
cursor_y -= line_height
end
end
# Subtract the cursor's y offset
cursor_y -= y_offset
# Set the cursor sprite's y positon
@cursor_sprite.y = cursor_y
end
#--------------------------------------------------------------------------
# * Update Current Line
#--------------------------------------------------------------------------
def self.update_current_line
# If the currently selected command is not the current command
if @command_index != @commands.size
# Set the current command to the newly selected command
@current_command = @commands[@command_index].clone
end
# Set the new command to a blank string if it is nil
@current_command = [] if @current_command == nil
# Set the text index to the end of the line, if it is beyond the end
@text_index = @current_command.size if @text_index > @current_command.size
# Set a temporary variable to the width of a character
character_width = @line_sprites[0].bitmap.text_size('O').width
# Set a temporary variable to the width of a line, in characters
line_width = (@line_sprites[0].src_rect.width / character_width)
# Reset the current lines
@current_lines = []
# Set a blank line
line = ''
# Iterate through the current command
for i in 0...@current_command.size
# Add the specifiec character to the new line
line += @current_command[i].to_s
# If the line is the maximum width
if line.split(//).size == line_width
# Add the new line to the current line list
@current_lines.push(line)
# Reset the current line
line = ''
end
end
# Add the line to the current line list if it is not empty
@current_lines.push(line) if !line.empty?
end
#--------------------------------------------------------------------------
# * Update Console Text
#--------------------------------------------------------------------------
def self.update_text
# Set a temporary variable to the old line array
old_lines = @copyright.dup + @lines.dup
# Initialize the sprite count
sprite_index = 0
# Until the line array is not greater than the number of lines in a sprite
until (old_lines.size <= (line_count + @lines_size))
# Iterate through the number of lines in a srite
for i in 0...line_count
# Remove the first line in the line array
old_lines.shift
end
# Increment the sprite count
sprite_index += 1
end
# If the line sprite exists
if @line_sprites[sprite_index] != nil
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
# If the sprite does not exist
else
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Add the current lines to the old line array
lines = old_lines + @current_lines
# Iterate through the line array
for i in 0...lines.size
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# if the line is on the next sprite
if (i % line_count) == 0 && i != 0
# Increment the sprite index
sprite_index += 1
# If the sprite in question does not exist
if @line_sprites[sprite_index] == nil
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
# If the sprite does exist
else
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
end
end
# Determine line properties
y = ((i % line_count) * line_height)
width = 640 - 20
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[i])
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# If not on the first sprite
if sprite_index != 0
# Set the scroll percent to 100
@scroll_line = scroll_limit
# Set the scroll bar to the bottom
@scroll_bar.y = 480 - 40
end
end
end
#--------------------------------------------------------------------------
# * Update Console Text
#--------------------------------------------------------------------------
def self.update_scroll
# Set a temporary variable to the scroll bar area
area = Rect.new(640 - 20, 0, 20, 480)
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# If the mouse is over the scrollbar
if Mouse.in_area?(area)
# If the mouse is over the top button
if Mouse.in_area?(640 - 20, 0, 20, 20) && !@slider_drag
# If the button bitmap is not highlighted
if @scroll_bar_button_top.bitmap != @h_scroll_bar_button_top_bmp
# Set the button_bitmap
@scroll_bar_button_top.bitmap = @h_scroll_bar_button_top_bmp
end
# If a click was detected and it is possible to scroll up
if Mouse.repeat?(Mouse::PRIMARY) && @scroll_line > 0
# Scroll up one line
@scroll_line -= 1
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = 480 - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
# If a click was detected and it is not possible to scroll up
elsif Mouse.repeat?(Mouse::PRIMARY)
# Return true
return true
end
# If the mouse is over the bottom scrollbar button
elsif (!@slider_drag &&
Mouse.in_area?(640 - 20, 480 - 20, 20, 20))
# If the button bitmap is not highlighted
if @scroll_bar_button_bottom.bitmap != @h_scroll_bar_button_bottom_bmp
# Set the button_bitmap
@scroll_bar_button_bottom.bitmap = @h_scroll_bar_button_bottom_bmp
end
# If a click was detected and scrolling is not past the limit
if (Mouse.repeat?(Mouse::PRIMARY) && @scroll_line < scroll_limit &&
!@slider_drag)
# Scroll up one line
@scroll_line += 1
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = 480 - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
# If a click was detected and it is not possible to scroll down
elsif Mouse.repeat?(Mouse::PRIMARY)
# Return true
return true
end
# If the mouse is over the scroll bar slider
elsif Mouse.in_area?(Rect.new(640 - 20, @scroll_bar.y, 20, 20))
# If the slider bitmap is not highlighted
if @scroll_bar.bitmap != @h_scroll_bar_bmp
# Set the slider_bitmap
@scroll_bar.bitmap = @h_scroll_bar_bmp
end
# If a click was detected and scrolling is allowed
if Mouse.trigger?(Mouse::PRIMARY) && scroll_limit > 0
# Scroll up one line
@slider_drag = true
end
# If the mouse is over the scroll bar
else
# If a click was detected and scrolling is allowed
if Mouse.trigger?(Mouse::PRIMARY) && scroll_limit > 0 && !@slider_drag
# Set a temporary variable to the current height of the bar
height = 480 - 60
# Set a temporary variable to the percentage of the height chosen
percent = (Mouse.y.to_f / height.to_f)
# Set the scroll position to that percentage
@scroll_line = (scroll_limit.to_f * percent).to_i
end
end
end
# If the mouse is released and the slider is dragging
if @slider_drag && Mouse.release?(Mouse::PRIMARY)
# Set the slider so that it is no longer dragging
@slider_drag = false
# If the scroll bar's slider is active
elsif @slider_drag
# Set a temporary variable to the mouse's y position
mouse_y = Mouse.y
# Force the position within range
mouse_y = 480 - 40 if mouse_y > 480 - 40
mouse_y -= 20
mouse_y = 0 if mouse_y < 0
# set a temporary variable to the scrollbar height
height = 480 - 60
# Calculate the mouse's percentage along the scrollbar
mouse_percent = (mouse_y.to_f / height.to_f)
# Set the scroll position to that percentage
@scroll_line = (scroll_limit.to_f * mouse_percent).to_i
# Set the scroll bar bitmap's y position
@scroll_bar.y = mouse_y + 20
end
# If the mouse is not over the top button
if !Mouse.in_area?(640 - 20, 0, 20, 20)
# If the button bitmap is highlighted
if @scroll_bar_button_top.bitmap != @scroll_bar_button_top_bmp
# Set the button_bitmap
@scroll_bar_button_top.bitmap = @scroll_bar_button_top_bmp
end
end
# If the mouse is not over the bottom scrollbar button
if !Mouse.in_area?(640 - 20, 480 - 20, 20, 20)
# If the button bitmap is not highlighted
if @scroll_bar_button_bottom.bitmap != @scroll_bar_button_bottom_bmp
# Set the button_bitmap
@scroll_bar_button_bottom.bitmap = @scroll_bar_button_bottom_bmp
end
end
# If the mouse is not over the scroll bar slider
if (!@slider_drag &&
!Mouse.in_area?(Rect.new(640 - 20, @scroll_bar.y, 20, 20)))
# If the slider bitmap is not highlighted
if @scroll_bar.bitmap != @scroll_bar_bmp
# Set the slider_bitmap
@scroll_bar.bitmap = @scroll_bar_bmp
end
end
# Set the console's scroll position
@console_viewport.oy = @scroll_line * line_height
end
#--------------------------------------------------------------------------
# * Object Initialization (part 2)
#--------------------------------------------------------------------------
begin
# Set up the script console
draw_initial
# Set the first line of the starting text
@current_command = 'RMXP RGSS Script Console [Version 1.10]'.split(//)
# Update the current line to check for line breaks
self.update_current_line
# Add the current line to the lines array
@copyright += @current_lines
# Set the second line of the starting text
@current_command = 'Copyright <c> 2010-2011 Glitchfinder. All rights'
@current_command += ' reserved.'
@current_command = @current_command.split(//)
# Update the current line to check for line breaks
update_current_line
# Add the current line to the lines array
@copyright += @current_lines
# Reset the current command
@current_command = []
# Reset the current lines array
@current_lines = []
# Dispose the current console
dispose
# Redraw the console
draw_initial
end
end
#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# This class performs title screen processing.
#==============================================================================
class Scene_Title
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
# This class performs map screen processing.
#==============================================================================
class Scene_Map
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
# This class performs menu screen processing.
#==============================================================================
class Scene_Menu
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Item
#------------------------------------------------------------------------------
# This class performs item screen processing.
#==============================================================================
class Scene_Item
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Skill
#------------------------------------------------------------------------------
# This class performs skill screen processing.
#==============================================================================
class Scene_Skill
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Equip
#------------------------------------------------------------------------------
# This class performs equipment screen processing.
#==============================================================================
class Scene_Equip
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Status
#------------------------------------------------------------------------------
# This class performs status screen processing.
#==============================================================================
class Scene_Status
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
# This is a superclass for the save screen and load screen.
#==============================================================================
class Scene_File
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Save
#------------------------------------------------------------------------------
# This class performs save screen processing.
#==============================================================================
class Scene_Save < Scene_File
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Load
#------------------------------------------------------------------------------
# This class performs load screen processing.
#==============================================================================
class Scene_Load < Scene_File
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_End
#------------------------------------------------------------------------------
# This class performs game end screen processing.
#==============================================================================
class Scene_End
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
# This class performs battle screen processing.
#==============================================================================
class Scene_Battle
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Shop
#------------------------------------------------------------------------------
# This class performs shop screen processing.
#==============================================================================
class Scene_Shop
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Name
#------------------------------------------------------------------------------
# This class performs name input screen processing.
#==============================================================================
class Scene_Name
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Gameover
#------------------------------------------------------------------------------
# This class performs game over screen processing.
#==============================================================================
class Scene_Gameover
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Debug
#------------------------------------------------------------------------------
# This class performs debug screen processing.
#==============================================================================
class Scene_Debug
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
RMVX Version
Code:
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
# ** Glitchfinder's Script Console [RPG Maker VX]
# Version 1.10
#------------------------------------------------------------------------------
# This script helps game designers debug their projects by giving them access
# to a fully fubnctional script console in-game.
#==============================================================================
# * Version History
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Version 1.00 ------------------------------------------------- (2010-08-21)
# - Initial version
# - Author: Glitchfinder
# Version 1.10 ------------------------------------------------ (2011-04-15)
# - Fixed crash on F12
# - Fixed version count on startup
# - 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.)
#
# This script requires Glitchfinder's Key Input Module (at least version 1.10)
# and Glitchfinder's Mouse Input Module.
#
# This script is designed in such a way that it is highly recommended that you
# remove it before releasing your game. This is because there is no way to
# keep the player from activating it, if they wish to. For example, players
# can access the default debug menu if they create a shortcut to your game
# that adds the correct instructions to the end of the call, and thus opens
# the game in debug mode.
#
# To activate this script, simply press the ~ key. Since this reads the actual
# text character instead of the key, shift may be required. You may use the
# same key to exit the console.
#
# To set the console to give verbose error output, set the variable
# @backtrace_errors to true. You can undo tghis by setting it to false.
#
# You can bind the console to another object, and operate from within that
# object. To do so, you call @binding = [object_name].set_binding, where
# [object_name] is the name of the object. (For example, calling
# @binding = $scene.set_binding would result in you operating from within the
# current scene's class.) To undo this, you must call
# Script_Console.reset_binding.
#
# This console is designed not to crash, and all errors should give debug
# output. However, if you edit something that would cause the game to crash
# while running, like deleting the command window in Scene_Title, it will
# still crash when you exit the console.
#==============================================================================
# *Glitchfinder's Advice
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# This script is meant for people with at least a basic level of scripting
# knowledge and ability. If you are unsure of your abilities, or don't know
# how to script, then it would be a good idea to avoid this script.
#==============================================================================
# * Contact
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Glitchfinder, the author of this script, may be contacted through his
# website, found at [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]
#
# You may also find Glitchfinder at [url=http://www.hbgames.org]http://www.hbgames.org[/url]
#==============================================================================
# * 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:
# [url=http://www.glitchkey.com]http://www.glitchkey.com[/url]
# [url=http://www.hbgames.org]http://www.hbgames.org[/url]
# 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 and theory, within reason.
#≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
#==============================================================================
# ** Object
#------------------------------------------------------------------------------
# Object is the parent class of all classes in Ruby. Its methods are
# therefore available to all objects unless explicitly overridden.
#==============================================================================
class Object
#--------------------------------------------------------------------------
# * Set Binding
#--------------------------------------------------------------------------
def set_binding
# Create a new process
Proc.new {}
end
end
#==============================================================================
# ** Script_Console
#------------------------------------------------------------------------------
# This is a container for the Script Console data
#==============================================================================
module Script_Console
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
begin
@commands = [] # Commands used
@current_command = [] # Command currently being typed
@backup_command = [] # Backup of the current command
@copyright = [] # Copyright information displayed at the top
@lines = [] # Lines displayed
@current_lines = [] # Current lines
@text_index = 0 # Current index of text cursor
@command_index = 0 # Index of the command repeater
@lines_size = 0 # Backup of the current line length
@scroll_line = 0 # Current scroll position
@font_size = 12 # Console font size
@line_spacing = 2 # Console vertical line spacing
@insert_on = false # Insert flag
@active = false # Active flag
@deactivated = false # Recently deactivated flag
@drawn = false # Console drawn flag
@slider_drag = false # Scroll bar slider drag state
@backtrace_errors = false # Flag to backtrace error messages
@binding = nil # Set to bind to a class
@keystate = Win32API.new('user32.dll', 'GetKeyState', 'I', 'I')
end
#--------------------------------------------------------------------------
# * Get Commands
#--------------------------------------------------------------------------
def self.commands(*args)
# If no arguments were given
if args.empty?
# Return the full commands array
return @commands
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific command in the Script "
message += "Console\nif you feed the commands method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified command
return @commands[args[0].join]
end
end
end
#--------------------------------------------------------------------------
# * Get Lines
#--------------------------------------------------------------------------
def self.lines(*args)
# If no arguments were given
if args.empty?
# Return the full lines array
return @lines
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific line in the Script "
message += "Console\nif you feed the lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified line
return @lines[args[0]]
end
end
end
#--------------------------------------------------------------------------
# * Get Current Lines
#--------------------------------------------------------------------------
def self.current_lines(*args)
# If no arguments were given
if args.empty?
# Return the full current lines array
return @current_lines
# If one argument was given
elsif args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot look up a specific line in the Script "
message += "Console\nif you feed the lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
# If the argument was a Fixnum
else
# Return the specified line
return @current_lines[args[0]]
end
end
end
#--------------------------------------------------------------------------
# * Get Total Lines
#--------------------------------------------------------------------------
def self.total_lines
# Return the total line count
return (@lines.size + @current_lines.size + @copyright.size)
end
#--------------------------------------------------------------------------
# * Get Text Index
#--------------------------------------------------------------------------
def self.text_index
# Return the command index
return @text_index
end
#--------------------------------------------------------------------------
# * Get Command Index
#--------------------------------------------------------------------------
def self.command_index
# Return the command index
return @command_index
end
#--------------------------------------------------------------------------
# * Get Number of Lines to Print
#--------------------------------------------------------------------------
def self.lines_size
# Return the number of lines set to print
return @lines_size
end
#--------------------------------------------------------------------------
# * Get Current Scroll Line
#--------------------------------------------------------------------------
def self.scroll_line
# Return the number of the line at the top of the screen
return @scroll_line
end
#--------------------------------------------------------------------------
# * Get Console Font Size
#--------------------------------------------------------------------------
def self.font_size
# Return the font size
return @font_size
end
#--------------------------------------------------------------------------
# * Get Console Vertical Line Spacing
#--------------------------------------------------------------------------
def self.line_spacing
# Return the number of pixels between lines of text
return @line_spacing
end
#--------------------------------------------------------------------------
# * Get Console Line Height
#--------------------------------------------------------------------------
def self.line_height
# Return the height of a line of text, in pixels
return (@font_size + @line_spacing)
end
#--------------------------------------------------------------------------
# * Get Console Line Count Per Sprite
#--------------------------------------------------------------------------
def self.line_count
# Return the number of lioines in a line sprite
return (@line_bitmap_height / line_height)
end
#--------------------------------------------------------------------------
# * Get Current Command
#--------------------------------------------------------------------------
def self.current_command
# Return the current command
return @current_command.join
end
#--------------------------------------------------------------------------
# * Get Backup Command
#--------------------------------------------------------------------------
def self.backup_command
# Return the backup of the current command
return @backup_command
end
#--------------------------------------------------------------------------
# * Get Insert Flag
#--------------------------------------------------------------------------
def self.insert_on?
# Return insert flag
return @insert_on
end
#--------------------------------------------------------------------------
# * Get Active Flag
#--------------------------------------------------------------------------
def self.active?
# Return active flag
return @active
end
#--------------------------------------------------------------------------
# * Get Drawn Flag
#--------------------------------------------------------------------------
def self.deactivated?
# If the console has just been deactivated
if @deactivated == true
# Set deactivated flag to false and return true
@deactivated = false
return true
end
# Return false
return false
end
#--------------------------------------------------------------------------
# * Get Drawn Flag
#--------------------------------------------------------------------------
def self.drawn?
# Return drawn flag
return @drawn
end
#--------------------------------------------------------------------------
# * Get Slider Dragging Flag
#--------------------------------------------------------------------------
def self.slider_drag?
# Return slider dragging flag
return @slider_drag
end
#--------------------------------------------------------------------------
# * Get Error Backtrace Flag
#--------------------------------------------------------------------------
def self.backtrace_errors?
# Return UK English flag
return @backtrace_errors
end
#--------------------------------------------------------------------------
# * Get Binding
#--------------------------------------------------------------------------
def self.binding
# Return eval binding
return @binding
end
#--------------------------------------------------------------------------
# * Set Commands
#--------------------------------------------------------------------------
def self.set_commands(*args)
# If one argument was given
if args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Array)
# Print an error message
message = "You cannot set the arguments array of the Script "
message += "Console\nif you feed the set_commands method a "
message += args[0].class.to_s + "\ninstead of an Array."
raise(ArgumentError, message)
end
# Set the arguments array
@arguments = args[0]
# If the argument was a Fixnum
elsif args.size == 2
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot set a specific argument in the Script "
message += "Console\nif you feed the set_arguments method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
elsif !args[1].instance_of?(String)
# Print an error message
message = "You cannot set a specific argument in the Script "
message += "Console\nif you feed the set_arguments method a "
message += args[0].class.to_s + "\ninstead of a String."
raise(ArgumentError, message)
end
# Set the specified command
@commands[args[0]] = args[1].split(//)
end
end
#--------------------------------------------------------------------------
# * Set Lines
#--------------------------------------------------------------------------
def self.set_lines(*args)
# If one argument was given
if args.size == 1
# If the argument was not a Fixnum
if !args[0].instance_of?(Array)
# Print an error message
message = "You cannot set the lines array of the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of an Array."
raise(ArgumentError, message)
end
# Set the lines array
@lines = args[0]
# Dispose the console
dispose if @drawn
# Redraw the console
draw_initial if !@drawn
# If the argument was a Fixnum
elsif args.size == 2
if !args[0].instance_of?(Fixnum)
# Print an error message
message = "You cannot set a specific line in the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of a Fixnum."
raise(ArgumentError, message)
elsif !args[1].instance_of?(String)
# Print an error message
message = "You cannot set a specific line in the Script "
message += "Console\nif you feed the set_lines method a "
message += args[0].class.to_s + "\ninstead of a String."
raise(ArgumentError, message)
end
# Set the specified line
@lines[args[0]] = args[1]
# Redraw the line
redraw_line(args[1])
end
end
#--------------------------------------------------------------------------
# * Set Text Index
#--------------------------------------------------------------------------
def self.text_index=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the text index in the Script Console\n"
message += "if you feed the text_index=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = @current_command.size if new_value > @current_command.size
# Set the current text index
@text_index = new_value
end
#--------------------------------------------------------------------------
# * Set Command Index
#--------------------------------------------------------------------------
def self.command_index=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the command index in the Script Console\n"
message += "if you feed the command_index=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = @commands.size if new_value > @commands.size
# Set the current command index
@command_index = new_value
end
#--------------------------------------------------------------------------
# * Set Scroll Line
#--------------------------------------------------------------------------
def self.scroll_line=(new_value)
# If the input is not a Fixnum
if !new_value.instance_of?(Fixnum)
# Print an error message
message = "You cannot set the scroll line in the Script Console\n"
message += "if you feed the scroll_line=(Fixnum) method a\n"
message += new_value.class.to_s + " instead of a Fixnum."
raise(ArgumentError, message)
end
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Correct the value if it is out of range
new_value = 0 if new_value < 0
new_value = scroll_limit if new_value > scroll_limit
# Set the current command index
@scroll_line = new_value
end
#--------------------------------------------------------------------------
# * Set Current Command
#--------------------------------------------------------------------------
def self.current_command=(new_value)
# If the input is not a String
if !new_value.instance_of?(String)
# Print an error message
message = "You cannot set the current command in the Script Console\n"
message += "if you feed the current_command=(String) method a\n"
message += new_value.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# Set the current command index
@current_command = new_value.split(//)
# Update the cursor index
@text_index = @current_command.size if @command_index == @commands.size
# Update current line
update_current_line if @command_index == @commands.size
# Update Console Text
update_console_text if @command_index == @commands.size
end
#--------------------------------------------------------------------------
# * Set Backup Command
#--------------------------------------------------------------------------
def self.backup_command=(new_value)
# If the input is not a String
if !new_value.instance_of?(String)
# Print an error message
message = "You cannot set the backup command in the Script Console\n"
message += "if you feed the backup_command=(String) method a\n"
message += new_value.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# Set the current command index
@backup_command = new_value.split(//)
end
#--------------------------------------------------------------------------
# * Set Insert Flag
#--------------------------------------------------------------------------
def self.insert_on=(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the insert flag in the Script Console\n"
message += "if you feed the insert_on=(boolean) method a\n"
message += new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@insert_on = new_value
# If insert is now on
if @insert_on
# Set the text cursor bitmap
@cursor_sprite.bitmap = @insert_bitmap
# If insert if now off
else
# Set the text cursor bitmap
@cursor_sprite.bitmap = @cursor_bitmap
end
end
#--------------------------------------------------------------------------
# * Set Active Flag
#--------------------------------------------------------------------------
def self.active=(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the active flag in the Script Console\n"
message += "if you feed the active=(boolean) method a\n"
message += new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@active = new_value
# If the console is now active
if @active
# Make the console visible
@console_viewport.visible = true
@scroll_viewport.visible = true
# If the console is now inactive
else
# Hide the console
@console_viewport.visible = false
@scroll_viewport.visible = false
# Set the console to recently deactivated status
@deactivated = true
end
end
#--------------------------------------------------------------------------
# * Set Error Backtrace Flag
#--------------------------------------------------------------------------
def self.backtrace_errors(new_value)
# If the input is not a boolean
if !(new_value.instance_of?(TrueClass) ||
new_value.instance_of?(FalseClass))
# Print an error message
message = "You cannot set the error backtrace flag in the Script "
message += "Console\n if you feed the backtrace_errors=(boolean) method"
message += " a\n" + new_value.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# Set the insert flag
@backtrace_errors = new_value
end
#--------------------------------------------------------------------------
# * Set Binding
#--------------------------------------------------------------------------
def self.set_binding(object)
# Set the binding scope to that of the specified object
@binding = object.binding
end
#--------------------------------------------------------------------------
# * Reset Binding
#--------------------------------------------------------------------------
def self.reset_binding
# Reset the binding
@binding = nil
end
#--------------------------------------------------------------------------
# * Dump Log to Text
#--------------------------------------------------------------------------
def self.dump_log(name = nil)
# If the input is not a String
if !name.instance_of?(String) && name != nil
# Print an error message
message = "You cannot dump a log of the Script Console text\n"
message += "if you feed the dump_log(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If no name was specified
if name == nil
# Get the current time
time = Time.new
# Generate a generic filename
name = 'log_' + time.year.to_s + '_' + time.mon.to_s + '_'
name += time.mday.to_s + '_' + time.hour.to_s + '_' + time.min.to_s
name += '_' + time.sec.to_s + '.txt'
# If the filename is not for a .txt file
elsif name[-4, 4] != '.txt'
# Append the filetype to the end of the filename
name += '.txt'
end
# Create an array of all lines
lines = @lines + @current_lines
# Create a string containing the lines
text = lines.join("\n")
# Create the log file
log = File.new(name, "w")
# Write to the log
log.write(text)
# Close the log file
log.close
end
#--------------------------------------------------------------------------
# * Save Command List
#--------------------------------------------------------------------------
def self.save_commands(name)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot save the commands of the Script Console\n"
message += "if you feed the save_commands(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# Create the command file
file = File.new(name, "wb")
# Write to the file
Marshal.dump(@commands, file)
# Close the file
file.close
end
#--------------------------------------------------------------------------
# * Save Line List
#--------------------------------------------------------------------------
def self.save_output(name)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot save the output of the Script Console\n"
message += "if you feed the save_output(String) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# Create the output file
file = File.new(name, "wb")
# Write to the file
Marshal.dump(@lines, file)
# Close the file
file.close
end
#--------------------------------------------------------------------------
# * Load Command List
#--------------------------------------------------------------------------
def self.load_commands(name, after = true)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot load the commands of the Script Console\n"
message += "if you feed the load_commands(String, Boolean) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the input is not a boolean
if !(after.instance_of?(TrueClass) || after.instance_of?(FalseClass))
# Print an error message
message = "You cannot load the commands of the Script Console\n"
message += "if you feed the load_commands(String, Boolean) method a\n"
message += after.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# If the file does not exist
if !FileTest.exist?(name)
# Print an error message
message = 'Cannot find the file ' + name + '.'
raise(ENOENT, message)
end
# Load the command file
file = File.open(name, "rb")
# Write to the file
new_commands = Marshal.load(file)
# Close the file
file.close
# If not set to load the old commands before the new ones
if after == false
# Set a temporary variable to the command list size
size = new_commands.size
# Iterate through the list of old commands
for i in 0...size
# Set the current command index
index = (size - 1) - i
# If the new command already exists
if @commands.include?(new_commands[index])
# Delete the command
new_commands.delete_at(index)
end
end
# Add the old commands to the new command array
new_commands += @commands
# Reset the command array
@commands = new_commands
# If set to load the old commands after the new ones
else
# Set a temporary variable to the command list size
size = @commands.size
# Iterate through the list of old commands
for i in 0...size
# Set the current command index
index = (size - 1) - i
# If the new command already exists
if new_commands.include?(@commands[index])
# Delete the command
@commands.delete_at(index)
end
end
# Add the new commands to the old command list
@commands += new_commands
end
# Reset the command index
@command_index = @commands.size
end
#--------------------------------------------------------------------------
# * Load Line List
#--------------------------------------------------------------------------
def self.load_output(name, after = true)
# If the input is not a String
if !name.instance_of?(String)
# Print an error message
message = "You cannot load the output of the Script Console\n"
message += "if you feed the load_output(String, Boolean) method a\n"
message += name.class.to_s + " instead of a String."
raise(ArgumentError, message)
end
# If the input is not a boolean
if !(after.instance_of?(TrueClass) || after.instance_of?(FalseClass))
# Print an error message
message = "You cannot load the output of the Script Console\n"
message += "if you feed the load_output(String, Boolean) method a\n"
message += after.class.to_s + " instead of true or false."
raise(ArgumentError, message)
end
# If the filename is not for a .bin file
if name[-4, 4] != '.bin'
# Append the filetype to the end of the filename
name += '.bin'
end
# If the file does not exist
if !FileTest.exist?(name)
# Print an error message
message = 'Cannot find the file ' + name + '.'
raise(ENOENT, message)
end
# Load the output file
file = File.open(name, "rb")
# Write to the file
new_lines = Marshal.load(file)
# Close the file
file.close
# If not set to load the old lines before the new ones
if after == false
# Add the old commands to the new command array
new_lines += @lines
# Reset the command array
@lines = new_lines
# Freeze the graphics
Graphics.freeze
# Dispose the Script Console
dispose
# Redraw the console
draw_initial
# Set the console to active
self.active = true
# Reload the graphics
Graphics.transition(1)
# If set to load the old lines after the new ones
else
# Add the new commands to the old command list
@lines += new_lines
# Clear the @lines_size variable
#@lines_size = 0
# Set the number of lines to print
@lines_size += new_lines.size
# Update the console text
update_text
end
end
#--------------------------------------------------------------------------
# * Clear Output
#--------------------------------------------------------------------------
def self.clear
# Delete output lines
@lines = []
# Freeze the graphics
Graphics.freeze
# Dispose the Script Console
dispose
# Redraw the console
draw_initial
# Set the console to active
self.active = true
# Set the scroll line to 0
@scroll_line = 0
# Reload the graphics
Graphics.transition(1)
end
#--------------------------------------------------------------------------
# * Input Non-Executed Text
#--------------------------------------------------------------------------
def self.input_text
# Update the current line of text
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
end
#--------------------------------------------------------------------------
# * Set Up Console Screen
#--------------------------------------------------------------------------
def self.draw_initial
# Create colors
@black = Color.new(0, 0, 0, 255)
@white = Color.new(255, 255, 255, 255)
# Create the console's viewport
@console_viewport = Viewport.new(0, 0, Graphics.width - 20, Graphics.height)
@console_viewport.z = 1000
# Hide the console's viewport
@console_viewport.visible = false
# Create the background bitmap for the console
console_background = Bitmap.new(32, 32)
console_background.fill_rect(0, 0, 32, 32, @black)
# Create the console bacground
@console_background = Plane.new(@console_viewport)
# Set the console background bitmap
@console_background.bitmap = console_background
# Create the console scroll bar viewport
@scroll_viewport = Viewport.new(Graphics.width - 20, 0, 20, Graphics.height)
@scroll_viewport.z = 1000
# Hide the console scroll bar viewport
@scroll_viewport.visible = false
# Create the scroll bar background bitmap
scroll_bar_background_bmp = Bitmap.new(20, Graphics.height - 40)
scroll_bar_background_bmp.fill_rect(0, 0, 20, Graphics.height - 40, @black)
scroll_bar_background_bmp.fill_rect(0, 0, 1, Graphics.height - 40, @white)
scroll_bar_background_bmp.fill_rect(19, 0, 1,Graphics.height - 40, @white)
# Create the scroll bar slider bitmap
@scroll_bar_bmp = Bitmap.new(20, 20)
@scroll_bar_bmp.blt(0, 0, scroll_bar_background_bmp, Rect.new(0, 0, 20, 20))
@scroll_bar_bmp.fill_rect(0, 0, 20, 1, @white)
@scroll_bar_bmp.fill_rect(0, 19, 20, 1, @white)
# Creare the top scroll bar button bitmap
@scroll_bar_button_top_bmp = @scroll_bar_bmp.clone
@scroll_bar_button_top_bmp.fill_rect(6, 11, 8, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(7, 10, 6, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(8, 9, 4, 1, @white)
@scroll_bar_button_top_bmp.fill_rect(9, 8, 2, 1, @white)
# Creare the bottom scroll bar button bitmap
@scroll_bar_button_bottom_bmp = @scroll_bar_bmp.clone
@scroll_bar_button_bottom_bmp.fill_rect(6, 8, 8, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(7, 9, 6, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(8, 10, 4, 1, @white)
@scroll_bar_button_bottom_bmp.fill_rect(9, 11, 2, 1, @white)
# Create the highlighted scroll bar slider bitmap
@h_scroll_bar_bmp = Bitmap.new(20, 20)
@h_scroll_bar_bmp.fill_rect(0, 0, 20, 20, @white)
# Creare the highlighted top scroll bar button bitmap
@h_scroll_bar_button_top_bmp = @h_scroll_bar_bmp.clone
@h_scroll_bar_button_top_bmp.fill_rect(6, 11, 8, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(7, 10, 6, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(8, 9, 4, 1, @black)
@h_scroll_bar_button_top_bmp.fill_rect(9, 8, 2, 1, @black)
# Creare the highlighted bottom scroll bar button bitmap
@h_scroll_bar_button_bottom_bmp = @h_scroll_bar_bmp.clone
@h_scroll_bar_button_bottom_bmp.fill_rect(6, 8, 8, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(7, 9, 6, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(8, 10, 4, 1, @black)
@h_scroll_bar_button_bottom_bmp.fill_rect(9, 11, 2, 1, @black)
# Create the scroll bar background
@scroll_bar_background = Sprite.new(@scroll_viewport)
@scroll_bar_background.y = 20
@scroll_bar_background.bitmap = scroll_bar_background_bmp
# Create the scroll bar slider
@scroll_bar = Sprite.new(@scroll_viewport)
@scroll_bar.y = 20
@scroll_bar.z = 10
@scroll_bar.bitmap = @scroll_bar_bmp
# Create the top scroll bar button
@scroll_bar_button_top = Sprite.new(@scroll_viewport)
@scroll_bar_button_top.y = 0
@scroll_bar_button_top.bitmap = @scroll_bar_button_top_bmp
# Create the bottom scroll bar button
@scroll_bar_button_bottom = Sprite.new(@scroll_viewport)
@scroll_bar_button_bottom.y = Graphics.height - 20
@scroll_bar_button_bottom.bitmap = @scroll_bar_button_bottom_bmp
# Set console text properties
@console_font = Font.new("Lucida Console", @font_size)
@console_font.color = @white
# Create array to store line sprites
@line_sprites = []
# Create blank line sprite bitmap
@line_bitmap_height = ((Graphics.height / line_height) * line_height)
@line_bitmap = Bitmap.new(Graphics.width - 20, @line_bitmap_height)
@line_bitmap.font = @console_font
# Create first line sprite
sprite = Sprite.new(@console_viewport)
sprite.bitmap = @line_bitmap.clone
sprite.z = 100
@line_sprites[0] = sprite
# Create an array that merges the old lines and the current line
lines = @copyright + @lines + @current_lines
# Iterate through lines array
for i in 0...lines.size
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# Calculate line sprite index
sprite_index = (i / line_count)
# If the sprite in question does not exist
if @line_sprites[sprite_index] == nil
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Determine line properties
y = ((i % (@line_bitmap_height / line_height)) * line_height)
width = Graphics.width - 20
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[i])
end
# Create the text cursor bitmaps
@cursor_bitmap = Bitmap.new(7, line_height)
@insert_bitmap = @cursor_bitmap.clone
@cursor_bitmap.fill_rect(0, 0, 1, line_height, @white)
@insert_bitmap.fill_rect(0, 12, 7, 2, @white)
# Create the cursor sprite
@cursor_sprite = Sprite.new(@console_viewport)
@cursor_sprite.x = (@text_index *
@line_sprites[0].bitmap.text_size('O').width)
if ((@cursor_sprite.x + @line_sprites[0].bitmap.text_size('O').width) >
@line_sprites[0].width)
@cursor_sprite.x = 0
end
@cursor_sprite.y = lines.size * line_height
@cursor_sprite.y -= line_height unless @current_lines.empty?
@cursor_sprite.bitmap = @cursor_bitmap
# Set the cursor sprite timer
@cursor_timer = Graphics.frame_rate / 2
# Set the console drawn flag to true
@drawn = true
end
#--------------------------------------------------------------------------
# * Dispose Console Screen
#--------------------------------------------------------------------------
def self.dispose
# Dispose the console background
@console_background.bitmap.dispose
@console_background.dispose
# Dispose the scroll bar background
@scroll_bar_background.bitmap.dispose
@scroll_bar_background.dispose
# Dispose the scroll bar slider
@scroll_bar_bmp.dispose
@h_scroll_bar_bmp.dispose
@scroll_bar.dispose
# Dispose the top scroll bar button
@scroll_bar_button_top_bmp.dispose
@h_scroll_bar_button_top_bmp.dispose
@scroll_bar_button_top.dispose
# Dispose the bottom scroll bar button
@scroll_bar_button_bottom_bmp.dispose
@h_scroll_bar_button_bottom_bmp.dispose
@scroll_bar_button_bottom.dispose
# Iterate through the line sprite array
for sprite in @line_sprites
# Skip if not a sprite
next unless sprite.instance_of?(Sprite)
# Dispose the sprite's bitmap
sprite.bitmap.dispose
# Dispose the sprite
sprite.dispose
end
# Dispose the default line sprite bitmap
@line_bitmap.dispose
# Dispose the cursor
@cursor_bitmap.dispose
@insert_bitmap.dispose
@cursor_sprite.dispose
# Set the console drawn flag to false
@drawn = false
end
#--------------------------------------------------------------------------
# * Redraw Line
#--------------------------------------------------------------------------
def self.redraw_line(index)
# Return if the line is out of bounds
return if index < 0 || index >= @lines.size + @copyright.size
# Set a temporary variable to sprite 0
sprite_index = 0
# Iterate through the lines
until index < line_count
# Subtract the number of lines in a sprite
line -= line_count
# Increment the sprite index
sprite_index += 1
end
# If the line sprite exists
if @line_sprites[sprite_index] != nil
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
# If the sprite does not exist
else
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Set the line's y position to 0
y = 0
# Set the line's width
width = Graphics.width - 20
# Set the index to the beginning of the sprite
index = sprite_index * line_height
# Iterate through the lines on the sprite
for i in 0...line_count
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[index])
# Increment the line index
index += 1
# Increment the y position
y += line_height
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def self.update
# Reset the line size
@lines_size = 0
# Set a temporary variable to false
graphics_update = false
# Set the temporary variable to true if control input was detected
graphics_update = true if update_control_input
# If text input was detected
if update_text_input || graphics_update
# If the current command was not the selected one
if @command_index != @commands.size
# Set the current command to the newly selected command
@current_command = @commands[@command_index].clone
# Reset the current command if it is equal to nil
@current_command = [] if @current_command == nil
# Set the command index to the newly selected command
@command_index = @commands.size
# Set the text index to the end of the new command if it is too small
@text_index = @current_command.size if (@text_index >
@current_command.size)
# Update the text input with the new command
update_text_input
end
# Increment the text index unless a control character was called
@text_index += 1 unless graphics_update
# If insert is on, and the text index is not at the end of the line
if @insert_on && @text_index < @current_command.size
# Delete the currently selected character
@current_command.delete_at(@text_index)
end
# Set the temporary variable to true
graphics_update = true
end
# Update the cursor
update_cursor
# If input was detected
if graphics_update
# Update the current line
update_current_line
# Update the text view
update_text
end
# Update the console's scroll position
update_scroll
end
#--------------------------------------------------------------------------
# * Update Control Input
#--------------------------------------------------------------------------
def self.update_control_input
# If the Escape key is being pressed
if Keys.trigger?(Keys::ESCAPE)
# Set the console to inactive
self.active = false
# Return that no character input was given
return false
# If the Tab key is being pressed
elsif Keys.trigger?(Keys::TAB)
# Add two spaces to the current command
@current_command.insert(@text_index, ' ')
@current_command.insert(@text_index, ' ')
# Increment the text index
@text_index += 2
# Return true
return true
# If the Backspace key is being pressed
elsif Keys.repeat?(Keys::BACKSPACE)
# If there are no characters to remove
if @text_index == 0
# Return false
return false
end
# Remove a character from the command
@current_command.delete_at(@text_index - 1)
# Decrement the text index
@text_index -= 1
# Return true
return true
# If the Delete key is being pressed
elsif (Keys.repeat?(Keys::DELETE) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.repeat?(Keys::DECIMAL)))
# If there are no characters to remove
if @text_index >= @current_command.size
# Return false
return false
end
# Remove a character from the command
@current_command.delete_at(@text_index)
# Return true
return true
# If the Insert key is being pressed
elsif (Keys.trigger?(Keys::INSERT) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.trigger?(Keys::NUMPAD0)))
# Change the insert key state
@insert_on = ((@insert_on == true) ? false : true)
# If insert is now on
if @insert_on
# Set the text cursor bitmap
@cursor_sprite.bitmap = @insert_bitmap
# If insert if now off
else
# Set the text cursor bitmap
@cursor_sprite.bitmap = @cursor_bitmap
end
# Return false
return false
# If the Left key is being pressed
elsif (Keys.repeat?(Keys::LEFT) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD4)))
# If the text index is 0
if @text_index <= 0
# Return false
return false
end
# Decrement the text index
@text_index -= 1
# Return false
return false
# If the Right key is being pressed
elsif (Keys.repeat?(Keys::RIGHT) ||
((@keystate.call(Keys::NUMLOCK) == 0) && Keys.repeat?(Keys::NUMPAD6)))
# If the text index is at the end of the line
if @text_index >= @current_command.size
# Return false
return false
end
# Increment the text index
@text_index += 1
# Return false
return false
# If the Up key is being pressed
elsif (Keys.repeat?(Keys::UP) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD8)))
# If the command index is 0
if @command_index <= 0
# Return false
return false
end
# If the command index is set to the current command
if @command_index == @commands.size
# Set the backup command to the current command
@backup_command = @current_command
end
# Decrement the text index
@command_index -= 1
# If the new commend is not nil
if @commands[@command_index] != nil
# Set the text index to the end of the new line
@text_index = @commands[@command_index].size
# If the command does not exist
else
# Set the text index to 0
@text_index = 0
end
# Return true
return true
# If the Down key is being pressed
elsif (Keys.repeat?(Keys::DOWN) || ((@keystate.call(Keys::NUMLOCK) == 0) &&
Keys.repeat?(Keys::NUMPAD2)))
# If the command index is at the latest command
if @command_index >= @commands.size
# Return false
return false
end
# Increment the command index
@command_index += 1
# If the new commend is not nil
if @commands[@command_index] != nil
# Set the text index to the end of the new line
@text_index = @commands[@command_index].size
# If the new command is set to the current command
elsif @command_index == @commands.size
# Set the current command to the backup command
@current_command = @backup_command
# Set the tezxt index to the currently selected command
@text_index = @current_command.size
# If the command does not exist
else
# Set the current command to an empty line
@current_command = []
# Set the text index to 0
@text_index = 0
end
# Return true
return true
# If the Enter key is being pressed
elsif Keys.trigger?(Keys::RETURN)
# Interpret the command
interpret_command
# Return true
return true
end
end
#--------------------------------------------------------------------------
# * Update Text Input
#--------------------------------------------------------------------------
def self.update_text_input
# Get the currently pressed character
character = Keys.character_repeat
# Return false if no chracter was returned
return false if !character
# If the character was a ~
if character[0] == 126
# Set the console to inactive
self.active = false
# Return false to prevent input
return false
end
# Insert the returned character
@current_command.insert(@text_index, character.strip)
# If the stripped character is an empty string
if character.strip == ''
# Insert a space into the command array
@current_command.insert(@text_index, ' ')
end
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Set the slider to idle, if being dragged
@slider_drag = false
# If scrolling is possible
if scroll_limit > 0
# Set the scroll line to the bottom
@scroll_line = scroll_limit
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = Graphics.height - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
end
# Return true if a character was inserted
return true
end
#--------------------------------------------------------------------------
# * Interpret Command
#--------------------------------------------------------------------------
def self.interpret_command
# If the command index is not set to the current command
if @command_index != @commands.size
# Set the current command to the one selected
@current_command = @commands[@command_index].clone
# Set the current command to an empty string if it is nil
@current_command = [] if @current_command == nil
end
# If the current command has already been entered
if @commands.include?(@current_command)
# Delete the existing command
@commands.delete_at(@commands.index(@current_command))
end
# Add the current command to the commands array
@commands.push(@current_command)
# Set the command index to the latest command
@command_index = @commands.size
# Add the current lines to the lines array
@lines += @current_lines
# Backup current line length
@lines_size = @current_lines.size
# Clear the current line array
@current_lines = []
# Set the text cursor index to 0
@text_index = 0
# Set up a block for debugging purposes
begin
# If a binding is set
if @binding != nil
# Evaluate the currently selected command
eval @current_command.join, @binding.binding
# If a binding is not set
else
# Evaluate the currently selected command
eval @current_command.join
end
# If there was a syntax error
rescue SyntaxError => exception
# Print the error
print_error(exception)
# If there was an error
rescue => exception
# Print the error
print_error(exception)
# If a binding error was detected
if exception.message.include?("private method `binding' called for")
# Reset method binding
@binding = nil
end
end
# Reset the current command
@current_command = []
# Reset the text index
@text_index = 0
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# Set the slider to idle, if being dragged
@slider_drag = false
# If scrolling is possible
if scroll_limit > 0
# Set the scroll line to the bottom
@scroll_line = scroll_limit
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = Graphics.height - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
end
end
#--------------------------------------------------------------------------
# * Update Cursor Position
#--------------------------------------------------------------------------
def self.print_error(exception)
# Add the exception class to the current line array
@current_command = exception.class.to_s.split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
# Add the exception message to the current line array
@current_command = exception.message.split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
# Return if not set to backtrace errors
return if !@backtrace_errors
# Add the exception backtrace to the current line array
for i in 0...exception.backtrace.size
@current_command = exception.backtrace[i].split(//)
update_current_line
# Add the current line array to the line array
@lines += @current_lines
# Backup current line length
@lines_size += @current_lines.size
# Empty the current line array
@current_lines = []
end
end
#--------------------------------------------------------------------------
# * Update Cursor Position
#--------------------------------------------------------------------------
def self.update_cursor
# If the cursor timer has run out
if @cursor_timer <= 0
# Set the cursor's visibility
@cursor_sprite.visible = (@cursor_sprite.visible == true ? false : true)
# Set the curosr timer to half a second
@cursor_timer = Graphics.frame_rate / 2
# If the cursor timer is still running
else
# Decrement the cursor timer
@cursor_timer -= 1
end
# set a temporary variable to the width of a character
character_width = @line_sprites[0].bitmap.text_size('O').width
# set a temporary variable to the width of a line, in characters
line_width = ((@line_sprites[0].width / character_width) * character_width)
# set the cursor sprite's x position
@cursor_sprite.x = (@text_index * character_width) % line_width
# Set blank y offset
y_offset = 0
# If there is more than one line in the current command
if @current_lines.size > 1
# Calculate the text index, from the end of the last line
text_index = @current_command.size - @text_index
# If the last line is not full
if @current_lines[-1].split(//).size != (line_width / character_width)
# Remove any incomplete lines from the new index
text_index -= @current_lines[-1].split(//).size
# Increment the line offset unless at the beginning of a line
y_offset += 1 unless @cursor_sprite.x == 0
end
# Calculate the line offset
y_offset += ((text_index * character_width) / line_width)
# Modify offset to reflect y positioning
y_offset *= line_height
end
# Calculate the curosr sprite's y position
cursor_y = total_lines * line_height
# If the current line is not empty
if !@current_lines.empty?
# If the cursor is not at the beginning of a new line
unless ((@cursor_sprite.x == 0) &&
(@current_command.size - @text_index == 0))
# Move the cursor up a line
cursor_y -= line_height
end
end
# Subtract the cursor's y offset
cursor_y -= y_offset
# Set the cursor sprite's y positon
@cursor_sprite.y = cursor_y
end
#--------------------------------------------------------------------------
# * Update Current Line
#--------------------------------------------------------------------------
def self.update_current_line
# If the currently selected command is not the current command
if @command_index != @commands.size
# Set the current command to the newly selected command
@current_command = @commands[@command_index].clone
end
# Set the new command to a blank string if it is nil
@current_command = [] if @current_command == nil
# Set the text index to the end of the line, if it is beyond the end
@text_index = @current_command.size if @text_index > @current_command.size
# Set a temporary variable to the width of a character
character_width = @line_sprites[0].bitmap.text_size('O').width
# Set a temporary variable to the width of a line, in characters
line_width = (@line_sprites[0].width / character_width)
# Reset the current lines
@current_lines = []
# Set a blank line
line = ''
# Iterate through the current command
for i in 0...@current_command.size
# Add the specifiec character to the new line
line += @current_command[i].to_s
# If the line is the maximum width
if line.split(//).size == line_width
# Add the new line to the current line list
@current_lines.push(line)
# Reset the current line
line = ''
end
end
# Add the line to the current line list if it is not empty
@current_lines.push(line) if !line.empty?
end
#--------------------------------------------------------------------------
# * Update Console Text
#--------------------------------------------------------------------------
def self.update_text
# Set a temporary variable to the old line array
old_lines = @copyright.dup + @lines.dup
# Initialize the sprite count
sprite_index = 0
# Until the line array is not greater than the number of lines in a sprite
until (old_lines.size <= (line_count + @lines_size))
# Iterate through the number of lines in a srite
for i in 0...line_count
# Remove the first line in the line array
old_lines.shift
end
# Increment the sprite count
sprite_index += 1
end
# If the line sprite exists
if @line_sprites[sprite_index] != nil
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
# If the sprite does not exist
else
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
end
# Add the current lines to the old line array
lines = old_lines + @current_lines
# Iterate through the line array
for i in 0...lines.size
# Skip if the line is not a String
next if !lines[i].instance_of?(String)
# if the line is on the next sprite
if (i % line_count) == 0 && i != 0
# Increment the sprite index
sprite_index += 1
# If the sprite in question does not exist
if @line_sprites[sprite_index] == nil
# Create a new line sprite
sprite = Sprite.new(@console_viewport)
sprite.y = sprite_index * @line_bitmap_height
sprite.z = 100
sprite.bitmap = @line_bitmap.clone
@line_sprites[sprite_index] = sprite
# If the sprite does exist
else
# Dispose the current line sprite's bitmap
@line_sprites[sprite_index].bitmap.dispose
# Set a blank bitmap to the current line sprite
@line_sprites[sprite_index].bitmap = @line_bitmap.clone
end
end
# Determine line properties
y = ((i % line_count) * line_height)
width = Graphics.width - 20
# Generate console text
@line_sprites[sprite_index].bitmap.draw_text(0, y, width, line_height,
lines[i])
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# If not on the first sprite
if sprite_index != 0
# Set the scroll percent to 100
@scroll_line = scroll_limit
# Set the scroll bar to the bottom
@scroll_bar.y = Graphics.height - 40
end
end
end
#--------------------------------------------------------------------------
# * Update Console Text
#--------------------------------------------------------------------------
def self.update_scroll
# Set a temporary variable to the scroll bar area
area = Rect.new(Graphics.width - 20, 0, 20, Graphics.height)
# Set a temporary variable to the scroll limit
scroll_limit = (total_lines - line_count)
# Increment the scroll limit if no text has been entered
scroll_limit += 1 if @current_lines.empty?
# If the mouse is over the scrollbar
if Mouse.in_area?(area)
# If the mouse is over the top button
if Mouse.in_area?(Graphics.width - 20, 0, 20, 20) && !@slider_drag
# If the button bitmap is not highlighted
if @scroll_bar_button_top.bitmap != @h_scroll_bar_button_top_bmp
# Set the button_bitmap
@scroll_bar_button_top.bitmap = @h_scroll_bar_button_top_bmp
end
# If a click was detected and it is possible to scroll up
if Mouse.repeat?(Mouse::PRIMARY) && @scroll_line > 0
# Scroll up one line
@scroll_line -= 1
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = Graphics.height - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
# If a click was detected and it is not possible to scroll up
elsif Mouse.repeat?(Mouse::PRIMARY)
# Return true
return true
end
# If the mouse is over the bottom scrollbar button
elsif (!@slider_drag &&
Mouse.in_area?(Graphics.width - 20, Graphics.height - 20, 20, 20))
# If the button bitmap is not highlighted
if @scroll_bar_button_bottom.bitmap != @h_scroll_bar_button_bottom_bmp
# Set the button_bitmap
@scroll_bar_button_bottom.bitmap = @h_scroll_bar_button_bottom_bmp
end
# If a click was detected and scrolling is not past the limit
if (Mouse.repeat?(Mouse::PRIMARY) && @scroll_line < scroll_limit &&
!@slider_drag)
# Scroll up one line
@scroll_line += 1
# Calculate the scroll line percentage
percent = (@scroll_line.to_f / scroll_limit.to_f)
# Set a temporary variable to the height of the scrollbar
height = Graphics.height - 60
# Set the y position of the scroll bar slider
@scroll_bar.y = ((percent * height.to_f).to_i + 20)
# If a click was detected and it is not possible to scroll down
elsif Mouse.repeat?(Mouse::PRIMARY)
# Return true
return true
end
# If the mouse is over the scroll bar slider
elsif Mouse.in_area?(Rect.new(Graphics.width - 20, @scroll_bar.y, 20, 20))
# If the slider bitmap is not highlighted
if @scroll_bar.bitmap != @h_scroll_bar_bmp
# Set the slider_bitmap
@scroll_bar.bitmap = @h_scroll_bar_bmp
end
# If a click was detected and scrolling is allowed
if Mouse.trigger?(Mouse::PRIMARY) && scroll_limit > 0
# Scroll up one line
@slider_drag = true
end
# If the mouse is over the scroll bar
else
# If a click was detected and scrolling is allowed
if Mouse.trigger?(Mouse::PRIMARY) && scroll_limit > 0 && !@slider_drag
# Set a temporary variable to the current height of the bar
height = Graphics.height - 60
# Set a temporary variable to the percentage of the height chosen
percent = (Mouse.y.to_f / height.to_f)
# Set the scroll position to that percentage
@scroll_line = (scroll_limit.to_f * percent).to_i
end
end
end
# If the mouse is released and the slider is dragging
if @slider_drag && Mouse.release?(Mouse::PRIMARY)
# Set the slider so that it is no longer dragging
@slider_drag = false
# If the scroll bar's slider is active
elsif @slider_drag
# Set a temporary variable to the mouse's y position
mouse_y = Mouse.y
# Force the position within range
mouse_y = Graphics.height - 40 if mouse_y > Graphics.height - 40
mouse_y -= 20
mouse_y = 0 if mouse_y < 0
# set a temporary variable to the scrollbar height
height = Graphics.height - 60
# Calculate the mouse's percentage along the scrollbar
mouse_percent = (mouse_y.to_f / height.to_f)
# Set the scroll position to that percentage
@scroll_line = (scroll_limit.to_f * mouse_percent).to_i
# Set the scroll bar bitmap's y position
@scroll_bar.y = mouse_y + 20
end
# If the mouse is not over the top button
if !Mouse.in_area?(Graphics.width - 20, 0, 20, 20)
# If the button bitmap is highlighted
if @scroll_bar_button_top.bitmap != @scroll_bar_button_top_bmp
# Set the button_bitmap
@scroll_bar_button_top.bitmap = @scroll_bar_button_top_bmp
end
end
# If the mouse is not over the bottom scrollbar button
if !Mouse.in_area?(Graphics.width - 20, Graphics.height - 20, 20, 20)
# If the button bitmap is not highlighted
if @scroll_bar_button_bottom.bitmap != @scroll_bar_button_bottom_bmp
# Set the button_bitmap
@scroll_bar_button_bottom.bitmap = @scroll_bar_button_bottom_bmp
end
end
# If the mouse is not over the scroll bar slider
if (!@slider_drag &&
!Mouse.in_area?(Rect.new(Graphics.width - 20, @scroll_bar.y, 20, 20)))
# If the slider bitmap is not highlighted
if @scroll_bar.bitmap != @scroll_bar_bmp
# Set the slider_bitmap
@scroll_bar.bitmap = @scroll_bar_bmp
end
end
# Set the console's scroll position
@console_viewport.oy = @scroll_line * line_height
end
#--------------------------------------------------------------------------
# * Object Initialization (part 2)
#--------------------------------------------------------------------------
begin
# Set up the script console
draw_initial
# Set the first line of the starting text
@current_command = 'RMVX RGSS2 Script Console [Version 1.10]'.split(//)
# Update the current line to check for line breaks
self.update_current_line
# Add the current line to the lines array
@copyright += @current_lines
# Set the second line of the starting text
@current_command = 'Copyright <c> 2010-2011 Glitchfinder. All rights'
@current_command += ' reserved.'
@current_command = @current_command.split(//)
# Update the current line to check for line breaks
update_current_line
# Add the current line to the lines array
@copyright += @current_lines
# Reset the current command
@current_command = []
# Reset the current lines array
@current_lines = []
# Dispose the current console
dispose
# Redraw the console
draw_initial
end
end
#==============================================================================
# ** Scene_Base
#------------------------------------------------------------------------------
# This is a superclass of all scenes in the game.
#==============================================================================
class Scene_Base
#--------------------------------------------------------------------------
# * Start processing
#--------------------------------------------------------------------------
def start
# If the console has not been initialized
unless Script_Console.drawn?
# Set up the script console
Script_Console.draw_initial
end
end
#--------------------------------------------------------------------------
# * Post-Start Processing
#--------------------------------------------------------------------------
def post_start
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# If the script console is active
if Script_Console.active?
# Update the script console
Script_Console.update
# If the script console is inactive
else
# Get the currently pressed character
character = Keys.character_repeat
# If there was a character returned
unless !character
# If the character was a ~
if character[0] == 126
# If the script console was not recently deactivated
unless Script_Console.deactivated?
# Activate the script console
Script_Console.active = true
end
end
end
end
end
end
#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# This class performs the title screen processing.
#==============================================================================
class Scene_Title < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Map
#------------------------------------------------------------------------------
# This class performs the map screen processing.
#==============================================================================
class Scene_Map < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Menu
#------------------------------------------------------------------------------
# This class performs the menu screen processing.
#==============================================================================
class Scene_Menu < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Item
#------------------------------------------------------------------------------
# This class performs the item screen processing.
#==============================================================================
class Scene_Item < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Skill
#------------------------------------------------------------------------------
# This class performs the skill screen processing.
#==============================================================================
class Scene_Skill < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Equip
#------------------------------------------------------------------------------
# This class performs the equipment screen processing.
#==============================================================================
class Scene_Equip < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Status
#------------------------------------------------------------------------------
# This class performs the status screen processing.
#==============================================================================
class Scene_Status < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_File
#------------------------------------------------------------------------------
# This class performs the save and load screen processing.
#==============================================================================
class Scene_File < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_End
#------------------------------------------------------------------------------
# This class performs game end screen processing.
#==============================================================================
class Scene_End < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Shop
#------------------------------------------------------------------------------
# This class performs shop screen processing.
#==============================================================================
class Scene_Shop < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Name
#------------------------------------------------------------------------------
# This class performs name input screen processing.
#==============================================================================
class Scene_Name < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Debug
#------------------------------------------------------------------------------
# This class performs debug screen processing.
#==============================================================================
class Scene_Debug < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Battle
#------------------------------------------------------------------------------
# This class performs battle screen processing.
#==============================================================================
class Scene_Battle < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
#==============================================================================
# ** Scene_Gameover
#------------------------------------------------------------------------------
# This class performs game over screen processing.
#==============================================================================
class Scene_Gameover < Scene_Base
#--------------------------------------------------------------------------
# * Alias Methods
#--------------------------------------------------------------------------
unless method_defined?(:script_console_update)
# Alias the basic action result method
alias script_console_update update
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Return if the script console is active
return if Script_Console.active?
# Call the original update method
script_console_update
end
end
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.)
This script requires Glitchfinder's Key Input Module (at least version 1.10) and Glitchfinder's Mouse Input Module.
This script is designed in such a way that it is highly recommended that you remove it before releasing your game. This is because there is no way to keep the player from activating it, if they wish to. For example, players can access the default debug menu if they create a shortcut to your game that adds the correct instructions to the end of the call, and thus opens the game in debug mode.
To activate this script, simply press the ~ key. Since this reads the actual text character instead of the key, shift may be required. You may use the same key to exit the console.
To set the console to give verbose error output, set the variable @backtrace_errors to true. You can undo tghis by setting it to false.
You can bind the console to another object, and operate from within that object. To do so, you call @binding = [object_name].set_binding, where [object_name] is the name of the object. (For example, calling @binding = $scene.set_binding would result in you operating from within the current scene's class.) To undo this, you must call Script_Console.reset_binding.
This console is designed not to crash, and all errors should give debug output. However, if you edit something that would cause the game to crash while running, like deleting the command window in Scene_Title, it will still crash when you exit the console.
Requirements
Glitchfinder's Key Input Module
Glitchfinder's Mouse Input Module
Terms and Conditions
- 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.
- This script may only be hosted at the following domains:
http://www.glitchkey.com
http://www.hbgames.org - If you wish to host this script elsewhere, please contact Glitchfinder.
- 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.
- The script header must remain intact at all times.
- Glitchfinder remains the sole owner of this code. He may modify or revoke this license at any time, for any reason.
- 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.
- This license applies to all code derived from the code within this script.
- If you use this script within your project, you must include visible credit to Glitchfinder, within reason.