code:
//=============================================================================
// Yanfly Engine Plugins - Auto Passive States
// YEP_AutoPassiveStates.js
//=============================================================================

var Imported = Imported || {};
Imported.YEP_AutoPassiveStates = true;

var Yanfly = Yanfly || {};
Yanfly.APS = Yanfly.APS || {};
Yanfly.APS.version = 1.17;

//=============================================================================
 /*:
 * @plugindesc v1.17 This plugin allows for some states to function as
 * passives for actors, enemies, skills, and equips.
 * @author Yanfly Engine Plugins
 *
 * @param ---Basic---
 * @default
 *
 * @param Actor Passives
 * @parent ---Basic---
 * @desc These states will always appear on actors as passives.
 * Place a space in between each state ID.
 * @default 0
 *
 * @param Enemy Passives
 * @parent ---Basic---
 * @desc These states will always appear on enemies as passives.
 * Place a space in between each state ID.
 * @default 0
 *
 * @param Global Passives
 * @parent ---Basic---
 * @desc These states will always appear on all battlers as passives.
 * Place a space in between each state ID.
 * @default 0
 *
 * @param ---List---
 * @default ...Requires RPG Maker MV 1.5.0+...
 *
 * @param Actor Passives List
 * @parent ---List---
 * @type state[]
 * @desc These states will always appear on actors as passives.
 * Use with RPG Maker MV 1.5.0+.
 * @default []
 *
 * @param Enemy Passives List
 * @parent ---List---
 * @type state[]
 * @desc These states will always appear on enemies as passives.
 * Use with RPG Maker MV 1.5.0+.
 * @default []
 *
 * @param Global Passives List
 * @parent ---List---
 * @type state[]
 * @desc These states will always appear on all battlers as passives.
 * Use with RPG Maker MV 1.5.0+.
 * @default []
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * Passive states are states that are automatically active. You can think of
 * them as an extension of traits but with more flexibility. They will always
 * be there as long as the actor or enemy has auto passive state notetags.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * For those who would like to allocate passive states to your battlers, use
 * the notetags below:
 *
 * Actor, Class, Skills, Weapon, Armor, Enemy Notetags:
 *   <Passive State: x>
 *   <Passive State: x, x, x>
 *   This will allow the actor or enemy to have state x as a passive state.
 *   If placed inside a weapon or armor notebox, the user will have that
 *   passive state.
 *
 *   <Passive State: x to y>
 *   This will add the states x through y (in a sequence) for the actor or
 *   enemy to have as a passive state. If placed inside a weapon or armor
 *   notebox, the user will have that passive state.
 *
 * For those who don't want their passive states to always be on, you can use
 * the following notetags to introduce conditions for your passive states. All
 * conditions must be fulfilled in order for the passive state to appear.
 *
 * State Notetags:
 *   <Passive Condition: HP Above x%>
 *   <Passive Condition: HP Below x%>
 *   <Passive Condition: MP Above x%>
 *   <Passive Condition: MP Below x%>
 *   If the user's HP or MP is above/below x% of the MaxHP or MaxMP, this
 *   condition will be met for the passive state to appear.
 *
 *   <Passive Condition: Stat Above x>
 *   <Passive Condition: Stat Below x>
 *   Replace 'stat' with 'HP', 'MP', 'TP', 'MAXHP', 'MAXMP', 'ATK', 'DEF',
 *   'MAT', 'MDF', 'AGI', 'LUK'. If the above stat is above/below x, then the
 *   condition is met for the passive state to appear.
 *
 *   <Passive Condition: Switch x ON>
 *   <Passive Condition: Switch x OFF>
 *   If switch x is either ON/OFF, then the condition is met for the passive
 *   state to appear.
 *
 *   <Passive Condition: Variable x Above y>
 *   <Passive Condition: Variable x Below y>
 *   Replace x with the variable you wish to check to see if it's above/below
 *   y, then the condition is met for the passive state to appear.
 *
 * ============================================================================
 * Lunatic Mode - Conditional Passives
 * ============================================================================
 *
 * For those who understand a bit of JavaScript and would like for their
 * passive states to appear under specific conditions, you can use this notetag
 * to accomplish conditional factors.
 *
 * State Notetags:
 *   <Custom Passive Condition>
 *   if (user.hp / user.mhp <= 0.25) {
 *     condition = true;
 *   } else {
 *     condition = false;
 *   }
 *   </Custom Passive Condition>
 *   This enables you to input conditions to be met in order for the passive
 *   state to appear. If the 'condition' variable returns true, the passive
 *   state will appear. If the 'condition' returns false, it won't appear. If
 *   condition is not defined, it will return true and the passive state will
 *   appear on the battler.
 *   * Note: All non-custom passive conditions must be met before this one can
 *   be fulfilled and allow the custom condition to appear.
 *   * Note: If you decide to use a condition that requires the actor to have a
 *   particular state, it cannot be a passive state to prevent infinite loops.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.17:
 * - Optimization update. There should be less lag spikes if there are more
 * passive conditions present on a battler.
 *
 * Version 1.16:
 * - Bypass the isDevToolsOpen() error when bad code is inserted into a script
 * call or custom Lunatic Mode code segment due to updating to MV 1.6.1.
 *
 * Version 1.15:
 * - Bug fixed that made global passives not apply to actors.
 *
 * Version 1.14:
 * - Updated for RPG Maker MV version 1.5.0.
 * - Added parameters: Actor Passives List, Enemy Passives List, and
 *   Global Passives List
 *
 * Version 1.13:
 * - Lunatic Mode fail safes added.
 *
 * Version 1.12:
 * - Implemented <Custom Passive Condition> to now affect passive state ID's
 * added by Equip Battle Skills.
 *
 * Version 1.11:
 * - Added 'Global Passives' that encompass both actors and enemies.
 *
 * Version 1.10:
 * - Added compatibility functionality for Equip Battle Skills to add the
 * equipped passive states during battle test.
 *
 * Version 1.09:
 * - Added 'Actor Passives' and 'Enemy Passives' plugin parameters. This will
 * cause all actors and enemies respectively to be affected by the listed
 * states as passives.
 *
 * Version 1.08:
 * - Fixed conditional checks to make sure all states are being checked
 * properly without conflict with other conditional states.
 *
 * Version 1.07:
 * - Updated for RPG Maker MV version 1.1.0.
 *
 * Version 1.06:
 * - Added a mass member refresh whenever $gamePlayer is refreshed.
 *
 * Version 1.05a:
 * - Added Lunatic Mode - <Custom Passive Condition> notetag for states.
 * - Fixed a bug that would cause infinite loops.
 *
 * Version 1.04:
 * - Added a lot of passive condition notetags for states.
 * --- <Passive Condition: HP/MP Above/Below x%>
 * --- <Passive Condition: Stat Above/Below x>
 * --- <Passive Condition: Switch x ON/OFF>
 * --- <Passive Condition: Variable x Above/Below y>
 *
 * Version 1.03:
 * - Added refreshing whenever a new skill is learned to update passives.
 *
 * Version 1.02:
 * - Optimized passive state calculations to reduce lag.
 *
 * Version 1.01:
 * - Fixed a bug with having multiple passive states of the same ID.
 *
 * Version 1.00:
 * - Finished plugin!
 */
//=============================================================================

//=============================================================================
// Parameter Variables
//=============================================================================

