RMMV How do I convert plugin parameters into variables?

SwordSkill

Veteran
Veteran
Joined
Jul 16, 2013
Messages
43
Reaction score
21
First Language
Greek
Primarily Uses
RMMV
I've recently seen this post about how to make parameters, but there is no mention as to how these parameters can be turned into different kinds of variables, may anyone willing to shed some light onto it?
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,969
Reaction score
4,553
First Language
English
Primarily Uses
RMMZ
var parameters = PluginManager.parameters(pluginname);

Then you can do parameters.parametername to get the individual values and do whatever you need to with them.

Note that all parameters are stored as strings regardless of type setting, so you need to parse them as numbers, eval booleans, or JSON.parse object arrays to use them properly.
 

SwordSkill

Veteran
Veteran
Joined
Jul 16, 2013
Messages
43
Reaction score
21
First Language
Greek
Primarily Uses
RMMV
var parameters = PluginManager.parameters(pluginname);

Then you can do parameters.parametername to get the individual values and do whatever you need to with them.

Note that all parameters are stored as strings regardless of type setting, so you need to parse them as numbers, eval booleans, or JSON.parse object arrays to use them properly.
Correct me if I'm wrong, but with a quick look at "Community_Basic" plugin, I think it's actually "parameters['parameter name']", unless I'm missing something?
 

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,969
Reaction score
4,553
First Language
English
Primarily Uses
RMMZ
Correct me if I'm wrong, but with a quick look at "Community_Basic" plugin, I think it's actually "parameters['parameter name']", unless I'm missing something?
You only need to do it that way if the parameter has a space in it. It can be accessed as a property otherwise.
 

Nolonar

Veteran
Veteran
Joined
Feb 18, 2018
Messages
390
Reaction score
545
First Language
French, German
Primarily Uses
RMMZ
I personally only use parameters["parameter name"] instead of parameters.parameterName. The reason is, normally you should define your parameter like this:
Code:
@param paramName
@text Parameter Name
and in your code you would access your parameter like this:
JavaScript:
parameters.paramName
// or
parameters["paramName"]

Whoever uses your plugin will see "Parameter Name" instead of "paramName". This is particularly useful if you intend to translate your plugin, since you'd keep the @param and translate the @text

But in reality, nobody does this (at least I've never seen a plugin that does), because it means writing an extra line of metadata (@text Parameter Name). As a result, pretty much every plugin (mine included) is written in following style:
Code:
@param Parameter Name
and accessed like this:
JavaScript:
parameters["Parameter Name"]

The reason why the parameters have to be retrieved using the dictionary indexer ["property name"] is because their name includes characters that are not allowed for property/variable names. These characters include (but are not limited to):
  • whitespace
  • any mathematical operator (+, -, *, /, etc.)
  • any punctuation (., ,, ;, :, etc.)
  • any type of bracket ((), [], {}, etc.)
  • any type of quote marks (", ', ´)
  • the name starts with a number (e.g. 3d)


One (very important) thing to keep in mind: Plugin parameters are always stored as string.

At some point, you might create a plugin that expects a parameter that isn't a string (e.g. a boolean, a number, or even a custom structure). You might also want to have some default parameters, in case the user doesn't enter their own, or they somehow manage to corrupt the parameter.

Here's how to handle different types of parameters, including default values:
JavaScript:
// Strings
const paramString = parameters["String parameter"] || "default value";
// if default value is not empty, but empty values are allowed
const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value");

// Numbers
// defaults to 42
const paramNumber = Number(parameters["Number parameter"]) || 42;
// if default value is not 0, but 0 is allowed
const paramNumber2 = parameters["Number parameter"] === "0" ? 0 : (Number(parameters["Number parameter"]) || 42);

// Booleans
// defaults to true
const paramBool_trueDefault = parameters["Boolean parameter"]) !== "false";
// defaults to false
const paramBool_falseDefault = parameters["Boolean parameter"]) === "true";

You've probably noticed how I didn't use the Boolean() function for boolean parameters. That's because both Boolean("true") and Boolean("false") both evaluate to true

Object selector types (such as @type actor, @type switch, @type variable, @type common_event, etc.) are basically numbers (they represent the ID of the object). Since you most likely won't be doing any mathematical operations on those, there's no real need to convert them to a number using the Number() function. I'd still recommend doing it to avoid picking up bad habits, but the decision lies with you.

@type file is basically a string (the path to the file). @type select can be a string or a number, depending on what you need (for booleans, just use a boolean instead). For numbers I'd recommend using @type number with @min and @max instead of @type select, unless you have a very strict and limited set of valid values.

