code:
//=============================================================================
// Yanfly Engine Plugins - Skill Core Extension - Limited Skill Uses
// YEP_X_LimitedSkillUses.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.LSU = Yanfly.LSU || {};
Yanfly.LSU.version = 1.05;

//=============================================================================
 /*:
 * @plugindesc v1.05 (Requires YEP_SkillCore.js) Make certain skills have
 * a limited amount of times they can be used in battle.
 * @author Yanfly Engine Plugins
 *
 * @param ---General---
 * @default
 *
 * @param Limited Use Icon
 * @parent ---General---
 * @desc The icon used for limited uses. Set 0 to hide.
 * @default 160
 *
 * @param Font Size
 * @parent ---General---
 * @type number
 * @min 1
 * @desc Font size used for limited uses.
 * Default: 28
 * @default 20
 *
 * @param Text Color
 * @parent ---General---
 * @type number
 * @min 0
 * @max 31
 * @desc The text color used for limited uses.
 * @default 0
 *
 * @param Cost Format
 * @parent ---General---
 * @desc The text format for limited uses. Leave empty to hide.
 * %1 - Current     %2 - Maximum
 * @default %1/%2
 *
 * @param Empty Icon
 * @parent ---General---
 * @type number
 * @min 0
 * @desc The icon used for empty limited uses. Set 0 to hide.
 * @default 168
 *
 * @param Empty Text
 * @parent ---General---
 * @desc The text displayed when a skill's uses are used up.
 * @default Empty
 *
 * @param Absolute Max
 * @parent ---General---
 * @type number
 * @min 1
 * @desc This is the absolute maximum value Limited Uses can
 * go up to and cannot go past.
 * @default 100
 *
 * @param Bypass Limits
 * @parent ---General---
 * @desc This is a list of skills that cannot be limited.
 * Separate each skill ID with a space.
 * @default 1 2 3 4 5 6 7
 *
 * @param Bypass List
 * @parent ---Bypass---
 * @type skill[]
 * @desc This is a list of skills that cannot be limited so that
 * way, skills like Attack, Guard. Requires RPG Maker MV 1.5.0+
 * @default []
 *
 * @param ---Defaults---
 * @default
 *
 * @param Limit All Skills
 * @parent ---Defaults---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Give limits to all skills by default?
 * NO - false     YES - true
 * @default false
 *
 * @param Limit Charges
 * @parent ---Defaults---
 * @type number
 * @min 1
 * @desc The default amount of limit charges for skills.
 * @default 2
 *
 * @param Recover All
 * @parent ---Defaults---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Restore all charges when using Recover All event?
 * NO - false     YES - true
 * @default true
 *
 * @param Victory Recover
 * @parent ---Defaults---
 * @type number
 * @min 0
 * @desc How many uses are recovered after winning a battle.
 * @default 10
 *
 * @param Escape Recover
 * @parent ---Defaults---
 * @type number
 * @min 0
 * @desc How many uses are recovered after escaping a battle.
 * @default 5
 *
 * @param Lose Recover
 * @parent ---Defaults---
 * @type number
 * @min 0
 * @desc How many uses are recovered after losing a battle.
 * @default 5
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * This plugin requires YEP_SkillCore.
 * Make sure this plugin is located under YEP_SkillCore in the plugin list.
 *
 * This plugin enables you to set a limited amount of times certain skills (or
 * all skills) can be used per battle or ever. This adds a different type of
 * skill currency and balance mechanic in limiting the amount of times a skill
 * can be used without directly having to alter MP, TP, or the like.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * You can use these notetags to govern the various Limited Uses aspects of
 * your skills.
 *
 * Skill Notetags:
 *
 *   <Unlimited Use>
 *   If you've enabled 'Limit All Skills' in the plugin parameters, this will
 *   forcefully make the skill unlimited use. If you use this notetag, it will
 *   override any of the Limited Use settings.
 *
 *   <Limit Uses: x>
 *   This will set the number of times the skill can be used to x. If the skill
 *   has 0 charges left, the skill cannot be used.
 *
 *   <Recover All Uses>
 *   <Not Recover All Uses>
 *   When using the recover all command, depending on the settings within the
 *   plugin parameters, all limited use charges are recovered or not. These
 *   notetags will enable you to utilize the other setting for the skill.
 *
 *   <Victory Uses Recover: x>
 *   <Escape uses Recover: x>
 *   <Lose Uses Recover: x>
 *   When the player wins a battle, escapes a battle, or loses a battle, the
 *   skill use will recover x amount of uses for the respective outcome. If the
 *   notetags aren't used, the amounts restored will be equal to settings made
 *   in the plugin's parameters.
 *
 *   <After Battle Uses Recover: x>
 *   This will set the recovery rate of victory, escape, or loss of battle to
 *   be equal to x indiscriminately.
 *
 * Skill and Item Notetags:
 *
 *   <Global Limited Uses: +x>
 *   <Global Limited Uses: -x>
 *   This will change the target's limited uses by +x or -x for all skills.
 *   +x will increase the amount of times the skills can be used. -x will
 *   decrease the amount of times the skills can be used.
 *
 *   <SType x Limited Uses: +y>
 *   <SType x Limited Uses: -y>
 *   This will change the target's limited uses by +y or -y for all skills of
 *   the skill type x. +y will increase the amount of times the skills can be
 *   used. -y will decrease the amount of times the skills can be used.
 *
 *   <Skill x Limited Uses: +y>
 *   <Skill x Limited Uses: -y>
 *   <Skill name Limited Uses: +y>
 *   <Skill name Limited Uses: -y>
 *   This will change the target's limited uses by +y or -y for skill x. If
 *   you use the named notetag varient and have multiple skills in the database
 *   with the same name, priority will be given to the skill with the highest
 *   ID. +y will increase the amount of times the skills can be used. -y will
 *   decrease the amount of times the skills can be used.
 *
 * Actor, Class, Enemy, Weapon, Armor, and State Notetags:
 *
 *   <Global Use Max: +x>
 *   <Global Use Max: -x>
 *   A battler affected by this property will have any Limited Use skills alter
 *   the maximum times used by +x or -x.
 *
 *   <SType x Use Max: +y>
 *   <SType x Use Max: -y>
 *   A battler affected by this property will have Limited Use skills from
 *   skill type x alter the maximum times used by +y or -y.
 *
 *   <Skill x Use Max: +y>
 *   <Skill x Use Max: -y>
 *   <Skill name Use Max: +y>
 *   <Skill name Use Max: -y>
 *   A battler affected by this property will have Limited Use for skill x (or
 *   named if you're using that version of the notetag instead) alter the
 *   maximum times used by +y or -y. If you are using the named version of the
 *   notetag and have multiple skills in the database with the same name, then
 *   priority will be given to the skill with the highest ID.
 *
 * ============================================================================
 * Lunatic Mode - Altering Target's Limited Uses
 * ============================================================================
 *
 * For those with JavaScript proficiency, you can use the following notetags to
 * perform conditional changes to the target's Limited Uses.
 *
 * Skill and Item Notetags:
 *
 *   --- --- ---
 *
 *   <Custom Global Limited Uses>
 *    value += user.level;
 *   </Custom Global Limited Uses>
 *   The 'value' variable is the number of uses the user will gain for all
 *   Limited Use skills.
 *
 *   --- --- ---
 *
 *   <Custom SType x Limited Uses>
 *    value += user.level;
 *   </Custom SType x Limited Uses>
 *   The 'value' variable is the number of uses the user will gain for all
 *   Limited Use skills of skill type x.
 *
 *   --- --- ---
 *
 *   <Custom Skill x Limited Uses>
 *    value += user.level;
 *   </Custom Skill x Limited Uses>
 *
 *   or
 *
 *   <Custom Skill name Limited Uses>
 *    value += user.level;
 *   </Custom Skill name Limited Uses>
 *
 *   The 'value' variable is the number of uses the user will gain for all
 *   Limited Use skills of skill x. If you are using the named version of the
 *   notetag and you have multiple skills in your database with the same name,
 *   priority will be given to the skill with the highest ID.
 *
 *   --- --- ---
 *
 * ============================================================================
 * Lunatic Mode - Conditional Max Uses
 * ============================================================================
 *
 * For those with JavaScript proficiency, you can use the following notetags to
 * perform conditional changes to the target's Limited Use Maximums.
 *
 * Actor, Class, Enemy, Weapon, Armor, State Notetags:
 *
 *   --- --- ---
 *
 *   <Custom Global Use Max>
 *    value += user.level;
 *   </Custom Global Use Max>
 *   The 'value' variable is the maximum uses the target will gain for all
 *   Limited Use skills.
 *
 *   --- --- ---
 *
 *   <Custom SType x Use Max>
 *    value += user.level;
 *   </Custom SType x Use Max>
 *   The 'value' variable is the maximum uses the target will gain for all
 *   Limited Use skills of skill type x.
 *
 *   --- --- ---
 *
 *   <Custom Skill x Use Max>
 *    value += user.level;
 *   </Custom Skill x Use Max>
 *
 *   or
 *
 *   <Custom Skill name Use Max>
 *    value += user.level;
 *   </Custom Skill name Use Max>
 *
 *   The 'value' variable is the maximum uses the target will gain for all
 *   Limited Use skills of skill x. If you are using the named version of the
 *   notetag and you have multiple skills in your database with the same name,
 *   priority will be given to the skill with the highest ID.
 *
 *   --- --- ---
 *
 * * Note: Keep in mind that none of the adjustments here will bypass the
 * 'Absolute Max' setting in the plugin parameters. That is the ceiling.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.05:
 * - Updated for RPG Maker MV version 1.5.0.
 * - Added new 'Bypass List' plugin parameter.
 *
 * Version 1.04:
 * - Lunatic Mode fail safes added.
 *
 * Version 1.03:
 * - Compatibility update with Equip Battle Skills and Equip Skill Tiers.
 *
 * Version 1.02a:
 * - Updated for RPG Maker MV version 1.1.0.
 * - Fixed notetag category in documentation for Lunatic Mode - Conditional Max
 * Uses. Updated from Skill and Items to Actor, Class, Enemy, Weapon, Armor,
 * and State Notetags.
 *
 * Version 1.01a:
 * - Optimization Update.
 * - Various functions in the skill window will now return their x positions.
 *
 * Version 1.00:
 * - Finished Plugin!
 */
//=============================================================================