Yanfly.SetupParameters = function() {
  Yanfly.Parameters = PluginManager.parameters('YEP_AutoPassiveStates');
  Yanfly.Param = Yanfly.Param || {};
  Yanfly.Param.APSActorPas = String(Yanfly.Parameters['Actor Passives']);
  Yanfly.Param.APSActorPas = Yanfly.Param.APSActorPas.split(' ');
  for (var i = 0; i < Yanfly.Param.APSActorPas.length; ++i) {
    Yanfly.Param.APSActorPas[i] = parseInt(Yanfly.Param.APSActorPas[i]);
    Yanfly.Param.APSActorPas[i] = Yanfly.Param.APSActorPas[i] || 0;
  }
  var data = JSON.parse(Yanfly.Parameters['Actor Passives List']);
  for (var i = 0; i < data.length; ++i) {
    var stateId = parseInt(data[i]);
    if (stateId <= 0) continue;
    if (Yanfly.Param.APSActorPas.contains(stateId)) continue;
    Yanfly.Param.APSActorPas.push(stateId);
  }
  Yanfly.Param.APSEnemyPas = String(Yanfly.Parameters['Enemy Passives']);
  Yanfly.Param.APSEnemyPas = Yanfly.Param.APSEnemyPas.split(' ');
  for (var i = 0; i < Yanfly.Param.APSEnemyPas.length; ++i) {
    Yanfly.Param.APSEnemyPas[i] = parseInt(Yanfly.Param.APSEnemyPas[i]);
    Yanfly.Param.APSEnemyPas[i] = Yanfly.Param.APSEnemyPas[i] || 0;
  }
  var data = JSON.parse(Yanfly.Parameters['Enemy Passives List']);
  for (var i = 0; i < data.length; ++i) {
    var stateId = parseInt(data[i]);
    if (stateId <= 0) continue;
    if (Yanfly.Param.APSEnemyPas.contains(stateId)) continue;
    Yanfly.Param.APSEnemyPas.push(stateId);
  }
  Yanfly.Param.APSGlobalPas = String(Yanfly.Parameters['Global Passives']);
  Yanfly.Param.APSGlobalPas = Yanfly.Param.APSGlobalPas.split(' ');
  for (var i = 0; i < Yanfly.Param.APSGlobalPas.length; ++i) {
    id = parseInt(Yanfly.Param.APSGlobalPas[i]);
    Yanfly.Param.APSActorPas.push(id);
    Yanfly.Param.APSEnemyPas.push(id);
  }
  var data = JSON.parse(Yanfly.Parameters['Global Passives List']);
  for (var i = 0; i < data.length; ++i) {
    var stateId = parseInt(data[i]);
    if (stateId <= 0) continue;
    if (!Yanfly.Param.APSActorPas.contains(stateId)) {
      Yanfly.Param.APSActorPas.push(stateId);
    }
    if (!Yanfly.Param.APSEnemyPas.contains(stateId)) {
      Yanfly.Param.APSEnemyPas.push(stateId);
    }
  }
};
Yanfly.SetupParameters();

//=============================================================================
// DataManager
//=============================================================================

Yanfly.APS.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.APS.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_AutoPassiveStates) {
    this.processAPSNotetags1($dataActors, Yanfly.Param.APSActorPas);
    this.processAPSNotetags1($dataClasses);
    this.processAPSNotetags1($dataEnemies, Yanfly.Param.APSEnemyPas);
    this.processAPSNotetags1($dataSkills);
    this.processAPSNotetags1($dataWeapons);
    this.processAPSNotetags1($dataArmors);
    this.processAPSNotetags2($dataStates);
    Yanfly._loaded_YEP_AutoPassiveStates = true;
  }
  return true;
};

DataManager.processAPSNotetags1 = function(group, inheritArray) {
  var note1 = /<(?:PASSIVE STATE):[ ]*(\d+(?:\s*,\s*\d+)*)>/i;
  var note2 = /<(?:PASSIVE STATE):[ ](\d+)[ ](?:THROUGH|to)[ ](\d+)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.passiveStates = [];
    if (inheritArray) {
      obj.passiveStates = obj.passiveStates.concat(inheritArray);
    }

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        var array = JSON.parse('[' + RegExp.$1.match(/\d+/g) + ']');
        obj.passiveStates = obj.passiveStates.concat(array);
      } else if (line.match(note2)) {
        var range = Yanfly.Util.getRange(parseInt(RegExp.$1),
          parseInt(RegExp.$2));
        obj.passiveStates = obj.passiveStates.concat(range);
      }
    }
  }
};

DataManager.processAPSNotetags2 = function(group) {
  var note1a = /<(?:PASSIVE CONDITION):[ ](.*)[ ](?:ABOVE)[ ](\d+)([%％])>/i;
  var note1b = /<(?:PASSIVE CONDITION):[ ](.*)[ ](?:BELOW)[ ](\d+)([%％])>/i;
  var note2a = /<(?:PASSIVE CONDITION):[ ](.*)[ ](?:ABOVE)[ ](\d+)>/i;
  var note2b = /<(?:PASSIVE CONDITION):[ ](.*)[ ](?:BELOW)[ ](\d+)>/i;
  var note3a = /<(?:PASSIVE CONDITION):[ ]SWITCH[ ](\d+)[ ](.*)>/i;
  var notez1 = /<(?:CUSTOM PASSIVE CONDITION)>/i;
  var notez2 = /<\/(?:CUSTOM PASSIVE CONDITION)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.passiveCondition = '';
    obj.passiveConditionEval = '';
    var evalMode = 'none';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1a)) {
        var rate = parseFloat(RegExp.$2) * 0.01;
        var param = this.getPassiveConditionParamRate(String(RegExp.$1));
        var pass = 'if (' + param + ' <= ' + rate + ') condition = false;';
        obj.passiveCondition = obj.passiveCondition + pass + '\n';
      } else if (line.match(note1b)) {
        var rate = parseFloat(RegExp.$2) * 0.01;
        var param = this.getPassiveConditionParamRate(String(RegExp.$1));
        var pass = 'if (' + param + ' >= ' + rate + ') condition = false;';
        obj.passiveCondition = obj.passiveCondition + pass + '\n';
      } else if (line.match(note2a)) {
        var rate = parseInt(RegExp.$2);
        var param = this.getPassiveConditionParam(String(RegExp.$1));
        var pass = 'if (' + param + ' <= ' + rate + ') condition = false;';
        obj.passiveCondition = obj.passiveCondition + pass + '\n';
      } else if (line.match(note2b)) {
        var rate = parseInt(RegExp.$2);
        var param = this.getPassiveConditionParam(String(RegExp.$1));
        var pass = 'if (' + param + ' >= ' + rate + ') condition = false;';
        obj.passiveCondition = obj.passiveCondition + pass + '\n';
      } else if (line.match(note3a)) {
        var id = parseInt(RegExp.$1);
        var value = String(RegExp.$2).toUpperCase();
        var pass = ''
        if (['ON', 'TRUE', 'ENABLE', 'ENABLED'].contains(value)) {
          pass = 'if (!$gameSwitches.value(' + id + ')) condition = false;'
        }
        if (['OFF', 'FALSE', 'DISABLE', 'DISABLED'].contains(value)) {
          pass = 'if ($gameSwitches.value(' + id + ')) condition = false;'
        }
        if (pass === '') continue;
        obj.passiveCondition = obj.passiveCondition + pass + '\n';
      } else if (line.match(notez1)) {
        evalMode = 'custom passive condition';
      } else if (line.match(notez2)) {
        evalMode = 'none';
      } else if (evalMode === 'custom passive condition') {
        obj.passiveConditionEval = obj.passiveConditionEval + line + '\n';
      }
    }

    obj.passiveCondition = new Function('condition','a','user','subject','b',
      'target','s','v', obj.passiveCondition + '\nreturn condition;');
    obj.passiveConditionEval = new Function('condition','a','user','subject',
      'b','target','s','v', obj.passiveConditionEval + '\nreturn condition;');
  }
};

DataManager.getPassiveConditionParam = function(string) {
    string = string.toUpperCase();
    var text = 'user.';
    if (['HP'].contains(string)) text += 'hp';
    if (['MP', 'SP'].contains(string)) text += 'mp';
    if (['TP'].contains(string)) text += 'tp';
    if (['ATK'].contains(string)) text += 'param(2)';
    if (['DEF'].contains(string)) text += 'param(3)';
    if (['MAT', 'INT'].contains(string)) text += 'param(4)';
    if (['MDF', 'RES'].contains(string)) text += 'param(5)';
    if (['AGI'].contains(string)) text += 'param(6)';
    if (['LUK'].contains(string)) text += 'param(7)';
    if (['MAX HP', 'MAXHP'].contains(string)) text += 'mhp';
    if (['MAX MP', 'MAX SP', 'MAXMP', 'MAXSP'].contains(string)) text += 'mmp';
    if (string.match(/VARIABLE[ ](\d+)/i)) {
      text = '$gameVariables.value(' + parseInt(RegExp.$1) + ')';
    }
    return text;
};

