Plugin Parameters: boolean / eval

Status
Not open for further replies.

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
1,695
Reaction score
1,113
First Language
Portuguese - Br
Primarily Uses
RMMZ
Hello people!! :D

I 'am thinking if there is another way to set a boolean parameter and not use eval on it.

I have this parameter, to that function:

Code:
@param Cancel Two Fingers
@type boolean
@on Yes
@off No
@desc
@default true

Eli.Param.Utilities = {
    CancelTwoFingers: eval(Eli.Parameters['Cancel Two Fingers'])
};

TouchInput.isCancelled = function() {
        if (Eli.Param.Utilities.CancelTwoFingers === true) {
            return false;
        } else {
            return this._cancelled;
        }
};
I know, it's only one eval, but maybe it will have others. So I was wondering if it has a way to not use eval.
Also, I have seen some plugins doing that with boolean parameters, using a string and then eval.
What I'm missing?

Code:
Eli.Param.CancelTwoFingers= String(Eli.Parameters['Cancel Two Fingers']);
Eli.Param.CancelTwoFingers= eval(Eli.Param.Cancel Two Fingers);
 

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
You can use JSON.parse(Eli.Parameters['Cancel Two Fingers']) I personally recommend using JSON.parse on the entire set of parameters so you don't have to do any conversion.

I use this method for all my plugins
PHP:
function convertParameters (parameters) {
  function parseParameters (string) {
    try {
      return JSON.parse(string, (key, value) => {
        try {
          return parseParameters(value)
        } catch (e) {
          return value
        }
      })
    } catch (e) {
      return string
    }
  }
  return parseParameters(JSON.stringify(parameters))
}

PHP:
const rawParameters = PluginManager.parameters('plugin')

const _Params = convertParameters(rawParameters)
 

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
1,695
Reaction score
1,113
First Language
Portuguese - Br
Primarily Uses
RMMZ
You can use JSON.parse(Eli.Parameters['Cancel Two Fingers']) I personally recommend using JSON.parse on the entire set of parameters so you don't have to do any conversion.

I use this method for all my plugins
PHP:
function convertParameters (parameters) {
  function parseParameters (string) {
    try {
      return JSON.parse(string, (key, value) => {
        try {
          return parseParameters(value)
        } catch (e) {
          return value
        }
      })
    } catch (e) {
      return string
    }
  }
  return parseParameters(JSON.stringify(parameters))
}

PHP:
const rawParameters = PluginManager.parameters('plugin')

const _Params = convertParameters(rawParameters)
Hm... I'm still a newbie(I think), so I suppose you post it here, is that you allow me to use, right?
I really like to use that, if I avoid the eval. But, I can't understand it hahaha

I know what JSON.parse does. But I look at your code, and I can't follow it xD
After I put that in my plugin, I simply continue to set my parameters that this function convertParameters will be applied to them? I put that after or before defining the below in my plugin?
Code:
var Imported = Imported || {};
Imported.Eli_DevSwitches = true;

var Eli = Eli || {};
Eli.DevSwitches = Eli.DevSwitches || {};


Eli.Parameters = PluginManager.parameters('Eli_DevSwitches');
Eli.Param = Eli.Param || {};

    Eli.Param.DevSwitches = {
        Playtest: Number(Eli.Parameters['Playtest Switch']),
        BattleSc: Number(Eli.Parameters['Battle Switch']), // falta fazer
        Mobile: Number(Eli.Parameters['Mobile Switch']),
        Desktop: Number(Eli.Parameters['Desktop Switch']),
        Vehicle: Number(Eli.Parameters['isInVehicle Switch']),
        Airship: Number(Eli.Parameters['isInAirship Switch']),
        Boat: Number(Eli.Parameters['isInBoat Switch']),
        Ship: Number(Eli.Parameters['isInShip Switch']),
        DmgFloor: Number(Eli.Parameters['isOnDmgFloor Switch']),
        Dashing: Number(Eli.Parameters['isDashing Switch']),
        Bushed: Number(Eli.Parameters['isOnBush Switch']),
        Ladder: Number(Eli.Parameters['isOnLadder Switch']),
        Timerw: Number(Eli.Parameters['Timer running Switch'])
    };