if (Imported.YEP_SkillCore) {

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

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

Yanfly.Icon.LimitedUse = Number(Yanfly.Parameters['Limited Use Icon']);
Yanfly.Param.LSUFontSize = Number(Yanfly.Parameters['Font Size']);
Yanfly.Param.LSUTextColor = Number(Yanfly.Parameters['Text Color']);
Yanfly.Param.LSUFormat = String(Yanfly.Parameters['Cost Format']);
Yanfly.Icon.LimitedEmpty = Number(Yanfly.Parameters['Empty Icon']);
Yanfly.Param.LSUEmpty = String(Yanfly.Parameters['Empty Text']);
Yanfly.Param.LimitedAbsMax = Number(Yanfly.Parameters['Absolute Max']);
Yanfly.Param.LSUBypass = String(Yanfly.Parameters['Bypass Limits']);
Yanfly.Param.LSUBypass = Yanfly.Param.LSUBypass.split(' ');
Yanfly.SetupParameters = function() {
  for (var i = 0; i < Yanfly.Param.LSUBypass.length; ++i) {
    Yanfly.Param.LSUBypass[i] = parseInt(Yanfly.Param.LSUBypass[i]);
  };
  var data = JSON.parse(Yanfly.Parameters['Bypass List'] || '[]');
  for (var i = 0; i < data.length; ++i) {
    var id = parseInt(data[i]);
    if (id <= 0) continue;
    if (Yanfly.Param.LSUBypass.contains(id)) continue;
    Yanfly.Param.LSUBypass.push(id);
  }
}
Yanfly.SetupParameters();

Yanfly.Param.LSUDefLimitAll = String(Yanfly.Parameters['Limit All Skills']);
Yanfly.Param.LSUDefLimitAll = eval(Yanfly.Param.LSUDefLimitAll);
Yanfly.Param.LSUDefCharges = Number(Yanfly.Parameters['Limit Charges']);
Yanfly.Param.LSURecoverAll = eval(String(Yanfly.Parameters['Recover All']));
Yanfly.Param.LSUVictoryRecover = Number(Yanfly.Parameters['Victory Recover']);
Yanfly.Param.LSUEscapeRecover = Number(Yanfly.Parameters['Escape Recover']);
Yanfly.Param.LSULoseRecover = Number(Yanfly.Parameters['Lose Recover']);

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

Yanfly.LSU.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.LSU.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_X_LimitedSkillUses) {
    this.processLSUNotetagsS($dataSkills);
    this.processLSUNotetags1($dataSkills);
    this.processLSUNotetags2($dataSkills);
    this.processLSUNotetags2($dataItems);
    this.processLSUNotetags3($dataActors);
    this.processLSUNotetags3($dataClasses);
    this.processLSUNotetags3($dataEnemies);
    this.processLSUNotetags3($dataWeapons);
    this.processLSUNotetags3($dataArmors);
    this.processLSUNotetags3($dataStates);
    Yanfly._loaded_YEP_X_LimitedSkillUses = true;
  }
  return true;
};

DataManager.processLSUNotetagsS = function(group) {
  if (Yanfly.SkillIdRef) return;
  Yanfly.SkillIdRef = {};
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    if (obj.name.length <= 0) continue;
    Yanfly.SkillIdRef[obj.name.toUpperCase()] = n;
  }
};

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

    obj.isLimitedUse = Yanfly.Param.LSUDefLimitAll;
    obj.limitUses = Yanfly.Param.LSUDefCharges;
    obj.limitRecoverAllUses = Yanfly.Param.LSURecoverAll;
    obj.limitBattleRecover = [
      Yanfly.Param.LSUVictoryRecover,
      Yanfly.Param.LSUEscapeRecover,
      Yanfly.Param.LSULoseRecover
    ];

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:LIMIT USES|LIMIT USE|LIMITED USE):[ ](\d+)>/i)) {
        obj.limitUses = parseInt(RegExp.$1);
        obj.isLimitedUse = true;
      } else if (line.match(/<(?:RECOVER ALL USES)>/i)) {
        obj.limitRecoverAllUses = true;
      } else if (line.match(/<(?:NOT RECOVER ALL USES)>/i)) {
        obj.limitRecoverAllUses = false;
      } else if (line.match(/<(?:VICTORY USES RECOVER):[ ](\d+)>/i)) {
        obj.limitBattleRecover[0] = parseInt(RegExp.$1);
      } else if (line.match(/<(?:ESCAPE USES RECOVER):[ ](\d+)>/i)) {
        obj.limitBattleRecover[1] = parseInt(RegExp.$1);
      } else if (line.match(/<(?:LOSE USES RECOVER):[ ](\d+)>/i)) {
        obj.limitBattleRecover[2] = parseInt(RegExp.$1);
      } else if (line.match(/<(?:AFTER BATTLE USES RECOVER):[ ](\d+)>/i)) {
        obj.limitBattleRecover[0] = parseInt(RegExp.$1);
        obj.limitBattleRecover[1] = parseInt(RegExp.$1);
        obj.limitBattleRecover[2] = parseInt(RegExp.$1);
      }
    }

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:UNLIMITED USE)>/i)) {
        obj.isLimitedUse = false;
      }
    }
  }
};

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

    obj.globalLimitedUses = 0;
    obj.stypeLimitedUses = {};
    obj.skillLimitedUses = {};
    var evalMode = 'none';
    var evalLine = '';
    obj.globalLimitedUsesEval = '';
    obj.stypeLimitedUsesEval = {};
    obj.skillLimitedUsesEval = {};

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<GLOBAL LIMITED USES:[ ]([\+\-]\d+)>/i)) {
        obj.globalLimitedUses = parseInt(RegExp.$1);
      } else if (line.match(/<STYPE[ ](\d+)[ ]LIMITED USES:[ ]([\+\-]\d+)>/i)) {
        obj.stypeLimitedUses[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<SKILL[ ](\d+)[ ]LIMITED USES:[ ]([\+\-]\d+)>/i)) {
        obj.skillLimitedUses[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<SKILL[ ](.*)[ ]LIMITED USES:[ ]([\+\-]\d+)>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.skillLimitedUses[id] = parseInt(RegExp.$2);
      } else if (line.match(/<CUSTOM GLOBAL LIMITED USES>/i)) {
        evalMode = 'customGlobalLimitedUses';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM GLOBAL LIMITED USES>/i)) {
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customGlobalLimitedUses') {
        obj.globalLimitedUsesEval = obj.globalLimitedUsesEval + line + '\n';
      } else if (line.match(/<CUSTOM STYPE[ ](\d+)[ ]LIMITED USES>/i)) {
        evalMode = 'customStypeLimitedUses';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM STYPE[ ](\d+)[ ]LIMITED USES>/i)) {
        var id = parseInt(RegExp.$1);
        obj.stypeLimitedUsesEval[id] = evalLine;
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customStypeLimitedUses') {
        evalLine = evalLine + line + '\n';
      } else if (line.match(/<CUSTOM SKILL[ ](.*)[ ]LIMITED USES>/i)) {
        evalMode = 'customSkillLimitedUses';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM SKILL[ ](\d+)[ ]LIMITED USES>/i)) {
        var id = parseInt(RegExp.$1);
        obj.skillLimitedUsesEval[id] = evalLine;
        evalMode = 'none';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM SKILL[ ](.*)[ ]LIMITED USES>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        var id = Yanfly.SkillIdRef[name] || 0;
        obj.skillLimitedUsesEval[id] = evalLine;
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customSkillLimitedUses') {
        evalLine = evalLine + line + '\n';
      }
    }
  }
};

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

    obj.globalUseMax = 0;
    obj.stypeUseMax = {};
    obj.skillUseMax = {};
    var evalMode = 'none';
    var evalLine = '';
    obj.globalUseMaxEval = '';
    obj.stypeUseMaxEval = {};
    obj.skillUseMaxEval = {};

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<GLOBAL USE MAX:[ ]([\+\-]\d+)>/i)) {
        obj.globalUseMax = parseInt(RegExp.$1);
      } else if (line.match(/<STYPE[ ](\d+)[ ]USE MAX:[ ]([\+\-]\d+)>/i)) {
        obj.stypeUseMax[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<SKILL[ ](\d+)[ ]USE MAX:[ ]([\+\-]\d+)>/i)) {
        obj.skillUseMax[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<SKILL[ ](.*)[ ]USE MAX:[ ]([\+\-]\d+)>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.skillUseMax[id] = parseInt(RegExp.$2);
      } else if (line.match(/<CUSTOM GLOBAL USE MAX>/i)) {
        evalMode = 'customGlobalMaxUse';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM GLOBAL USE MAX>/i)) {
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customGlobalMaxUse') {
        obj.globalUseMaxEval = obj.globalUseMaxEval + line + '\n';
      } else if (line.match(/<CUSTOM STYPE[ ](\d+)[ ]USE MAX>/i)) {
        evalMode = 'customStypeMaxUse';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM STYPE[ ](\d+)[ ]USE MAX>/i)) {
        var id = parseInt(RegExp.$1);
        obj.stypeUseMaxEval[id] = evalLine;
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customStypeMaxUse') {
        evalLine = evalLine + line + '\n';
      } else if (line.match(/<CUSTOM SKILL[ ](.*)[ ]USE MAX>/i)) {
        evalMode = 'customSkillMaxUse';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM SKILL[ ](\d+)[ ]USE MAX>/i)) {
        var id = parseInt(RegExp.$1);
        obj.skillUseMaxEval[id] = evalLine;
        console.log(id);
        evalMode = 'none';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM SKILL[ ](.*)[ ]USE MAX>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        var id = Yanfly.SkillIdRef[name] || 0;
        obj.skillUseMaxEval[id] = evalLine;
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'customSkillMaxUse') {
        evalLine = evalLine + line + '\n';
      }
    }
  }
};

//=============================================================================
// BattleManager
//=============================================================================

Yanfly.LSU.BattleManager_endBattle = BattleManager.endBattle;
BattleManager.endBattle = function(result) {
    Yanfly.LSU.BattleManager_endBattle.call(this, result);
    $gameParty.recoverLimitedSkillUses(result);
};

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

Yanfly.LSU.Game_BattlerBase_refresh = Game_BattlerBase.prototype.refresh;
Game_BattlerBase.prototype.refresh = function() {
    this._cacheLimitedUseMax = {};
    Yanfly.LSU.Game_BattlerBase_refresh.call(this);
};

Game_BattlerBase.prototype.initSkillLimitedUses = function() {
    this._skillLimitedUses = {};
};

Yanfly.LSU.Game_BattlerBase_meetsSkillConditions =
    Game_BattlerBase.prototype.meetsSkillConditions;
Game_BattlerBase.prototype.meetsSkillConditions = function(skill) {
    if (this.isSkillLimitedEmpty(skill)) return false;
    return Yanfly.LSU.Game_BattlerBase_meetsSkillConditions.call(this, skill);
};

Game_BattlerBase.prototype.isSkillLimitedUse = function(skill) {
    if (!skill) return false;
    if (Yanfly.Param.LSUBypass.contains(skill.id)) return false;
    return skill.isLimitedUse;
};

Game_BattlerBase.prototype.isSkillLimitedEmpty = function(skill) {
    if (this.isSkillLimitedUse(skill)) {
      if (this.skillLimitedUseCurrent(skill.id) <= 0) return true;
    }
    return false;
};

Game_BattlerBase.prototype.getObjLimitedUseMax = function(obj, skill) {
  if (!obj) return 0;
  var value = 0;
  if (obj.globalUseMax) value += obj.globalUseMax;
  if (obj.stypeUseMax) {
    if (obj.stypeUseMax[skill.stypeId]) value += obj.stypeUseMax[skill.stypeId];
  }
  if (obj.skillUseMax) {
    if (obj.skillUseMax[skill.id]) value += obj.skillUseMax[skill.id];
  }
  value = this.getObjLimitUseMaxEval(obj, skill, value);
  return value;
};