DataManager.getPassiveConditionParamRate = function(string) {
    string = string.toUpperCase();
    var text = '0';
    if (['HP'].contains(string)) return 'user.hpRate()';
    if (['MP'].contains(string)) return 'user.mpRate()';
    return text;
};

//=============================================================================
// Game_BattlerBase
//=============================================================================

Yanfly.APS.Game_BattlerBase_refresh = Game_BattlerBase.prototype.refresh;
Game_BattlerBase.prototype.refresh = function() {
    this._passiveStatesRaw = undefined;
    Yanfly.APS.Game_BattlerBase_refresh.call(this);
};

Yanfly.APS.Game_BattlerBase_states = Game_BattlerBase.prototype.states;
Game_BattlerBase.prototype.states = function() {
    var array = Yanfly.APS.Game_BattlerBase_states.call(this);
    array = array.concat(this.passiveStates());
    this.sortPassiveStates(array);
    return array;
};

Yanfly.APS.Game_BattlerBase_isStateAffected =
    Game_BattlerBase.prototype.isStateAffected;
Game_BattlerBase.prototype.isStateAffected = function(stateId) {
    if (this.isPassiveStateAffected(stateId)) return true;
    return Yanfly.APS.Game_BattlerBase_isStateAffected.call(this, stateId);
};

Game_BattlerBase.prototype.passiveStates = function() {
    var array = [];
    var raw = this.passiveStatesRaw();
    for (var i = 0; i < raw.length; ++i) {
      var state = $dataStates[raw[i]];
      if (state && array.contains(state)) continue;
      array.push(state);
    }
    return array;
};

Game_BattlerBase.prototype.passiveStatesRaw = function() {
    var array = [];
    return array.filter(Yanfly.Util.onlyUnique);
};

Game_BattlerBase.prototype.getPassiveStateData = function(obj) {
    if (!obj) return [];
    if (!obj.passiveStates) return [];
    var array = [];
    for (var i = 0; i < obj.passiveStates.length; ++i) {
      var stateId = obj.passiveStates[i];
      if (!this.meetPassiveStateCondition(stateId)) continue;
      array.push(stateId);
    }
    var added = this.addEquipBattleTestSkillPassives(obj);
    if (added.length > 0) {
      for (var i = 0; i < added.length; ++i) {
        var stateId = added[i];
        if (!this.meetPassiveStateCondition(stateId)) continue;
        array.push(stateId);
      }
    }
    return array;
};

Game_BattlerBase.prototype.addEquipBattleTestSkillPassives = function(obj) {
  if (!Imported.YEP_EquipBattleSkills) return [];
  if (!DataManager.isBattleTest()) return [];
  if (!DataManager.isSkill(obj)) return [];
  return obj.equipStates;
};

Game_BattlerBase.prototype.meetPassiveStateCondition = function(stateId) {
    this._checkPassiveStateCondition = this._checkPassiveStateCondition || [];
    if (this._checkPassiveStateCondition.contains(stateId)) return false;
    var state = $dataStates[stateId];
    if (!state) return false;
    if (state.passiveCondition !== '') {
      if (!this.passiveStateConditions(state)) return false;
    }
    if (state.passiveConditionEval === '') return true;
    return this.passiveStateConditionEval(state);
};

Game_BattlerBase.prototype.passiveStateConditions = function(state) {
  this._checkPassiveStateCondition = this._checkPassiveStateCondition || [];
  this._checkPassiveStateCondition.push(state.id);
  var condition = true;
  var a = this;
  var user = this;
  var subject = this;
  var b = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  var code = state.passiveCondition;
  try {
    condition = state.passiveCondition.call(this, condition, a, user, subject,
      b, target, s, v);
  } catch (e) {
    Yanfly.Util.displayError(e, code, 'PASSIVE STATE CUSTOM CONDITION ERROR');
  }
  var index = this._checkPassiveStateCondition.indexOf(state.id);
  this._checkPassiveStateCondition.splice(index, 1);
  return condition;
};

Game_BattlerBase.prototype.passiveStateConditionEval = function(state) {
  this._checkPassiveStateCondition = this._checkPassiveStateCondition || [];
  this._checkPassiveStateCondition.push(state.id);
  var condition = true;
  var a = this;
  var user = this;
  var subject = this;
  var b = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  var code = state.passiveConditionEval;
  try {
    condition = state.passiveConditionEval.call(this, condition, a, user,
      subject, b, target, s, v);
  } catch (e) {
    Yanfly.Util.displayError(e, code, 'PASSIVE STATE CUSTOM CONDITION ERROR');
  }
  var index = this._checkPassiveStateCondition.indexOf(state.id);
  this._checkPassiveStateCondition.splice(index, 1);
  return condition;
};

Game_BattlerBase.prototype.sortPassiveStates = function(array) {
    array.sort(function(a, b) {
      var p1 = a.priority;
      var p2 = b.priority;
      if (p1 !== p2) return p2 - p1;
      return a - b;
    });
};

Game_BattlerBase.prototype.isPassiveStateAffected = function(stateId) {
    return this.passiveStatesRaw().contains(stateId);
};

//=============================================================================
// Game_Battler
//=============================================================================

Yanfly.APS.Game_Battler_isStateAddable = Game_Battler.prototype.isStateAddable;
Game_Battler.prototype.isStateAddable = function(stateId) {
    if (this.isPassiveStateAffected(stateId)) return false;
    return Yanfly.APS.Game_Battler_isStateAddable.call(this, stateId);
};

Yanfly.APS.Game_Battler_removeState = Game_Battler.prototype.removeState;
Game_Battler.prototype.removeState = function(stateId) {
    if (this.isPassiveStateAffected(stateId)) return;
    Yanfly.APS.Game_Battler_removeState.call(this, stateId);
};

//=============================================================================
// Game_Actor
//=============================================================================

Game_Actor.prototype.passiveStatesRaw = function() {
    if (this._passiveStatesRaw !== undefined) return this._passiveStatesRaw;
    var array = Game_BattlerBase.prototype.passiveStatesRaw.call(this);
    array = array.concat(this.getPassiveStateData(this.actor()));
    array = array.concat(this.getPassiveStateData(this.currentClass()));
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      array = array.concat(this.getPassiveStateData(equip));
    }
    for (var i = 0; i < this._skills.length; ++i) {
      var skill = $dataSkills[this._skills[i]];
      array = array.concat(this.getPassiveStateData(skill));
    }
    this._passiveStatesRaw = array.filter(Yanfly.Util.onlyUnique)
    return this._passiveStatesRaw;
};

Yanfly.APS.Game_Actor_learnSkill = Game_Actor.prototype.learnSkill;
Game_Actor.prototype.learnSkill = function(skillId) {
    Yanfly.APS.Game_Actor_learnSkill.call(this, skillId);
    this._passiveStatesRaw = undefined;
};

Yanfly.APS.Game_Actor_forgetSkill = Game_Actor.prototype.forgetSkill;
Game_Actor.prototype.forgetSkill = function(skillId) {
    Yanfly.APS.Game_Actor_forgetSkill.call(this, skillId);
    this._passiveStatesRaw = undefined;
};

//=============================================================================
// Game_Enemy
//=============================================================================