PluginManager.parameters('plugin')
This 'plugin' I replace with the name of my plugin right?
 

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
Yea you can freely use it, its a slightly adapted version that @waynee95 showed me a year or so ago, but he's allowed free use of that function.

Okay so basically the function will "loop" through each parameter it does this by using a method called a recursive function. I don't want to go into detail about a recursive function but I would recommend googling it to stimulate that brain of yours

Anyway, you will need to treat your parameters slightly different than how you currently do it. The convertParameter function will return a full object from your parameters, with all the strings correctly converted, so numbers will be numbers and booleans will be booleans, lists will be an array and structs will be an object etc.


PHP:
var Imported = Imported || {};
Imported.Eli_DevSwitches = true;

var Eli = Eli || {};
Eli.DevSwitches = Eli.DevSwitches || {};

function convertParameters (parameters) {
  function parseParameters (string) {
    try {
      return JSON.parse(string, (key, value) => {
        try {
          return parseParameters(value)
        } catch (e) {
          return value
        }
      })
    } catch (e) {
      return string
    }
  }
  return parseParameters(JSON.stringify(parameters))
}

Eli.Parameters = PluginManager.parameters('Eli_DevSwitches');

Eli.Param = convertParameters(Eli.Parameters) || {};

/**
 * This is how you setup a parameter.
 * The @param  field will be you object property after conversion
 * and @text is what the plugin user sees in the plugin manager
 *
 *
 * @param playTest
 * @text Play Test
 * @type boolean
 * @desc
 * @default true
 *
 */


 Eli.Param.playTest  // this will return true, no need for manual conversion or using Eli.Parameters['blah blah']

// You won't need to do this anymore XXXXX
    Eli.Param.DevSwitches = {
        Playtest: Number(Eli.Parameters['Playtest Switch']),
        BattleSc: Number(Eli.Parameters['Battle Switch']), // falta fazer
        Mobile: Number(Eli.Parameters['Mobile Switch']),
        Desktop: Number(Eli.Parameters['Desktop Switch']),
        Vehicle: Number(Eli.Parameters['isInVehicle Switch']),
        Airship: Number(Eli.Parameters['isInAirship Switch']),
        Boat: Number(Eli.Parameters['isInBoat Switch']),
        Ship: Number(Eli.Parameters['isInShip Switch']),
        DmgFloor: Number(Eli.Parameters['isOnDmgFloor Switch']),
        Dashing: Number(Eli.Parameters['isDashing Switch']),
        Bushed: Number(Eli.Parameters['isOnBush Switch']),
        Ladder: Number(Eli.Parameters['isOnLadder Switch']),
        Timerw: Number(Eli.Parameters['Timer running Switch'])
    }


  // But if you want to do it  for organization purposes or because it feels right to you
  // then you can still do this
  Eli.Param.DevSwitches = {
    playTest: Eli.Param.playTest
    // airship: Eli.Param.airship
  }
Edit: Had a small mistake in code I just fixed

I hope this helps you more, if not let me know and I'll see if I can explain some more.
P.S Once you understand and get used to doing this, you will never look back. It makes life so much easier and saves you a ton of time.
 
Last edited:

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
1,695
Reaction score
1,113
First Language
Portuguese - Br
Primarily Uses
RMMZ
@LTN Games It helps me a lot!
I don't know the concept of a recursive function, I will get there anytime soon.
But I already manage to understand what the coding is doing by the way you explained it to me.

