[RGSS3] [SOLVED] YANFLY COMMAND EQUIP & LUNA ENGINE WORKS
Posts
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
Good news: I think I figured out how to get Yanfly's Command Equip to work with the Luna Engine. Bad news: it requires a defunct Window_EquipStatus, a pretty important component of the equip scene. Hopeful news: I think I may know what to do, but I have no clue how to go about doing it. Hence the topic.
First, here's the temporary solution: Go to YEA's Equip engine line 1109 and add:
Just below the line: @last_item = item. Now Yanfly's Command Equip should work during battle:
Don't mind the battle HUD. That's an issue that can come later if this can work.
Battle HUD aside, do you notice something odd? That's right: the price you pay is that you can't see the changes in parameters when you highlight the individual equips. They still occur, don't worry, but you can no longer see it.
Now comment that line out, because the rest of my process doesn't have that line in. I just mentioned it so anyone who's fine with not seeing parameter changes can now use the script.
The reason the line is added is because the game crashes is due to the very next line:
In battle, the Luna Engine adds extra classes/properties to actors that Marshal's dump method doesn't recognize (mostly sprite properties). These new classes have neither marshal_dump nor marshal_load(obj) methods defined, so the game crashes. Well, okay, that's easy enough to fix. Those new classes aren't necessary for the equip scene to function, so creating some blank functions just to keep the game from crashing should work. After doing this for all the classes that cause the game to crash, I've got this little piece of code:
I run the program and... the game still crashes. However, it's no longer because of a lack of Marshal dumps. Instead, I've got:
That. And here, unfortunately, is where I'm stuck. It appears that something's screwy with marshal_load(obj) now that it won't even recognize the info. I don't think I messed anything up too badly, but I could be very wrong.
Now, I'm aware that the Command Equip script is listed as incompatible with the Luna Engine, and I'm also aware that, even if I can figure this out, there's no promise that it'll make everything work right. However, I've gotten this far in getting it to work, I feel like it's not much more before it'll work as intended unless I royally screwed something up with my current adjustment.
If anyone sees something I don't, I'd really appreciate it.
First, here's the temporary solution: Go to YEA's Equip engine line 1109 and add:
return if $game_party.in_battle
Just below the line: @last_item = item. Now Yanfly's Command Equip should work during battle:

Don't mind the battle HUD. That's an issue that can come later if this can work.
Battle HUD aside, do you notice something odd? That's right: the price you pay is that you can't see the changes in parameters when you highlight the individual equips. They still occur, don't worry, but you can no longer see it.
Now comment that line out, because the rest of my process doesn't have that line in. I just mentioned it so anyone who's fine with not seeing parameter changes can now use the script.
The reason the line is added is because the game crashes is due to the very next line:
temp_actor = Marshal.load(Marshal.dump(@actor))
In battle, the Luna Engine adds extra classes/properties to actors that Marshal's dump method doesn't recognize (mostly sprite properties). These new classes have neither marshal_dump nor marshal_load(obj) methods defined, so the game crashes. Well, okay, that's easy enough to fix. Those new classes aren't necessary for the equip scene to function, so creating some blank functions just to keep the game from crashing should work. After doing this for all the classes that cause the game to crash, I've got this little piece of code:
class Sprite_Base def marshal_dump; end def marshal_load(obj); end end class Sprite def marshal_dump; end def marshal_load(obj); end end class Bitmap def marshal_dump; end def marshal_load(obj); end end class Window_BattleActor < Window_BattleStatus def marshal_dump; end def marshal_load(obj); end end class Font def marshal_dump; end def marshal_load(obj); end end class Method def marshal_dump; end end class Viewport def marshal_dump; end end
I run the program and... the game still crashes. However, it's no longer because of a lack of Marshal dumps. Instead, I've got:

That. And here, unfortunately, is where I'm stuck. It appears that something's screwy with marshal_load(obj) now that it won't even recognize the info. I don't think I messed anything up too badly, but I could be very wrong.
Now, I'm aware that the Command Equip script is listed as incompatible with the Luna Engine, and I'm also aware that, even if I can figure this out, there's no promise that it'll make everything work right. However, I've gotten this far in getting it to work, I feel like it's not much more before it'll work as intended unless I royally screwed something up with my current adjustment.
If anyone sees something I don't, I'd really appreciate it.
Don't use marshal to deep copy an object, use this instead. Then replace
with
with the deep copy code from SO pasted somewhere in your game
temp_actor = Marshal.load(Marshal.dump(@actor))
with
temp_actor = @actor.deep_copy
with the deep copy code from SO pasted somewhere in your game
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
Well, this solution prevents the game from crashing, so yay! Unfortunately, unless I mislabeled something, the deep_copy isn't actually making a copy of the actor. On the field equip menu, I see this:

The selected sword changes a few of the character's parameters. Both sets of stats, however, are the altered versions, not a before/after comparison. What's worse, this messes up the actor's equip slots. Newly equipped items get deleted (not just unequipped!), and the newly equipped weapon isn't taken out of my inventory.
EDIT: I tested it some more, and it seems the actor's equip slots are deleted even without changing equips. Just selecting it, looking through the available options, and hitting cancel causes deletion.
EDIT2: This exact same result can be replicated by replacing
with
Without the need for SO's code, which tells me I'm doing something wrong. Just can't figure out what...

The selected sword changes a few of the character's parameters. Both sets of stats, however, are the altered versions, not a before/after comparison. What's worse, this messes up the actor's equip slots. Newly equipped items get deleted (not just unequipped!), and the newly equipped weapon isn't taken out of my inventory.
EDIT: I tested it some more, and it seems the actor's equip slots are deleted even without changing equips. Just selecting it, looking through the available options, and hitting cancel causes deletion.
EDIT2: This exact same result can be replicated by replacing
temp_actor = @actor.deep_copy
temp_actor = @actor.clone
Without the need for SO's code, which tells me I'm doing something wrong. Just can't figure out what...
Damnit, that should be creating a deep copy! All the issues sounds like it didn't copy the object instances inside of the actor object. I admit I haven't tested SO's code in Ace so maybe I missed something. I'll give it a more indepth look tonight when I get home from work.
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
I'd appreciate that, thanks! I tried something myself, but I'm not sure if it's the best solution.
*Redacted because that was definitely a bad idea.*
*Redacted because that was definitely a bad idea.*
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
Update on the situation: GRS, I tested your solution on the Luna Engine Base and a fresh new project. Both tests ended in the same result: a deep_copy of the actor was not created.
What's really puzzling me is that I looked online for deep_copy solutions in Ruby, and I'm greeted with either the same result as you posted or a recommendation to just use the clone function. Neither of which produce the right result.
This is making me think that the issue isn't so much an incompatibility issue as it is a possible issue with RGSS3. Does anyone know which functions/settings/whatever Enterbrain modified for VX Ace? That could go a long way to figuring out what's going on here. I'll keep trying different things in the meantime. GRS, any luck on your end?
What's really puzzling me is that I looked online for deep_copy solutions in Ruby, and I'm greeted with either the same result as you posted or a recommendation to just use the clone function. Neither of which produce the right result.
This is making me think that the issue isn't so much an incompatibility issue as it is a possible issue with RGSS3. Does anyone know which functions/settings/whatever Enterbrain modified for VX Ace? That could go a long way to figuring out what's going on here. I'll keep trying different things in the meantime. GRS, any luck on your end?
I completely forgot about this the entire weekend, sorry!
I'm not sure what bits of ruby are missing in RGSS3 but I certainly wouldn't put it past EB to leave bits out (in RMMV one if the first things I found out is that isNan(obj) is missing in their ECMA engine because ???). One possible solution is to just make our own actor copy code since that's all that's needed in your situation. Something like
that'll copy all the important bits. It'll have to be done by hand though. I do want to look more into SO's deep copy because that'll fix all kinds of script compatibility issues for whoever decided to put non-serializable data in a class that others assumed would remain serializable.