Game_BattlerBase.prototype.getObjLimitUseMaxEval = function(obj, skill, value) {
  var a = this;
  var user = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  if (obj.globalUseMaxEval !== '') {
    var code = obj.globalUseMaxEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'LIMITED USE GLOBAL ERROR');
    }
  }
  if (obj.stypeUseMaxEval[skill.stypeId]) {
    var code = obj.stypeUseMaxEval[skill.stypeId];
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'LIMITED USE STYPE ERROR');
    }
  }
  if (obj.skillUseMaxEval[skill.id]) {
    var code = obj.skillUseMaxEval[skill.id];
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'LIMITED USE SKILL ERROR');
    }
  }
  return value;
};

Game_BattlerBase.prototype.skillLimitedUseMax = function(skillId) {
    var skill = $dataSkills[skillId];
    if (!skill) return 0;
    var value = skill.limitUses;
    return value;
};

Game_BattlerBase.prototype.skillLimitedUseCurrent = function(skillId) {
    var skill = $dataSkills[skillId];
    if (!skill) return 0;
    if (this._skillLimitedUses === undefined) this.initSkillLimitedUses();
    if (this._skillLimitedUses[skillId] === undefined) {
      this._skillLimitedUses[skillId] = 0;
    }
    var value = this.skillLimitedUseMax(skillId);
    value -= this._skillLimitedUses[skillId];
    return Math.max(0, value);
};

Yanfly.LSU.Game_BattlerBase_paySkillCost =
    Game_BattlerBase.prototype.paySkillCost;
Game_BattlerBase.prototype.paySkillCost = function(skill) {
    Yanfly.LSU.Game_BattlerBase_paySkillCost.call(this, skill);
    if (!skill) return;
    if (this.isSkillLimitedUse(skill)) this.paySkillLimitedUseCost(skill.id);
};

Game_BattlerBase.prototype.paySkillLimitedUseCost = function(skillId, value) {
    var skill = $dataSkills[skillId];
    if (value === undefined) value = 1;
    if (this._skillLimitedUses === undefined) this.initSkillLimitedUses();
    if (this._skillLimitedUses[skillId] === undefined) {
      this._skillLimitedUses[skillId] = 0;
    }
    var max = this.skillLimitedUseMax(skillId);
    this._skillLimitedUses[skillId] += value;
    this.setSkillLimitedUse(skillId, this._skillLimitedUses[skillId]);
};

Game_BattlerBase.prototype.setSkillLimitedUse = function(skillId, value) {
    var skill = $dataSkills[skillId];
    if (!this.isSkillLimitedUse(skill)) return;
    if (this._skillLimitedUses === undefined) this.initSkillLimitedUses();
    var max = (value === 0) ? 0 : this.skillLimitedUseMax(skillId);
    this._skillLimitedUses[skillId] = Math.floor(value.clamp(0, max));
};

Yanfly.LSU.Game_BattlerBase_recoverAll = Game_BattlerBase.prototype.recoverAll;
Game_BattlerBase.prototype.recoverAll = function() {
    Yanfly.LSU.Game_BattlerBase_recoverAll.call(this);
    this.recoverAllLimitedSkillUses();
};

Game_BattlerBase.prototype.recoverAllLimitedSkillUses = function() {
    if (!this.isActor()) return;
    var length = this.skills().length;
    for (var i = 0; i < length; ++i) {
      var skill = this.skills()[i];
      if (!skill) continue;
    if (!this.isSkillLimitedUse(skill)) continue;
      if (skill.limitRecoverAllUses) this.setSkillLimitedUse(skill.id, 0);
    }
};

Game_BattlerBase.prototype.recoverLimitedSkillUsesBattle = function(result) {
    var length = this.skills().length;
    for (var i = 0; i < length; ++i) {
      var skill = this.skills()[i];
      if (!skill) continue;
    if (!this.isSkillLimitedUse(skill)) continue;
      var value = this.skillLimitedUseRecovery(skill.id, result);
      this.paySkillLimitedUseCost(skill.id, -value)
    }
};

Game_BattlerBase.prototype.skillLimitedUseRecovery = function(skillId, result) {
    var skill = $dataSkills[skillId];
    if (!skill) return 0;
    if (!this.isSkillLimitedUse(skill)) return 0;
    var value = skill.limitBattleRecover[result];
    return value;
};

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

Yanfly.LSU.Game_Battler_initMembers = Game_Battler.prototype.initMembers;
Game_Battler.prototype.initMembers = function() {
    Yanfly.LSU.Game_Battler_initMembers.call(this);
    this.initSkillLimitedUses();
};

Game_Battler.prototype.alterLimitedUses = function(item, user) {
    var length = this.skills().length;
    for (var i = 0; i < length; ++i) {
      var skill = this.skills()[i];
      if (!skill) continue;
      if (!this.isSkillLimitedUse(skill)) continue;
      var value = this.getAlterLimitedUses(item, user, skill);
      this.paySkillLimitedUseCost(skill.id, -value);
    }
};

Game_Battler.prototype.getAlterLimitedUses = function(item, user, skill) {
    var value = item.globalLimitedUses;
    if (item.stypeLimitedUses[skill.stypeId]) {
      value += item.stypeLimitedUses[skill.stypeId];
    }
    if (item.skillLimitedUses[skill.id]) {
      value += item.skillLimitedUses[skill.id];
    }
    value = this.getAltLimitUseEval(item, user, skill, value);
    return value;
};

Game_Battler.prototype.getAltLimitUseEval = function(obj, user, skill, value) {
  var item = obj;
  var a = this;
  var user = this;
  var target = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  if (obj.globalLimitedUsesEval !== '') {
    var code = obj.globalLimitedUsesEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'GLOBAL LIMITED USES EVAL ERROR');
    }
  }
  if (obj.stypeLimitedUsesEval[skill.stypeId]) {
    var code = obj.stypeLimitedUsesEval[skill.stypeId];
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'LIMITED USES STYPE EVAL ERROR');
    }
  }
  if (obj.skillLimitedUsesEval[skill.id]) {
    var code = obj.skillLimitedUsesEval[skill.id];
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'LIMITED USES SKILL EVAL ERROR');
    }
  }
  return value;
};

Game_Battler.prototype.skillLimitedUseMax = function(skillId) {
  var skill = $dataSkills[skillId];
  if (!skill) return 0;
  var value = Game_BattlerBase.prototype.skillLimitedUseMax.call(this, skillId);
  var length = this.states().length;
  for (var i = 0; i < length; ++i) {
    var obj = this.states()[i];
    value += this.getObjLimitedUseMax(obj, skill);
  }
  return value;
};

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

Game_Actor.prototype.skillLimitedUseMax = function(skillId) {
  var skill = $dataSkills[skillId];
  if (!skill) return 0;
  if (this._cacheLimitedUseMax[skillId] !== undefined) {
    return this._cacheLimitedUseMax[skillId];
  }
  var value = Game_Battler.prototype.skillLimitedUseMax.call(this, skillId);
  var length = this.equips().length;
  for (var i = 0; i < length; ++i) {
    var obj = this.equips()[i];
    value += this.getObjLimitedUseMax(obj, skill);
  }
  value += this.getObjLimitedUseMax(this.actor(), skill);
  value += this.getObjLimitedUseMax(this.currentClass(), skill);
  value = value.clamp(0, Yanfly.Param.LimitedAbsMax)
  this._cacheLimitedUseMax[skillId] = value;
  return this._cacheLimitedUseMax[skillId];
};

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

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_Enemy.prototype.skillLimitedUseMax = function(skillId) {
  var skill = $dataSkills[skillId];
  if (!skill) return 0;
  if (this._cacheLimitedUseMax[skillId] !== undefined) {
    return this._cacheLimitedUseMax[skillId];
  }
  var value = Game_Battler.prototype.skillLimitedUseMax.call(this, skillId);
  value += this.getObjLimitedUseMax(this.enemy(), skill);
  value = value.clamp(0, Yanfly.Param.LimitedAbsMax)
  this._cacheLimitedUseMax[skillId] = value;
  return this._cacheLimitedUseMax[skillId];
};

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

Yanfly.LSU.Game_Action_applyItemUserEffect =
    Game_Action.prototype.applyItemUserEffect;
Game_Action.prototype.applyItemUserEffect = function(target) {
    Yanfly.LSU.Game_Action_applyItemUserEffect.call(this, target);
    if (target && this.item()) {
      target.alterLimitedUses(this.item(), this.subject());
    }
};

//=============================================================================
// Game_Party
//=============================================================================

Game_Party.prototype.recoverLimitedSkillUses = function(result) {
    var condition = this._inBattle;
    this._inBattle = false;
    var length = this.allMembers().length;
    for (var i = 0; i < length; ++i) {
      var member = this.allMembers()[i];
      if (member) member.recoverLimitedSkillUsesBattle(result);
    }
    this._inBattle = condition;
};

//=============================================================================
// Window_SkillList
//=============================================================================

Yanfly.LSU.Window_SkillList_drawSkillCost =
    Window_SkillList.prototype.drawSkillCost;
Window_SkillList.prototype.drawSkillCost = function(skill, wx, wy, width) {
    if (skill && this._actor.isSkillLimitedEmpty(skill)) {
      return this.drawSkillLimitEmpty(skill, wx, wy, width);
    }
    return Yanfly.LSU.Window_SkillList_drawSkillCost.call(this, skill, wx,
      wy, width);
};

Window_SkillList.prototype.drawSkillLimitEmpty = function(skill, wx, wy, ww) {
    if (Yanfly.Icon.LimitedEmpty > 0) {
      var iw = wx + ww - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.LimitedEmpty, iw, wy + 2);
      ww -= Window_Base._iconWidth + 2;
    }
    this.contents.fontSize = Yanfly.Param.LSUFontSize;
    this.changeTextColor(this.textColor(Yanfly.Param.LSUTextColor));
    var text = Yanfly.Param.LSUEmpty;
    this.drawText(text, wx, wy, ww, 'right');
    var returnWidth = ww - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetTextColor();
    this.resetFontSettings();
    return returnWidth;
};

Yanfly.LSU.Window_SkillList_dOC = Window_SkillList.prototype.drawOtherCost;
Window_SkillList.prototype.drawOtherCost = function(skill, wx, wy, dw) {
    dw = this.drawLimitedSkillUses(skill, wx, wy, dw);
    return Yanfly.LSU.Window_SkillList_dOC.call(this, skill, wx, wy, dw);
};