Game_Enemy.prototype.passiveStatesRaw = function() {
    if (this._passiveStatesRaw !== undefined) return this._passiveStatesRaw;
    var array = Game_BattlerBase.prototype.passiveStatesRaw.call(this);
    array = array.concat(this.getPassiveStateData(this.enemy()));
    for (var i = 0; i < this.skills().length; ++i) {
      var skill = this.skills()[i];
      array = array.concat(this.getPassiveStateData(skill));
    }
    this._passiveStatesRaw = array.filter(Yanfly.Util.onlyUnique)
    return this._passiveStatesRaw;
};

if (!Game_Enemy.prototype.skills) {
    Game_Enemy.prototype.skills = function() {
      var skills = []
      for (var i = 0; i < this.enemy().actions.length; ++i) {
        var skill = $dataSkills[this.enemy().actions[i].skillId];
        if (skill) skills.push(skill);
      }
      return skills;
    }
};

//=============================================================================
// Game_Unit
//=============================================================================

Game_Unit.prototype.refreshMembers = function() {
    var group = this.allMembers();
    var length = group.length;
    for (var i = 0; i < length; ++i) {
      var member = group[i];
      if (member) member.refresh();
    }
};

Game_Unit.prototype.allMembers = function() {
    return this.members();
};

//=============================================================================
// Game_Player
//=============================================================================

Yanfly.APS.Game_Player_refresh = Game_Player.prototype.refresh;
Game_Player.prototype.refresh = function() {
    $gameParty.refreshMembers();
    Yanfly.APS.Game_Player_refresh.call(this);
};

//=============================================================================
// Utilities
//=============================================================================

Yanfly.Util = Yanfly.Util || {};

Yanfly.Util.displayError = function(e, code, message) {
  console.log(message);
  console.log(code || 'NON-EXISTENT');
  console.error(e);
  if (Utils.RPGMAKER_VERSION && Utils.RPGMAKER_VERSION >= "1.6.0") return;
  if (Utils.isNwjs() && Utils.isOptionValid('test')) {
    if (!require('nw.gui').Window.get().isDevToolsOpen()) {
      require('nw.gui').Window.get().showDevTools();
    }
  }
};

Yanfly.Util.getRange = function(n, m) {
    var result = [];
    for (var i = n; i <= m; ++i) result.push(i);
    return result;
};

Yanfly.Util.onlyUnique = function(value, index, self) {
    return self.indexOf(value) === index;
};

//=============================================================================
// End of File
//=============================================================================


code:
//=============================================================================
// Yanfly Engine Plugins - Base Parameter Control
// YEP_BaseParamControl.js
//=============================================================================

var Imported = Imported || {};
Imported.YEP_BaseParamControl = true;

var Yanfly = Yanfly || {};
Yanfly.BPC = Yanfly.BPC || {};
Yanfly.BPC.version = 1.04;