I'm not sure what bits of ruby are missing in RGSS3 but I certainly wouldn't put it past EB to leave bits out (in RMMV one if the first things I found out is that isNan(obj) is missing in their ECMA engine because ???). One possible solution is to just make our own actor copy code since that's all that's needed in your situation. Something like
temp_actor = Actor.new(@actor)
that'll copy all the important bits. It'll have to be done by hand though. I do want to look more into SO's deep copy because that'll fix all kinds of script compatibility issues for whoever decided to put non-serializable data in a class that others assumed would remain serializable.
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
No worries!
Your solution was actually the one I tried earlier but redacted. Granted, it IS the closest we've gotten to a working solution. I tried the line you showed, but that caused the game to crash. The line that works is
And it works. It'll change the equipment and show the before/after comparison for you parameters. Almost. If there are any changes in stats from stat-up items, that will not be reflected in the before/after comparison. Unless the copy of the stats are what you meant when you say "done by hand"
Your solution was actually the one I tried earlier but redacted. Granted, it IS the closest we've gotten to a working solution. I tried the line you showed, but that caused the game to crash. The line that works is
temp_actor = Game_Actor.new(@actor.id)
And it works. It'll change the equipment and show the before/after comparison for you parameters. Almost. If there are any changes in stats from stat-up items, that will not be reflected in the before/after comparison. Unless the copy of the stats are what you meant when you say "done by hand"
Haha, I should've thought my snippet a bit more thoroughly. I meant make our own clone style method but only for actors that would copy the instance variables over (like the stat ups, current class, equipment, etc.). So more like, with your bit of code:
with
I don't have the Actor's internal structure available on-hand so I can't make my example more explicit. Array values should be deep copied and the Marshal load/dump will work in this case (since we're just doing the explicit data arrays and not the entire class with the luna landmines hidden in them)
temp_actor = Game_Actor.new(@actor.id) temp_actor.copy_from(@actor)
with
class Game_Actor < Game_Battler def copy_from(actor) # copy stuff like statups from the passed actor, read access may need to be given so that we can copy the appropriate stuff @statups = Marshal.load(Marshal.dump(actor.statups)) @equipment = Marshal.load(Marshal.dump(actor.equipment)) # etc.. end end
I don't have the Actor's internal structure available on-hand so I can't make my example more explicit. Array values should be deep copied and the Marshal load/dump will work in this case (since we're just doing the explicit data arrays and not the entire class with the luna landmines hidden in them)
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
If it's not one thing, it's another -_-
The property we're looking for here is this method
This collects all the different modifications to the stats, including item use. However, this include changes made from equipment too, so we can't just copy over this property in the copy_from method.
Even if we could, the copying of equipment is crashing the game.
This line is causing the crash
I have no idea how this is happening.
The property we're looking for here is this method
def param_plus(param_id) equips.compact.inject(super) {|r, item| r += item.params[param_id] } end
This collects all the different modifications to the stats, including item use. However, this include changes made from equipment too, so we can't just copy over this property in the copy_from method.
Even if we could, the copying of equipment is crashing the game.
@equips = Marshal.load(Marshal.dump(actor.equips))
This line is causing the crash

I have no idea how this is happening.
They way it was deep copying turned out to be really... lacking. Numeric/True/False can't be cloned the way it was doing it (they are just set values that can't be copied) and how it was doing arrays wasn't doing a deep copy of them. I just expanded some use cases on classes and got this:
It worked in a vanilla Ace project where I replaced the Marshal.load/dump line in Window_EquipItem and it looked to work fine... except that there's a three point mystery discrepancy in the temp_actor that I haven't found the cause of yet. Haven't found any other issues yet but it's a pretty light test so far (weapon and some stat up items).
e: Oops, meant there's a 3 point stat difference in defense even when nothing touches it. Varies a bit between the default actors too.
class Object def deep_clone return @deep_cloning_obj if @deep_cloning @deep_cloning_obj = clone @deep_cloning_obj.instance_variables.each do |var| print "Cloning #{var}\n" val = @deep_cloning_obj.instance_variable_get(var) begin @deep_cloning = true val = val.deep_clone rescue TypeError print "TypeError occured :( #{$!} \n" next ensure @deep_cloning = false end @deep_cloning_obj.instance_variable_set(var, val) end deep_cloning_obj = @deep_cloning_obj @deep_cloning_obj = nil deep_cloning_obj end end class Array def deep_clone return map { |x| x.deep_clone } end end class Numeric def deep_clone return self end end class FalseClass def deep_clone return self end end class TrueClass def deep_clone return self end end class NilClass def deep_clone return self end end
e: Oops, meant there's a 3 point stat difference in defense even when nothing touches it. Varies a bit between the default actors too.
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
I'm looking at it myself. It looks like the stat changes from each individual piece of equipment isn't registering with the others. I tested it by creating a piece of armor that boosts all parameters by 1 and a weapon that makes no changes. When I highlight the weapon with the armor equipped, the stat parameters all drop down by 1.
EDIT: Here's what I mean:

No actual changes are made to the stats outside of the equipment's parameters. It just looks that way from the status window.
EDIT: Here's what I mean:


No actual changes are made to the stats outside of the equipment's parameters. It just looks that way from the status window.
Ahh, that explains it. I was poking in the entirely wrong place. I'll look more into the gear itself then and see what horrible mistake I made.
e: Looks like... the deep_clone isn't working arrays of objects. Primitives are fine, so I'm overlooking something again!
e2: Or not. hmmmmmmmmm
e: Looks like... the deep_clone isn't working arrays of objects. Primitives are fine, so I'm overlooking something again!
e2: Or not. hmmmmmmmmm
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
Thanks man! I wish there was more I could do to help.
Found the sneaky bugger. The deep_clone was in fact too aggressive. It would clone the class reference of Game_BaseItems which would trip up its own code because it no longer had an idea what the RPG::BaseItem class associated with the Game_BaseItem was! Simply not cloning a class is sufficient to get the deep_clone to work.
Updated code:
No more missing 3 DEF in my two second test project! Let me know how it turns out on your end.
Updated code:
class Object def deep_clone return @deep_cloning_obj if @deep_cloning @deep_cloning_obj = clone @deep_cloning_obj.instance_variables.each do |var| val = @deep_cloning_obj.instance_variable_get(var) begin @deep_cloning = true if(val.is_a? Class) val = val else val = val.deep_clone end rescue TypeError next ensure @deep_cloning = false end @deep_cloning_obj.instance_variable_set(var, val) end deep_cloning_obj = @deep_cloning_obj @deep_cloning_obj = nil return deep_cloning_obj end end class Array def deep_clone return map { |x| x.deep_clone } end end class Numeric def deep_clone return self end end class FalseClass def deep_clone return self end end class TrueClass def deep_clone return self end end class NilClass def deep_clone return self end end
No more missing 3 DEF in my two second test project! Let me know how it turns out on your end.
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
YES! IT WORKS! Thank you GRS! You're the best!
Red_Nova
Sir Redd of Novus: He who made Prayer of the Faithless that one time, and that was pretty dang rad! :D
9192
... Almost.
Remember that battle HUD issue I passed off earlier as an easy fix? Turns out it's not quite that easy.
The command window was easy enough to hide during the equip scene, but the status window and character bust will not disappear until after the equip scene is over, which is weird. I tested this by removing the calls to show the HUDs after Scene_Equip is over.

The face and bust are there despite calling the methods to hide them. Now, when I exit Scene_Equip...

Yikes.
So there's a delayed reaction in the sprites being erased, and I have no idea why. They can't be covered up because the Z values for all the windows in Scene_Equip are already higher than the windows in Scene_Battle
EDIT: Update: I figured out how to get the character busts to work:
Where the commented lines are what has been replaced. If I can figure out how to do the same thing with @status_window then it'll be perfect.
Remember that battle HUD issue I passed off earlier as an easy fix? Turns out it's not quite that easy.
The command window was easy enough to hide during the equip scene, but the status window and character bust will not disappear until after the equip scene is over, which is weird. I tested this by removing the calls to show the HUDs after Scene_Equip is over.

The face and bust are there despite calling the methods to hide them. Now, when I exit Scene_Equip...

Yikes.
So there's a delayed reaction in the sprites being erased, and I have no idea why. They can't be covered up because the Z values for all the windows in Scene_Equip are already higher than the windows in Scene_Battle
EDIT: Update: I figured out how to get the character busts to work:
def show_battler_picture #$game_troop.screen.pictures[1].show("ActorSelection_" + BattleManager.actor.class_id.to_s, 0, 0, 90, 100.0, 100.0, 255, 0) @leaf = Sprite.new @leaf.bitmap = Cache.picture("ActorSelection_" + BattleManager.actor.class_id.to_s) end def hide_battler_picture #$game_troop.screen.pictures[1].erase if $game_troop.screen.pictures[1] @leaf.bitmap.dispose @leaf.dispose end
Where the commented lines are what has been replaced. If I can figure out how to do the same thing with @status_window then it'll be perfect.