Window_SkillList.prototype.drawLimitedSkillUses = function(skill, wx, wy, dw) {
    if (!this._actor.isSkillLimitedUse(skill)) return dw;
    if (Yanfly.Param.LSUFormat === '') return dw;
    if (Yanfly.Icon.LimitedUse > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.LimitedUse, iw, wy + 2);
      dw -= Window_Base._iconWidth + 2;
    }
    this.contents.fontSize = Yanfly.Param.LSUFontSize;
    this.changeTextColor(this.textColor(Yanfly.Param.LSUTextColor));
    var fmt = Yanfly.Param.LSUFormat;
    var current = this._actor.skillLimitedUseCurrent(skill.id);
    current = Yanfly.Util.toGroup(current);
    var max = this._actor.skillLimitedUseMax(skill.id);
    max = Yanfly.Util.toGroup(max);
    var text = fmt.format(current, max);
    this.contents.fontSize = Yanfly.Param.LSUFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetTextColor();
    this.resetFontSettings();
    return returnWidth;
};

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

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

if (!Yanfly.Util.toGroup) {
    Yanfly.Util.toGroup = function(inVal) {
        return inVal;
    }
};

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

//=============================================================================
// End of File
//=============================================================================
};


code:
//=============================================================================
// Yanfly Engine Plugins - Message Core Extension - Backlog
// YEP_X_MessageBacklog.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.MsgBacklog = Yanfly.MsgBacklog || {};
Yanfly.MsgBacklog.version = 1.01;

//=============================================================================
 /*:
 * @plugindesc v1.01 (Requires YEP_MessageCore.js) Add a message backlog
 * function to your game's message system!
 * @author Yanfly Engine Plugins
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * This plugin requires the following plugins:
 * - YEP_MessageCore
 *
 * * Note: If you have any Extended Message Pack plugins from the YEP library,
 * place this plugin under those entries in the plugin list.
 *
 * It's not uncommon for RPG's to have a message backlog, an in-game tool for
 * the player to review any and all dialogue he/she has encountered previously.
 * This tool can be helpful in case a player would accidentally skip some
 * dialogue and/or would like to revisit what kind of messages were made before
 * making a decision during an important moment.
 *
 * This plugin creates a message backlog system for your game's message system.
 * Upon pressing 'Shift' (or any other button you desire) during a message, the
 * player can open up a Backlog window to review over the last 20 encountered
 * messages (number of stored messages can be modified within the parameters).
 * These saved messages can also include any choices from the choice lists they
 * have selected, any numbers they may have inputted, or items they selected
 * from special events.
 *
 * Now, your players can go forward, knowing full well they have little to
 * worry about in case they've missed any messages.
 *
 * ============================================================================
 * Disabled Text Codes
 * ============================================================================
 *
 * Due to the nature of some text codes, some of them are disabled for the
 * message log. Most of the default RPG Maker MV text codes will work, but some
 * custom ones added through the Message Core or Extension Packs are disabled
 * for various reasons. Here is a list of those disabled message codes:
 *
 *    RPG Maker MV Default:
 *    \{          Changes to font sizes cause errors in the backlog.
 *    \}          Changes to font sizes cause errors in the backlog.
 *
 *    Message Core:
 *    \AF[x]      Face graphics aren't displayed in the backlog.
 *    \PF[x]      Face graphics aren't displayed in the backlog.
 *    \FS[X]      Changes to font sizes cause errors in the backlog.
 *
 *    \PY[X]      While this works, it is known to cause some problems.
 *
 *    Extended Message Pack 1:
 *    \LSON       Letter sounds are disabled for the backlog.
 *    \LSOFF      Letter sounds are disabled for the backlog.
 *    \LSR        Letter sounds are disabled for the backlog.
 *    \FACEINDEX  Face graphics aren't displayed in the backlog.
 *    \MSGPOSX    Backlog does not change message window size.
 *    \MSGPOSY    Backlog does not change message window size.
 *    \MSGEVENT   Backlog does not change message window size.
 *    \MSGACTOR   Backlog does not change message window size.
 *    \MSGPARTY   Backlog does not change message window size.
 *    \MSGENEMY   Backlog does not change message window size.
 *    \AUTOEVENT  Backlog does not change message window size.
 *    \AUTOACTOR  Backlog does not change message window size.
 *    \AUTOPARTY  Backlog does not change message window size.
 *    \AUTOENEMY  Backlog does not change message window size.
 *    \MSGROWS    Backlog does not change message window size.
 *    \MSGWIDTH   Backlog does not change message window size.
 *    \AUTO       Backlog does not change message window size.
 *    \MSGRESET   Backlog does not change message window size.
 *
 *    Extended Message Pack 2:
 *    - Quantity, Actor, and Enemy text codes will be converted before added.
 *    This is so the data made will be localized instead of current.
 *
 * ============================================================================
 * Plugin Commands
 * ============================================================================
 *
 * The following plugin commands can be used to alter various settings
 * regarding the Message Backlog.
 *
 * Plugin Command:
 *
 *   EnableMessageBacklog
 *   DisableMessageBacklog
 *   - This enables/disables the message backlog from being playeraccessed.
 *
 *   EnableMessageLogging
 *   DisableMessageLogging
 *   - If enabled, new messages will be recorded to the backlog.
 *   If disabled, they won't be recorded.
 *
 *   OpenMessageBacklog
 *   - This will forcefully open the message backlog if done on the map scene.
 *   (Highly recommended to be used with Button Common Events)
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.01:
 * - Message Backlog now removes more text codes regarding Letter Sounds.
 *
 * Version 1.00:
 * - Finished Plugin!
 *
 * ============================================================================
 * End of Helpfile
 * ============================================================================
 *
 * @param ---Backlog Key---
 * @default
 *
 * @param LogKeyButton
 * @text Backlog Key Button
 * @parent ---Backlog Key---
 * @type combo
 * @option tab
 * @option shift
 * @option control
 * @option pageup
 * @option pagedown
 * @desc When pressed during a message, this will open up
 * the Backlog window.
 * @default shift
 *
 * @param EnableLogKey
 * @text Enable Backlog Key
 * @parent ---Backlog Key---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Enable Backlog button for your messages by default?
 * NO - false     YES - true
 * @default true
 *
 * @param ---Settings---
 * @default
 *
 * @param DefaultLogging
 * @text Default Logging
 * @parent ---Settings---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Log all messages by default?
 * NO - false     YES - true
 * @default true
 *
 * @param LogSpecialInput
 * @text Log Special Inputs
 * @parent ---Settings---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Log the special inputs made by the player?
 * NO - false     YES - true
 * @default true
 *
 * @param SpecialInputFmt
 * @text Special Input Format
 * @parent LogSpecialInput
 * @desc Format used to display special input text in backlog.
 * %1 - The text used in the selected choice.
 * @default »%1
 *
 * @param MaximumEntries
 * @text Maximum Entries
 * @parent ---Settings---
 * @type number
 * @min 1
 * @desc This is the maximum number of backlog entries.
 * If more than max are added, oldest entry will be removed.
 * @default 20
 *
 * @param ScrollBarEnabled
 * @text Scroll Bar Enabled
 * @parent ---Settings---
 * @type boolean
 * @on SHOW
 * @off HIDE
 * @desc Show a scroll bar for the message log?
 * HIDE - false     SHOW - true
 * @default true
 *
 * @param ScrollBarColor
 * @text Scroll Bar Color
 * @parent ScrollBarEnabled
 * @type number
 * @min 0
 * @max 31
 * @desc This is the text color used for the scroll bar.
 * @default 0
 *
 * @param ScrollBarSpriteCode
 * @text Sprite Code
 * @parent ScrollBarEnabled
 * @type note
 * @desc This is the code used for the scroll bar's sprite.
 * Edit this if you wish to customize it for your game.
 * @default "// Establish basic measurements\nvar padding = backlogWindow.standardPadding();\nvar width = padding / 2;\nvar height = Graphics.boxHeight;\n\n// Calculate number of visible rows\nvar visibleRows = backlogWindow.height - padding * 2;\nvisibleRows = Math.floor(visibleRows / backlogWindow.lineHeight());\nif (visibleRows < backlogWindow.maxItems()) {\n  height *= visibleRows / Math.max(1, backlogWindow.maxItems());\n}\n\n// Calculate the size of a basic scrolling increment\nvar max = Math.floor(Math.max(1, backlogWindow.maxItems()) / backlogWindow.maxCols()) - 1;\nthis._increment = Graphics.boxHeight / Math.max(1, max);\n\n// Generate the bitmap\nthis.bitmap = new Bitmap(width, height);\nthis.bitmap.fillAll(backlogWindow.textColor(scrollBarColor));"
 *
 * @param ScrollSpeed
 * @text Scroll Speed
 * @parent ---Settings---
 * @type number
 * @min 0
 * @desc This is the scroll speed used for backlog.
 * Lower numbers are faster. Higher numbers are slower.
 * @default 4
 *
 * @param ScrollWrap
 * @text Scroll Wrap
 * @parent ---Settings---
 * @type boolean
 * @on YES
 * @off NO
 * @desc If player is at the bottom log entry, hitting down
 * would wrap the player back to the top. Enable this?
 * @default true
 *
 * @param ---Visual---
 * @default
 *
 * @param BackgroundType
 * @text Background Type
 * @parent ---Visual---
 * @type select
 * @option Window
 * @value 0
 * @option Dimmed
 * @value 1
 * @option Picture
 * @value 2
 * @option Transparent
 * @value 3
 * @desc What kind of background type do you wish to use
 * for the message backlog window?
 * @default 1
 *
 * @param BackOpacity
 * @text Back Opacity
 * @parent ---Visual---
 * @type number
 * @min 0
 * @max 255
 * @desc If you are using a Window background type,
 * adjust this number to set the window's back opacity.
 * @default 192
 *
 * @param DimColor1
 * @text Dim Color 1
 * @parent ---Visual---
 * @desc If you are using a Dimmed background type,
 * adjust the first color here. Default: rgba(0, 0, 0, 0.6)
 * @default rgba(0, 0, 0, 0.8)
 *
 * @param DimColor2
 * @text Dim Color 2
 * @parent ---Visual---
 * @desc If you are using a Dimmed background type,
 * adjust the first color here. Default: rgba(0, 0, 0, 0)
 * @default rgba(0, 0, 0, 0.8)
 *
 * @param Picture
 * @parent ---Visual---
 * @type file
 * @dir img/pictures/
 * @require 1
 * @desc If you are using a Picture background type,
 * select a picture to use for your background.
 * @default
 *
 * @param PictureOpacity
 * @text Picture Opacity
 * @parent ---Visual---
 * @type number
 * @min 0
 * @max 255
 * @desc If you are using a Picture background type,
 * adjust this number to set the picture's opacity.
 * @default 255
 *
 * @param PictureStretch
 * @text Picture Stretch
 * @parent ---Visual---
 * @type boolean
 * @on Stretch
 * @off Don't Stretch
 * @desc If the picture used for the background is smaller than
 * the screen, stretch it to fit the screen?
 * @default true
 *
 */
//=============================================================================