//=============================================================================
 /*:
 * @plugindesc v1.04 Gain control over the method of calculation for base
 * parameters: MaxHP, MaxMP, ATK, DEF, MAT, MDF, AGI, LUK.
 * @author Yanfly Engine Plugins
 *
 * @param ---MaxHP---
 * @default
 *
 * @param MHP Formula
 * @parent ---MaxHP---
 * @desc The formula used to determine MHP: MaxHP
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param MHP Maximum
 * @parent ---MaxHP---
 * @desc This is the highest value for MHP.
 * This is a formula.
 * @default customMax || (user.isActor() ? 9999 : 999999)
 *
 * @param MHP Minimum
 * @parent ---MaxHP---
 * @desc This is the lowest value for MHP.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---MaxMP---
 * @default
 *
 * @param MMP Formula
 * @parent ---MaxMP---
 * @desc The formula used to determine MMP: MaxMP
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param MMP Maximum
 * @parent ---MaxMP---
 * @desc This is the highest value for MMP.
 * This is a formula.
 * @default customMax || (user.isActor() ? 9999 : 9999)
 *
 * @param MMP Minimum
 * @parent ---MaxMP---
 * @desc This is the lowest value for MMP.
 * This is a formula.
 * @default customMin || 0
 *
 * @param ---Attack---
 * @default
 *
 * @param ATK Formula
 * @parent ---Attack---
 * @desc The formula used to determine ATK: Attack
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param ATK Maximum
 * @parent ---Attack---
 * @desc This is the highest value for ATK.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param ATK Minimum
 * @parent ---Attack---
 * @desc This is the lowest value for ATK.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---Defense---
 * @default
 *
 * @param DEF Formula
 * @parent ---Defense---
 * @desc The formula used to determine DEF: Defense
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param DEF Maximum
 * @parent ---Defense---
 * @desc This is the highest value for DEF.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param DEF Minimum
 * @parent ---Defense---
 * @desc This is the lowest value for DEF.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---M.Attack---
 * @default
 *
 * @param MAT Formula
 * @parent ---M.Attack---
 * @desc The formula used to determine MAT: M.Attack
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param MAT Maximum
 * @parent ---M.Attack---
 * @desc This is the highest value for MAT.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param MAT Minimum
 * @parent ---M.Attack---
 * @desc This is the lowest value for MAT.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---M.Defense---
 * @default
 *
 * @param MDF Formula
 * @parent ---M.Defense---
 * @desc The formula used to determine MDF: M.Defense
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param MDF Maximum
 * @parent ---M.Defense---
 * @desc This is the highest value for MDF.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param MDF Minimum
 * @parent ---M.Defense---
 * @desc This is the lowest value for MDF.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---Agility---
 * @default
 *
 * @param AGI Formula
 * @parent ---Agility---
 * @desc The formula used to determine AGI: Agility
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param AGI Maximum
 * @parent ---Agility---
 * @desc This is the highest value for AGI.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param AGI Minimum
 * @parent ---Agility---
 * @desc This is the lowest value for AGI.
 * This is a formula.
 * @default customMin || 1
 *
 * @param ---Luck---
 * @default
 *
 * @param LUK Formula
 * @parent ---Luck---
 * @desc The formula used to determine LUK: Luck
 * This is a formula.
 * @default (base + plus) * paramRate * buffRate + flat
 *
 * @param LUK Maximum
 * @parent ---Luck---
 * @desc This is the highest value for LUK.
 * This is a formula.
 * @default customMax || (user.isActor() ? 999 : 999)
 *
 * @param LUK Minimum
 * @parent ---Luck---
 * @desc This is the lowest value for LUK.
 * This is a formula.
 * @default customMin || 1
 *
 * @param LUK Effect
 * @parent ---Luck---
 * @desc The formula used to influence state success rates.
 * This is a formula
 * @default Math.max(1.0 + (user.luk - target.luk) * 0.001, 0.0)
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * The base parameters, MaxHP, MaxMP, ATK, DEF, MAT, MDF, AGI, and LUK all play
 * a very important part of battle, yet, so very little control is given to the
 * developer in regards to these important stats. This plugin will give more
 * control over how the stats are handled and more.
 *
 * Note: If you are using the Core Engine and have modified the settings there
 * for higher parameter caps, this plugin will override those settings if this
 * plugin is placed beneath the Core Engine (recommended).
 *
 * ============================================================================
 * Instructions - Base Parameter Explanation
 * ============================================================================
 *
 * For those who do not understand what the base parameters are used for in RPG
 * Maker MV, this section will provide a brief summary of their most important
 * roles of what the base parameters do.
 *
 * ---
 *
 * MHP - MaxHP
 * - This is the maximum health points value. The amount of health points (HP)
 * a battler has determines whether or not the battler is in a living state or
 * a dead state. If the HP value is above 0, then the battler is living. If it
 * is 0 or below, the battler is in a dead state unless the battler has a way
 * to counteract death (usually through immortality). When the battler takes
 * damage, it is usually dealt to the HP value and reduces it. If the battler
 * is healed, then the HP value is increased. The MaxHP value determines what's
 * the maximum amount the HP value can be held at, meaning the battler cannot
 * be healed past that point.
 *
 * ---
 *
 * MMP - MaxMP
 * - This is the maximum magic points value. Magic points (MP) are typically
 * used for the cost of skills and spells in battle. If the battler has enough
 * MP to fit the cost of the said skill, the battler is able to use the said
 * skill provided that all of the skill's other conditions are met. If not, the
 * battler is then unable to use the skill. Upon using a skill that costs MP,
 * the battler's MP is reduced. However, the battler's MP can be recovered and
 * results in a gain of MP. The MaxMP value determines what is the maximum
 * amount the MP value can be held at, meaning the battler cannot recover MP
 * past the MaxMP value.
 *
 * ---
 *
 * ATK - Attack
 * - This is the attack value of the battler. By default, this stat is used for
 * the purpose of damage calculations only, and is typically used to represent
 * the battler's physical attack power. Given normal damage formulas, higher
 * values mean higher damage output for physical attacks.
 *
 * ---
 *
 * DEF - Defense
 * - This is the defense value of the battler. By default, this stat is used
 * for the purpose of damage calculations only, and is typically used to
 * represent the battler's physical defense. Given normal damage formulas,
 * higher values mean less damage received from physical attacks.
 *
 * ---
 *
 * MAT - Magic Attack
 * - This is the magic attack value of the battler. By default, this stat is
 * used for the purpose of damage calculations only, and is typically used to
 * represent the battler's magical attack power. Given normal damage formulas,
 * higher values mean higher damage output for magical attacks.
 *
 * ---
 *
 * MDF - Magic Defense
 * - This is the magic defense value of the battler. By default, this stat is
 * used for the purpose of damage calculations only, and is typically used to
 * represent the battler's magical defense. Given normal damage formulas,
 * higher values mean less damage received from magical attacks.
 *
 * ---
 *
 * AGI - Agility
 * - This is the agility value of the battler. By default, this stat is used to
 * determine battler's position in the battle turn's order. Given a normal turn
 * calculation formula, the higher the value, the faster the battler is, and
 * the more likely the battler will have its turn earlier in a turn.
 *
 * ---
 *
 * LUK - Luck
 * - This is the luck value of the battler. By default, this stat is used to
 * affect the success rate of states, buffs, and debuffs applied by the battler
 * and received by the battler. If the user has a higher LUK value, the state,
 * buff, or debuff is more likely to succeed. If the target has a higher LUK
 * value, then the state, buff, or debuff is less likely to succeed.
 *
 * ---
 *
 * ============================================================================
 * Instructions - Custom Formulas
 * ============================================================================
 *
 * The values calculated by the formulas in the plugin parameters are to come
 * out as integer values. If the result is a float, it will be rounded up and
 * then clamped based around the maximum and minimum values the parameter can
 * be (also calculated by the plugin parameters).
 *
 * By default, the formula looks as such:
 *
 * ---
 *
 *      (base + plus) * paramRate * buffRate + flat
 *
 * ---
 *
 * Below is an explanation of each of the parts of the formula.
 *
 * BASE
 * - This value is determined in multiple ways. If the battler is an actor, the
 * base value is the base parameter value calculated by the position based on
 * the battler's level on the parameter curve for the battler's current class.
 * If the battler is an enemy, the base parameter value, by default, is equal
 * to the value inserted on the enemy's database entry for that parameter.
 *
 * PLUS
 * - This value is determined in multiple ways. For both actors and enemies,
 * this value is a flat value given to the battler through events or script
 * calls that manually increase the battler's parameter value. If the battler
 * is an actor, this value is also increased by any equipment the battler has
 * equipped. This value can be influenced by notetags provided by this plugin.
 *
 * PARAMRATE
 * - This value is determined the same way for both actors and enemies. This is
 * a percentile rate that is calculated by the multiplicative product of all
 * of the parameter spread across the battler's traits, independent of the
 * battler's buff rate. This value can be influenced by notetags provided by
 * this plugin.
 *
 * BUFFRATE
 * - This value is determined by the number of buff stacks (or debuff stacks)
 * on a battler, regardless of whether or not the battler is an actor or enemy.
 * The percentile modifier is calculated relative to the number of stacks in
 * regards to that particular parameter for the battler. This value is NOT
 * influenced by notetags provided by this plugin.
 *
 * FLAT
 * - This is a new variable added by this plugin. Its purpose is to provide a
 * final additive modifier to the total value of the parameter. This additive
 * value is determined by the various database objects through notetags and can
 * only be affected by those notetags.
 *
 * ---
 *
 * The parameter Maximum and Minimum values also have formulas. They will work
 * something along the lines of this by default:
 *
 *      customMax || (user.isActor() ? 9999 : 999999)
 *      customMin || 1
 *
 * For those wondering about the 'customMax' and 'customMin' values, they are
 * new variables added by this plugin.
 *
 * CUSTOMMAX
 * - This is the custom maximum limit provided by this plugin through either a
 * script call or notetags. The custom max will look through the battler's
 * individual noteboxes. If the battler is an actor, it will look through the
 * actor, class, each of the noteboxes of the equipment worn by the actor, and
 * the noteboxes of each of the states affecting the actor. If the battler is
 * an enemy, it wil look through the enemy notebox and each of the noteboxes of
 * the states affecting the enemy. The highest custom maximum value becomes the
 * newest 'customMax' value for the battler and will take priority over the
 * default maximum value. If there is no 'customMax' value, then the value
 * becomes the default maximum value written in the formula.
 *
 * CUSTOMMIN
 * - This is the custom minimum limit provided by this plugin through either a
 * script call or notetags. The custom min will look through the battler's
 * individual noteboxes. If the battler is an actor, it will look through the
 * actor, class, each of the noteboxes of the equipment worn by the actor, and
 * the noteboxes of each of the states affecting the actor. If the battler is
 * an enemy, it wil look through the enemy notebox and each of the noteboxes of
 * the states affecting the enemy. The highest custom minimum value becomes the
 * newest 'customMin' value for the battler and will take priority over the
 * default minimum value. If there is no 'customMin' value, then the value
 * becomes the default minimum value written in the formula.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * You can use the following notetags to alter the various aspects that modify
 * the base parameter values:
 *
 * Actor, Class, Enemy, Weapon, Armor, and State Notetags:
 *
 *   <stat Plus: +x>
 *   <stat Plus: -x>
 *   Replace 'stat' with 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf', 'agi',
 *   or 'luk'. This is the value added to the base parameter before the rate
 *   and flat values contribute to the total parameter value assuming the
 *   plugin's default formula is utilized.
 *
 *   <stat Rate: x%>
 *   <stat Rate: x.y>
 *   Replace 'stat' with 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf', 'agi',
 *   or 'luk'. This is the value multiplied to the sum of the base and plus of
 *   the parameter before affected by the buffRate and flat value assuming the
 *   plugin's default formula is utilized.
 *
 *   <stat Flat: +x>
 *   <stat Flat: -x>
 *   Replace 'stat' with 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf', 'agi',
 *   or 'luk'. This is the value added at the end after the sum of the base and
 *   plus parameters have been added and multiplied by the rate values assuming
 *   the plugin's default formula is utilized.
 *
 *   <stat Max: x>
 *   <stat Min: x>
 *   Replace 'stat' with 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf', 'agi',
 *   or 'luk'. This sets the maximum or minimum cap of the the stat parameter
 *   to x. If a battler is affected by multiple of these notetags, then the
 *   value used will be the largest value of the notetag used.
 *
 * ============================================================================
 * Lunatic Mode - New JavaScript Functions
 * ============================================================================
 *
 * You can use the following JavaScript functions to alter the base parameter
 * values of the battlers. In these listed functions, the 'battler' variable
 * is to be referenced by an actor:
 *
 * ie. battler = $gameActors.actor(3);
 *     - or -
 *     battler = $gameTroop.members()[2];
 *
 * Function:
 *
 *   battler.clearParamPlus()
 *   - This will clear all 'plus' variable modifiers for all base parameters.
 *
 *   battler.setMaxHp(x)
 *   battler.setMaxMp(x)
 *   battler.setAtk(x)
 *   battler.setDef(x)
 *   battler.setMat(x)
 *   battler.setMdf(x)
 *   battler.setAgi(x)
 *   battler.setLui(x)
 *   - Sets the battler's respective base parameter value to x. This will alter
 *   the 'plus' variable to fit this setting as best as possible without taking
 *   into consideration the rates and flats.
 *
 *   battler.setMaxHpPlus(x)
 *   battler.setMaxMpPlus(x)
 *   battler.setAtkPlus(x)
 *   battler.setDefPlus(x)
 *   battler.setMatPlus(x)
 *   battler.setMdfPlus(x)
 *   battler.setAgiPlus(x)
 *   battler.setLuiPlus(x)
 *   - Sets the battler's respective base parameter plus value to x.
 *
 *   battler.addMaxHp(x)
 *   battler.addMaxMp(x)
 *   battler.addAtk(x)
 *   battler.addDef(x)
 *   battler.addMat(x)
 *   battler.addMdf(x)
 *   battler.addAgi(x)
 *   battler.addLui(x)
 *   - Adds x value to battler's respective base parameter plus value.
 *
 *   battler.minusMaxHp(x)
 *   battler.minusMaxMp(x)
 *   battler.minusAtk(x)
 *   battler.minusDef(x)
 *   battler.minusMat(x)
 *   battler.minusMdf(x)
 *   battler.minusAgi(x)
 *   battler.minusLui(x)
 *   - Subtracts x value to battler's respective base parameter plus value.
 *
 *   battler.clearCustomParamLimits();
 *   - Clears any custom parameter limits placed upon the battler through a
 *   script call. This does not remove the custom parameter limits applied to
 *   a battler through notetags.
 *
 *   battler.setCustomMaxHpMax(x)
 *   battler.setCustomMaxMpMax(x)
 *   battler.setCustomAtkMax(x)
 *   battler.setCustomDefMax(x)
 *   battler.setCustomMatMax(x)
 *   battler.setCustomMdfMax(x)
 *   battler.setCustomAgiMax(x)
 *   battler.setCustomLukMax(x)
 *   - Sets the maximum parameter limit of the respective base parameter to x.
 *   This value is calculated against any <stat Max: x> notetags that the
 *   battler may have. If there are multiple max values, the larges value is
 *   used as the parameter maximum.
 *
 *   battler.setCustomMaxHpMin(x)
 *   battler.setCustomMaxMpMin(x)
 *   battler.setCustomAtkMin(x)
 *   battler.setCustomDefMin(x)
 *   battler.setCustomMatMin(x)
 *   battler.setCustomMdfMin(x)
 *   battler.setCustomAgiMin(x)
 *   battler.setCustomLukMin(x)
 *   - Sets the minimum parameter limit of the respective base parameter to x.
 *   This value is calculated against any <stat Min: x> notetags that the
 *   battler may have. If there are multiple min values, the larges value is
 *   used as the parameter minimum.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.04:
 * - Bypass the isDevToolsOpen() error when bad code is inserted into a script
 * call or custom Lunatic Mode code segment due to updating to MV 1.6.1.
 *
 * Version 1.03:
 * - Updated for RPG Maker MV version 1.5.0.
 *
 * Version 1.02:
 * - Lunatic Mode fail safes added.
 *
 * Version 1.01:
 * - Fixed an issue with the battler.setParam functions that made them take the
 * wrong value due caching issues.
 */