Finally, @type note, arrays (e.g. @type number[]), and structs (e.g. @type struct<customStruct>) all require JSON.parse(). If they are nested (e.g. an array of structs), you'll need multiple calls to JSON.parse().

Note that JSON.parse() can crash if the input can not be parsed by JSON.parse(). This means that you'll either need to trust that the user won't corrupt the parameter, or you'll need to wrap the parameter in try-catch:
JavaScript:
let paramNote;
try {
    paramNote = JSON.parse(parameters["Note parameter"]);
} catch() {
    paramNote = "default value";
}
Honestly, at this point sanitizing the input becomes a huge pain (for instance, JSON.parse("null") gives us null, which can cause the game to crash depending on the code). And since it's the plugin user's responsibility to avoid code injections, I wouldn't bother trying to sanitize parameters against that. Might as well not bother with try-catches either.

Arrays of structs might be worth mentioning:
JavaScript:
const paramStructArray = parseStructArray(JSON.parse(parameters["Struct array parameter"]));

function parseStructArray(arr) {
    return arr.map(function(struct) { return JSON.parse(struct); });
}
You'll need the first JSON.parse() to get the array, and for each element in the array, you'd need another JSON.parse() to get the struct object itself. Things get even more complex when your struct itself contains arrays or structs. I'm still figuring out if there isn't a better way to handle this case.
 
Last edited:

Trihan

Speedy Scripter
Veteran
Joined
Apr 12, 2012
Messages
4,969
Reaction score
4,553
First Language
English
Primarily Uses
RMMZ
I personally only use parameters["parameter name"] instead of parameters.parameterName. The reason is, normally you should define your parameter like this:
Code:
@param paramName
@text Parameter Name
and in your code you would access your parameter like this:
JavaScript:
parameters.paramName
// or
parameters["paramName"]

Whoever uses your plugin will see "Parameter Name" instead of "paramName". This is particularly useful if you intend to translate your plugin, since you'd keep the @param and translate the @text

But in reality, nobody does this (at least I've never seen a plugin that does), because it means writing an extra line of metadata (@text Parameter Name). As a result, pretty much every plugin (mine included) is written in following style:
Code:
@param Parameter Name
and accessed like this:
JavaScript:
parameters["Parameter Name"]

The reason why the parameters have to be retrieved using the dictionary indexer ["property name"] is because their name includes characters that are not allowed for property/variable names. These characters include (but are not limited to):
  • whitespace
  • any mathematical operator (+, -, *, /, etc.)
  • any punctuation (., ,, ;, :, etc.)
  • any type of bracket ((), [], {}, etc.)
  • any type of quote marks (", ', ´)
  • the name starts with a number (e.g. 3d)


One (very important) thing to keep in mind: Plugin parameters are always stored as string.

At some point, you might create a plugin that expects a parameter that isn't a string (e.g. a boolean, a number, or even a custom structure). You might also want to have some default parameters, in case the user doesn't enter their own, or they somehow manage to corrupt the parameter.

Here's how to handle different types of parameters, including default values:
JavaScript:
// Strings
const paramString = parameters["String parameter"] || "default value";
// if default value is not empty, but empty values are allowed
const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value");

// Numbers
// defaults to 42
const paramNumber = Number(parameters["Number parameter"]) || 42;
// if default value is not 0, but 0 is allowed
const paramNumber2 = parameters["Number parameter"] === "0" ? 0 : (Number(parameters["Number parameter"]) || 42);

// Booleans
// defaults to true
const paramBool_trueDefault = parameters["Boolean parameter"]) !== "false";
// defaults to false
const paramBool_falseDefault = parameters["Boolean parameter"]) === "true";

You've probably noticed how I didn't use the Boolean() function for boolean parameters. That's because both Boolean("true") and Boolean("false") both evaluate to true

Object selector types (such as @type actor, @type switch, @type variable, @type common_event, etc.) are basically numbers (they represent the ID of the object). Since you most likely won't be doing any mathematical operations on those, there's no real need to convert them to a number using the Number() function. I'd still recommend doing it to avoid picking up bad habits, but the decision lies with you.

@type file is basically a string (the path to the file). @type select can be a string or a number, depending on what you need (for booleans, just use a boolean instead). For numbers I'd recommend using @type number with @min and @max instead of @type select, unless you have a very strict and limited set of valid values.

Finally, @type note, arrays (e.g. @type number[]), and structs (e.g. @type struct<customStruct>) all require JSON.parse(). If they are nested (e.g. an array of structs), you'll need multiple calls to JSON.parse().