if (Imported.YEP_MessageCore) {

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

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

Yanfly.Param.MsgBacklogKeyButton = String(Yanfly.Parameters['LogKeyButton']);
Yanfly.Param.MsgBacklogEnableKey = String(Yanfly.Parameters['EnableLogKey']);
Yanfly.Param.MsgBacklogEnableKey = eval(Yanfly.Param.MsgBacklogEnableKey);

Yanfly.Param.MsgBacklogDefaultLog = String(Yanfly.Parameters['DefaultLogging']);
Yanfly.Param.MsgBacklogDefaultLog = eval(Yanfly.Param.MsgBacklogDefaultLog);
Yanfly.Param.MsgBacklogSpcInput = String(Yanfly.Parameters['LogSpecialInput']);
Yanfly.Param.MsgBacklogSpcInput = eval(Yanfly.Param.MsgBacklogSpcInput);
Yanfly.Param.MsgBacklogSpcFmt = String(Yanfly.Parameters['SpecialInputFmt']);
Yanfly.Param.MsgBacklogMaxEntries = Number(Yanfly.Parameters['MaximumEntries']);
Yanfly.Param.MsgBacklogScrBarEn = String(Yanfly.Parameters['ScrollBarEnabled']);
Yanfly.Param.MsgBacklogScrBarEn = eval(Yanfly.Param.MsgBacklogScrBarEn);
Yanfly.Param.MsgBacklogScrBarCol = Number(Yanfly.Parameters['ScrollBarColor']);
Yanfly.Param.MsgBacklogScrBarSpriteCode =
  JSON.parse(Yanfly.Parameters['ScrollBarSpriteCode']);
Yanfly.Param.MsgBacklogScrollSpd = Number(Yanfly.Parameters['ScrollSpeed']);
Yanfly.Param.MsgBacklogScrollWrap = String(Yanfly.Parameters['ScrollWrap']);
Yanfly.Param.MsgBacklogScrollWrap = eval(Yanfly.Param.MsgBacklogScrollWrap);

Yanfly.Param.MsgBacklogBgType = Number(Yanfly.Parameters['BackgroundType']);
Yanfly.Param.MsgBacklogBackOpacity = Number(Yanfly.Parameters['BackOpacity']);
Yanfly.Param.MsgBacklogDimColor1 = String(Yanfly.Parameters['DimColor1']);
Yanfly.Param.MsgBacklogDimColor2 = String(Yanfly.Parameters['DimColor2']);
Yanfly.Param.MsgBacklogPicture = String(Yanfly.Parameters['Picture']);
Yanfly.Param.MsgBacklogPicOpacity = Number(Yanfly.Parameters['PictureOpacity']);
Yanfly.Param.MsgBacklogPicStretch = String(Yanfly.Parameters['PictureStretch']);
Yanfly.Param.MsgBacklogPicStretch = eval(Yanfly.Param.MsgBacklogPicStretch);

//=============================================================================
// Game_Temp
//=============================================================================

Game_Temp.prototype.isMessageBacklogOpened = function() {
  if (SceneManager._scene && SceneManager._scene._messageWindow) {
    var win = SceneManager._scene._messageWindow;
    if (win._backlogWindow && win._backlogWindow.isOpenAndActive()) {
      return true;
    }
  }
  return false;
};

//=============================================================================
// Game_System
//=============================================================================

Yanfly.MsgBacklog.Game_System_initialize = Game_System.prototype.initialize;
Game_System.prototype.initialize = function() {
  Yanfly.MsgBacklog.Game_System_initialize.call(this);
  this.initMessageBacklog();
};

Game_System.prototype.initMessageBacklog = function() {
  this._messageBacklog = [];
  this._messageBacklogKeyEnable = Yanfly.Param.MsgBacklogEnableKey;
  this._messageBacklogLoggingEnable = Yanfly.Param.MsgBacklogDefaultLog;
};

Game_System.prototype.addMessageBacklog = function(text) {
  if (!this.isMessageBacklogLoggingEnabled()) return;
  text = this.convertMessageBacklogText(text);
  this._messageBacklog.push(text);
  while (this._messageBacklog.length > Yanfly.Param.MsgBacklogMaxEntries) {
    this._messageBacklog.shift();
  }
};

Game_System.prototype.convertMessageBacklogText = function(text) {
  if (SceneManager._scene && SceneManager._scene._messageWindow) {
    var win = SceneManager._scene._messageWindow._backlogWindow;
    if (win) text = win.convertMessageText(text);
  }
  return text;
};

Game_System.prototype.getMessageBacklog = function() {
  if (this._messageBacklog === undefined) this.initMessageBacklog();
  return this._messageBacklog;
};

Game_System.prototype.isMessageBacklogKeyEnabled = function() {
  if (this._messageBacklogKeyEnable === undefined) this.initMessageBacklog();
  return this._messageBacklogKeyEnable;
};

Game_System.prototype.setMessageBacklogKeyEnable = function(value) {
  if (this._messageBacklogKeyEnable === undefined) this.initMessageBacklog();
  this._messageBacklogKeyEnable = value;
};

Game_System.prototype.isMessageBacklogLoggingEnabled = function() {
  if (this._messageBacklogLoggingEnable === undefined) {
    this.initMessageBacklog();
  }
  return this._messageBacklogKeyEnable;
};

Game_System.prototype.setMessageBacklogLoggingEnable = function(value) {
  if (this._messageBacklogLoggingEnable === undefined) {
    this.initMessageBacklog();
  }
  this._messageBacklogLoggingEnable = value;
};

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

Yanfly.MsgBacklog.Game_Player_canMove = Game_Player.prototype.canMove;
Game_Player.prototype.canMove = function() {
  if ($gameTemp.isMessageBacklogOpened()) return false;
  return Yanfly.MsgBacklog.Game_Player_canMove.call(this);
};

//=============================================================================
// Game_Event
//=============================================================================

Yanfly.MsgBacklog.Game_Event_updateSelfMovement =
  Game_Event.prototype.updateSelfMovement;
Game_Event.prototype.updateSelfMovement = function() {
  if ($gameTemp.isMessageBacklogOpened()) return;
  Yanfly.MsgBacklog.Game_Event_updateSelfMovement.call(this);
};

//=============================================================================
// Game_Interpreter
//=============================================================================

Yanfly.MsgBacklog.Game_Interpreter_pluginCommand =
  Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
  Yanfly.MsgBacklog.Game_Interpreter_pluginCommand.call(this, command, args);
  // Plugin Commands
  if (command === 'EnableMessageBacklog') {
    $gameSystem.setMessageHideKeyEnable(true);

  } else if (command === 'DisableMessageBacklog') {
    $gameSystem.setMessageHideKeyEnable(false);

  } else if (command === 'EnableMessageLogging') {
    $gameSystem.setMessageBacklogLoggingEnable(true);

  } else if (command === 'DisableMessageLogging') {
    $gameSystem.setMessageBacklogLoggingEnable(false);

  } else if (command === 'OpenMessageBacklog') {
    if (SceneManager._scene instanceof Scene_Map) {
      var win = SceneManager._scene._messageWindow;
      if (win) win.openBacklogWindow();
    }

  // End
  }
};

//=============================================================================
// Scene_Map
//=============================================================================

Yanfly.MsgBacklog.Scene_Map_isMenuEnabled = Scene_Map.prototype.isMenuEnabled;
Scene_Map.prototype.isMenuEnabled = function() {
  if ($gameTemp.isMessageBacklogOpened()) return false;
  return Yanfly.MsgBacklog.Scene_Map_isMenuEnabled.call(this);
};

//=============================================================================
// Window_Message
//=============================================================================

Yanfly.MsgBacklog.Window_Message_createSubWindows =
  Window_Message.prototype.createSubWindows;
Window_Message.prototype.createSubWindows = function() {
  Yanfly.MsgBacklog.Window_Message_createSubWindows.call(this);
  this.createMessageBacklogWindow();
};

Window_Message.prototype.createMessageBacklogWindow = function() {
  this._backlogWindow = new Window_MessageBacklog();
  SceneManager._scene.addChild(this._backlogWindow);
};

Yanfly.MsgBacklog.Window_Message_isAnySubWindowActive =
  Window_Message.prototype.isAnySubWindowActive;
Window_Message.prototype.isAnySubWindowActive = function() {
  if (this._backlogWindow.active) return true;
  return Yanfly.MsgBacklog.Window_Message_isAnySubWindowActive.call(this);
};

Yanfly.MsgBacklog.Window_Message_startMessage =
  Window_Message.prototype.startMessage;
Window_Message.prototype.startMessage = function() {
  Yanfly.MsgBacklog.Window_Message_startMessage.call(this);
  $gameSystem.addMessageBacklog($gameMessage.allText());
};

Yanfly.MsgBacklog.Window_Message_updateInput =
  Window_Message.prototype.updateInput;
Window_Message.prototype.updateInput = function() {
  if (this.isAnySubWindowActive()) return true;
  this.updateBacklogInput();
  var value = Yanfly.MsgBacklog.Window_Message_updateInput.call(this);
  return value;
};

Window_Message.prototype.updateBacklogInput = function() {
  if (!this.pause) return;
  if (!$gameSystem.isMessageBacklogKeyEnabled()) return;
  if (Input.isTriggered(Yanfly.Param.MsgBacklogKeyButton)) {
    this.openBacklogWindow();
  }
};

Window_Message.prototype.openBacklogWindow = function() {
  this._backlogWindow.fullActivate();
};

Window_Message.prototype.setReturnWindow = function(target) {
  this._backlogWindow.setReturnWindow(target);
};

//=============================================================================
// Window_ChoiceList
//=============================================================================

Yanfly.MsgBacklog.Window_ChoiceList_processHandling =
  Window_ChoiceList.prototype.processHandling;
Window_ChoiceList.prototype.processHandling = function() {
  if (this.isOpenAndActive()) this.updateBacklogInput();
  Yanfly.MsgBacklog.Window_ChoiceList_processHandling.call(this);
};

Window_ChoiceList.prototype.updateBacklogInput = function() {
  if (!$gameSystem.isMessageBacklogKeyEnabled()) return;
  if (Input.isTriggered(Yanfly.Param.MsgBacklogKeyButton)) {
    this.openBacklogWindow();
  }
};

Window_ChoiceList.prototype.openBacklogWindow = function() {
  if (SceneManager._scene && SceneManager._scene._messageWindow) {
    SceneManager._scene._messageWindow.setReturnWindow(this);
    SceneManager._scene._messageWindow.openBacklogWindow();
  }
};

Yanfly.MsgBacklog.Window_ChoiceList_callOkHandler =
  Window_ChoiceList.prototype.callOkHandler;
Window_ChoiceList.prototype.callOkHandler = function() {
  this.backlogAddSelectedChoice();
  Yanfly.MsgBacklog.Window_ChoiceList_callOkHandler.call(this);
};

Window_ChoiceList.prototype.backlogAddSelectedChoice = function() {
  if (!Yanfly.Param.MsgBacklogSpcInput) return;
  var fmt = Yanfly.Param.MsgBacklogSpcFmt;
  var text = fmt.format(this.commandName(this.index()));
  $gameSystem.addMessageBacklog(text);
};

//=============================================================================
// Window_NumberInput
//=============================================================================

Yanfly.MsgBacklog.Window_NumberInput_processHandling =
  Window_NumberInput.prototype.processHandling;
Window_NumberInput.prototype.processHandling = function() {
  if (this.isOpenAndActive()) this.updateBacklogInput();
  Yanfly.MsgBacklog.Window_NumberInput_processHandling.call(this);
};

