Reload Scripts at Runtime

Started by G_G, August 17, 2011, 11:57:28 pm

Previous topic - Next topic

G_G

When Blizzard said something about it being really difficult to reload scripts while playing. While looking through Blizzard's script extractor, why couldn't we just re-eval all the scripts? For the most part it worked. But then when it reloaded main it went back to the title screen. But then I just added a little check to see if the script name was in the Exclude.
Exclude = ["Main"]
for script in load_data("Data/Scripts.rxdata")
 if (!Exclude.include?(script[1]))
   eval(Zlib::Inflate.inflate(script[2]))
 end
end


Then just for safety precautions, just reload the scene you're on.
$scene = $scene.class.new


It seemed to work alright without any issues. Of course I'm expecting F0, Blizzard, or someone else to come in here and prove me wrong. xD Anyways its a quick workaround if you're tired of reloading your game constantly.

This isn't the full package, you'll have to put this in your own method or event or whatever. And for scripts you don't want to load, put the name that you entered in the Exclude array.

Blizzard

Reloading the scripts can cause unexpected errors. One of the first cases that would come to my mind would be the F12 reset bug fix. The $game variable is set the first time and when you run all scripts a second time, the variable would cause the script to abort right at the beginning. As you said, it's not impossible to do, but generally it's a bad idea. You would need a special script to "reset" the state of the Ruby VM before you eval all scripts again. This cannot be automated as it depends on the scripts you are using.

Also, when you re-eval all scripts, you have to keep in mind that all these classes already exist. Your old definitions would be overwritten and the aliasing applied afterwards can cause even more expected behavior, especially in classes/modules that are not yours. If you alias e.g. Input#update once, then a second run would alias it another time with the same name and actually just cause the whole thing to turn into an infinite recursive loop. Using safety precautions everywhere such as "if defined?()" is not much of a option either as you would have to yet again edit all the scripts.

It's not really possible to do it in an easy way. Deal with it. xD
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

Does this actually change anything, or just refresh the scene?  Without every re-entering "main", I don't see how it would actually change any of the globals, since they never lose scope, and they are never re-initialized.  Just at a glance, the only line that I see even doing anything is "$scene = $scene.class.new".  I'm too lazy to test at the moment, though. :P
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Zeriab

You can open a new instance of the game and close the current one.

G_G

Quote from: Blizzard on August 18, 2011, 02:19:24 am
Reloading the scripts can cause unexpected errors. One of the first cases that would come to my mind would be the F12 reset bug fix. The $game variable is set the first time and when you run all scripts a second time, the variable would cause the script to abort right at the beginning. As you said, it's not impossible to do, but generally it's a bad idea. You would need a special script to "reset" the state of the Ruby VM before you eval all scripts again. This cannot be automated as it depends on the scripts you are using.

Also, when you re-eval all scripts, you have to keep in mind that all these classes already exist. Your old definitions would be overwritten and the aliasing applied afterwards can cause even more expected behavior, especially in classes/modules that are not yours. If you alias e.g. Input#update once, then a second run would alias it another time with the same name and actually just cause the whole thing to turn into an infinite recursive loop. Using safety precautions everywhere such as "if defined?()" is not much of a option either as you would have to yet again edit all the scripts.

It's not really possible to do it in an easy way. Deal with it. xD


Yeah I know. :S I knew you'd bring your lingo to show me up again. xD

Quote from: ForeverZer0 on August 18, 2011, 02:21:32 am
Does this actually change anything, or just refresh the scene?  Without every re-entering "main", I don't see how it would actually change any of the globals, since they never lose scope, and they are never re-initialized.  Just at a glance, the only line that I see even doing anything is "$scene = $scene.class.new".  I'm too lazy to test at the moment, though. :P


You'd have to reinitialize the globals if you modified the global classes. This would more or so be helpful with on the fly menu positioning or something. This was more or so a discussion type thing and not a "here's a script, copypasta and use it." kind of thread.

Quote from: Zeriab on August 18, 2011, 03:05:58 am
You can open a new instance of the game and close the current one.


True and thats probably the best way to go at it. But for people who have issues loading MIDI files with RMXP this would be better if it was perfected that is.

Anyways I know this method isn't even near half-way to being perfect but it works for dirty jobs like positioning menu windows and whatnot.

ForeverZer0

Quote from: game_guy on August 18, 2011, 05:03:01 am
You'd have to reinitialize the globals if you modified the global classes. This would more or so be helpful with on the fly menu positioning or something. This was more or so a discussion type thing and not a "here's a script, copypasta and use it." kind of thread.


Yeah, I know what this is, I'm saying what is being accomplished by re-loading the scripts into Ruby's scope?  They are still the same as they were when the game loaded, your not actually changing anything except creating errors that Blizz mentioned above. The only actual thing that changes anything is the re-initializing the scene, but no other variables except what it changes are going to modified. 
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

G_G

I'm aware. What I meant is that I expected people to already know that or to figure that out and finish the script themselves.

nathmatt

y use
$scene = $scene.class.new


instead of just

$scene.initialize


Join Dead Frontier
Sorry, I will no longer be scripting for RMXP. I may or may not give support for my scripts. I don't have the will to script in RGSS anymore.
My script


ForeverZer0

Quote from: nathmatt on August 18, 2011, 01:37:59 pm
y use
$scene = $scene.class.new


instead of just

$scene.initialize



Because "initialize" is a private method and will result in a crash if you attempt to call it directly.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.