Note that JSON.parse() can crash if the input can not be parsed by JSON.parse(). This means that you'll either need to trust that the user won't corrupt the parameter, or you'll need to wrap the parameter in try-catch:
JavaScript:
let paramNote;
try {
    paramNote = JSON.parse(parameters["Note parameter"]);
} catch() {
    paramNote = "default value";
}
Honestly, at this point sanitizing the input becomes a huge pain (for instance, JSON.parse("null") gives us null, which can cause the game to crash depending on the code). And since it's the plugin user's responsibility to avoid code injections, I wouldn't bother trying to sanitize parameters against that. Might as well not bother with try-catches either.

Arrays of structs might be worth mentioning:
JavaScript:
const paramStructArray = parseStructArray(JSON.parse(parameters["Struct array parameter"]));

function parseStructArray(arr) {
    return arr.map(function(struct) { return JSON.parse(struct); });
}
You'll need the first JSON.parse() to get the array, and for each element in the array, you'd need another JSON.parse() to get the struct object itself. Things get even more complex when your struct itself contains arrays or structs. I'm still figuring out if there isn't a better way to handle this case.
1642717554912.pngNobody uses text metadata, huh? :p
 

SwordSkill

Veteran
Veteran
Joined
Jul 16, 2013
Messages
43
Reaction score
21
First Language
Greek
Primarily Uses
RMMV
// Strings
const paramString = parameters["String parameter"] || "default value";
// if default value is not empty, but empty values are allowed
const paramString2 = parameters["String parameter"] === "" ? "" : (parameters["String parameter"] || "default value");
But wouldn't the || operator return a boolean?
 

Eliaquim

Hakuen Studio
Veteran
Joined
May 22, 2018
Messages
2,747
Reaction score
2,105
First Language
Portuguese - Br
Primarily Uses
RMMZ
Hi there!
I think Nolonar said pretty much everything.
I just want to point out that if I was you, I would use the pattern:

@param paramName
@text Param Name

Because for the coder, there might be some names that are more readable inside code, and other names that are best for the plugin users. A random example:

@param mhp
@text Max Hp

That is not a big deal either. Just a new opinion ^^''
 

Nolonar

Veteran
Veteran
Joined
Feb 18, 2018
Messages
390
Reaction score
545
First Language
French, German
Primarily Uses
RMMZ
But wouldn't the || operator return a boolean?

Normally, yes. In JavaScript it's... complicated.

The || operator (boolean OR) returns what's on the left side if it's true, or the right side otherwise.

However, JavaScript has its own concept of what is "true" and "false". We call it "truthy" and "falsey". It's also the reason why you can't do Boolean("false") even though you can do Number("13").

Here's a list of what is considered "falsey" (everything else is "truthy"):
  • false (boolean)
  • 0, -0, 0.0, -0.0, 0b0, 0o0, 0x0, 0n, etc. (number)
  • NaN, -NaN (number)
  • "", '', `` (emtpy string)
  • null
  • undefined
  • document.all
document.all is a bit of a special case. It was originally introduced by IE (Internet Explorer), and later added to the official specs to prevent other browsers from breaking if they visited sites written for IE. if (document.all) used to be a popular way to detect if the browser was IE, so browsers nowadays just consider document.all to be falsey (except maybe for some versions of IE).

Thus, if Number(bla) returns NaN (because bla wasn't a valid number), the || operator will allow us to fall back to a default. The same applies to strings, though only for empty strings.

As for Boolean(x), it just tells you if x is truthy or falsey. Since "false" isn't an empty string, it's truthy, thus Boolean("false") returns true. It's confusing, but that's just how JavaScript is.
 

Latest Threads

Latest Profile Posts

ScreenShot_5_25_2022_7_37_13.png

my game has distinct areas where travel through what are known as "battle stations" these are more or less areas to explore and fight. occasionally, you'll stumble across secret rooms with sidequests ready to be taken. this area is in the high school attic of all places... but how do ya get there is the question.
Redoing my intro scene for the 10 millionth time is pain
So this flat Earther named Mike Hughes build his own rocket to prove that the Earth was flat. But on liftoff he still had the ladder he climbed up to the rocket laying against it. Needless to say things didn't go as planned.
Anyone else just get battle system ideas but not have a game to attach them to?
Update to the Bootleg YS Battle system. Butt-stabbing is now a thing.
If you hit a monsters back, that hit does triple damage and the monster doesn't hit you; however the monster will immediately turn to face you. Also, figured out how to make Bombs, Sling-shot, a Hammer, and a Saw if you didn't see my previous video. Also made Teleportation circles and a warp whistle.

Forum statistics

Threads
122,122
Messages
1,146,679
Members
160,407
Latest member
Meowsica
Top