(NOTE: I think a long time ago I see in some thread Wayne telling you that. Don't remember if it is in this forum or in another one. Well, I have this impression... Anyways...)

Thank you a lot. I will try it after I learn the recursive function thing in my javascript course ^^
 

Aloe Guvner

Walrus
Veteran
Joined
Sep 28, 2017
Messages
1,628
Reaction score
1,115
First Language
English
Primarily Uses
RMMV

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,639
First Language
Czech
Primarily Uses
RMMV
The string is either "true", or "false", so it's possible to use JSON.parse, or...
Code:
parsedParam = param === "true" ? true : false;
Nevertheless, one note. If you're comparing Boolean, you don't need to use
Code:
if (Eli.Param.Utilities.CancelTwoFingers === true)
.
true, non-zero number, array, object and non-empty string
are so called "truthy values", while
0, empty string, false, null and in cases of object attributes undefined are called "falsey values". This means that if you do just
Code:
if (Eli.Param.Utilities.CancelTwoFingers)
it will return either true, or false, depending if the value is truthy, or falsey.
 

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
1,695
Reaction score
1,113
First Language
Portuguese - Br
Primarily Uses
RMMZ
@LTN Games
Well, for curiosity, I try your method and it works fine!:rwink:
However, I have two parameters that the user can input a formula there.
These two are not working. I guess there's no way for them, instead of using eval.
Look at the code.

Code:
// RPG OBJECTS

    //1723
Eli.Utilities.Game_Action_applyCritical = Game_Action.prototype.applyCritical;
    Game_Action.prototype.applyCritical = function(damage) {
        if (Eli.Param.Utilities.CritType === true) {
            return Eli.Utilities.Game_Action_applyCritical.call(this, damage);
        } else {
            return Eli.Param.Utilities.CritFormSet;
        }
    };

    //3524
Eli.Utilities.Game_Actor_expForLevel = Game_Actor.prototype.expForLevel; //alias
    Game_Actor.prototype.expForLevel = function(level) {
        if (Eli.Param.Utilities.ExpType) {
            return Eli.Utilities.Game_Actor_expForLevel.call(this, level); //callback
        } else {
            return Eli.Param.Utilities.ExpFormSet;
        }
    };

I put the formulas:
for apply critical = damage * 5
for expForLevel = (level-1) * 100

In that way, when I open the status window, it shows this information for me in the fields:
"Current Exp" - (level-1) * 100
"To Next Level" - NaN.
And in battle, the critical do no damage in the enemy.


However, if I put in the functions:
return eval(Eli.Param.Utilities.CritFormSet);
return eval(Eli.Param.Utilities.ExpFormSet);

It works ok.

I don't mind to use them. I'm just talking to you to see if I am doing something wrong, if I'm missing something.

@Poryg
if (Eli.Param.Utilities.CancelTwoFingers)
Yes! I don't miss that! I had already changed to this. I was still working on the code. This is from a long time ago :D
 

Poryg

Dark Lord of the Castle of Javascreeps
Veteran
Joined
Mar 23, 2017
Messages
4,125
Reaction score
10,639
First Language
Czech
Primarily Uses
RMMV
An NaN means you're doing a math operation using something that is not convertible to numbers. Try to see what the damage and level values are maybe?
 

nio kasgami

VampCat
Veteran
Joined
May 21, 2013
Messages
8,949
Reaction score
3,042
First Language
French
Primarily Uses
RMMV
if you don't want to approach wayne method or you think that the plugin is so small that you could just use a method you can approach my method as well which was creating a function :

Code:
/**
 * Will convert the parameters string into a boolean or make sure it's a boolean.
 * @param {Plugin} plugin The plugin variable.
 * @param {String} parameters The parameters name in string.
 * @returns {Boolean}
 */
PluginManager.toBoolean = function (plugin, parameters) {
    var n = plugin[parameters];
    if (n === 'true' || n === '1') {
        return true;
    } else if (n === 'false' || n === '0') {
        return false;
    } else {
        throw new Error(parameters + ' is a boolean. Please set it to true or false only.');
    }
};
you can access the code there :
https://github.com/niokasgami/Emoji..._Dev/bin/Tool Plugin/PluginManagerExtender.js

even if this one is quite obsolete since how MV handle things now

I personally will use both wayne and my method now since to be fair theres no need to always run a full JSON parse recursive method when theres no depth in the plugin (aka one or two parameters)
 

LTN Games

Indie Studio
Veteran
Joined
Jun 25, 2015
Messages
704
Reaction score
631
First Language
English
Primarily Uses
RMMV
My very first suggestion seems to have been missed, it may be because it was not in a code box but only bold text instead. Anyway, using JSON.parse() still turns a string into a boolean and there is no need for all the extra fancy code the last few people offered, even if your plugin has few parameters, I'd say this is the simplest and least cluttered solution.

PHP:
const stringBool = "true"

JSON.parse(stringBool) // Returns true.. JSON.parse() turn the "true" string into boolean

console.log(typeof JSON.parse(stringBool) === 'boolean') // Return true
 

Aloe Guvner

Walrus
Veteran
Joined
Sep 28, 2017
Messages
1,628
Reaction score
1,115
First Language
English
Primarily Uses
RMMV
@Eliaquim If I understand you correctly, your next question was about letting the user define their own functions for something. For example, they input the string "damage * 5" into a plugin parameter that represents the critical damage formula.

I'm sure you know it already, but I'm specifying when something is a string -- that's important because a string won't actually do anything by itself, it's only a sequence of characters.

You have two options generally here. If the string should be evaluated as Javascript only once, it's fine to use eval. If it should be evaluated as Javascript more than once, it should be turned into a function that can be called as many times as you want, just like any other function.

To be very precise, evaluate as Javascript means to take the string, which is just a plain sequence of characters and actually convert it to Javascript. This uses the native Javascript parser, for desktop games it would be the V8 parser which is part of Chromium. This is generally an expensive operation.

To create a function dynamically, you can use the Function constructor.

Code:
let myString = 'damage * 5'
window.customCriticalFormula = new Function('damage', 'return ' + myString)
Then inside the applyCritical that you alias
Code:
if (window.customCriticalFormula) {
   return window.customCriticalFormula(damage)
}
return alias...
You should use *not* the window or global to save the function, use your own Eli object, but hopefully you get my meaning.

Edit: you create the function when the game loads

Edit2: Forgot the word *not*
 
Last edited:

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
1,695
Reaction score
1,113
First Language
Portuguese - Br
Primarily Uses
RMMZ
@nio kasgami ohh! An interesting method too! It feels more "my way", because it makes me feel that I'm in more control.
I will save that and use it when it's possible!

@LTN Games
My very first suggestion seems to have been missed, it may be because it...
Yes, I don't forget that. In fact, I think I will stick with that method. Since it's more readable for me ^^

@Aloe Guvner Yes you are right, this is what I want to achieve.
Holy... hahahaha xD
I think I understand. But I will try that just to be sure.
Just a doubt.
If I put the eval in the parameter when I'm setting it, not in the function apply critical.

Code:
Eli.Param.Utilities = {
CritFormSet: eval(Eli.Parameters['Critical Formula Set'])
};

Eli.Utilities.Game_Action_applyCritical = Game_Action.prototype.applyCritical;
    Game_Action.prototype.applyCritical = function(damage) {
        if (Eli.Param.Utilities.CritType === true) {
            return Eli.Utilities.Game_Action_applyCritical.call(this, damage);
        } else {
            return Eli.Param.Utilities.CritFormSet;
        }
    };

Code:
Eli.Param.Utilities = {
CritFormSet: String(Eli.Parameters['Critical Formula Set'])
};

Eli.Utilities.Game_Action_applyCritical = Game_Action.prototype.applyCritical;
    Game_Action.prototype.applyCritical = function(damage) {
        if (Eli.Param.Utilities.CritType === true) {
            return Eli.Utilities.Game_Action_applyCritical.call(this, damage);
        } else {
            return eval(Eli.Param.Utilities.CritFormSet);
        }
    };

Every time I execute that function, the eval will run?
Or in the parameters, the eval will only run once?
 

slimmmeiske2

Little Red Riding Hood
Global Mod
Joined
Sep 6, 2012
Messages
7,833
Reaction score
5,221
First Language
Dutch
Primarily Uses
RMXP

This thread is being closed, due to being solved. If for some reason you would like this thread re-opened, please report this post and leave a message why. Thank you.

 
Status
Not open for further replies.

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

Latest Threads

Latest Posts

Latest Profile Posts

How many parameters is 'too many'??
Yay, now back in action Happy Christmas time, coming back!






Back in action to develop the indie game that has been long overdue... Final Fallacy. A game that keeps on giving! The development never ends as the developer thinks to be the smart cookie by coming back and beginning by saying... "Oh bother, this indie game has been long overdue..." How could one resist such? No-one c
So I was playing with filters and this looked interesting...

Versus the normal look...

Kind of gives a very different feel. :LZSexcite:
To whom ever person or persons who re-did the DS/DS+ asset packs for MV (as in, they are all 48x48, and not just x2 the pixel scale) .... THANK-YOU!!!!!!!!! XwwwwX

Forum statistics

Threads
105,849
Messages
1,016,977
Members
137,563
Latest member
cexojow
Top