//=============================================================================

//=============================================================================
// Parameter Variables
//=============================================================================

Yanfly.Parameters = PluginManager.parameters('YEP_BaseParamControl');
Yanfly.Param = Yanfly.Param || {};

Yanfly.Param.BPCFormula = []
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['MHP Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['MMP Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['ATK Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['DEF Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['MAT Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['MDF Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['AGI Formula']));
Yanfly.Param.BPCFormula.push(String(Yanfly.Parameters['LUK Formula']));

Yanfly.Param.BPCMaximum = []
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['MHP Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['MMP Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['ATK Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['DEF Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['MAT Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['MDF Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['AGI Maximum']));
Yanfly.Param.BPCMaximum.push(String(Yanfly.Parameters['LUK Maximum']));

Yanfly.Param.BPCMinimum = []
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['MHP Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['MMP Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['ATK Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['DEF Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['MAT Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['MDF Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['AGI Minimum']));
Yanfly.Param.BPCMinimum.push(String(Yanfly.Parameters['LUK Minimum']));

Yanfly.Param.BPCLukEffectRate = String(Yanfly.Parameters['LUK Effect']);

//=============================================================================
// DataManager
//=============================================================================

Yanfly.BPC.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.BPC.DataManager_isDatabaseLoaded.call(this)) return false;

  if (!Yanfly._loaded_YEP_BaseParamControl) {
    this.processBPCNotetags1($dataActors);
    this.processBPCNotetags1($dataClasses);
    this.processBPCNotetags1($dataEnemies);
    this.processBPCNotetags1($dataWeapons);
    this.processBPCNotetags1($dataArmors);
    this.processBPCNotetags1($dataStates);
    Yanfly._loaded_YEP_BaseParamControl = true;
  }

  return true;
};

DataManager.processBPCNotetags1 = function(group) {
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.plusParams = [0, 0, 0, 0, 0, 0, 0, 0];
    obj.rateParams = [1, 1, 1, 1, 1, 1, 1, 1];
    obj.flatParams = [0, 0, 0, 0, 0, 0, 0, 0];
    obj.maxParams = [];
    obj.minParams = [];

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(.*) PLUS:[ ]([\+\-]\d+)>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var value = parseInt(RegExp.$2);
        var id = this.getParamId(text);
        if (id !== null) obj.plusParams[id] = value;
      } else if (line.match(/<(.*) RATE:[ ](\d+)([%％])>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var rate = parseFloat(RegExp.$2) * 0.01;
        var id = this.getParamId(text);
        if (id !== null) obj.rateParams[id] = rate;
      } else if (line.match(/<(.*) RATE:[ ](\d+).(\d+)>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var rate = parseFloat(String(RegExp.$2) + '.' + String(RegExp.$3));
        var id = this.getParamId(text);
        if (id !== null) obj.rateParams[id] = rate;
      } else if (line.match(/<(.*) FLAT:[ ]([\+\-]\d+)>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var value = parseInt(RegExp.$2);
        var id = this.getParamId(text);
        if (id !== null) obj.flatParams[id] = value;
      } else if (line.match(/<(.*) MAX:[ ](\d+)>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var value = parseInt(RegExp.$2);
        var id = this.getParamId(text);
        if (id !== null) obj.maxParams[id] = value;
      } else if (line.match(/<(.*) MIN:[ ](\d+)>/i)) {
        var text = String(RegExp.$1).toUpperCase();
        var value = parseInt(RegExp.$2);
        var id = this.getParamId(text);
        if (id !== null) obj.minParams[id] = value;
      }
    }
  }
};

DataManager.getParamId = function(string) {
    if (['MHP',, 'MAXHP', 'MAX HP', 'HP'].contains(string)) {
      return 0;
    } else if (['MMP',, 'MAXMP', 'MAX MP', 'MP'].contains(string)) {
      return 1;
    } else if (['ATK', 'ATTACK', 'STR'].contains(string)) {
      return 2;
    } else if (['DEF', 'DEFENSE', 'END'].contains(string)) {
      return 3;
    } else if (['MAT', 'MAGIC ATTACK', 'M.ATTACK', 'INT', 'DEX'].contains(string)) {
      return 4;
    } else if (['MDF', 'MAGIC DEFENSE', 'M.DEFENSE', 'RES', 'MIND'].contains(string)) {
      return 5;
    } else if (['AGI', 'AGILITY', 'SPD'].contains(string)) {
      return 6;
    } else if (['LUK', 'LUK', 'CHARM', 'CHA'].contains(string)) {
      return 7;
    } else {
      return null;
    }
};

//=============================================================================
// Game_BattlerBase
//=============================================================================

Game_BattlerBase.prototype.param = function(paramId) {
  this._baseParamCache = this._baseParamCache || [];
  if (this._baseParamCache[paramId]) return this._baseParamCache[paramId];
  var base = this.paramBase(paramId);
  var plus = this.paramPlus(paramId);
  var paramRate = this.paramRate(paramId);
  var buffRate = this.paramBuffRate(paramId);
  var flat = this.paramFlat(paramId);
  var minValue = this.paramMin(paramId);
  var maxValue = Math.max(minValue, this.paramMax(paramId));
  var a = this;
  var user = this;
  var subject = this;
  var b = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  var code = Yanfly.Param.BPCFormula[paramId];
  try {
    var value = eval(code);
  } catch (e) {
    var value = 0;
    Yanfly.Util.displayError(e, code, 'CUSTOM PARAM FORMULA ERROR');
  }
  value = Math.round(value.clamp(minValue, maxValue));
  this._baseParamCache[paramId] = value;
  return this._baseParamCache[paramId];
};

Game_BattlerBase.prototype.paramMax = function(paramId) {
  var customMax = this.customParamMax(paramId);
  var a = this;
  var user = this;
  var subject = this;
  var b = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  var code = Yanfly.Param.BPCMaximum[paramId];
  try {
    var value = eval(code);
  } catch (e) {
    var value = 0;
    Yanfly.Util.displayError(e, code, 'CUSTOM PARAM MAX FORMULA ERROR');
  }
  value = Math.ceil(value);
  return value;
};

Game_BattlerBase.prototype.paramMin = function(paramId) {
  var customMin = this.customParamMin(paramId);
  var a = this;
  var user = this;
  var subject = this;
  var b = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  var code = Yanfly.Param.BPCMinimum[paramId];
  try {
    var value = eval(code);
  } catch (e) {
    var value = 0;
    Yanfly.Util.displayError(e, code, 'CUSTOM PARAM MIN FORMULA ERROR');
  }
  value = Math.ceil(value);
  return value;
};

Yanfly.BPC.Game_BattlerBase_initMembers =
    Game_BattlerBase.prototype.initMembers;
Game_BattlerBase.prototype.initMembers = function() {
    Yanfly.BPC.Game_BattlerBase_initMembers.call(this);
    this.clearCustomParamLimits();
};

Game_BattlerBase.prototype.clearCustomParamLimits = function() {
    this._paramLimitMin = [0,0,0,0,0,0,0,0];
    this._paramLimitMax = [0,0,0,0,0,0,0,0];
};

Game_BattlerBase.prototype.customParamMax = function(paramId) {
    if (!this._paramLimitMax) this.clearCustomParamLimits();
    var value = this._paramLimitMax[paramId];
    return value;
};

Game_BattlerBase.prototype.customParamMin = function(paramId) {
    if (!this._paramLimitMin) this.clearCustomParamLimits();
    var value = this._paramLimitMin[paramId];
    return value;
};

Game_BattlerBase.prototype.setParam = function(id, value) {
    this._paramPlus[id] = 0;
    this._baseParamCache = [];
    this._paramPlus[id] = value - this.param(id);
    this.refresh();
};

Game_BattlerBase.prototype.setMaxHp = function(value) {
    this.setParam(0, value);
};

Game_BattlerBase.prototype.setMaxMp = function(value) {
    this.setParam(1, value);
};

Game_BattlerBase.prototype.setAtk = function(value) {
    this.setParam(2, value);
};

Game_BattlerBase.prototype.setDef = function(value) {
    this.setParam(3, value);
};

Game_BattlerBase.prototype.setMat = function(value) {
    this.setParam(4, value);
};

Game_BattlerBase.prototype.setMdf = function(value) {
    this.setParam(5, value);
};

Game_BattlerBase.prototype.setAgi = function(value) {
    this.setParam(6, value);
};

Game_BattlerBase.prototype.setLuk = function(value) {
    this.setParam(7, value);
};

Game_BattlerBase.prototype.setParamPlus = function(id, value) {
    this._paramPlus[id] = value;
    this.refresh();
};

Game_BattlerBase.prototype.setMaxHpPlus = function(value) {
    this.setParamPlus(0, value);
};

Game_BattlerBase.prototype.setMaxMpPlus = function(value) {
    this.setParamPlus(1, value);
};

Game_BattlerBase.prototype.setAtkPlus = function(value) {
    this.setParamPlus(2, value);
};

Game_BattlerBase.prototype.setDefPlus = function(value) {
    this.setParamPlus(3, value);
};

Game_BattlerBase.prototype.setMatPlus = function(value) {
    this.setParamPlus(4, value);
};

Game_BattlerBase.prototype.setMdfPlus = function(value) {
    this.setParamPlus(5, value);
};

Game_BattlerBase.prototype.setAgiPlus = function(value) {
    this.setParamPlus(6, value);
};

Game_BattlerBase.prototype.setLukPlus = function(value) {
    this.setParamPlus(7, value);
};

Game_BattlerBase.prototype.addMaxHp = function(value) {
    this.addParam(0, value);
};

Game_BattlerBase.prototype.addMaxMp = function(value) {
    this.addParam(1, value);
};

Game_BattlerBase.prototype.addAtk = function(value) {
    this.addParam(2, value);
};

Game_BattlerBase.prototype.addDef = function(value) {
    this.addParam(3, value);
};

Game_BattlerBase.prototype.addMat = function(value) {
    this.addParam(4, value);
};

Game_BattlerBase.prototype.addMdf = function(value) {
    this.addParam(5, value);
};

Game_BattlerBase.prototype.addAgi = function(value) {
    this.addParam(6, value);
};

Game_BattlerBase.prototype.addLuk = function(value) {
    this.addParam(7, value);
};

Game_BattlerBase.prototype.minusMaxHp = function(value) {
    this.addParam(0, -value);
};

Game_BattlerBase.prototype.minusMaxMp = function(value) {
    this.addParam(1, -value);
};

Game_BattlerBase.prototype.minusAtk = function(value) {
    this.addParam(2, -value);
};

Game_BattlerBase.prototype.minusDef = function(value) {
    this.addParam(3, -value);
};

Game_BattlerBase.prototype.minusMat = function(value) {
    this.addParam(4, -value);
};

Game_BattlerBase.prototype.minusMdf = function(value) {
    this.addParam(5, -value);
};

Game_BattlerBase.prototype.minusAgi = function(value) {
    this.addParam(6, -value);
};

Game_BattlerBase.prototype.minusLuk = function(value) {
    this.addParam(7, -value);
};

Game_BattlerBase.prototype.setCustomParamLimitMax = function(id, value) {
    if (!this._paramLimitMax) this.clearCustomParamLimits();
    this._paramLimitMax[id] = value;
    this.refresh();
};

Game_BattlerBase.prototype.setCustomMaxHpMax = function(value) {
    this.setCustomParamLimitMax(0, value)
};

Game_BattlerBase.prototype.setCustomMaxMpMax = function(value) {
    this.setCustomParamLimitMax(1, value)
};

Game_BattlerBase.prototype.setCustomAtkMax = function(value) {
    this.setCustomParamLimitMax(2, value)
};

Game_BattlerBase.prototype.setCustomDefMax = function(value) {
    this.setCustomParamLimitMax(3, value)
};

Game_BattlerBase.prototype.setCustomMatMax = function(value) {
    this.setCustomParamLimitMax(4, value)
};

Game_BattlerBase.prototype.setCustomMdfMax = function(value) {
    this.setCustomParamLimitMax(5, value)
};

Game_BattlerBase.prototype.setCustomAgiMax = function(value) {
    this.setCustomParamLimitMax(6, value)
};

Game_BattlerBase.prototype.setCustomLukMax = function(value) {
    this.setCustomParamLimitMax(7, value)
};

Game_BattlerBase.prototype.setCustomParamLimitMin = function(id, value) {
    if (!this._paramLimitMin) this.clearCustomParamLimits();
    this._paramLimitMin[id] = value;
    this.refresh();
};

Game_BattlerBase.prototype.setCustomMaxHpMin = function(value) {
    this.setCustomParamLimitMin(0, value)
};

Game_BattlerBase.prototype.setCustomMaxMpMin = function(value) {
    this.setCustomParamLimitMin(1, value)
};

Game_BattlerBase.prototype.setCustomAtkMin = function(value) {
    this.setCustomParamLimitMin(2, value)
};

Game_BattlerBase.prototype.setCustomDefMin = function(value) {
    this.setCustomParamLimitMin(3, value)
};

Game_BattlerBase.prototype.setCustomMatMin = function(value) {
    this.setCustomParamLimitMin(4, value)
};

Game_BattlerBase.prototype.setCustomMdfMin = function(value) {
    this.setCustomParamLimitMin(5, value)
};

Game_BattlerBase.prototype.setCustomAgiMin = function(value) {
    this.setCustomParamLimitMin(6, value)
};

Game_BattlerBase.prototype.setCustomLukMin = function(value) {
    this.setCustomParamLimitMin(7, value)
};

//=============================================================================
// Game_Battler
//=============================================================================

Yanfly.BPC.Game_Battler_refresh = Game_Battler.prototype.refresh;
Game_Battler.prototype.refresh = function() {
    this._baseParamCache = undefined;
    Yanfly.BPC.Game_Battler_refresh.call(this);
};

Game_Battler.prototype.paramPlus = function(paramId) {
    var value = Game_BattlerBase.prototype.paramPlus.call(this, paramId);
    var length = this.states().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.states()[i];
      if (obj && obj.plusParams) value += obj.plusParams[paramId];
    }
    return value;
};

Game_Battler.prototype.paramRate = function(paramId) {
    var rate = Game_BattlerBase.prototype.paramRate.call(this, paramId);
    var length = this.states().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.states()[i];
      if (obj && obj.rateParams) rate *= obj.rateParams[paramId];
    }
    return rate;
};