Window_NumberInput.prototype.updateBacklogInput = function() {
  if (!$gameSystem.isMessageBacklogKeyEnabled()) return;
  if (Input.isTriggered(Yanfly.Param.MsgBacklogKeyButton)) {
    this.openBacklogWindow();
  }
};

Window_NumberInput.prototype.openBacklogWindow = function() {
  if (SceneManager._scene && SceneManager._scene._messageWindow) {
    SceneManager._scene._messageWindow.setReturnWindow(this);
    SceneManager._scene._messageWindow.openBacklogWindow();
  }
};

Yanfly.MsgBacklog.Window_NumberInput_processOk =
  Window_NumberInput.prototype.processOk;
Window_NumberInput.prototype.processOk = function() {
  this.backlogAddSelectedChoice();
  Yanfly.MsgBacklog.Window_NumberInput_processOk.call(this);
};

Window_NumberInput.prototype.backlogAddSelectedChoice = function() {
  if (!Yanfly.Param.MsgBacklogSpcInput) return;
  var fmt = Yanfly.Param.MsgBacklogSpcFmt;
  var text = fmt.format(Yanfly.Util.toGroup(this._number));
  $gameSystem.addMessageBacklog(text);
};

//=============================================================================
// Window_EventItem
//=============================================================================

Yanfly.MsgBacklog.Window_EventItem_processHandling =
  Window_EventItem.prototype.processHandling;
Window_EventItem.prototype.processHandling = function() {
  if (this.isOpenAndActive()) this.updateBacklogInput();
  Yanfly.MsgBacklog.Window_EventItem_processHandling.call(this);
};

Window_EventItem.prototype.updateBacklogInput = function() {
  if (!$gameSystem.isMessageBacklogKeyEnabled()) return;
  if (Input.isTriggered(Yanfly.Param.MsgBacklogKeyButton)) {
    this.openBacklogWindow();
  }
};

Window_EventItem.prototype.openBacklogWindow = function() {
  if (SceneManager._scene && SceneManager._scene._messageWindow) {
    SceneManager._scene._messageWindow.setReturnWindow(this);
    SceneManager._scene._messageWindow.openBacklogWindow();
  }
};

Yanfly.MsgBacklog.Window_EventItem_onOk = Window_EventItem.prototype.onOk;
Window_EventItem.prototype.onOk = function() {
  this.backlogAddSelectedChoice();
  Yanfly.MsgBacklog.Window_EventItem_onOk.call(this);
};

Window_EventItem.prototype.backlogAddSelectedChoice = function() {
  if (!Yanfly.Param.MsgBacklogSpcInput) return;
  var fmt = Yanfly.Param.MsgBacklogSpcFmt;
  var item = this.item();
  var text = fmt.format('\\i[' + item.iconIndex + ']' + item.name);
  $gameSystem.addMessageBacklog(text);
};

//=============================================================================
// Sprite_BacklogScroll
//=============================================================================

function Sprite_BacklogScroll() {
    this.initialize.apply(this, arguments);
}

Sprite_BacklogScroll.prototype = Object.create(Sprite.prototype);
Sprite_BacklogScroll.prototype.constructor = Sprite_BacklogScroll;

Sprite_BacklogScroll.prototype.initialize = function(target) {
  this._target = target;
  Sprite.prototype.initialize.call(this);
  this._target._scrollSprite = this;
  this.initMembers();
  this.createBitmap();
};

Sprite_BacklogScroll.prototype.initMembers = function() {
  this.anchor.x = 1;
  this.anchor.y = 0;
  this.x = Graphics.boxWidth;
  this.y = 0;
  this._increment = 1;
};

Sprite_BacklogScroll.prototype.createBitmap = function() {
  var scrollBarColor = Yanfly.Param.MsgBacklogScrBarCol;
  var backlogWindow = this._target;
  this._increment = 1;
  eval(Yanfly.Param.MsgBacklogScrBarSpriteCode);
};

Sprite_BacklogScroll.prototype.resize = function() {
  this.bitmap.clear();
  this.createBitmap();
};

Sprite_BacklogScroll.prototype.update = function() {
  Sprite.prototype.update.call(this);
  if (!this._target) return;
  this.updateOpacity();
  //this.updatePosition();
};

Sprite_BacklogScroll.prototype.updateOpacity = function() {
  this.opacity = this._target.isOpen() ? 255 : 0;
};

Sprite_BacklogScroll.prototype.updatePosition = function() {
  var target = this._target;
  if (!target.isOpen()) return;
  this.y = target.topRow() * this._increment;
};

//=============================================================================
// Window_MessageBacklog
//=============================================================================

function Window_MessageBacklog() {
    this.initialize.apply(this, arguments);
}

Window_MessageBacklog.prototype = Object.create(Window_Command.prototype);
Window_MessageBacklog.prototype.constructor = Window_MessageBacklog;

Window_MessageBacklog.prototype.initialize = function() {
  this._touchHold = 0;
  this._ready = false;
  Window_Command.prototype.initialize.call(this, 0, 0);
  this.createScrollSprite(this);
  this.setBackgroundType(Yanfly.Param.MsgBacklogBgType);
  this.deactivate();
  this.openness = 0;
  this._ready = true;
};

Window_MessageBacklog.prototype.createScrollSprite = function() {
  if (!Yanfly.Param.MsgBacklogScrBarEn) return;
  this._scrollSprite = new Sprite_BacklogScroll(this);
  this.addChild(this._scrollSprite);
};

Window_MessageBacklog.prototype.windowWidth = function() {
  return Graphics.boxWidth;
};

Window_MessageBacklog.prototype.windowHeight = function() {
  return Graphics.boxHeight;
};

Window_MessageBacklog.prototype.dimColor1 = function() {
  return Yanfly.Param.MsgBacklogDimColor1;
};

Window_MessageBacklog.prototype.dimColor2 = function() {
  return Yanfly.Param.MsgBacklogDimColor2;
};

Window_MessageBacklog.prototype.setBackgroundType = function(type) {
  Window_Base.prototype.setBackgroundType.call(this, type);
  if (type === 2) this.createBackgroundPicture();
};

Window_MessageBacklog.prototype.createBackgroundPicture = function() {
  var filename = Yanfly.Param.MsgBacklogPicture;
  if (filename === '') return;
  this._backgroundPicture = new Sprite();
  this._backgroundPicture.bitmap = ImageManager.loadPicture(filename, 0);
  SceneManager._scene.addChild(this._backgroundPicture);
  this._backgroundPicture.opacity = 0;
  this._backgroundPicture.anchor.x = 0.5;
  this._backgroundPicture.anchor.y = 0.5;
  this._backgroundPicture.x = Graphics.boxWidth / 2;
  this._backgroundPicture.y = Graphics.boxHeight / 2;
};

Window_MessageBacklog.prototype.setBgPictureOpacity = function(opacity) {
  this._backgroundPicture.opacity = opacity;

  this.stretchBgPicture();
};

Window_MessageBacklog.prototype.stretchBgPicture = function() {
  if (!Yanfly.Param.MsgBacklogPicStretch) return;
  if (this._backgroundPicture.width < Graphics.boxWidth) {
    var rate = Graphics.boxWidth / this._backgroundPicture.width;
    this._backgroundPicture.scale.x = rate;
  }
  if (this._backgroundPicture.height < Graphics.boxHeight) {
    var rate = Graphics.boxHeight / this._backgroundPicture.height;
    this._backgroundPicture.scale.y = rate;
  }
};

Window_MessageBacklog.prototype.standardFontFace = function() {
  return Window_Message.prototype.standardFontFace.call(this);
};

Window_MessageBacklog.prototype.standardFontSize = function() {
  return Window_Message.prototype.standardFontSize.call(this);
};

Window_MessageBacklog.prototype.standardBackOpacity = function() {
  return Yanfly.Param.MsgBacklogBackOpacity;
};

Window_MessageBacklog.prototype.makeFontBigger = function() {
};

Window_MessageBacklog.prototype.makeFontSmaller = function() {
};

Window_MessageBacklog.prototype.select = function(index) {
};

Window_MessageBacklog.prototype.moveSelect = function(index) {
  Window_Command.prototype.select.call(this, index);
  if (this._scrollSprite) this._scrollSprite.updatePosition();
};

Window_MessageBacklog.prototype.deselect = function() {
  this.moveSelect(-1);
};

Window_MessageBacklog.prototype.processHandling = function() {
  if (!this.isOpenAndActive()) return;
  Window_Command.prototype.processHandling.call(this);
  //if (Input.isTriggered(Yanfly.Param.MsgBacklogKeyButton)) {
  //  this.processCancel();
  //}
};

Window_MessageBacklog.prototype.setReturnWindow = function(target) {
  this._returnWindow = target;
  this._returnWindow.deactivate();
};

Window_MessageBacklog.prototype.fullActivate = function() {
  this.updateInputData();
  Input.clear();
  TouchInput.clear();
  this.refresh();
  this.activate();
  this.openness = 255;
  this.moveSelect(this.maxItems() - 1);
  if (this._scrollSprite) this._scrollSprite.resize();
  if (this._backgroundPicture) {
    this.setBgPictureOpacity(Yanfly.Param.MsgBacklogPicOpacity);
  }
};

Window_MessageBacklog.prototype.processOk = function() {
  SoundManager.playOk();
  this.fullDeactivate();
};

Window_MessageBacklog.prototype.isCancelEnabled = function() {
  return true;
};

Window_MessageBacklog.prototype.processCancel = function() {
  SoundManager.playCancel();
  this.fullDeactivate();
};

Window_MessageBacklog.prototype.fullDeactivate = function() {
  this.updateInputData();
  Input.clear();
  TouchInput.clear();
  this.deactivate();
  this.openness = 0;
  this.deselect();
  if (this._returnWindow) {
    this._returnWindow.activate();
    this._returnWindow = undefined;
  }
  if (this._backgroundPicture) this.setBgPictureOpacity(0)
};

Window_MessageBacklog.prototype.isCursorVisible = function() {
  return false;
};

Window_MessageBacklog.prototype.cursorDown = function(wrap) {
  var index = this.bottomRow();
  var maxItems = this.maxItems();
  var maxCols = this.maxCols();
  wrap = Yanfly.Param.MsgBacklogScrollWrap;
  if (index < maxItems - maxCols || (wrap && maxCols === 1)) {
    this.moveSelect((index + maxCols) % maxItems);
  }
};

Window_MessageBacklog.prototype.cursorUp = function(wrap) {
  var index = this.topRow();
  var maxItems = this.maxItems();
  var maxCols = this.maxCols();
  wrap = Yanfly.Param.MsgBacklogScrollWrap;
  if (index >= maxCols || (wrap && maxCols === 1)) {
    this.moveSelect((index - maxCols + maxItems) % maxItems);
  }
};

Window_MessageBacklog.prototype.cursorPagedown = function() {
  var index = this.index();
  var maxItems = this.maxItems();
  if (this.topRow() + this.maxPageRows() < this.maxRows()) {
    SoundManager.playCursor();
  }
  Window_Selectable.prototype.cursorPagedown.call(this);
  if (this._scrollSprite) this._scrollSprite.updatePosition();
};

