If someone, anyone, dares convert my shitty Ar Tonelico script for Ace, I'll commit suicide by watching 300 episodes of Naruto in a row.
RGSS3 is vastly superior to RGSS2 and especially RGSS1. Just because we aren't remaking the exact same stuff doesn't mean it's bad. It means we're writing different scripts, better scripts. Not huge messes that break compatibility with everything else, but smaller, more compatible scripts. It also means you need to pick more carefully and combine what you really need instead of plugging something because it looks cool.
If someone, anyone, dares convert my shitty Ar Tonelico script for Ace, I'll commit suicide by watching 300 episodes of Naruto in a row.
RGSS3 is vastly superior to RGSS2 and especially RGSS1. Just because we aren't remaking the exact same stuff doesn't mean it's bad. It means we're writing different scripts, better scripts. Not huge messes that break compatibility with everything else, but smaller, more compatible scripts. It also means you need to pick more carefully and combine what you really need instead of plugging something because it looks cool.
Thanks I'm glad you guys found some use for it! I made a tiny update to the autoreload script in the OP. Now the code that is evaluated from the interactive console will be rescued if it throws an error, and the error message will be printed to the console instead of crashing the game. Because it is really really easy to do something wrong and crash the game when you play around with the console. (haha I have no idea why I didn't think of putting this in until now...)
So everyone who has Ruby installed on their computer has used IRB, the built in interactive console, right? Just in case you don't know what I am talking about you can try an online version of IRB here: http://tryruby.org/
With IRB you can run any valid Ruby code, and you will see the result immediately in the console window. You can even define methods and classes in IRB and play with them in IRB.
So in this tutorial I'll explain how do implement a similiar feature for VX Ace. The goal is to have a console window where you can type in Ruby code that then gets evaluated in the context of your game. For example, typing the following at the console:
> SceneManager.call(Scene_Title)
Should take you to the title screen.
Let's get started. First follow the steps in my autoreload tutorial, which can be found here http://www.rpgmakerv...n-vx-ace-trial/ right now (I'll probably make it it's own tutorial soon).
Now that we have our autoreload.rb file in place, we are going to make some minor changes to it and then implement our interactive console Ruby script.
When everything is done the system will work like this:
This time around, let's start by making some small changes to autoreload.rb to handle the special case of the console file:
module Autoreload
puts "Autoreload loaded"
SCRIPT_PATH = "C:/AceScripts"
CONSOLE_NAME = "console.rb"
WAIT_TIME = 60 # wait 60 frames (1 second) before we check for changes
@counter = 0
def self.reload!
@counter += 1
if @counter == WAIT_TIME
@counter = 0
else
return
end
@scripts ||= read_all_scripts # the first time this line is executed set @scripts to our scripts
new_scripts = read_all_scripts
@scripts.each_with_index do |script, index|
name = script[:filename]
case name
when CONSOLE_NAME
handle_console
when script[:source] != new_scripts[index][:source] && !__FILE__.include?(name)
puts "reloading #{name}"
load_script(name)
end
end
@scripts = new_scripts
end
def self.read_all_scripts
Dir[sCRIPT_PATH + "/*.rb"].map do |file|
{filename: File.basename(file), source: File.read(file)}
end
end
def self.load_script(filename)
load File.join(SCRIPT_PATH, filename)
end
def self.handle_console
path = File.join(SCRIPT_PATH, CONSOLE_NAME)
begin
load path
rescue => e
puts "Console error: #{e.message}"
end
File.open(path, "w") { |console| console.write("") }
end
end
class Scene_Base
alias_method :autoreload_update_orig, :update
def update
Autoreload.reload!
autoreload_update_orig
end
end
So now if console.rb is the file autoreload will call the handle_console method, which will load whatever is is in the console.rb file at the time and evaluate it as Ruby code, and then delete everything (writing a blank string) from the file.
Now let's code the interactive console Ruby script (I'll call mine ic.rb). It just needs to write the Ruby code that is entered in the cmd.exe window to the console.rb file. However, it would be nice if it supported class and method definitions all that stuff too, which is not too hard to implement.
So basically, what ic.rb should do is that it should write any valid Ruby code to the console.rb file. What i mean by valid is that it should not write the following: def a_method(a, v)
if that is all that's been entered, because you need a closing end statement to make that code valid.
So to implement this we'll create a buffer that will hold the code that's been entered thus far, and we'll only write the buffer to console.rb if it is valid Ruby code (meaning it will not raise a SyntaxError). So here is our ic.rb code (and by the way, i put ic.rb in a folder called 'console' inside the script folder so it won't get autoloaded into Ace)
require 'stringio'
WRITE_FILE = File.join(Dir.getwd, "../console.rb")
$stdout = StringIO.new
buffer = "" # a string buffer that will hold our code
def buffer_valid?(buffer)
begin
begin
eval buffer
rescue SyntaxError
return false
end
rescue Exception
return true
end
true # no exception
end
loop do
line = gets
exit if line.chomp == "EXIT"
buffer << line
if buffer_valid?(buffer)
File.open(WRITE_FILE, "a") do |f|
f.write(buffer)
buffer.clear
end
end
end
So the main loop here reads lines from standard input, adds them to the buffer (which is just a string), checks if the buffer is valid Ruby code, and writes it to console.rb if it is. There are two more interesting bits in this code: the StringIO part and the buffer_valid? method.
I set the global variable $stdout to a new StringIO object. StringIO is a class from the Ruby standard library that is a string that acts like a file (or IO) object. So you can use methods like read, readlines, seek and so on on a StringIO object. The reason I am assigning it to $stdout is because we want to suppress any output when we run ic.rb with the Ruby interpreter. For example, if I enter the following code in the interactive console
> puts "woot!"
I don't want to see "woot!" in the interactive console window, I just want to see it in the VX Ace console. When you use the methods puts and print in Ruby, they actually get called on the $stdout object like this: $stdout.puts "woot!"
This means that if we set $stdout to some other object, that object will become the receiver of the puts and print calls. In practice this means that our puts and print methods will be called on the StringIO object, and thus their result won't be shown on the screen.
Now on to the buffer_valid? method. This method will take a string, evaluate it as Ruby code and return true if it is valid Ruby code or false if it is not. When I say valid in this context that means that it is syntactically valid. We don't care if it raises any other errors like say NoMethodError or NameError because it will be evaluated in the context of our Ace game.
So to implement this method we have a nested exception check that first sees if the code raises a SyntaxError and if it does the method will return false, but if the code raises any other error, or no error, it is considered valid Ruby, and the method returns true.
Since we do not write to console.rb unless the code is valid, you can enter for example "def woot(x,y)" in the interactive console and then go back to your Ace game and you won't get an error. The code will only be loaded and executed once it is valid (in this case once you add a closing "end").
That's all there's to it! You can exit the ic.rb loop by typing "EXIT" (all caps). And here's another tip: if you are using Windows 7 (this most likely works on Vista as well) you can alternate between the two most recently active windows by pressing ALT+TAB. So by pressing ALT+TAB you can switch between the interactive console and your game fast and easy.
And by the way, you need to have Ruby installed to run the ic.rb script. You can download an easy installer here: http://www.rubyinstaller.org
Yep, that's how << works, just as Kread explained. It's quite interesting how it's implemented too. When you do something like $game_temp.effect_sprites << sprite it looks like << is a built in language operator, but it is actually a method call! (and that is why it does different things when called on an array, string or IO object - you're actually calling the << method on that object). This means that you can implement your own version of << if you want to like this:
So that's a pretty useless class that overrides the << method so that it calls unshift instead (which adds an object to the beginning of the array, as opposed to the end of the array). As you see it's defined just as a normal method with a parenthesis and argument list (object) but you don't need to call it like a normal method (in which case it would look like this my_array.<<("woot") which still works by the way because this is what happens behind the scenes!). The reason you can omit the dot and add a space is to make it look more natural, and more operator like.
The same is true for most other "operators" such as +, +=, -= and so on.