Game_Battler.prototype.paramFlat = function(paramId) {
    var value = 0;
    var length = this.states().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.states()[i];
      if (obj && obj.flatParams) value += obj.flatParams[paramId];
    }
    return value;
};

Game_Battler.prototype.customParamMax = function(paramId) {
    var value = Game_BattlerBase.prototype.customParamMax.call(this, paramId);
    var length = this.states().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.states()[i];
      if (obj && obj.maxParams && obj.maxParams[paramId]) {
        value = Math.max(value, obj.maxParams[paramId]);
      }
    }
    return value;
};

Game_Battler.prototype.customParamMin = function(paramId) {
    var value = Game_BattlerBase.prototype.customParamMin.call(this, paramId);
    var length = this.states().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.states()[i];
      if (obj && obj.minParams && obj.minParams[paramId]) {
        value = Math.max(value, obj.minParams[paramId]);
      }
    }
    return value;
};

//=============================================================================
// Game_Actor
//=============================================================================

Yanfly.BPC.Game_Actor_setup = Game_Actor.prototype.setup;
Game_Actor.prototype.setup = function(actorId) {
    Yanfly.BPC.Game_Actor_setup.call(this, actorId);
    this.clearCustomParamLimits();
};

Game_Actor.prototype.paramPlus = function(paramId) {
    var value = Game_Battler.prototype.paramPlus.call(this, paramId);
    value += this.actor().plusParams[paramId];
    value += this.currentClass().plusParams[paramId];
    var length = this.equips().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.equips()[i];
      if (!obj) continue;
      value += obj.params[paramId];
      if (obj.plusParams) value += obj.plusParams[paramId];
    }
    return value;
};