Window_MessageBacklog.prototype.cursorPageup = function() {
  var index = this.index();
  if (this.topRow() > 0) {
    SoundManager.playCursor();
  }
  Window_Selectable.prototype.cursorPageup.call(this);
  if (this._scrollSprite) this._scrollSprite.updatePosition();
};

Window_MessageBacklog.prototype.processTouch = function() {
  if (!this.isOpenAndActive()) return;
  this._touchHold -= 1;
  if (TouchInput.isPressed() && this._touchHold <= 0) {
    if (TouchInput.y < Graphics.boxHeight / 4) {
      this.scrollUp();
      this._touchHold = Yanfly.Param.MsgBacklogScrollSpd;
    } else if (TouchInput.y > Graphics.boxHeight * 3 / 4) {
      this.scrollDown();
      this._touchHold = Yanfly.Param.MsgBacklogScrollSpd;
    } else {
      this.processOk();
    }
  } else if (TouchInput.isCancelled()) {
    if (this.isCancelEnabled()) {
      this.processCancel();
    }
  }
};

Window_MessageBacklog.prototype.drawItem = function(index) {
  var rect = this.itemRectForText(index);
  var align = this.itemTextAlign();
  var symbol = this.commandSymbol(index);
  if (symbol === 'linebreak') {
    this.drawHorzLine(rect.y);
    this.resetFontSettings();
  } else if (symbol === 'text') {
    this.drawTextEx(this.commandName(index), rect.x, rect.y);
  } else if (symbol === 'buffer') {
    if (index !== this.topRow()) return;
    var ext = this._list[index].ext;
    this.drawItem(index - ext);
  }
};

Window_MessageBacklog.prototype.drawHorzLine = function(y) {
  var lineY = y + this.lineHeight() / 2 - 1;
  this.contents.paintOpacity = 48;
  this.contents.fillRect(0, lineY, this.contentsWidth(), 2, this.normalColor());
  this.contents.paintOpacity = 255;
};

Window_MessageBacklog.prototype.drawTextEx = function(text, x, y) {
  if (text) {
    var textState = { index: 0, x: x, y: y, left: x };
    textState.text = this.convertEscapeCharacters(text);
    textState.height = this.calcTextHeight(textState, false);
    while (textState.index < textState.text.length) {
      this.processCharacter(textState);
    }
    return textState.x - x;
  } else {
    return 0;
  }
};

Window_MessageBacklog.prototype.textHeightEx = function(text) {
  return this.getTextExHeight(text, 0, 0);
};

Window_MessageBacklog.prototype.getTextExHeight = function(text, x, y) {
  if (text) {
    var textState = { index: 0, x: x, y: y, left: x };
    textState.text = this.convertEscapeCharacters(text);
    textState.height = this.calcTextHeight(textState, false);
    while (textState.index < textState.text.length) {
      this.processCharacter(textState);
    }
    this.contents.clear();
    return textState.y;
  } else {
    return 0;
  }
};

Window_MessageBacklog.prototype.makeCommandList = function() {
  if (!this._ready) return;
  var backlog = $gameSystem.getMessageBacklog();
  var length = backlog.length;
  for (var i = 0; i < length; ++i) {
    var text = backlog[i];
    this.addCommand('---', 'linebreak');
    this.addIndividualLines(text);
  }
  this.addCommand('---', 'linebreak');
};

Window_MessageBacklog.prototype.addIndividualLines = function(text) {
  var text = this.convertMessageText(text);
  var items = text.split('\n');
  var length = items.length;
  console.log(items)
  for (var i = 0; i < length; ++i) {
    var line = items[i];
    if (line.length <= 0) continue;
    this.addCommand(line, 'text');
    this.addWordWrapBuffer(line);
  }
};

Window_MessageBacklog.prototype.convertMessageText = function(text) {
  text = this.convertMessageMacros(text);
  text = text.replace(/\\/g, '\x1b');
  text = this.convertNameboxCodes(text);
  text = this.convertBasicCodes(text);
  text = this.convertSpecialCodes(text);
  text = this.removeMessageBoxOnlyCodes(text);
  text = TextManager.convertEscapeCharacters(text);
  text = TextManager.convertExtraEscapeCharacters(text);
  return text;
};

Window_MessageBacklog.prototype.convertMessageMacros = function(text) {
  if (Imported.YEP_X_MessageMacros1) {
    text = this.convertMacroText(text);
  }
  return text;
};

Window_MessageBacklog.prototype.convertNameboxCodes = function(text) {
  var name = '';
  // \x1b
  if (text.match(/\x1bN\<(.*?)\>/gi)) {
    name = RegExp.$1;
  } else if (text.match(/\x1bN(\d+)\<(.*?)\>/gi)) {
    name = RegExp.$2;
  } else if (text.match(/\x1bN(?:T|D|L|C|R|DL|DC|DR|TL|TC|TR)\<(.*?)\>/gi)) {
    name = RegExp.$1;
  } else if
  (text.match(/\x1bN(?:T|D|L|C|R|DL|DC|DR|TL|TC|TR)(\d+)\<(.*?)\>/gi)) {
    name = RegExp.$2;
  }
  if (name.length > 0) {
    var nameText = Yanfly.Param.MSGNameBoxText + name + '\\c[0]\n';
    text = nameText + text;
  }
  // \x1b version
  text = text.replace(/\x1bN\<(.*?)\>/gi, '');
  text = text.replace(/\x1bN(\d+)\<(.*?)\>/gi, '');
  text = text.replace(/\x1bN(?:T|D|L|C|R|DL|DC|DR|TL|TC|TR)\<(.*?)\>/gi, '');
  text = text.replace(/\x1bN\<(.*?)\>/gi, '');
  text =
    text.replace(/\x1bN(?:T|D|L|C|R|DL|DC|DR|TL|TC|TR)(\d+)\<(.*?)\>/gi, '');
  return text;
};

Window_MessageBacklog.prototype.convertBasicCodes = function(text) {
  text = text.replace(/\\/g, '\x1b');
  text = text.replace(/\x1b\x1b/g, '\\');
  text = text.replace(/\x1bV\[(\d+)\]/gi, function() {
    return $gameVariables.value(parseInt(arguments[1]));
  }.bind(this));
  text = text.replace(/\x1bV\[(\d+)\]/gi, function() {
    return $gameVariables.value(parseInt(arguments[1]));
  }.bind(this));
  text = text.replace(/\x1bN\[(\d+)\]/gi, function() {
    return this.actorName(parseInt(arguments[1]));
  }.bind(this));
  text = text.replace(/\x1bP\[(\d+)\]/gi, function() {
    return this.partyMemberName(parseInt(arguments[1]));
  }.bind(this));
  text = text.replace(/\x1bG/gi, TextManager.currencyUnit);
  return text;
};

Window_MessageBacklog.prototype.convertSpecialCodes = function(text) {
  if (Imported.YEP_X_ExtMesPack2) {
    text = this.convertItemQuantitiesCodes(text);
    text = this.convertActorParameterCodes(text);
    text = this.convertEnemyParameterCodes(text);
  }
  return text;
};

Window_MessageBacklog.prototype.removeMessageBoxOnlyCodes = function(text) {
  text = text.replace(/\x1b/gi, '\\');
  // Message Core
  text = text.replace(/\\AF\[(\d+)\]/gi, '');
  text = text.replace(/\\PF\[(\d+)\]/gi, '');
  text = text.replace(/\\FS\[(\d+)\]/gi, '');
  // Extended Message Pack 1
  text = text.replace(/\\LSON/gi, '');
  text = text.replace(/\\LSOFF/gi, '');
  text = text.replace(/\\LSRESET/gi, '');
  text = text.replace(/\\LSR/gi, '');
  text = text.replace(/\\LSN\[(.*?)\]/gi, '');
  text = text.replace(/\\LSV\[(\d+)\]/gi, '');
  text = text.replace(/\\LSPIV\[(\d+)\]/gi, '');
  text = text.replace(/\\LSPI\[(\d+)\]/gi, '');
  text = text.replace(/\\LSPAV\[(\d+)\]/gi, '');
  text = text.replace(/\\LSPA\[(\d+)\]/gi, '');
  text = text.replace(/\\LSI\[(\d+)\]/gi, '');
  text = text.replace(/\\MSGPOSX\[(.*?)\]/gi, '');
  text = text.replace(/\\MSGPOSY\[(.*?)\]/gi, '');
  text = text.replace(/\\MSGEVENT\[(\d+)\]/gi, '');
  text = text.replace(/\\MSGACTOR\[(\d+)\]/gi, '');
  text = text.replace(/\\MSGPARTY\[(\d+)\]/gi, '');
  text = text.replace(/\\MSGENEMY\[(\d+)\]/gi, '');
  text = text.replace(/\\AUTOEVENT\[(\d+)\]/gi, '');
  text = text.replace(/\\AUTOACTOR\[(\d+)\]/gi, '');
  text = text.replace(/\\AUTOPARTY\[(\d+)\]/gi, '');
  text = text.replace(/\\AUTOENEMY\[(\d+)\]/gi, '');
  text = text.replace(/\\MSGROWS\[(.*?)\]/gi, '');
  text = text.replace(/\\MSGWIDTH\[(.*?)\]/gi, '');
  text = text.replace(/\\AUTO/gi, '');
  text = text.replace(/\\MSGRESET/gi, '');
  text = text.replace(/\\FACEINDEX\[(\d+)\]/gi, '');
  return text;
};

Window_MessageBacklog.prototype.addWordWrapBuffer = function(text) {
  if (!text.match(/<(?:WordWrap)>/gi)) return;
  var textHeight = this.textHeightEx(text);
  var bufferTimes = Math.ceil(textHeight / this.lineHeight());
  for (var i = 1; i <= bufferTimes; ++i) {
    this.addCommand('', 'buffer', true, i);
  }
};

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

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

if (!Yanfly.Util.toGroup) {

Yanfly.Util.toGroup = function(inVal) {
  return inVal;
}

};

//=============================================================================
// End of File
//=============================================================================
} else {

var text = '';
text += 'You are getting this error because you are trying to run ';
text += 'YEP_X_MessageBacklog without the required plugins. Please visit ';
text += 'Yanfly.moe and install the required plugins neede for this plugin ';
text += 'found in this plugin\'s help file before you can use it.';
console.log(text);
require('nw.gui').Window.get().showDevTools();

}; // Imported.YEP_MessageCore

repo_name: voidljb/karryn

license: unknown


code:
//=============================================================================
// Yanfly Engine Plugins - Message Core Extension - Message Speed Option
// YEP_X_MessageSpeedOpt.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.MsgSpdOpt = Yanfly.MsgSpdOpt || {};
Yanfly.MsgSpdOpt.version = 1.00;

