Redefining default object with a plugin conflict

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,824
Reaction score
1,883
First Language
Spanish
Primarily Uses
RMVXA
I need to partially redefine Spriteset_Map from the default script to insert a custom call to a different function, while at the same time NOT interfering with a plugin that also redefines it.

here's how it is structured:
-Spriteset_Map
-Battle Plugin
-my plugin

Battle Plugin has it's own initialize block, as expected:
Code:
class Spriteset_Map
 ...
 alias original_init initialize
 def initialize(*args)
   original_init(*args)
   if $game_party.in_battle
    <new instructions>
   ...
   end
 end
end


my plugin requires a new instruction to be injected in between the original ones, so I copied the original block as it was, effectively restoring it to it's original structure.
Code:
class Spriteset_Map
  def initialize
    create_viewports
    create_tilemap
    create_parallax
    create_characters
    create_shadow
    create_weather
    create_pictures
    create_lighting if Lighting::ENABLE_LIGHTING     #my edit, because, reasons.
    create_timer
    update(true)
  end
  ...
  ...
end

now, this overrides the battle spriteset's initialize, which needs to be run because:
Code:
...
   if $game_party.in_battle
     ...
     create_cursor
    ...
   end
...

which goes to:
Code:
def create_cursor
  @cursor = Battle_Cursor.new
end

and since it never runs:
Spriteset.cursor.x -> NoMethod
nuevo-1.jpg

is there any way to "inject" the line I need, without modifying the structure too much, while still having the battle plugin run last?
like, can I override a top script with a bottom script while having another one in the middle not notice the difference?
 
Last edited:

Andar

Veteran
Veteran
Joined
Mar 5, 2013
Messages
36,679
Reaction score
9,855
First Language
German
Primarily Uses
RMMV
you're making and using scripts for VXA, VXA never had plugins.

and what you want should be done using alias correctly - which you didn't.

the important commands are
Code:
alias original_init initialize
 def initialize(*args)
   original_init(*args)


alias renames the original function, so that the script writer can use the original name for its own.
then in the first step of the new function the old version is called and the new code executed after that.
this results in a sequence of aliased functions to be executed when the original initialize is called.

and you have two ways to influence that sequence without causing problems or undefines:
1) you can decide if the original is called before or after or between your added functions when you alias it in your script.
2) by changing the order of the scripts that alias the function, you can influence if the other additions to the chain are added before or after your additions.

If you need to go between the original function commands instead of adding before or after them, then you need to replace that function - but in that case you need to make sure that your replacement is the first script that runs, so that all other scripts alias your version of the function.
Because you cannot retain the aliases added before you override the original, you can only allow other scripts to alias after your override.

and that also means that if you're using two scripts that override instead of alias, they will always remain incompatible and would have to get a patch to rewrite both to function.
 

AkiraKotatsuhime

炬燵姫
Veteran
Joined
Jan 2, 2013
Messages
207
Reaction score
155
First Language
DE / ドイツ語
Primarily Uses
N/A
Stuff like that is why I'm not a big fan of adding (multiple) scripts to the list that mess with already existing functions instead of manually editing the defaults, but okay, let's go for it. What Andar says is right, overrides must be done before any ALIAS is occuring.

Also, there is a detail about ALIAS you should know. It's a well-known old cause of problems in all versions of RGSS because of how the F12-reset of the game-executable is programmed. You should always add a layer of security to it. If not, it will create an infinite loop of selfcalls, hangup and crash.

Ruby:
alias original_init initialize unless $@

This is dirty code, but working in RGSS/2/3. It prevents repeatings of ALIAS execution if the game was reset because "Reset" or "RGSSReset" is an Exception-throw (which makes "$@" contain a value). If you prefer to do it as clean as possible, you can do it this way:

Ruby:
alias original_init initialize unless respond_to?(:original_init)

Okay, not perfectly clean, but according to Core 1.9.2 docs, "method_defined?", which is better than "respond_to?", didn't exist back then (or wasn't part of Object, didn't check if it works in RGSS3).

~炬燵あ
 

Roninator2

Gamer
Veteran
Joined
May 22, 2016
Messages
4,256
Reaction score
1,157
First Language
English
Primarily Uses
RMVXA
If you have to recreate the initialize method you can try in integrate all the functions that it uses.
Ruby:
[CODE=none]class Spriteset_Map
def initialize
create_viewports
create_tilemap
create_parallax
create_characters
create_shadow
create_weather
create_pictures
   if $game_party.in_battle
    <new instructions>
     create_cursor
     ...
   end
create_lighting if Lighting::ENABLE_LIGHTING #my edit, because, reasons.
create_timer
update(true)
end
...
...
end
[/CODE]
but a layered alias would normally be the best way. However I do get how sometimes you want your method to run in the middle of the other calls. Which would make an alias not work since all calls to methods would run before yours.
 
