How to override effects/traits properties

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,108
Reaction score
13,713
First Language
English
Primarily Uses
RMMV
I'm working on porting my Dynamic Features (Traits) and Effects scripts to MV.

In Ace I could just do this:

class RPG::BaseItem def features if <features were changed> return <changed features> else return @features end endendbecause $dataXYZ inherited from RPG::BaseItem.Now, in MV, there are no RPG::BaseItem classes - $dataXYZ is just an array of Objects.

So I think I can still do something similar, by creating a getter for effects and traits under Object, that will check a condition and return the modified traits/effects list, or the original one. But I'm not sure how to set a getter for Object, or how to make it refer to the real trait/effect without going into a recursive loop.

Any help appreciated.

The alternative is to override the functions that refer to .effects and .traits and I don't want to do that as I would have to overwrite them rather than alias them, and they're probably used by some of the battle plugins, which would result in incompatibility issues.

Edit: I tried the following just to see if I could get it to work, and a script call of console.log($dataActors[1].name) always prints out Harold. It doesn't even go into the getter.

Code:
(function() {  Object.defineProperty(Object, "name", {    get: function name() {      if ($gameSwitches.value(10)) {        return "overridden name";      } else {        return this.name;      }    }  });})();
 
Last edited by a moderator:

Ramiro

Now with an army of Mecha-Ralphs!
Veteran
Joined
Aug 5, 2015
Messages
858
Reaction score
364
First Language
Spanish
I can explain why this doesn't work:

(function() {// You define a property on Object.defineProperty(Object /*... The Object class! (no it's prototype)*/, "name", {// you are defining a getter (Object.name) wich is not the same as Object.prototype.nameget: function name() {if ($gameSwitches.value(10)) {// this will work... for any objectreturn "overridden name";} else {// So you are calling this.name wich is... Object.name, wich is a getter wich... uh oh! infinite loop!return this.name;}}});})();Sadly there is no easy way to do that, you have to monkey patch the items:

Code:
// You want them on weapons, armors, skills and items, right, then concat 'em all$dataItems.concat($dataWeapons).concat($dataArmors).concat($dataSkils).forEach(function (item) {   if (item) { // because the first one is null always...     if (item.meta.ChangeFeatures) { // if it's a meta called ChangeFeatures (<ChangeFeatures> as a note)        item.features = /* altered features  */;     }   }});
 
Last edited by a moderator:

Zalerinian

Jack of all Errors
Veteran
Joined
Dec 17, 2012
Messages
4,696
Reaction score
935
First Language
English
Primarily Uses
N/A
$dataActors will only ever be an object, so you can't really create a class around it. I suppose, seeing your edit, that that may be a valid way to do things, except for 2 things.

1. I'd suggest you try Object.prototype as the first argument, as a variable would be an instance of Object, and you're defining  'name' for the static object, i.e. Object.name.

2. return this.name will be broken. "this.name" will once again call the get function, which will call the get function, which will call the get function.... That's why, for all the default objects where they define getters similar to what you're doing for name, the actual variable is named with a '_' in the beginning.

In fact, I'd suggest you do something like this, once $dataActors is loaded. Since that file will contain information for all actors, and thus will probably never be reloaded, you should be able to copy the value of all the properties you want to change to a new key name, such as move name to _name, and then define your getter to return the _name variable.

I haven't tested this, but I think this might work.

(function(){ var DM_onLoad = DataManager.onLoad; DataManager.onLoad = function(obj) { DM_onLoad.call(this, obj); if(obj === $dataActors) { for(var i = 0; i < $dataActors.length; i++) { $dataActors._name = $dataActors.name; Object.defineProperty($dataActors, 'name', { get: function() { if(/* <name changed> */) { return "Something extra special"; } else { return this._name; } } }); } } }})();EDIT: Oh go figure, I had made a few mistakes in my code, so I've gone and edited it.
 
Last edited by a moderator:

Shaz

Veteran
Veteran
Joined
Mar 2, 2012
Messages
40,108
Reaction score
13,713
First Language
English
Primarily Uses
RMMV
I tried it on the prototype first and it also didn't work. But you've pretty much confirmed what I was afraid would happen.


I think I'll look at something half way between your suggestion and what I did in Ace. I really don't want to modify the battle functions.


Thanks for your input :)
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Posts

Latest Profile Posts

Just beat the last of us 2 last night and starting jedi: fallen order right now, both use unreal engine & when I say i knew 80% of jedi's buttons right away because they were the same buttons as TLOU2 its ridiculous, even the same narrow hallway crawl and barely-made-it jump they do. Unreal Engine is just big budget RPG Maker the way they make games nearly identical at its core lol.
Can someone recommend some fun story-heavy RPGs to me? Coming up with good gameplay is a nightmare! I was thinking of making some gameplay platforming-based, but that doesn't work well in RPG form*. I also was thinking of removing battles, but that would be too much like OneShot. I don't even know how to make good puzzles!
one bad plugin combo later and one of my followers is moonwalking off the screen on his own... I didn't even more yet on the new map lol.
time for a new avatar :)

Forum statistics

Threads
106,018
Messages
1,018,357
Members
137,803
Latest member
andrewcole
Top