//=============================================================================
 /*:
 * @plugindesc v1.00 (Requires YEP_MessageCore.js) Let your places adjust the
 * speed the message window displays text.
 * @author Yanfly Engine Plugins
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * This plugin requires YEP_MessageCore.
 * Make sure this plugin is located under YEP_MessageCore in the plugin list.
 *
 * The option to control the message speed is quite common in RPG's nowadays.
 * Players can put in whatever option they feel like for the text to go at, or
 * if they wish, to have the text display instantly! This plugin will add in
 * the 'Message Speed' option into your Options Menu for players to adjust! It
 * comes with speeds from 0 (slowest) to 10 (fastest) and even an "11th" speed
 * of being instant!
 *
 * ============================================================================
 * Options Core Settings - Adding the New Options
 * ============================================================================
 *
 * If you are using YEP_OptionsCore.js, you can add a new Option using this
 * plugin. Here's the following code/parameter settings you can use with it.
 *
 * ---------
 * Settings:
 * ---------
 *
 * Name:
 * \i[87]Message Speed
 *
 * Help Description:
 * Changes the speed text is displayed during messages.
 *
 * Symbol:
 * messageSpeed
 *
 * Show/Hide:
 * show = Imported.YEP_X_MessageSpeedOpt;
 *
 * Enable:
 * enabled = true;
 *
 * Ext:
 * ext = 0;
 *
 * ----------
 * Functions:
 * ----------
 *
 * Make Option Code:
 * this.addCommand(name, symbol, enabled, ext);
 *
 * Draw Option Code:
 * var rect = this.itemRectForText(index);
 * var statusWidth = this.statusWidth();
 * var titleWidth = rect.width - statusWidth;
 * this.resetTextColor();
 * this.changePaintOpacity(this.isCommandEnabled(index));
 * this.drawOptionsName(index);
 * var value = this.getConfigValue(symbol);
 * var rate = ((value) / 10).clamp(0, 1);
 * if (value > 10) {
 *   var gaugeColor1 = this.textColor(14);
 *   var gaugeColor2 = this.textColor(6);
 * } else {
 *   var gaugeColor1 = this.textColor(20);
 *   var gaugeColor2 = this.textColor(21);
 * }
 * this.drawOptionsGauge(index, rate, gaugeColor1, gaugeColor2);
 * this.drawText(this.statusText(index), titleWidth, rect.y, statusWidth, 'center');
 *
 * Process OK Code:
 * var index = this.index();
 * var symbol = this.commandSymbol(index);
 * var value = this.getConfigValue(symbol);
 * value += 1;
 * if (value > 11) value = 0;
 * value = value.clamp(0, 11);
 * this.changeValue(symbol, value);
 *
 * Cursor Right Code:
 * var index = this.index();
 * var symbol = this.commandSymbol(index);
 * var value = this.getConfigValue(symbol);
 * value += 1;
 * value = value.clamp(0, 11);
 * this.changeValue(symbol, value);
 *
 * Cursor Left Code:
 * var index = this.index();
 * var symbol = this.commandSymbol(index);
 * var value = this.getConfigValue(symbol);
 * value -= 1;
 * value = value.clamp(0, 11);
 * this.changeValue(symbol, value);
 *
 * Default Config Code:
 * // Empty. Provided by this plugin.
 *
 * Save Config Code:
 * // Empty. Provided by this plugin.
 *
 * Load Config Code:
 * // Empty. Provided by this plugin.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version BETA:
 * - Started Plugin!
 *
 * ============================================================================
 * End of Helpfile
 * ============================================================================
 *
 * @param OptionsCommand
 * @text Options Command
 * @desc The name of the option to be used.
 * @default Message Speed
 *
 * @param DefaultSpeed
 * @text Default Speed
 * @type number
 * @min 0
 * @max 11
 * @desc Default speed used by text messages. Use a number betwee
 * 0 - Slowest, 10 - Fastest, 11 - Instant
 * @default 8
 *
 * @param InstantText
 * @text Instant Text
 * @desc The text to display to show the speed is instant.
 * @default Instant
 *
 */
//=============================================================================

if (Imported.YEP_MessageCore) {

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

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

Yanfly.Param.MsgSpeedOptCmd = String(Yanfly.Parameters['OptionsCommand']);
Yanfly.Param.MsgSpeedOptDefault = Number(Yanfly.Parameters['DefaultSpeed']);
Yanfly.Param.MsgSpeedOptInstant = String(Yanfly.Parameters['InstantText']);

//=============================================================================
// ConfigManager
//=============================================================================

ConfigManager.messageSpeed = Yanfly.Param.MsgSpeedOptDefault;

Yanfly.MsgSpdOpt.ConfigManager_makeData = ConfigManager.makeData;
ConfigManager.makeData = function() {
  var config = Yanfly.MsgSpdOpt.ConfigManager_makeData.call(this);
  config.messageSpeed = this.messageSpeed;
  return config;
};

Yanfly.MsgSpdOpt.ConfigManager_applyData = ConfigManager.applyData;
ConfigManager.applyData = function(config) {
  Yanfly.MsgSpdOpt.ConfigManager_applyData.call(this, config);
  this.messageSpeed = this.readConfigMessageSpeed(config, 'messageSpeed');
};

ConfigManager.readConfigMessageSpeed = function(config, name) {
  var value = config[name];
  if (value !== undefined) {
      return value;
  } else {
      return Yanfly.Param.MsgSpeedOptDefault;
  }
};

//=============================================================================
// Window_Message
//=============================================================================

Yanfly.MsgSpdOpt.Window_Message_newPage = Window_Message.prototype.newPage;
Window_Message.prototype.newPage = function(textState) {
  Yanfly.MsgSpdOpt.Window_Message_newPage.call(this, textState);
  this._textDelay = 0;
};

Yanfly.MsgSpdOpt.Window_Message_updateShowFast =
  Window_Message.prototype.updateShowFast;
Window_Message.prototype.updateShowFast = function() {
  Yanfly.MsgSpdOpt.Window_Message_updateShowFast.call(this);
  if (this.messageSpeed() < 0) this._showFast = true;
};

Window_Message.prototype.messageSpeed = function() {
  return 10 - (ConfigManager.messageSpeed.clamp(0, 11));
};

Window_Message.prototype.updateMessage = function() {
  if (this._textState) {
    while (!this.isEndOfText(this._textState)) {
      if (this.needsNewPage(this._textState)) {
          this.newPage(this._textState);
      }
      this.updateShowFast();
      if (this._textDelay <= 0 || this._showFast || this._lineShowFast || $gameMessage._forcedShowFast) {
        this.processCharacter(this._textState);
        this._textDelay = this.messageSpeed();
      } else {
        this._textDelay -= 1;
        break;
      }
      if (!this._showFast && !this._lineShowFast && !$gameMessage._forcedShowFast) {
        break;
      }
      if (this.pause || this._waitCount > 0) {
        break;
      }
    }
    if (this.isEndOfText(this._textState)) {
      this.onEndOfText();
    }
    return true;
  } else {
    return false;
  }
};

if (Imported.YEP_X_ExtMesPack1) {

Yanfly.EMP1.Window_Message_updateMessage =
  Window_Message.prototype.updateMessage;
Window_Message.prototype.updateMessage = function() {
  var state = Yanfly.EMP1.Window_Message_updateMessage.call(this);
  if (state) {
    this._soundCount = this._soundCount || 0;
    if (this._soundCount-- <= 0) {
      this._soundCount = $gameSystem.messageSoundInterval();
      if ($gameSystem.isMessageSoundEnabled()) SoundManager.playMessageSound();
    }
  }
  return state;
}

}; // Imported.YEP_X_ExtMesPack1

Yanfly.MsgSpdOpt.Window_Message_updateWait =
  Window_Message.prototype.updateWait;
Window_Message.prototype.updateWait = function() {
  if (this.messageSpeed() < 0) {
    this._waitCount = 0;
    this._lineShowFast = true;
    this._showFast = true;
  }
  return Yanfly.MsgSpdOpt.Window_Message_updateWait.call(this);
};

//=============================================================================
// Window_Options
//=============================================================================

Yanfly.MsgSpdOpt.Window_Options_addGeneralOptions =
  Window_Options.prototype.addGeneralOptions;
Window_Options.prototype.addGeneralOptions = function() {
  Yanfly.MsgSpdOpt.Window_Options_addGeneralOptions.call(this);
  if (Imported.YEP_OptionsCore) return;
  this.addMessageSpeedOptions();
};

Window_Options.prototype.addMessageSpeedOptions = function() {
  this.addCommand(Yanfly.Param.MsgSpeedOptCmd, 'messageSpeed');
};

Yanfly.MsgSpdOpt.Window_Options_statusText = Window_Options.prototype.statusText;
Window_Options.prototype.statusText = function(index) {
  var symbol = this.commandSymbol(index);
  var value = this.getConfigValue(symbol);
  if (symbol === 'messageSpeed') {
    if (value > 10) return TextManager.yanflyOptionsMessageSpeedNoWait;
    return Yanfly.Util.toGroup(value);
  } else {
    return Yanfly.MsgSpdOpt.Window_Options_statusText.call(this, index);
  }
};

if (!Imported.YEP_OptionsCore) {

Yanfly.MsgSpdOpt.Window_Options_processOk = Window_Options.prototype.processOk;
Window_Options.prototype.processOk = function() {
  var index = this.index();
  var symbol = this.commandSymbol(index);
  if (symbol === 'messageSpeed') {
    var value = this.getConfigValue(symbol);
    value += 1;
    if (value > 11) value = 0;
    value = value.clamp(0, 11);
    this.changeValue(symbol, value);
  } else {
    Yanfly.MsgSpdOpt.Window_Options_processOk.call(this);
  }
};

Yanfly.MsgSpdOpt.Window_Options_cursorRight =
  Window_Options.prototype.cursorRight;
Window_Options.prototype.cursorRight = function(wrap) {
  var index = this.index();
  var symbol = this.commandSymbol(index);
  if (symbol === 'messageSpeed') {
    var value = this.getConfigValue(symbol);
    value += 1;
    value = value.clamp(0, 11);
    this.changeValue(symbol, value);
  } else {
    Yanfly.MsgSpdOpt.Window_Options_cursorRight.call(this, wrap);
  }
};

Yanfly.MsgSpdOpt.Window_Options_cursorLeft =
  Window_Options.prototype.cursorLeft;
Window_Options.prototype.cursorLeft = function(wrap) {
  var index = this.index();
  var symbol = this.commandSymbol(index);
  if (symbol === 'messageSpeed') {
    var value = this.getConfigValue(symbol);
    value -= 1;
    value = value.clamp(0, 11);
    this.changeValue(symbol, value);
  } else {
    Yanfly.MsgSpdOpt.Window_Options_cursorLeft.call(this, wrap);
  }
};

}; // Imported.YEP_OptionsCore

//=============================================================================
// End of File
//=============================================================================
} else {

var text = '';
text += 'You are getting this error because you are trying to run ';
text += 'YEP_X_MessageSpeedOpt without the required plugins. Please visit ';
text += 'Yanfly.moe and install the required plugins neede for this plugin ';
text += 'found in this plugin\'s help file before you can use it.';
console.log(text);
require('nw.gui').Window.get().showDevTools();

}; // Imported.YEP_MessageCore