/*:
* @plugindesc This plugin allows a user to modify stats on Classes or Enemies based on other stats.
* For example, raising maximum HP by a percentage of their defense.
* @author Zevia
*
* @help In a class or enemy's note box, put ,
* where firstStat is the stat you want to increase, secondStat is the stat you
* want to reference to increase the first stat by, and x is the percentage you
* want to increase based on the secondStat.
*
* As an example, would translate to "increase this class's
* maximum hp by 50% of the class's defense".
*
* You can tie multiple stats to one stat by separating them with commas.
* For example, would mean, "increase this
* class's maximum hp by 50% of the class's defense and 40% of the class's
* luck".
*
* If you want to be able to define a class or enemy's entire stat in relation
* to another stat, you can change the minimums of their stats. As an example,
* if you want a class's maximum HP to be solely dependent on their DEF and
* LUK, you can change the minimum HP parameter to 0, then do
*
* @param mhp
* @text HP minimum
* @type number
* @desc The minimum value for HP. By default, it's 1.
* @default 1
*
* @param mmp
* @text MP minimum
* @type number
* @desc The minimum value for MP. By default, it's 0.
* @default 0
*
* @param atk
* @text ATK minimum
* @type number
* @desc The minimum value for ATK. By default, it's 1.
* @default 1
*
* @param def
* @text DEF minimum
* @type number
* @desc The minimum value for DEF. By default, it's 1.
* @default 1
*
* @param mat
* @text MAT minimum
* @type number
* @desc The minimum value for MAT. By default, it's 1.
* @default 1
*
* @param mdf
* @text MDF minimum
* @type number
* @desc The minimum value for MDF. By default, it's 1.
* @default 1
*
* @param agi
* @text AGI minimum
* @type number
* @desc The minimum value for AGI. By default, it's 1.
* @default 1
*
* @param luk
* @text LUK minimum
* @type number
* @desc The minimum value for LUK. By default, it's 1.
* @default 1
*/
(function(module) {
'use strict';
// Polyfill for older versions of RPG Maker MV
Array.prototype.find = Array.prototype.find || function(finderFunction) {
for (var i = 0; i < this.length; i++) {
var element = this[i];
if (finderFunction(element, i, this)) { return element; }
}
};
module.Zevia = module.Zevia || {};
var LinkedStats = module.Zevia.LinkedStats = {};
var LINK_MATCH = 'link\\s+';
var params = ['mhp', 'mmp', 'atk', 'def', 'mat', 'mdf', 'agi', 'luk'];
var parameters = PluginManager.parameters('LinkedStats');
var minimums = params.reduce(function(paramMinimums, param) {
var minimumParam = parseInt(parameters[param]);
if (isNaN(minimumParam)) {
if (param === 'mmp') { paramMinimums[param] = 0; }
else { paramMinimums[param] = 1; }
} else {
paramMinimums[param] = minimumParam;
}
return paramMinimums;
}, {});
LinkedStats.getLinkedStats = function(meta, paramId) {
if (!meta || !params[paramId]) { return; }
var regExp = new RegExp(LINK_MATCH + params[paramId], 'i');
return meta[Object.keys(meta).find(function(key) {
return key.match(regExp);
})];
};
LinkedStats.getValues = function(values) {
if (!values) { return; }
return values.split(',').map(function(value) {
var percentage = value.match(/\d+/);
if (!percentage) { return; }
var linkedMatch = value.match(/[a-zA-Z]+/);
if (!linkedMatch) { return; }
var linkedStat = params.find(function(param) {
return param === linkedMatch[0];
});
if (!linkedStat) { return; }
return {
stat: linkedStat,
percentage: percentage[0]
};
});
};
LinkedStats.getMinimumValue = function(value, paramId) {
if (value === 1 && minimums[params[paramId]] === 0) { return 0; }
return value;
};
LinkedStats.paramMin = Game_BattlerBase.prototype.paramMin;
Game_BattlerBase.prototype.paramMin = function(paramId) {
return minimums[params[paramId]];
};
LinkedStats.actorParamBase = Game_Actor.prototype.paramBase;
Game_Actor.prototype.paramBase = function(paramId) {
return LinkedStats.getMinimumValue(LinkedStats.actorParamBase.call(this, paramId), paramId);
};
LinkedStats.enemyParamBase = Game_Enemy.prototype.paramBase;
Game_Enemy.prototype.paramBase = function(paramId) {
return LinkedStats.getMinimumValue(LinkedStats.enemyParamBase.call(this, paramId), paramId);
};
LinkedStats.param = Game_BattlerBase.prototype.param;
Game_BattlerBase.prototype.param = function(paramId) {
var meta = this instanceof Game_Actor ? this.currentClass().meta : $dataEnemies[this._enemyId].meta;
var value = LinkedStats.param.call(this, paramId);
var linkedStats = LinkedStats.getLinkedStats(meta, paramId);
if (!linkedStats || !linkedStats.length) { return value; }
var linkedValues = LinkedStats.getValues(linkedStats);
if (!linkedValues || !linkedValues.length) { return value; }
return value + linkedValues.reduce(function(total, linkedValue) {
if (!linkedValue.stat || !linkedValue.percentage) { return total; }
return total += Math.round((this[linkedValue.stat] * (parseInt(linkedValue.percentage) / 100)));
}.bind(this), 0);
};
LinkedStats.actorParam = Game_Actor.prototype.param;
Game_Actor.prototype.param = Game_BattlerBase.prototype.param;
LinkedStats.enemyParam = Game_Enemy.prototype.param;
Game_Enemy.prototype.param = Game_BattlerBase.prototype.param;
})(window);