Last edited:

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,824
Reaction score
1,883
First Language
Spanish
Primarily Uses
RMVXA
you're making and using scripts for VXA, VXA never had plugins.
well, potatos...

and what you want should be done using alias correctly - which you didn't.
I did, right at the beginning when I wrote this.
it just happened that my insert has to be added on top of the spriteset's call to update so I had to rewrite the block, and I didn't realize it would conflict with GTBS until I ran a battle.
all of this works in the normal map.
it's during the battle that it doesn't because the battle scene also calls a map object, and has that edit.
I'm now thinking that I might be able to rewrite the method locally only at the map scene, by editing the variable that carries the spriteset.

changing the order of the scripts that alias the function
nope.
not viable at all, since the GTBS system does like 80% of the work.
I want it to be the main script, and add on top of it.

If you have to recreate the initialize method you can try in integrate all the functions that it uses.
I'm thinking that it might update twice, causing some lag.
I'm trying to leave my edit as non-invasive as possible to control it just from the module.

not a big fan of adding (multiple) scripts to the list that mess with already existing functions instead of manually editing the defaults
:D
editing the defaults it's what I've always done XD
now that I try to do it clean, this happens lol

"Reset" or "RGSSReset" is an Exception-throw (which makes "$@" contain a value)
I might have another script to take care of that globally.
never had an error with reset, so it's probably taken care of, way before I did any modifications to anything.

what I'm thinking is, since the battle scene needs to alias it's call and I'm just adding a fix to the map scene, I might just do this:

Code:
class Scene_Map < Scene_Base
 def create_spriteset
    @spriteset = Spriteset_Map.new
    @spriteset.lighting = Lighting.new
    @spriteset.update
  end
end

where spriteset.lighting = Lighting.new would be the same thing as calling initialize, then go to create_lighting, then back to initialize, and down to update.
the only thing that loads after the lighting is the timer, which I can't care less about right now, but all of this must always load before the battle scene's override.
as this, neither scene should care what the other does.
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,824
Reaction score
1,883
First Language
Spanish
Primarily Uses
RMVXA
(voice of Mr Miyagi)
"LIGHTS ONNNN..... LIGHTS OFFFF."

nuevo-1.jpg

nuevo-3.jpg

running in map and battle scene, event-based, directly-interactible and remotely-triggered picture-based and procedure-based lights.
one page.
no event commands.

.....yeah, I can fly.


I'm putting this up for public testing, if anyone wants to try.
I will not be supporting this release for the moment as this was more of a side gig, so use carefully.
 
Last edited:

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
492
Reaction score
206
First Language
English
Primarily Uses
RMXP
Actually it could have been solved by just aliasing the original Spriteset#initialize method, followed by the new lighting method and ending with a call to update it right away.
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,824
Reaction score
1,883
First Language
Spanish
Primarily Uses
RMVXA
@kyonides that would have updated it twice, one before loading and one after.
I don't need this to run just on the map, I need it to run on the battle scene which also calls a map object, and wasn't sure about the lag.
there's an incompatibility there that requires this to be loaded this way.
better to be safe this way, than sorry.

this is actually a test bed for another thing I'm working on, that draws things on top of other things, and I needed to figure out how to add another layer to the map without breaking it.
as I was working on this new thing, I remembered.... I think I forgot to dispose of the layer correctly and maybe there's an extra refresh in there that's not needed.
but eh... it works.

EDIT:
*done*
that thing? that *thing* I just mentioned? *it's working* :D
 

kyonides

Reforged is laughable
Veteran
Joined
Nov 17, 2019
Messages
492
Reaction score
206
First Language
English
Primarily Uses
RMXP
Well, then you could call the new sprite's update method instead of Spriteset's update.
 

gstv87

Veteran
Veteran
Joined
Oct 20, 2015
Messages
2,824
Reaction score
1,883
First Language
Spanish
Primarily Uses
RMVXA
that's what I ended up doing.... kinda...
the light layer is added to the spriteset, hooked up to the map update, so IT directs the update when loading, but at each individual update I just update that sprite instead of th whole spriteset.
that was the reason behind this: each glow sprite had to be it's own thing, so I could toggle them on and off at will.
I had to know how much I could squeeze the spriteset's flexibility to do *this* that I'm working on now.
 

Latest Threads

Latest Profile Posts

Can hopefully move onto doing visual effects and sound design now. :kaophew:

The latest RPG Maker Games Critique with Studio Blue starts now! Let's jump into Kamigami: Clash of the Gods!

Title Screen 100% Finished
Evangeline.png
I'm starting to enjoy doing pixel art! Not to mention it's getting easier to do commissions :kaojoy:

Forum statistics

Threads
124,363
Messages
1,163,052
Members
163,153
Latest member
Senetix
Top