Game_Actor.prototype.paramRate = function(paramId) {
    var rate = Game_Battler.prototype.paramRate.call(this, paramId);
    rate *= this.actor().rateParams[paramId];
    rate *= this.currentClass().rateParams[paramId];
    var length = this.equips().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.equips()[i];
      if (obj && obj.rateParams) rate *= obj.rateParams[paramId];
    }
    return rate;
};

Game_Actor.prototype.paramFlat = function(paramId) {
    var value = Game_Battler.prototype.paramFlat.call(this, paramId);
    value += this.actor().flatParams[paramId];
    value += this.currentClass().flatParams[paramId];
    var length = this.equips().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.equips()[i];
      if (obj && obj.flatParams) value += obj.flatParams[paramId];
    }
    return value;
};

Game_Actor.prototype.paramMax = function(paramId) {
    return Game_Battler.prototype.paramMax.call(this, paramId);
};

Game_Actor.prototype.customParamMax = function(paramId) {
    var value = Game_Battler.prototype.customParamMax.call(this, paramId);
    if (this.actor().maxParams[paramId]) {
      value = Math.max(value, this.actor().maxParams[paramId]);
    }
    if (this.currentClass().maxParams[paramId]) {
      value = Math.max(value, this.currentClass().maxParams[paramId]);
    }
    var length = this.equips().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.equips()[i];
      if (obj && obj.maxParams && obj.maxParams[paramId]) {
        value = Math.max(value, obj.maxParams[paramId]);
      }
    }
    return value;
};

Game_Actor.prototype.customParamMin = function(paramId) {
    var value = Game_Battler.prototype.customParamMin.call(this, paramId);
    if (this.actor().minParams[paramId]) {
      value = Math.max(value, this.actor().minParams[paramId]);
    }
    if (this.currentClass().minParams[paramId]) {
      value = Math.max(value, this.currentClass().minParams[paramId]);
    }
    var length = this.equips().length;
    for (var i = 0; i < length; ++i) {
      var obj = this.equips()[i];
      if (obj && obj.minParams && obj.minParams[paramId]) {
        value = Math.max(value, obj.minParams[paramId]);
      }
    }
    return value;
};

//=============================================================================
// Game_Enemy
//=============================================================================

Game_Enemy.prototype.paramPlus = function(paramId) {
    var value = Game_Battler.prototype.paramPlus.call(this, paramId);
    value += this.enemy().plusParams[paramId];
    return value;
};

Game_Enemy.prototype.paramRate = function(paramId) {
    var rate = Game_Battler.prototype.paramRate.call(this, paramId);
    rate *= this.enemy().rateParams[paramId];
    return rate;
};

Game_Enemy.prototype.paramFlat = function(paramId) {
    var value = Game_Battler.prototype.paramFlat.call(this, paramId);
    value += this.enemy().flatParams[paramId];
    return value;
};

Game_Enemy.prototype.customParamMax = function(paramId) {
    var value = Game_Battler.prototype.customParamMax.call(this, paramId);
    if (this.enemy().maxParams[paramId]) {
      value = Math.max(value, this.enemy().maxParams[paramId]);
    }
    return value;
};

Game_Enemy.prototype.customParamMin = function(paramId) {
    var value = Game_Battler.prototype.customParamMin.call(this, paramId);
    if (this.enemy().minParams[paramId]) {
      value = Math.max(value, this.enemy().minParams[paramId]);
    }
    return value;
};

//=============================================================================
// Game_Action
//=============================================================================

Game_Action.prototype.lukEffectRate = function(target) {
    var item = this.item();
    var skill = this.item();
    var a = this.subject();
    var user = this.subject();
    var subject = this.subject();
    var b = target;
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    return eval(Yanfly.Param.BPCLukEffectRate);
};

//=============================================================================
// Utilities
//=============================================================================

Yanfly.Util = Yanfly.Util || {};

Yanfly.Util.displayError = function(e, code, message) {
  console.log(message);
  console.log(code || 'NON-EXISTENT');
  console.error(e);
  if (Utils.RPGMAKER_VERSION && Utils.RPGMAKER_VERSION >= "1.6.0") return;
  if (Utils.isNwjs() && Utils.isOptionValid('test')) {
    if (!require('nw.gui').Window.get().isDevToolsOpen()) {
      require('nw.gui').Window.get().showDevTools();
    }
  }
};

//=============================================================================
// End of File
//=============================================================================

repo_name: Rexhunk/karryn

license: unknown