code:
//=============================================================================
// Yanfly Engine Plugins - Skill Cost Extension - Cooldowns
// YEP_X_SkillCooldowns.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.SCD = Yanfly.SCD || {};
Yanfly.SCD.version = 1.12;

//=============================================================================
 /*:
 * @plugindesc v1.12 (Requires YEP_SkillCore.js) Cooldowns can be applied
 * to skills to prevent them from being used continuously.
 * @author Yanfly Engine Plugins
 *
 * @param ---Cooldown---
 * @default
 *
 * @param Cooldown Format
 * @parent ---Cooldown---
 * @desc This is the text format used for cooldowns.
 * %1 - Turns Remaining
 * @default %1CD
 *
 * @param Cooldown Font Size
 * @parent ---Cooldown---
 * @type number
 * @min 0
 * @desc This is the font size used for cooldowns.
 * Default: 28
 * @default 20
 *
 * @param Cooldown Text Color
 * @parent ---Cooldown---
 * @type number
 * @min 0
 * @max 31
 * @desc Adjusts the text color used for cooldowns.
 * @default 6
 *
 * @param Cooldown Icon
 * @parent ---Cooldown---
 * @type number
 * @min 0
 * @desc What icon to be used for cooldowns.
 * Use 0 for no icon.
 * @default 75
 *
 * @param Cooldown After Battle
 * @parent ---Cooldown---
 * @type number
 * @desc How are cooldowns handled after battle?
 * @default -10
 *
 * @param Cooldown Steps
 * @parent ---Cooldown---
 * @type number
 * @min 0
 * @desc Outside of battle, this is how many steps on the map the
 * player must walk to drop each cooldown by 1.
 * @default 5
 *
 * @param Cooldown Bypass
 * @parent ---Cooldown---
 * @desc This is a list of skills that cannot be on cooldown so that
 * way, skills like Attack, Guard.
 * @default 1 2 3 4 5 6 7
 *
 * @param Cooldown Bypass List
 * @parent ---Cooldown---
 * @type skill[]
 * @desc This is a list of skills that cannot be on cooldown so that
 * way, skills like Attack, Guard. Requires RPG Maker MV 1.5.0+
 * @default []
 *
 * @param ---Warmup---
 * @default
 *
 * @param Warmup Format
 * @parent ---Warmup---
 * @desc This is the text format used for warmups.
 * %1 - Turns Remaining
 * @default %1WU
 *
 * @param Warmup Font Size
 * @parent ---Warmup---
 * @type number
 * @min 1
 * @desc This is the font size used for warmups.
 * Default: 28
 * @default 20
 *
 * @param Warmup Text Color
 * @parent ---Warmup---
 * @type number
 * @min 0
 * @max 31
 * @desc Adjusts the text color used for warmups.
 * @default 4
 *
 * @param Warmup Icon
 * @parent ---Warmup---
 * @type number
 * @min 0
 * @desc What icon to be used for warmups.
 * Use 0 for no icon.
 * @default 75
 *
 * @param ---Battle Core---
 * @default
 *
 * @param Time Based
 * @parent ---Battle Core---
 * @type boolean
 * @on Time-Based
 * @off Turn-Based
 * @desc If a battle system is Tick-based, use time instead
 * of turns for cooldowns? NO - false   YES - true
 * @default false
 *
 * @param Turn Time
 * @parent ---Battle Core---
 * @type number
 * @min 1
 * @desc How many ticks must pass to equal 1 cooldown turn?
 * @default 100
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * This plugin requires YEP_SkillCore.
 * Make sure this plugin is located under YEP_SkillCore in the plugin list.
 *
 * This plugin allows you to give your skills cooldowns. Cooldowns are a limit
 * enforced on a skill to prevent them from being used constantly.
 *
 * ============================================================================
 * Cooldown Types
 * ============================================================================
 *
 * Cooldown (Standard)
 * The standard cooldown only occurs if the skill has a cooldown to pay. When
 * used, the skill cannot be used for x turns as indicated by the cooldown.
 * There are a number of things that contribute to cooldowns going down. The
 * first would be simply waiting. Each turn in battle causes a cooldown to
 * drop by 1 turn. Skills and the such can be used to speed up this process.
 * The second would be to finish battles. Finishing a battle will cause all
 * cooldowns to drop by a certain amount (can be defined in the parameters).
 * And the third would be walking on the field map. Every certain amount of
 * steps allow a skill's cooldown to decrease.
 *
 * Warmups
 * As far as most things go, Warmups do the same thing as Cooldowns: prevent
 * skills from being used until their timer is up. The difference, however, is
 * that warmups only occur once during battle: at the very start of it. If a
 * skill has a warmup timer, it will trigger the moment it goes into battle
 * and instantly disappear after battle. Warmups do not stack on top of any
 * existing cooldowns. If a cooldown is already occurring when a skill is in
 * the warmup phase, both the warmup and cooldown simultaneously update.
 *
 * Linked Cooldowns
 * A linked cooldown occurs when a skill that's used causes another skill in
 * the owner's skill library to have a cooldown. All other attributes of this
 * cooldown are the same as a standard cooldown's. This cooldown type will take
 * priority over Skill Type Cooldowns and Global Cooldowns if this value is
 * defined.
 *
 * Skill Type Cooldowns
 * When a Skill Type Cooldown occurs, all skills currently in the battler's
 * skill library with the matching Skill Type will be on cooldown. All other
 * attributes of this cooldown are the same as a standard cooldown's. This
 * cooldown type will take priority over Global Cooldowns if this value is
 * defined.
 *
 * When a cooldown is applied for a skill that already has a cooldown, the
 * cooldown will change to whatever is the largest value. This means if a
 * skill has 3 turns for a cooldown and a Skill Type Cooldown would set for
 * 1 turn, the 3 turns would remain. On the flip side, if the skill has 3 turns
 * and the Skill Type Cooldown would set for 5 turns, then the cooldown would
 * be changed to 5 turns instead.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * Use the following notetags to alter the cooldown properties of a skill.
 *
 * Skill Notetags:
 *   <Cooldown: x>
 *   Sets the cooldown for the skill to X turns. This cooldown only affects
 *   this skill alone. This value will take priority over Skill Type Cooldowns
 *   and Global Cooldowns.
 *
 *   <Warmup: x>
 *   Sets the warmup for the skill to X turns. When entering a new battle, the
 *   skill will be on a warmup phase and cannot be used until the warmup phase
 *   is over.
 *
 *   <After Battle Cooldown: +x>
 *   <After Battle Cooldown: -x>
 *   After a battle ends (victory, loss, or escape), change the cooldown for
 *   this skill by +x turns or -x turns.
 *
 *   <Cooldown Steps: x>
 *   Outside of battle, every x steps that the Player takes, this skill's
 *   cooldown will drop by 1.
 *
 *   <Skill x Cooldown: y>
 *   <Skill name Cooldown: y>
 *   When using this skill, after paying the skill cost, skill x will have a
 *   linked cooldown of y turns. This value will take priority over Skill Type
 *   Cooldowns and Global Cooldowns.
 *
 *   <SType x Cooldown: y>
 *   When using this skill, after paying the skill cost, all skills with the
 *   matching Skill Type x to have a cooldown of y. This value will take
 *   priority over Global Cooldowns.
 *
 *   <Global Cooldown: x>
 *   When using this skill, all skills within the battler's skill library area
 *   set to be on cooldown for x turns. This value has less priority than
 *   Individual Cooldowns and Skill Type Cooldowns.
 *
 *   <Bypass Cooldown>
 *   This causes the skill to bypass cooldowns, no matter what. This should be
 *   used for skills like Attack, Guard, Escape, etc. that should not have a
 *   cooldown assigned to them.
 *
 * Skill and Item Notetags:
 *   <Skill x Cooldown: +y>
 *   <Skill x Cooldown: -y>
 *   <Skill name Cooldown: +y>
 *   <Skill name Cooldown: -y>
 *   Targets hit by this skill will have skill x's cooldown adjusted by y.
 *   This does not apply to the user and applies only to the targets.
 *
 *   <SType x Cooldown: +y>
 *   <SType x Cooldown: -y>
 *   Targets hit by this skill will have all skills in their skill library with
 *   Skill Type x to have their cooldowns adjusted by y. This does not apply to
 *   the user and applies only to the targets.
 *
 *   <Global Cooldown: +x>
 *   <Global Cooldown: -x>
 *   Targets hit by this skill will have all skills in their skill library to
 *   have their cooldowns adjusted by y. This does not apply to the user and
 *   applies only to the targets.
 *
 * Actor, Class, Enemy, Weapon, Armor, and State Notetags:
 *
 *   <Skill x Cooldown Duration: y%>
 *   <Skill name Cooldown Duration: y%>
 *   Alters the cooldown duration of skill x to y% when the cooldown cost is
 *   applied. This effect only applies to skill x.
 *
 *   <SType x Cooldown Duration: y%>
 *   Alters the cooldown duration of skills with Skill Type x to y% when the
 *   cooldown cost is applied. This effect only applies to Skill Type x.
 *
 *   <Global Cooldown Duration: x%>
 *   Alters the cooldown duration of all skills to x% when the cooldown cost
 *   is applied.
 *
 *   <Skill x Cooldown Rate: y%>
 *   <Skill name Cooldown Rate: y%>
 *   Sets the cooldown rate for skill x to y% when the cooldown counter goes
 *   down. This effect only applies to skill x.
 *
 *   <SType x Cooldown Rate: y%>
 *   Sets the cooldown rate for Skill Type x skills to y% when the cooldown
 *   counter goes down. This effect only applies to Skill Type x skills.
 *
 *   <Global Cooldown Rate: x%>
 *   Sets the cooldown rate for all skills to x% when the cooldown counter
 *   goes down.
 *
 *   <Skill x Cooldown: +y>
 *   <Skill x Cooldown: -y>
 *   <Skill name Cooldown: +y>
 *   <Skill name Cooldown: -y>
 *   If the user performs skill x, it will have an increased or decreased
 *   cooldown value as long as the user is the actor, class, enemy, or has the
 *   weapon or armor equipped, or is affected by the state with this notetag.
 *   These flat cooldown modifications are applied after the rates and duration
 *   modifiers have been calculated.
 *
 *   <SType x Cooldown: +y>
 *   <SType x Cooldown: -y>
 *   If the user performs skill with skill type x, it will have an increased or
 *   decreased cooldown value as long as the user is the actor, class, enemy,
 *   or has the weapon or armor equipped, or is affected by the state with this
 *   notetag. These flat cooldown modifications are applied after the rates and
 *   duration modifiers have been calculated.
 *
 *   <Global Cooldown: +x>
 *   <Global Cooldown: -x>
 *   If the user performs any skill, it will have an increased or decreased
 *   cooldown value as long as the user is the actor, class, enemy, or has the
 *   weapon or armor equipped, or is affected by the state with this notetag.
 *   These flat cooldown modifications are applied after the rates and duration
 *   modifiers have been calculated.
 *
 *   <Skill x Warmup: +y>
 *   <Skill x Warmup: -y>
 *   <Skill name Warmup: +y>
 *   <Skill name Warmup: -y>
 *   At the start of battle, skill x will have an increased or decreased warmup
 *   value as long as the user is the actor, class, enemy, or has the weapon or
 *   armor equipped, or is affected by the state with this notetag. These flat
 *   warmup modifications are applied after the rates and duration modifiers
 *   have been calculated.
 *
 *   <SType x Warmup: +y>
 *   <SType x Warmup: -y>
 *   At the start of battle, all skills with skill type x it will have an
 *   increased or decreased warmup value as long as the user is the actor,
 *   class, enemy, or has the weapon or armor equipped, or is affected by the
 *   state with this notetag. These flat warmup modifications are applied after
 *   the rates and duration modifiers have been calculated.
 *
 *   <Global Warmup: +x>
 *   <Global Warmup: -x>
 *   At the start of battle, all skills will have an increased or decreased
 *   warmup value as long as the user is the actor, class, enemy, or has the
 *   weapon or armor equipped, or is affected by the state with this notetag.
 *   These flat warmup modifications are applied after the rates and duration
 *   modifiers have been calculated.
 *
 * ============================================================================
 * Lunatic Mode - Specialized Cooldowns
 * ============================================================================
 *
 * For skills, you can set cooldowns to have a special code determine its value
 * when the skill is used.
 *
 * Skill Notetag
 *   <Cooldown Eval>
 *   cooldown = x;
 *   cooldown += x;
 *   </Cooldown Eval>
 *   Insert these two tags into the skill's notebox to give it a unique way to
 *   determine the cooldown's value. The 'cooldown' variable determines the
 *   amount of turns for the cooldown.
 *
 *   <Warmup Eval>
 *   warmup = x;
 *   warmup += x;
 *   </Warmup Eval>
 *   Insert these two tags into the skill's notebox to give it a unique way to
 *   determine the warmup's value. The 'warmup' variable determines the amount
 *   of turns for the warmup.
 *
 * ============================================================================
 * Yanfly Engine Plugins - Battle Engine Extension - Action Sequence Commands
 * ============================================================================
 *
 * If you have YEP_BattleEngineCore.js installed with this plugin located
 * underneath it in the Plugin Manager, you can make use of these extra
 * cooldown related action sequences.
 *
 *=============================================================================
 * GLOBAL COOLDOWN: targets, +X
 * GLOBAL COOLDOWN: targets, -X
 * GLOBAL COOLDOWN: targets, X
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Sets the cooldown for all of the targets to be adjusted by X value. This
 * applies to every skill that doesn't bypass cooldowns.
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Usage Example: global cooldown: target, +5
 *                global cooldown: user, -3
 *                global cooldown: enemies, 10
 *=============================================================================
 *
 *=============================================================================
 * SKILL X COOLDOWN: targets, +Y
 * SKILL X COOLDOWN: targets, -Y
 * SKILL X COOLDOWN: targets, Y
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Causes skill X to be adjusted by Y value for the targets. This only applies
 * the specific skill x's cooldown.
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Usage Example: skill 10 cooldown: target, +5
 *                skill 12 cooldown: user, -3
 *                skill 15 cooldown: enemies, 10
 *=============================================================================
 *
 *=============================================================================
 * SKILL TYPE X COOLDOWN: targets, +Y
 * SKILL TYPE X COOLDOWN: targets, -Y
 * SKILL TYPE X COOLDOWN: targets, Y
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Causes skill type X skills to be adjusted by Y value for the targets. This
 * only applies the specific skill type x skill's cooldown.
 *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 * Usage Example: skill type 1 cooldown: target, +5
 *                skill type 2 cooldown: user, -3
 *                skill type 5 cooldown: enemies, 10
 *=============================================================================
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.12:
 * - Updated for RPG Maker MV version 1.5.0.
 * - Added Parameter: Cooldown Bypass List
 *
 * Version 1.11:
 * - Lunatic Mode fail safes added.
 *
 * Version 1.10:
 * - Compatibility update with Equip Battle Skills.
 * - Documentation update. Added help information for <warmup: x>.
 *
 * Version 1.09:
 * - Fixed a bug with the <Skill x Cooldown Rate: y%>,
 * <SType x Cooldown Rate: y%>, and <Global Cooldown Rate: x%> notetags not
 * working as intended.
 *
 * Version 1.08:
 * - Updated for RPG Maker MV version 1.1.0.
 *
 * Version 1.07:
 * - Named versions of these notetags have been added:
 * <Skill x Cooldown: y>, <Skill x Cooldown: +/-y>,
 * <Skill x Cooldown Duration: y%>, <Skill x Cooldown: +/-y>,
 * <Skill x Warmup: +/-y>
 *
 * Version 1.06a:
 * - Fixed a bug with cooldown duration modifiers not modifying by the correct
 * value indicated.
 * - Added a fail safe for when there are no targets.
 *
 * Version 1.05:
 * - Fixed a bug that prevented <Cooldown Eval> from running properly.
 *
 * Version 1.04:
 * - Fixed a bug that didn't alter cooldowns correctly.
 *
 * Version 1.03:
 * - Optimized for Battle Engine Core v1.08.
 *
 * Version 1.02a:
 * - Added return for drawSkillCost to assist others scripters when making
 * compatibility notes.
 *
 * Version 1.01:
 * - Cooldowns can now be applied to skills that aren't learned by the actor.
 *
 * Version 1.00:
 * - Finished plugin!
 */
//=============================================================================

if (Imported.YEP_SkillCore) {

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

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

Yanfly.Param.CDFmt = String(Yanfly.Parameters['Cooldown Format']);
Yanfly.Param.CDFontSize = Number(Yanfly.Parameters['Cooldown Font Size']);
Yanfly.Param.CDTextColor = Number(Yanfly.Parameters['Cooldown Text Color']);
Yanfly.Icon.Cooldown = Number(Yanfly.Parameters['Cooldown Icon']);
Yanfly.Param.CDAfterBattle = Number(Yanfly.Parameters['Cooldown After Battle']);
Yanfly.Param.CDSteps = Number(Yanfly.Parameters['Cooldown Steps']);

Yanfly.Param.WUFmt = String(Yanfly.Parameters['Warmup Format']);
Yanfly.Param.WUFontSize = Number(Yanfly.Parameters['Warmup Font Size']);
Yanfly.Param.WUTextColor = Number(Yanfly.Parameters['Warmup Text Color']);
Yanfly.Param.CDTimeBased = String(Yanfly.Parameters['Time Based']);
Yanfly.Param.CDTurnTime = Number(Yanfly.Parameters['Turn Time']);
Yanfly.Icon.Warmup = Number(Yanfly.Parameters['Warmup Icon']);

Yanfly.SetupParameters = function() {
  Yanfly.Param.CDBypass = String(Yanfly.Parameters['Cooldown Bypass']);
  Yanfly.Param.CDBypass = Yanfly.Param.CDBypass.split(' ');
  for (var i = 0; i < Yanfly.Param.CDBypass.length; ++i) {
    Yanfly.Param.CDBypass[i] = parseInt(Yanfly.Param.CDBypass[i]);
  }
  var data = JSON.parse(Yanfly.Parameters['Cooldown Bypass List'] || '[]');
  for (var i = 0; i < data.length; ++i) {
    var id = parseInt(data[i]);
    if (id <= 0) continue;
    if (Yanfly.Param.CDBypass.contains(id)) continue;
    Yanfly.Param.CDBypass.push(id);
  }
};
Yanfly.SetupParameters()

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

Yanfly.SCD.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.SCD.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_X_SkillCooldowns) {
    this.processSCDNotetagsS($dataSkills);
    this.processSCDNotetags1($dataSkills);
    this.processSCDNotetags2($dataSkills);
    this.processSCDNotetags2($dataItems);
    this.processSCDNotetags2($dataActors);
    this.processSCDNotetags2($dataClasses);
    this.processSCDNotetags2($dataEnemies);
    this.processSCDNotetags2($dataWeapons);
    this.processSCDNotetags2($dataArmors);
    this.processSCDNotetags2($dataStates);
    this.processSCDNotetags3($dataActors);
    this.processSCDNotetags3($dataClasses);
    this.processSCDNotetags3($dataEnemies);
    this.processSCDNotetags3($dataWeapons);
    this.processSCDNotetags3($dataArmors);
    this.processSCDNotetags3($dataStates);
    Yanfly._loaded_YEP_X_SkillCooldowns = true;
  }
  return true;
};

DataManager.processSCDNotetagsS = 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.processSCDNotetags1 = function(group) {
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.cooldown = {};
    obj.stypeCooldown = {}
    obj.globalCooldown = 0;
    obj.afterBattleCooldown = Yanfly.Param.CDAfterBattle;
    obj.cooldownSteps = Math.max(1, parseInt(Yanfly.Param.CDSteps));
    obj.warmup = 0;
    obj.bypassCooldown = Yanfly.Param.CDBypass.contains(obj.id);
    obj.cooldownEval = '';
    obj.warmupEval = '';
    var evalMode = 'none';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:COOLDOWN):[ ](\d+)>/i)) {
        obj.cooldown[obj.id] = parseInt(RegExp.$1);
      } else if (line.match(/<(?:AFTER BATTLE COOLDOWN):[ ]([\+\-]\d+)>/i)) {
        obj.afterBattleCooldown = parseInt(RegExp.$1);
      } else if (line.match(/<(?:COOLDOWN STEPS):[ ](\d+)>/i)) {
        obj.cooldownSteps = parseInt(RegExp.$1);
      } else if (line.match(/<(?:WARMUP):[ ](\d+)>/i)) {
        obj.warmup = parseInt(RegExp.$1);
      } else if (line.match(/<(?:SKILL)[ ](\d+)[ ](?:COOLDOWN):[ ](\d+)>/i)) {
        obj.cooldown[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<(?:SKILL)[ ](.*)[ ](?:COOLDOWN):[ ](\d+)>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.cooldown[id] = parseInt(RegExp.$2);
      } else if (line.match(/<(?:STYPE)[ ](\d+)[ ](?:COOLDOWN):[ ](\d+)>/i)) {
        obj.stypeCooldown[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<(?:GLOBAL COOLDOWN):[ ](\d+)>/i)) {
        obj.globalCooldown = parseInt(RegExp.$1);
      } else if (line.match(/<(?:BYPASS COOLDOWN)>/i)) {
        obj.bypassCooldown = true;
      } else if (line.match(/<(?:COOLDOWN EVAL)>/i)) {
        obj.cooldown[obj.id] = obj.cooldown[obj.id] || 0;
        evalMode = 'cooldown';
      } else if (line.match(/<\/(?:COOLDOWN EVAL)>/i)) {
        evalMode = 'none';
      } else if (line.match(/<(?:WARMUP EVAL)>/i)) {
        evalMode = 'warmup';
      } else if (line.match(/<\/(?:WARMUP EVAL)>/i)) {
        evalMode = 'none';
      } else if (evalMode === 'cooldown') {
        obj.cooldownEval = obj.cooldownEval + line + '\n';
      } else if (evalMode === 'warmup') {
        obj.warmupEval = obj.warmupEval + line + '\n';
      }
    }
  }
};

DataManager.processSCDNotetags2 = function(group) {
  var note1 = /<(?:SKILL)[ ](\d+)[ ](?:COOLDOWN):[ ]([\+\-]\d+)>/i;
  var note1a = /<(?:SKILL)[ ](.*)[ ](?:COOLDOWN):[ ]([\+\-]\d+)>/i;
  var note2 = /<(?:STYPE)[ ](\d+)[ ](?:COOLDOWN):[ ]([\+\-]\d+)>/i;
  var note3 = /<(?:GLOBAL COOLDOWN):[ ]([\+\-]\d+)>/i;
  var note4 = /<(?:SKILL)[ ](\d+)[ ](?:WARMUP):[ ]([\+\-]\d+)>/i;
  var note4a = /<(?:SKILL)[ ](.*)[ ](?:WARMUP):[ ]([\+\-]\d+)>/i;
  var note5 = /<(?:STYPE)[ ](\d+)[ ](?:WARMUP):[ ]([\+\-]\d+)>/i;
  var note6 = /<(?:GLOBAL WARMUP):[ ]([\+\-]\d+)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.cooldownChange = {};
    obj.stypeCooldownChange = {};
    obj.globalCooldownChange = 0;
    obj.warmupChange = {};
    obj.stypeWarmupChange = {};
    obj.globalWarmupChange = 0;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        obj.cooldownChange[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(note1a)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.cooldownChange[id] = parseInt(RegExp.$2);
      } else if (line.match(note2)) {
        obj.stypeCooldownChange[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(note3)) {
        obj.globalCooldownChange = parseInt(RegExp.$1);
      } else if (line.match(note4)) {
        obj.warmupChange[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(note4a)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.warmupChange[id] = parseInt(RegExp.$2);
      } else if (line.match(note5)) {
        obj.stypeWarmupChange[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(note6)) {
        obj.globalWarmupChange = parseInt(RegExp.$1);
      }
    }
  }
};

DataManager.processSCDNotetags3 = function(group) {
  var note1 = /<(?:SKILL)[ ](\d+)[ ](?:COOLDOWN DURATION):[ ](\d+)([%％])>/i;
  var note1a = /<(?:SKILL)[ ](.*)[ ](?:COOLDOWN DURATION):[ ](\d+)([%％])>/i;
  var note2 = /<(?:STYPE)[ ](\d+)[ ](?:COOLDOWN DURATION):[ ](\d+)([%％])>/i;
  var note3 = /<(?:GLOBAL COOLDOWN DURATION):[ ](\d+)([%％])>/i;
  var note4 = /<(?:SKILL)[ ](\d+)[ ](?:COOLDOWN RATE):[ ](\d+)([%％])>/i;
  var note4a = /<(?:SKILL)[ ](.*)[ ](?:COOLDOWN RATE):[ ](\d+)([%％])>/i;
  var note5 = /<(?:STYPE)[ ](\d+)[ ](?:COOLDOWN RATE):[ ](\d+)([%％])>/i;
  var note6 = /<(?:GLOBAL COOLDOWN RATE):[ ](\d+)([%％])>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.cooldownDuration = {};
    obj.stypeCooldownDuration = {};
    obj.globalCooldownDuration = 1.0;
    obj.cooldownRate = {};
    obj.stypeCooldownRate = {};
    obj.globalCooldownRate = 1.0;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        obj.cooldownDuration[parseInt(RegExp.$1)] =
          parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note1a)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.cooldownDuration[id] = parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note2)) {
        obj.stypeCooldownDuration[parseInt(RegExp.$1)] =
          parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note3)) {
        obj.globalCooldownDuration = parseFloat(RegExp.$1) * 0.01;
      } else if (line.match(note4)) {
        obj.cooldownRate[parseInt(RegExp.$1)] = parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note4a)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.SkillIdRef[name]) {
          var id = Yanfly.SkillIdRef[name];
        } else {
          continue;
        }
        obj.cooldownRate[id] = parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note5)) {
        obj.stypeCooldownRate[parseInt(RegExp.$1)] =
          parseFloat(RegExp.$2) * 0.01;
      } else if (line.match(note6)) {
        obj.globalCooldownRate = parseFloat(RegExp.$1 * 0.01);
      }
    }
  }
};

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

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

BattleManager.timeBasedCooldowns = function() {
  if (!$gameParty.inBattle()) return false;
  if (!Imported.YEP_BattleEngineCore) return false;
  if (this.isTurnBased()) return false;
  if (this._timeBasedCooldowns !== undefined) return this._timeBasedCooldowns;
  this._timeBasedCooldowns = eval(Yanfly.Param.CDTimeBased);
  return this._timeBasedCooldowns;
};

if (Imported.YEP_BattleEngineCore) {
Yanfly.SCD.BattleManager_processActionSequence =
  BattleManager.processActionSequence;
  BattleManager.processActionSequence = function(actionName, actionArgs) {
    // GLOBAL COOLDOWN
    if (actionName === 'GLOBAL COOLDOWN') {
      return this.actionGlobalCooldown(actionArgs);
    }
    // SKILL COOLDOWN
    if (actionName.match(/SKILL[ ](\d+)[ ]COOLDOWN/i)) {
      return this.actionSkillCooldown(parseInt(RegExp.$1), actionArgs);
    }
    // SKILL TYPE COOLDOWN
    if (actionName.match(/SKILL[ ]TYPE[ ](\d+)[ ]COOLDOWN/i)) {
      return this.actionSTypeCooldown(parseInt(RegExp.$1), actionArgs);
    }
    // STYPE COOLDOWN
    if (actionName.match(/STYPE[ ](\d+)[ ]COOLDOWN/i)) {
      return this.actionSTypeCooldown(parseInt(RegExp.$1), actionArgs);
    }
    return Yanfly.SCD.BattleManager_processActionSequence.call(this,
      actionName, actionArgs);
  };
};

BattleManager.actionGlobalCooldown = function(actionArgs) {
    var targets = this.makeActionTargets(actionArgs[0]);
    if (targets.length < 1) return true;
    var cmd = actionArgs[1];
    if (cmd.match(/([\+\-]\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        for (var i = 0; i < target.allSkills().length; ++i) {
          var skill = target.allSkills()[i];
          if (skill) {
            target.addCooldown(skill.id, value);
          }
        }
      }
    } else if (cmd.match(/(\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        for (var i = 0; i < target.allSkills().length; ++i) {
          var skill = target.allSkills()[i];
          if (skill) {
            target.setCooldown(skill.id, value);
          }
        }
      }
    } else {
      return true;
    }
    return true;
};

BattleManager.actionSkillCooldown = function(skillId, actionArgs) {
    var targets = this.makeActionTargets(actionArgs[0]);
    if (targets.length < 1) return true;
    var cmd = actionArgs[1];
    if (cmd.match(/([\+\-]\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        target.addCooldown(skillId, value);
      }
    } else if (cmd.match(/(\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        target.setCooldown(skillId, value);
      }
    } else {
      return true;
    }
    return true;
};

BattleManager.actionSTypeCooldown = function(stypeId, actionArgs) {
    var targets = this.makeActionTargets(actionArgs[0]);
    if (targets.length < 1) return true;
    var cmd = actionArgs[1];
    if (cmd.match(/([\+\-]\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        for (var i = 0; i < target.allSkills().length; ++i) {
          var skill = target.allSkills()[i];
          if (skill && skill.stypeId === stypeId) {
            target.addCooldown(skill.id, value);
          }
        }
      }
    } else if (cmd.match(/(\d+)/i)) {
      var value = parseInt(RegExp.$1);
      for (var t = 0; t < targets.length; ++t) {
        var target = targets[t];
        for (var i = 0; i < target.allSkills().length; ++i) {
          var skill = target.allSkills()[i];
          if (skill && skill.stypeId === stypeId) {
            target.setCooldown(skill.id, value);
          }
        }
      }
    } else {
      return true;
    }
    return true;
};

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

Yanfly.SCD.Game_BattlerBase_initMembers =
    Game_BattlerBase.prototype.initMembers;
Game_BattlerBase.prototype.initMembers = function() {
    Yanfly.SCD.Game_BattlerBase_initMembers.call(this);
    this.clearCooldowns();
    this.clearWarmups();
};

Game_BattlerBase.prototype.clearCooldowns = function() {
    this._cooldownTurns = {};
};

Game_BattlerBase.prototype.clearWarmups = function() {
    this._warmupTurns = {};
};

Game_BattlerBase.prototype.cooldown = function(skillId) {
    if (this._cooldownTurns === undefined) this.clearCooldowns();
    if (this._cooldownTurns[skillId] === undefined) {
      this._cooldownTurns[skillId] = 0;
    }
    return this._cooldownTurns[skillId];
};

Game_BattlerBase.prototype.warmup = function(skillId) {
    if (this._warmupTurns === undefined) this.clearWarmups();
    if (this._warmupTurns[skillId] === undefined) {
      this._warmupTurns[skillId] = 0;
    }
    return this._warmupTurns[skillId];
};

Game_BattlerBase.prototype.setCooldown = function(skillId, value) {
    if (!$dataSkills[skillId]) return;
    if ($dataSkills[skillId].bypassCooldown) return;
    if (this._cooldownTurns === undefined) this.clearCooldowns();
    this._cooldownTurns[skillId] = value;
};

Game_BattlerBase.prototype.addCooldown = function(skillId, value) {
    if (!$dataSkills[skillId]) return;
    if ($dataSkills[skillId].bypassCooldown) return;
    if (this._cooldownTurns === undefined) this.clearCooldowns();
    if (!this._cooldownTurns[skillId]) this._cooldownTurns[skillId] = 0;
    this._cooldownTurns[skillId] += value;
};

Game_BattlerBase.prototype.setWarmup = function(skillId, value) {
    if (!$dataSkills[skillId]) return;
    if ($dataSkills[skillId].bypassCooldown) return;
    if (this._warmupTurns === undefined) this.clearWarmups();
    this._warmupTurns[skillId] = value;
};

Game_BattlerBase.prototype.startWarmups = function() {
    if (this._warmupTurns === undefined) this.clearWarmups();
    for (var i = 0; i < this.allSkills().length; ++i) {
      var skill = this.allSkills()[i];
      if (!skill) continue;
      var warmup = skill.warmup;
      if (skill.warmupEval.length > 0) {
        var item = skill;
        var a = this;
        var user = this;
        var subject = this;
        var s = $gameSwitches._data;
        var v = $gameVariables._data;
        var code = skill.warmupEval;
        try {
          eval(code);
        } catch (e) {
          Yanfly.Util.displayError(e, code, 'CUSTOM WARMUP EVAL ERROR');
        }
      }
      warmup *= this.cooldownDuration(skill);
      warmup += this.getWarmupMods(skill);
      this.setWarmup(skill.id, warmup);
    }
};

Game_BattlerBase.prototype.updateCooldowns = function() {
    if (this._cooldownTurns === undefined) this.clearCooldowns();
    for (var skillId in this._cooldownTurns) {
      var skill = $dataSkills[skillId];
      if (!skill) continue;
      this._cooldownTurns[skillId] -= this.cooldownRate(skill);
    }
};

Game_BattlerBase.prototype.updateWarmups = function() {
    if (this._warmupTurns === undefined) this.clearWarmups();
    for (var skillId in this._warmupTurns) {
      var skill = $dataSkills[skillId];
      if (!skill) continue;
      this._warmupTurns[skillId] -= this.cooldownRate(skill);
    }
};

Game_BattlerBase.prototype.cooldownRateTick = function(skill) {
    this._cooldownTickRate = this._cooldownTickRate || {};
    if (!this._cooldownTickRate[skill.id]) {
      this._cooldownTickRate[skill.id] = this.cooldownRate(skill);
    }
    var rate = this._cooldownTickRate[skill.id];
    rate *= BattleManager.tickRate() / Yanfly.Param.CDTurnTime;
    return rate;
};

Game_BattlerBase.prototype.updateCooldownTicks = function() {
    if (this._cooldownTurns === undefined) this.clearCooldowns();
    for (var skillId in this._cooldownTurns) {
      var skill = $dataSkills[skillId];
      if (!skill) continue;
      if (this._cooldownTurns[skillId] <= 0) continue;
      this._cooldownTurns[skillId] -= this.cooldownRateTick(skill);
      this._cooldownTurns[skillId] = Math.max(0, this._cooldownTurns[skillId]);
    }
};

Game_BattlerBase.prototype.updateWarmupTicks = function() {
    if (this._warmupTurns === undefined) this.clearWarmups();
    for (var skillId in this._warmupTurns) {
      var skill = $dataSkills[skillId];
      if (!skill) continue;
      if (this._warmupTurns[skillId] <= 0) continue;
      this._warmupTurns[skillId] -= this.cooldownRateTick(skill);
      this._warmupTurns[skillId] = Math.max(0, this._warmupTurns[skillId]);
    }
};

Yanfly.SCD.Game_BattlerBase_meetsSkillConditions =
    Game_BattlerBase.prototype.meetsSkillConditions;
Game_BattlerBase.prototype.meetsSkillConditions = function(skill) {
    if (this.cooldown(skill.id) > 0) return false;
    if (this.warmup(skill.id) > 0) return false;
    return Yanfly.SCD.Game_BattlerBase_meetsSkillConditions.call(this, skill);
};

Yanfly.SCD.Game_BattlerBase_paySkillCost =
    Game_BattlerBase.prototype.paySkillCost;
Game_BattlerBase.prototype.paySkillCost = function(skill) {
    Yanfly.SCD.Game_BattlerBase_paySkillCost.call(this, skill);
    this.payGlobalCooldown(skill);
    this.payStypeCooldownCost(skill);
    this.payCooldownCost(skill);
    this.applyCooldownMods(skill);
};

Game_BattlerBase.prototype.payGlobalCooldown = function(mainSkill) {
    for (var i = 0; i < this.allSkills().length; ++i) {
      var skill = this.allSkills()[i];
      if (!skill) continue;
      var value = mainSkill.globalCooldown;
      value *= this.cooldownDuration(mainSkill);
      value = Math.max(value, this.cooldown(skill.id));
      this.setCooldown(skill.id, value);
    }
};

Game_BattlerBase.prototype.payStypeCooldownCost = function(mainSkill) {
    for (var stypeId in mainSkill.stypeCooldown) {
      stypeId = parseInt(stypeId);
      for (var i = 0; i < this.allSkills().length; ++i) {
        var skill = this.allSkills()[i];
        if (!skill) continue;
        if (skill.stypeId !== stypeId) continue;
        var value = mainSkill.stypeCooldown[stypeId];
        value *= this.cooldownDuration(mainSkill);
        value = Math.max(value, this.cooldown(skill.id));
        this.setCooldown(skill.id, value);
      }
    }
};

Game_BattlerBase.prototype.payCooldownCost = function(skill) {
    for (var skillId in skill.cooldown) {
      skillId = parseInt(skillId);
      if (!$dataSkills[skillId]) continue;
      var cooldown = skill.cooldown[skillId];
      if (skill.id === skillId) {
        if (skill.cooldownEval.length > 0) {
          var item = skill;
          var a = this;
          var user = this;
          var subject = this;
          var s = $gameSwitches._data;
          var v = $gameVariables._data;
          var code = skill.cooldownEval;
          try {
            eval(code);
          } catch (e) {
            Yanfly.Util.displayError(e, code, 'CUSTOM COOLDOWN EVAL ERROR');
          }
        }
      }
      cooldown *= this.cooldownDuration(skill);
      cooldown = Math.max(cooldown, this.cooldown(skillId));
      this.setCooldown(skillId, cooldown);
    }
};

Game_BattlerBase.prototype.endBattleCooldowns = function() {
    this.resetCooldownTickRates();
    for (var skillId in this._cooldownTurns) {
      this._cooldownTurns[skillId] += $dataSkills[skillId].afterBattleCooldown;
    }
};

Game_BattlerBase.prototype.resetCooldownTickRates = function() {
    this._cooldownTickRate = {};
};

Game_BattlerBase.prototype.updateCooldownSteps = function() {
    for (var skillId in this._cooldownTurns) {
      var skill = $dataSkills[skillId];
      if (skill) {
        if ($gameParty.steps() % skill.cooldownSteps === 0) {
          this._cooldownTurns[skillId] -= this.cooldownRate(skill);
        }
      }
    }
};

Game_BattlerBase.prototype.applyCooldownEffect = function(skill) {
    this.applyGlobalCooldownChange(skill);
    this.applyStypeCooldownChange(skill);
    this.applyCooldownChange(skill);
};

Game_BattlerBase.prototype.applyCooldownChange = function(skill) {
    for (var skillId in skill.cooldownChange) {
      skillId = parseInt(skillId);
      if (!$dataSkills[skillId]) continue;
      if (!skill.cooldownChange[skillId]) continue;
      var value = skill.cooldownChange[skillId];
      this.addCooldown(skillId, value);
    }
};

Game_BattlerBase.prototype.applyStypeCooldownChange = function(mainSkill) {
    for (var stypeId in mainSkill.stypeCooldownChange) {
      stypeId = parseInt(stypeId);
      for (var i = 0; i < this.allSkills().length; ++i) {
        var skill = this.allSkills()[i];
        if (!skill) continue;
        if (skill.stypeId !== stypeId) continue;
        if (!mainSkill.stypeCooldownChange[stypeId]) continue;
        var value = mainSkill.stypeCooldownChange[stypeId];
        this.addCooldown(skill.id, value);
      }
    }
};

Game_BattlerBase.prototype.applyGlobalCooldownChange = function(mainSkill) {
    for (var i = 0; i < this.allSkills().length; ++i) {
      var skill = this.allSkills()[i];
      if (!skill) continue;
      var value = mainSkill.globalCooldownChange;
      this.addCooldown(skill.id, value);
    }
};

Game_BattlerBase.prototype.getWarmupMods = function(skill) {
    var value = 0;
    value += this.flatWarmupChange(skill);
    return value;
};

Game_BattlerBase.prototype.applyCooldownMods = function(skill) {
    var value = this.cooldown(skill.id);
    value += this.flatCooldownChange(skill);
    this.setCooldown(skill.id, Math.max(0, value));
};

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

Game_Battler.prototype.onBattleStartCooldowns = function() {
    this.resetCooldownTickRates();
    this.startWarmups();
};

Game_Battler.prototype.cooldownDuration = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = 1.0;
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.cooldownDuration[skillId] !== undefined) {
        value *= state.cooldownDuration[skillId];
      }
      if (state.stypeCooldownDuration[stypeId] !== undefined) {
        value *= state.stypeCooldownDuration[stypeId];
      }
      value *= state.globalCooldownDuration;
    }
    return value;
};

Game_Battler.prototype.cooldownRate = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = 1;
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.cooldownRate[skillId] !== undefined) {
        value *= state.cooldownRate[skillId];
      }
      if (state.stypeCooldownRate[stypeId] !== undefined) {
        value *= state.stypeCooldownRate[stypeId];
      }
      value *= state.globalCooldownRate;
    }
    return value;
};

Game_Battler.prototype.flatCooldownChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = 0;
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.cooldownChange[skillId] !== undefined) {
        value += state.cooldownChange[skillId];
      }
      if (state.stypeCooldownChange[stypeId] !== undefined) {
        value += state.stypeCooldownChange[stypeId];
      }
      value += state.globalCooldownChange;
    }
    return value;
};

Game_Battler.prototype.flatWarmupChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = 0;
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.warmupChange[skillId] !== undefined) {
        value += state.warmupChange[skillId];
      }
      if (state.stypeWarmupChange[stypeId] !== undefined) {
        value += state.stypeWarmupChange[stypeId];
      }
      value += state.globalWarmupChange;
    }
    return value;
};

Yanfly.SCD.Game_Battler_refresh = Game_Battler.prototype.refresh;
Game_Battler.prototype.refresh = function() {
    Yanfly.SCD.Game_Battler_refresh.call(this);
    this.resetCooldownTickRates();
};

if (Imported.YEP_BattleEngineCore) {

  Yanfly.SCD.Game_Battler_onTurnStart = Game_Battler.prototype.onTurnStart;
  Game_Battler.prototype.onTurnStart = function() {
    Yanfly.SCD.Game_Battler_onTurnStart.call(this);
    if (BattleManager.isTickBased() && !BattleManager.timeBasedCooldowns()) {
      this.updateCooldowns();
      this.updateWarmups();
    }
  };

  Yanfly.SCD.Game_Battler_updateTick = Game_Battler.prototype.updateTick;
  Game_Battler.prototype.updateTick = function() {
    Yanfly.SCD.Game_Battler_updateTick.call(this);
    if (BattleManager.isTickBased() && BattleManager.timeBasedCooldowns()) {
      this.updateCooldownTicks();
      this.updateWarmupTicks();
    };
  };

}; // Imported.YEP_BattleEngineCore

Game_Battler.prototype.allSkills = function() {
  var prevCase = $gameTemp._disableBattleSkills;
  $gameTemp._disableBattleSkills = true;
  var skills = this.skills();
  $gameTemp._disableBattleSkills = prevCase;
  return skills;
};

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

Game_Actor.prototype.cooldownDuration = function(skill) {
    var value = Game_Battler.prototype.cooldownDuration.call(this, skill);
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    if (this.actor().cooldownDuration[skillId] !== undefined) {
      value *= this.actor().cooldownDuration[skillId];
    }
    if (this.currentClass().cooldownDuration[skillId] !== undefined) {
      value *= this.currentClass().cooldownDuration[skillId];
    }
    if (this.actor().stypeCooldownDuration[stypeId] !== undefined) {
      value *= this.actor().stypeCooldownDuration[stypeId];
    }
    if (this.currentClass().stypeCooldownDuration[stypeId] !== undefined) {
      value *= this.currentClass().stypeCooldownDuration[stypeId];
    }
    value *= this.actor().globalCooldownDuration;
    value *= this.currentClass().globalCooldownDuration;
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.cooldownDuration !== undefined) {
        if (equip.cooldownDuration[skillId] !== undefined) {
          value *= equip.cooldownDuration[skillId];
        }
      }
      if (equip.stypeCooldownDuration !== undefined) {
        if (equip.stypeCooldownDuration[stypeId] !== undefined) {
          value *= equip.stypeCooldownDuration[stypeId];
        }
      }
      if (equip.globalCooldownDuration !== undefined) {
        value *= equip.globalCooldownDuration;
      }
    }
    return value;
};

Game_Actor.prototype.cooldownRate = function(skill) {
    var value = Game_Battler.prototype.cooldownRate.call(this, skill);
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    if (this.actor().cooldownRate[skillId] !== undefined) {
      value *= this.actor().cooldownRate[skillId];
    }
    if (this.currentClass().cooldownRate[skillId] !== undefined) {
      value *= this.currentClass().cooldownRate[skillId];
    }
    if (this.actor().stypeCooldownRate[stypeId] !== undefined) {
      value *= this.actor().stypeCooldownRate[stypeId];
    }
    if (this.currentClass().stypeCooldownRate[stypeId] !== undefined) {
      value *= this.currentClass().stypeCooldownRate[stypeId];
    }
    value *= this.actor().globalCooldownRate;
    value *= this.currentClass().globalCooldownRate;
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.cooldownRate !== undefined) {
        if (equip.cooldownRate[skillId] !== undefined) {
          value *= equip.cooldownRate[skillId];
        }
      }
      if (equip.stypeCooldownRate !== undefined) {
        if (equip.stypeCooldownRate[stypeId] !== undefined) {
          value *= equip.stypeCooldownRate[stypeId];
        }
      }
      if (equip.globalCooldownRate !== undefined) {
        value *= equip.globalCooldownRate;
      }
    }
    return value;
};

Game_Actor.prototype.flatCooldownChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = Game_Battler.prototype.flatCooldownChange.call(this, skill);
    if (this.actor().cooldownChange[skillId] !== undefined) {
      value += this.actor().cooldownChange[skillId];
    }
    if (this.currentClass().cooldownChange[skillId] !== undefined) {
      value += this.currentClass().cooldownChange[skillId];
    }
    if (this.actor().stypeCooldownChange[stypeId] !== undefined) {
      value += this.actor().stypeCooldownChange[stypeId];
    }
    if (this.currentClass().stypeCooldownChange[stypeId] !== undefined) {
      value += this.currentClass().stypeCooldownChange[stypeId];
    }
    value += this.actor().globalCooldownChange;
    value += this.currentClass().globalCooldownChange;
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.cooldownChange === undefined) continue;
      if (equip.cooldownChange[skillId] !== undefined) {
        value += equip.cooldownChange[skillId];
      }
      if (equip.stypeCooldownChange[stypeId] !== undefined) {
        value += equip.stypeCooldownChange[stypeId];
      }
      value += equip.globalCooldownChange;
    }
    return value;
};

Game_Actor.prototype.flatWarmupChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = Game_Battler.prototype.flatWarmupChange.call(this, skill);
    if (this.actor().warmupChange[skillId] !== undefined) {
      value += this.actor().warmupChange[skillId];
    }
    if (this.currentClass().warmupChange[skillId] !== undefined) {
      value += this.currentClass().warmupChange[skillId];
    }
    if (this.actor().stypeWarmupChange[stypeId] !== undefined) {
      value += this.actor().stypeWarmupChange[stypeId];
    }
    if (this.currentClass().stypeWarmupChange[stypeId] !== undefined) {
      value += this.currentClass().stypeWarmupChange[stypeId];
    }
    value += this.actor().globalWarmupChange;
    value += this.currentClass().globalWarmupChange;
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.warmupChange === undefined) continue;
      if (equip.warmupChange[skillId] !== undefined) {
        value += equip.warmupChange[skillId];
      }
      if (equip.stypeWarmupChange[stypeId] !== undefined) {
        value += equip.stypeWarmupChange[stypeId];
      }
      value += equip.globalWarmupChange;
    }
    return value;
};

//=============================================================================
// 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.cooldownDuration = function(skill) {
    var value = Game_Battler.prototype.cooldownDuration.call(this, skill);
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    if (this.enemy().cooldownDuration[skillId] !== undefined) {
      value *= this.enemy().cooldownDuration[skillId];
    }
    if (this.enemy().stypeCooldownDuration[stypeId] !== undefined) {
      value *= this.enemy().stypeCooldownDuration[stypeId];
    }
    value *= this.enemy().globalCooldownDuration;
    return value;
};

Game_Enemy.prototype.cooldownRate = function(skill) {
    var value = Game_Battler.prototype.cooldownRate.call(this, skill);
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    if (this.enemy().cooldownRate[skillId] !== undefined) {
      value *= this.enemy().cooldownRate[skillId];
    }
    if (this.enemy().stypeCooldownRate[stypeId] !== undefined) {
      value *= this.enemy().stypeCooldownRate[stypeId];
    }
    value *= this.enemy().globalCooldownRate;
    return value;
};

Game_Enemy.prototype.flatCooldownChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = Game_Battler.prototype.flatCooldownChange.call(this, skill);
    if (this.enemy().cooldownChange[skillId] !== undefined) {
      value += this.enemy().cooldownChange[skillId];
    }
    if (this.enemy().stypeCooldownChange[stypeId] !== undefined) {
      value += this.enemy().stypeCooldownChange[stypeId];
    }
    value += this.enemy().globalCooldownChange;
    return value;
};

Game_Enemy.prototype.flatWarmupChange = function(skill) {
    var skillId = skill.id;
    var stypeId = skill.stypeId;
    var value = Game_Battler.prototype.flatWarmupChange.call(this, skill);
    if (this.enemy().warmupChange[skillId] !== undefined) {
      value += this.enemy().warmupChange[skillId];
    }
    if (this.enemy().stypeWarmupChange[stypeId] !== undefined) {
      value += this.enemy().stypeWarmupChange[stypeId];
    }
    value += this.enemy().globalWarmupChange;
    return value;
};

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

Yanfly.SCD.Game_Action_applyItemUserEffect =
    Game_Action.prototype.applyItemUserEffect;
Game_Action.prototype.applyItemUserEffect = function(target) {
    Yanfly.SCD.Game_Action_applyItemUserEffect.call(this, target);
    if (target) target.applyCooldownEffect(this.item());
};

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

Yanfly.SCD.Game_Unit_onBattleStart = Game_Unit.prototype.onBattleStart;
Game_Unit.prototype.onBattleStart = function() {
  Yanfly.SCD.Game_Unit_onBattleStart.call(this);
  this.onBattleStartCooldowns();
};

Game_Unit.prototype.onBattleStartCooldowns = function() {
  var members = this.cooldownMembers();
  var length = members.length
  for (var i = 0; i < length; ++i) {
    var member = members[i];
    if (member) member.onBattleStartCooldowns();
  }
};

Game_Unit.prototype.updateCooldowns = function() {
  if (BattleManager.timeBasedCooldowns()) return;
  var members = this.members();
  var length = members.length
  for (var i = 0; i < length; ++i) {
    var member = members[i];
    if (member) {
      member.updateCooldowns();
      member.updateWarmups();
    }
  }
};

Game_Unit.prototype.endBattleCooldowns = function() {
  var members = this.members();
  var length = members.length
  for (var i = 0; i < length; ++i) {
    var member = members[i];
    if (member) {
      member.endBattleCooldowns();
      member.clearWarmups();
    }
  }
};

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

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

Yanfly.SCD.Game_Party_increaseSteps = Game_Party.prototype.increaseSteps;
Game_Party.prototype.increaseSteps = function() {
    Yanfly.SCD.Game_Party_increaseSteps.call(this);
    this.updateCooldownSteps();
};

Game_Party.prototype.updateCooldownSteps = function() {
    return this.members().forEach(function(member) {
        return member.updateCooldownSteps();
    });
};

Game_Party.prototype.cooldownMembers = function() {
  return this.allMembers();
};

//=============================================================================
// Game_Troop
//=============================================================================

Yanfly.SCD.Game_Troop_increaseTurn = Game_Troop.prototype.increaseTurn;
Game_Troop.prototype.increaseTurn = function() {
    Yanfly.SCD.Game_Troop_increaseTurn.call(this);
    if (Imported.YEP_BattleEngineCore) {
      if (BattleManager.isTurnBased()) {
        this.updateCooldowns();
        $gameParty.updateCooldowns();
      }
    } else {
      this.updateCooldowns();
      $gameParty.updateCooldowns();
    }
};

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

Yanfly.SCD.Window_SkillList_drawCost = Window_SkillList.prototype.drawSkillCost;
Window_SkillList.prototype.drawSkillCost = function(skill, wx, wy, ww) {
    if (this._actor.warmup(skill.id) > 0) {
      return this.drawWarmup(skill, wx, wy, ww);
    } else if (this._actor.cooldown(skill.id) > 0) {
      return this.drawCooldown(skill, wx, wy, ww);
    } else {
      return Yanfly.SCD.Window_SkillList_drawCost.call(this, skill, wx, wy, ww);
    }
};

Window_SkillList.prototype.drawCooldown = function(skill, wx, wy, dw) {
    if (Yanfly.Icon.Cooldown > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.Cooldown, iw, wy + REM_Y_ICON_PADDING);
      dw -= Window_Base._iconWidth + 2;
    }
    this.changeTextColor(this.textColor(Yanfly.Param.CDTextColor));
    var fmt = TextManager.cooldownTurnsPlural;
    var value = this._actor.cooldown(skill.id);
	if(value === 1) TextManager.cooldownTurnsSingular;
    if (value % 1 !== 0) value = value.toFixed(2);
    if (value <= 0.009) value = 0.01;
    var text = fmt.format(Yanfly.Util.toGroup(value));
    this.contents.fontSize = Yanfly.Param.CDFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.drawWarmup = function(skill, wx, wy, dw) {
    if (Yanfly.Icon.Warmup > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.Warmup, iw, wy + REM_Y_ICON_PADDING);
      dw -= Window_Base._iconWidth + 2;
    }
    this.changeTextColor(this.textColor(Yanfly.Param.WUTextColor));
    var fmt = Yanfly.Param.WUFmt;
    var value = this._actor.warmup(skill.id);
    if (value % 1 !== 0) value = value.toFixed(2);
    if (value <= 0.009) value = 0.01;
    var text = fmt.format(Yanfly.Util.toGroup(value));
    this.contents.fontSize = Yanfly.Param.WUFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

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

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

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

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

repo_name: Rexhunk/karryn

license: unknown


code:
//=============================================================================
// Yanfly Engine Plugins - Skill Core Extension - Skill Cost Items
// YEP_X_SkillCostItems.js
//=============================================================================

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

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

//=============================================================================
 /*:
 * @plugindesc v1.05 (Requires YEP_SkillCore.js) Skills can now have an
 * item cost attached to them.
 * @author Yanfly Engine Plugins
 *
 * @param ---General---
 * @default
 *
 * @param Cost Style
 * @parent ---General---
 * @type select
 * @option None
 * @value 0
 * @option Amount Over Icon
 * @value 1
 * @option Amount Then Icon
 * @value 2
 * @desc How do you want the costs to appear?
 * 0 - None   1 - Amount Over Icon   2 - Amount Then Icon
 * @default 2
 *
 * @param Font Size
 * @parent ---General---
 * @type number
 * @min 1
 * @desc Font size used for item costs.
 * Default: 28
 * @default 20
 *
 * @param Amount Format
 * @parent ---General---
 * @desc How do you wish to display the amount cost?
 * %1 - Need    %2 - Owned
 * @default ×%1
 *
 * @param Amount Y Buffer
 * @parent ---General---
 * @type number
 * @desc The Y Buffer amount used to display the cost.
 * @default 4
 *
 * @param ---Gauges---
 * @default
 *
 * @param Gauge Color 1
 * @parent ---Gauges---
 * @type number
 * @min 0
 * @max 31
 * @desc The text color used for item gauges.
 * @default 13
 *
 * @param Gauge Color 2
 * @parent ---Gauges---
 * @type number
 * @min 0
 * @max 31
 * @desc The text color used for item gauges.
 * @default 5
 *
 * @param Display Name
 * @parent ---Gauges---
 * @type boolean
 * @on YES
 * @off NO
 * @desc Display the Item Name by default for the gauge?
 * NO - false     YES - true
 * @default true
 *
 * @param Text Color
 * @parent ---Gauges---
 * @type number
 * @min 0
 * @max 31
 * @desc Text color of the gauge name displayed.
 * Default: 16
 * @default 16
 *
 * @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 be able to set costs for skills using items. The
 * item costs will appear next to the other skill costs displaying the icons of
 * the items needed and the amount of the items to be used. Item costs using
 * this plugin can be altered by set and percentile amounts in addition to
 * being replaced altogether by a substitute item.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * To enable skills to utilize items as costs, use the following notetags:
 *
 * Skill Notetags:
 *   <Item x Cost: y>
 *   <Weapon x Cost: y>
 *   <Armor x Cost: y>
 *   This will set the cost of the item, weapon, or armor x to require y of it
 *   before it can be used. If you are using YEP_ItemCore, independent items
 *   cannot be used as item costs as the game will not distinguish which of the
 *   independent items is fit to be used. If you use multiple of these tags,
 *   the skill will require all the listed items to be available for usage.
 *
 *   <Item Cost: x Potion>
 *   <Item Cost: x Sword>
 *   <Item Cost: x Feather Cap>
 *   If you prefer to use the names of the items instead, you can use the above
 *   notetag. This will make the skill require x amount of the named item,
 *   weapon, or armor. If you have multiple items with the same name, this
 *   notetag will give priority to the highest ID value in the order of items,
 *   weapons, then armors. If you are using YEP_ItemCore, independent items
 *   cannot be used as item costs as the game will not distinguish which of the
 *   independent items is fit to be used. If you use multiple of these tags,
 *   the skill will require all the listed items to be available for usage.
 *
 * Class, Weapon, Armor, State Notetags:
 *   <Swap Gauge x: Item y>
 *   <Swap Gauge x: Weapon y>
 *   <Swap Gauge x: Armor y>
 *   Swaps out gauge x to display how much of item, weapon, or armor y the
 *   player/party has. Priority is given in the following order:
 *   Weapons, Armors, States, Class, Enemy
 *
 *   <Swap Gauge x: Item Potion>
 *   <Swap Gauge x: Item Sword>
 *   <Swap Gauge x: Item Feather Cap>
 *   If you prefer to use the names of the items instead, you can use the above
 *   notetag. This will swap out gauge x to display how much of the mentioned
 *   item, weapon, or armor the player/party has. If you have multiple items
 *   with the same name, this notetag will give priority to the highest ID
 *   value in the order of items, weapons, then armors. Priority for the
 *   displayed gauge will be given in the following order: Weapons, Armors,
 *   States, Class, Enemy.
 *
 * Actor, Class, Weapon, Armor, and State Notetags:
 *   <Item x Cost: +y>
 *   <Item x Cost: -y>
 *   <Weapon x Cost: +y>
 *   <Weapon x Cost: -y>
 *   <Armor x Cost: +y>
 *   <Armor x Cost: -y>
 *   Increases or decreases the cost of item, weapon, or armor x when required
 *   by a value of y. If the item, weapon, or armor isn't required, then this
 *   effect does not apply to the skill cost.
 *
 *   <Item Cost: +x Potion>
 *   <Item Cost: -x Sword>
 *   <Item Cost: +x Feather Cap>
 *   If you prefer to use the names of the items instead, you can use the above
 *   notetag format. This will increase or decrease the mentioned item by x
 *   amount as long as the item is required as a cost. If you have multiple
 *   items with the same name, this notetag will give priority to the highest
 *   ID value in the order of items, weapons, then armors.
 *
 *   <Item x Cost: y%>
 *   <Weapon x Cost: y%>
 *   <Armor x Cost: y%>
 *   Alters the cost of item, weapon, or armor x by y%. If the item, weapon, or
 *   armor isn't required, then this effect does not apply to the skill cost.
 *
 *   <Item Cost: x% Potion>
 *   <Item Cost: x% Sword>
 *   <Item Cost: x% Feather Cap>
 *   If you prefer to use the names of the items instead, you can use the above
 *   notetag format. This will adjust the cost rate of the mentioned item by x%
 *   as long as the item is required as a cost. If you have multiple items with
 *   the same name, this notetag will give priority to the highest ID value in
 *   the order of items, weapons, then armors.
 *
 *   <Replace Type x Cost: Type y>
 *   Replace 'type' with either 'item', 'weapon', or 'armor'. This lets you
 *   exchange the costs used for a particular item for another (item y). The
 *   replacement is given priority to states, weapons, armors, class, and then
 *   actors.
 *
 *   <Replace Potion Cost: Ether>
 *   <Replace Sword Cost: Dagger>
 *   <Replace Feather Cap Cost: Bandana>
 *   If you prefer to use the names of the items instead, you can use the above
 *   notetag format. This lets you exchange the costs used for a particular
 *   item for another. The replacement is given priority to states, weapons,
 *   armors, class, and then actors. If you have multiple items with the same
 *   name, this notetag will give priority to the highest ID value in the order
 *   of items, weapons, then armors.
 *
 * Item, Weapon, Armor Notetags:
 *   <Item Gauge Color 1: x>
 *   <Item Gauge Color 2: x>
 *   If this item is the item used as gauge display, you can have it produce a
 *   unique color using text color x.
 *
 *   <Item Gauge Text: x>
 *   If this item is the item used as gauge display, you can have it show a
 *   different text other than its name. Replace x with what you want to write.
 *
 *   <Item Gauge Text Color: x>
 *   If you wish to use a text color other than the one predefined in the
 *   plugin's parameters, use this notetag and replace x with the text color
 *   you wish to label the gauge with.
 *
 * ============================================================================
 * Lunatic Mode - Custom Item Costs
 * ============================================================================
 *
 * For those with a bit of JavaScript knowledge, you can create dynamic item
 * costs for your skills using the following notetags:
 *
 * Skill Notetags:
 *
 *   <Custom Type x Cost>
 *    cost = user.level;
 *   </Custom Type x Cost>
 *   Replace 'type' with either 'item', 'weapon', or 'armor' to change the type
 *   and x as the ID of that item type. The 'cost' variable determines how much
 *   of the required item type is needed as the cost.
 *
 *   <Custom Item Cost: name>
 *    cost = user.level;
 *   </Custom Item Cost: name>
 *   For those who prefer to use names instead, replace 'name' with the name of
 *   the item to be used as the cost. The 'cost' variable determines how much
 *   of the named item is needed as the cost. If you have multiple items in
 *   your database with the same name, priority will be given to the item with
 *   the highest ID in the order of items, weapons, and armors.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.05:
 * - 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.04:
 * - Updated for RPG Maker MV version 1.5.0.
 *
 * Version 1.03:
 * - Lunatic Mode fail safes added.
 *
 * Version 1.02:
 * - Updated for RPG Maker MV version 1.1.0.
 *
 * Version 1.01:
 * - Fixed a bug that would display the wrong cost amount for multiple items.
 * - Shifted item icon cost 2 pixels down to match the skill icon Y level.
 *
 * Version 1.00:
 * - Finished Plugin!
 */
//=============================================================================

if (Imported.YEP_SkillCore) {

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

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

Yanfly.Param.SCICostStyle = Number(Yanfly.Parameters['Cost Style']);
Yanfly.Param.SCIFontSize = Number(Yanfly.Parameters['Font Size']);
Yanfly.Param.SCIAmountFmt = String(Yanfly.Parameters['Amount Format']);
Yanfly.Param.SCIYBuffer = Number(Yanfly.Parameters['Amount Y Buffer']);

Yanfly.Param.SCIGauge1 = Number(Yanfly.Parameters['Gauge Color 1']);
Yanfly.Param.SCIGauge2 = Number(Yanfly.Parameters['Gauge Color 2']);
Yanfly.Param.SCIDisplayName = eval(String(Yanfly.Parameters['Display Name']));
Yanfly.Param.SCIDisplayColor = Number(Yanfly.Parameters['Text Color']);

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

Yanfly.SCI.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.SCI.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_X_SkillCostItems) {
    this.processSCINotetagsI($dataItems);
    this.processSCINotetagsW($dataWeapons);
    this.processSCINotetagsA($dataArmors);
    this.processSCINotetags1($dataSkills);
    this.processSCINotetags2($dataActors);
    this.processSCINotetags2($dataClasses);
    this.processSCINotetags2($dataEnemies);
    this.processSCINotetags2($dataWeapons);
    this.processSCINotetags2($dataArmors);
    this.processSCINotetags2($dataStates);
    this.processSCINotetags3($dataItems);
    this.processSCINotetags3($dataWeapons);
    this.processSCINotetags3($dataArmors);
    Yanfly._loaded_YEP_X_SkillCostItems = true;
  }
  return true;
};

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

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

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

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

    obj.useItemCost = [];
    obj.useWeaponCost = [];
    obj.useArmorCost = [];
    var evalMode = 'none';
    var evalLine = '';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<ITEM[ ](\d+)[ ]COST:[ ](\d+)>/i)) {
        var item = $dataItems[parseInt(RegExp.$1)];
        var cost = parseInt(RegExp.$2);
        this.processSCIObjItemCost(obj, item, cost, '');
      } else if (line.match(/<WEAPON[ ](\d+)[ ]COST:[ ](\d+)>/i)) {
        var item = $dataWeapons[parseInt(RegExp.$1)];
        var cost = parseInt(RegExp.$2);
        this.processSCIObjItemCost(obj, item, cost, '');
      } else if (line.match(/<ARMOR[ ](\d+)[ ]COST:[ ](\d+)>/i)) {
        var item = $dataArmors[parseInt(RegExp.$1)];
        var cost = parseInt(RegExp.$2);
        this.processSCIObjItemCost(obj, item, cost, '');
      } else if (line.match(/<ITEM COST:[ ](\d+)[ ](.*)>/i)) {
        var cost = parseInt(RegExp.$1);
        var name = String(RegExp.$2).toUpperCase();
        if (Yanfly.ItemIdRef[name]) {
          var id = Yanfly.ItemIdRef[name];
          var item = $dataItems[id];
        } else if (Yanfly.WeaponIdRef[name]) {
          var id = Yanfly.WeaponIdRef[name];
          var item = $dataWeapons[id];
        } else if (Yanfly.ArmorIdRef[name]) {
          var id = Yanfly.ArmorIdRef[name];
          var item = $dataArmors[id];
        } else {
          continue;
        }
        this.processSCIObjItemCost(obj, item, cost, '');
      } else if (line.match(/<CUSTOM ITEM[ ](\d+)[ ]COST>/i)) {
        evalMode = 'custom item cost';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM ITEM[ ](\d+)[ ]COST>/i)) {
        var item = $dataItems[parseInt(RegExp.$1)];
        this.processSCIObjItemCost(obj, item, 0, evalLine);
        evalMode = 'none';
        evalLine = '';
      } else if (line.match(/<CUSTOM WEAPON[ ](\d+)[ ]COST>/i)) {
        evalMode = 'custom item cost';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM WEAPON[ ](\d+)[ ]COST>/i)) {
        var item = $dataWeapons[parseInt(RegExp.$1)];
        this.processSCIObjItemCost(obj, item, 0, evalLine);
        evalMode = 'none';
        evalLine = '';
      } else if (line.match(/<CUSTOM ARMOR[ ](\d+)[ ]COST>/i)) {
        evalMode = 'custom item cost';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM ARMOR[ ](\d+)[ ]COST>/i)) {
        var item = $dataArmors[parseInt(RegExp.$1)];
        this.processSCIObjItemCost(obj, item, 0, evalLine);
        evalMode = 'none';
        evalLine = '';
      } else if (line.match(/<CUSTOM ITEM COST:[ ](.*)>/i)) {
        evalMode = 'custom item cost';
        evalLine = '';
      } else if (line.match(/<\/CUSTOM ITEM COST:[ ](.*)>/i)) {
        var name = String(RegExp.$1).toUpperCase();
        if (Yanfly.ItemIdRef[name]) {
          var id = Yanfly.ItemIdRef[name];
          var item = $dataItems[id];
        } else if (Yanfly.WeaponIdRef[name]) {
          var id = Yanfly.WeaponIdRef[name];
          var item = $dataWeapons[id];
        } else if (Yanfly.ArmorIdRef[name]) {
          var id = Yanfly.ArmorIdRef[name];
          var item = $dataArmors[id];
        } else {
          evalMode = 'none';
          evalLine = '';
          continue;
        }
        this.processSCIObjItemCost(obj, item, 0, evalLine);
        evalMode = 'none';
        evalLine = '';
      } else if (evalMode === 'custom item cost') {
        evalLine = evalLine + line + '\n';
      }
    }
  }
};

DataManager.processSCIObjItemCost = function(obj, item, cost, code) {
    if (!item) return;
    if (Imported.YEP_ItemCore && this.isIndependent(item)) return;
    var arr = [item.id, cost, code];
    if (this.isItem(item)) {
      obj.useItemCost.push(arr);
    } else if (this.isWeapon(item)) {
      obj.useWeaponCost.push(arr);
    } else if (this.isArmor(item)) {
      obj.useArmorCost.push(arr);
    }
};

DataManager.processSCINotetags2 = function(group) {
  var note1 = /<(?:SWAP GAUGE|gauge)[ ](\d+):[ ](.*)>/i;
  var note2 = /<(?:SWAP GAUGE ICON|swap gauge icon)[ ](\d+):[ ](.*)>/i;
  var noteR1 = /<REPLACE[ ](.*)[ ](\d+)[ ]COST:[ ](.*)[ ](\d+)>/i;
  var noteR2 = /<REPLACE[ ](.*)[ ]COST:[ ](.*)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.itemGaugeColor1 = Yanfly.Param.SCIGauge1
    obj.itemGaugeColor2 = Yanfly.Param.SCIGauge2
    obj.useItemCostSet = {};
    obj.useWeaponCostSet = {};
    obj.useArmorCostSet = {};
    obj.useItemCostRate = {};
    obj.useWeaponCostRate = {};
    obj.useArmorCostRate = {};
    obj.replaceItemCost = {};

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        var gauge = parseInt(RegExp.$1);
        var text = String(RegExp.$2).toUpperCase();
        if (text.match(/(?:ITEM|WEAPON|ARMOR)[ ](\d+)/i)) {
          if (gauge === 1) obj.gauge1 = text;
          if (gauge === 2) obj.gauge2 = text;
          if (gauge === 3) obj.gauge3 = text;
        } else if (text.match(/(?:ITEM|WEAPON|ARMOR)[ ](.*)/i)) {
          var name = String(RegExp.$1).toUpperCase();
          if (Yanfly.ItemIdRef[name]) {
            var id = Yanfly.ItemIdRef[name];
          } else if (Yanfly.WeaponIdRef[name]) {
            var id = Yanfly.WeaponIdRef[name];
          } else if (Yanfly.ArmorIdRef[name]) {
            var id = Yanfly.ArmorIdRef[name];
          }
          var text = 'ITEM ' + id;
          if (gauge === 1) obj.gauge1 = text;
          if (gauge === 2) obj.gauge2 = text;
          if (gauge === 3) obj.gauge3 = text;
        }
      } else if (line.match(note2)) {
        var gauge = parseInt(RegExp.$1);
        var icon = parseInt(RegExp.$2);
        if (gauge === 1) obj.gaugeIcon1 = icon;
        if (gauge === 2) obj.gaugeIcon2 = icon;
        if (gauge === 3) obj.gaugeIcon3 = icon;
      } else if (line.match(/<ITEM[ ](\d+)[ ]COST:[ ]([\+\-]\d+)>/i)) {
        obj.useItemCostSet[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<WEAPON[ ](\d+)[ ]COST:[ ]([\+\-]\d+)>/i)) {
        obj.useWeaponCostSet[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<ARMOR[ ](\d+)[ ]COST:[ ]([\+\-]\d+)>/i)) {
        obj.useArmorCostSet[parseInt(RegExp.$1)] = parseInt(RegExp.$2);
      } else if (line.match(/<ITEM[ ](\d+)[ ]COST:[ ](\d+)([%％])>/i)) {
        var value = parseFloat(RegExp.$2) * 0.01;
        obj.useItemCostRate[parseInt(RegExp.$1)] = value;
      } else if (line.match(/<WEAPON[ ](\d+)[ ]COST:[ ](\d+)([%％])>/i)) {
        var value = parseFloat(RegExp.$2) * 0.01;
        obj.useWeaponCostRate[parseInt(RegExp.$1)] = value;
      } else if (line.match(/<ARMOR[ ](\d+)[ ]COST:[ ](\d+)([%％])>/i)) {
        var value = parseFloat(RegExp.$2) * 0.01;
        obj.useArmorCostRate[parseInt(RegExp.$1)] = value;
      } else if (line.match(/<ITEM COST:[ ]([\+\-]\d+)[ ](.*)>/i)) {
        var value = parseInt(RegExp.$1);
        var name = String(RegExp.$2).toUpperCase();
        if (Yanfly.ItemIdRef[name]) {
          var id = Yanfly.ItemIdRef[name];
          obj.useItemCostSet[id] = value;
        } else if (Yanfly.WeaponIdRef[name]) {
          var id = Yanfly.WeaponIdRef[name];
          obj.useWeaponCostSet[id] = value;
        } else if (Yanfly.ArmorIdRef[name]) {
          var id = Yanfly.ArmorIdRef[name];
          obj.useArmorCostSet[id] = value;
        }
      } else if (line.match(/<ITEM COST:[ ](\d+)([%％])[ ](.*)>/i)) {
        var value = parseFloat(RegExp.$1) * 0.01;
        var name = String(RegExp.$3).toUpperCase();
        if (Yanfly.ItemIdRef[name]) {
          var id = Yanfly.ItemIdRef[name];
          obj.useItemCostRate[id] = value;
        } else if (Yanfly.WeaponIdRef[name]) {
          var id = Yanfly.WeaponIdRef[name];
          obj.useWeaponCostRate[id] = value;
        } else if (Yanfly.ArmorIdRef[name]) {
          var id = Yanfly.ArmorIdRef[name];
          obj.useArmorCostRate[id] = value;
        }
      } else if (line.match(noteR1)) {
        var type1 = String(RegExp.$1).toUpperCase();
        var id1 = parseInt(RegExp.$2);
        var type2 = String(RegExp.$3).toUpperCase();
        var id2 = parseInt(RegExp.$4);
        if (!['ITEM', 'WEAPON', 'ARMOR'].contains(type1)) continue;
        if (!['ITEM', 'WEAPON', 'ARMOR'].contains(type2)) continue;
        obj.replaceItemCost[type1 + ' ' + id1] = type2 + ' ' + id2;
      } else if (line.match(noteR2)) {
        var name1 = String(RegExp.$1).toUpperCase();
        var name2 = String(RegExp.$2).toUpperCase();
        if (Yanfly.ItemIdRef[name1]) {
          var id = Yanfly.ItemIdRef[name1];
          var type1 = 'ITEM ' + id;
        } else if (Yanfly.WeaponIdRef[name1]) {
          var id = Yanfly.WeaponIdRef[name1];
          var type1 = 'WEAPON ' + id;
        } else if (Yanfly.ArmorIdRef[name1]) {
          var id = Yanfly.ArmorIdRef[name1];
          var type1 = 'ARMOR ' + id;
        } else {
          continue;
        }
        if (Yanfly.ItemIdRef[name2]) {
          var id = Yanfly.ItemIdRef[name2];
          var type2 = 'ITEM ' + id;
        } else if (Yanfly.WeaponIdRef[name2]) {
          var id = Yanfly.WeaponIdRef[name2];
          var type2 = 'WEAPON ' + id;
        } else if (Yanfly.ArmorIdRef[name2]) {
          var id = Yanfly.ArmorIdRef[name2];
          var type2 = 'ARMOR ' + id;
        } else {
          continue;
        }
        obj.replaceItemCost[type1] = type2;
      }
    }
  }
};

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

    obj.itemGaugeColor1 = Yanfly.Param.SCIGauge1
    obj.itemGaugeColor2 = Yanfly.Param.SCIGauge2
    obj.itemGaugeText = Yanfly.Param.SCIDisplayName ? obj.name : '';
    obj.itemGaugeTextColor = Yanfly.Param.SCIDisplayColor;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:ITEM GAUGE COLOR 1):[ ](\d+)>/i)) {
        obj.itemGaugeColor1 = parseInt(RegExp.$1);
      } else if (line.match(/<(?:ITEM GAUGE COLOR 2):[ ](\d+)>/i)) {
        obj.itemGaugeColor2 = parseInt(RegExp.$1);
      } else if (line.match(/<(?:ITEM GAUGE TEXT):[ ](.*)>/i)) {
        obj.itemGaugeText = String(RegExp.$1);
      } else if (line.match(/<(?:ITEM GAUGE TEXT COLOR):[ ](\d+)>/i)) {
        obj.itemGaugeTextColor = parseInt(RegExp.$1);
      }
    }
  }
};

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

Yanfly.SCI.Game_BattlerBase_canPaySkillCost =
    Game_BattlerBase.prototype.canPaySkillCost;
Game_BattlerBase.prototype.canPaySkillCost = function(skill) {
    if (!this.canPaySkillItemCost(skill)) return;
    return Yanfly.SCI.Game_BattlerBase_canPaySkillCost.call(this, skill);
};

Game_BattlerBase.prototype.canPaySkillItemCost = function(skill) {
    return true;
};

Game_BattlerBase.prototype.skillItemCost = function(skill) {
    return [];
};

Game_BattlerBase.prototype.combineSkillItemCostEntries = function(array) {
    var objData = [];
    var amtData = [];
    for (var i = 0; i < array.length; ++i) {
      var obj = array[i][0];
      var amt = array[i][1];
      if (objData.contains(obj)) {
        var index = objData.indexOf(obj);
        amtData[index] += amt;
        amtData[index] = Math.floor(amtData[index]);
        amtData[index] = Math.max(0, amtData[index]);
      } else {
        objData.push(obj);
        amtData.push(amt);
      }
    }
    var data = [];
    for (var i = 0; i < objData.length; ++i) {
      data.push([objData[i], amtData[i]]);
    }
    return data;
};

Game_BattlerBase.prototype.extractSkillItemCost = function(array, type) {
    var data = [];
    var max = array.length;
    for (var i = 0; i < max; ++i) {
      var id = array[i][0];
      var cost = array[i][1];
      var code = array[i][2];
      if (type === 0) {
        var item = $dataItems[id];
      } else if (type === 1) {
        var item = $dataWeapons[id];
      } else if (type === 2) {
        var item = $dataArmors[id];
      } else {
        continue;
      }
      if (!item) continue;

      cost = this.applySkillItemCostEval(item, cost, code);
      cost = this.applySkillItemCostModifier(item, cost);
      item = this.applySkillItemReplace(item);
      data.push([item, cost]);
    }
    return data;
};

Game_BattlerBase.prototype.applySkillItemCostEval = function(item, cost, code) {
    if (code === '') return cost;
    var a = this;
    var user = this;
    var subject = this;
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'APPLY SKILL ITEM COST ERROR');
    }
    return cost;
};

Game_BattlerBase.prototype.applySkillItemCostModifier = function(item, cost) {
    cost *= this.getSkillItemCostRate(item);
    cost += this.getSkillItemCostSet(item);
    return Math.floor(Math.max(0, cost));
};

Game_BattlerBase.prototype.getSkillItemCostRate = function(item) {
    var rate = 1;
    var max = this.states().length;
    for (var i = 0; i < max; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      rate *= this.getSkillItemCostObjRate(item, state);
    }
    return rate;
};

Game_BattlerBase.prototype.getSkillItemCostObjRate = function(item, obj) {
    if (!item) return 1;
    if (!obj) return 1;
    if (DataManager.isItem(item) && obj.useItemCostRate) {
      return obj.useItemCostRate[item.id] || 1;
    } else if (DataManager.isWeapon(item) && obj.useWeaponCostRate) {
      return obj.useWeaponCostRate[item.id] || 1;
    } else if (DataManager.isArmor(item) && obj.useArmorCostRate) {
      return obj.useArmorCostRate[item.id] || 1;
    }
    return 1;
};

Game_BattlerBase.prototype.getSkillItemCostSet = function(item) {
    var bonus = 0;
    var max = this.states().length;
    for (var i = 0; i < max; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      bonus += this.getSkillItemCostObjSet(item, state);
    }
    return bonus;
};

Game_BattlerBase.prototype.getSkillItemCostObjSet = function(item, obj) {
    if (!item) return 0;
    if (!obj) return 0;
    if (DataManager.isItem(item) && obj.useItemCostSet) {
      return obj.useItemCostSet[item.id] || 0;
    } else if (DataManager.isWeapon(item) && obj.useWeaponCostSet) {
      return obj.useWeaponCostSet[item.id] || 0;
    } else if (DataManager.isArmor(item) && obj.useArmorCostSet) {
      return obj.useArmorCostSet[item.id] || 0;
    }
    return 0;
};

Yanfly.SCI.Game_BattlerBase_paySkillCost =
    Game_BattlerBase.prototype.paySkillCost;
Game_BattlerBase.prototype.paySkillCost = function(skill) {
    Yanfly.SCI.Game_BattlerBase_paySkillCost.call(this, skill);
    this.paySkillItemCost(skill);
};

Game_BattlerBase.prototype.paySkillItemCost = function(skill) {
    var array = this.skillItemCost(skill);
    var max = array.length;
    for (var i = 0; i < max; ++i) {
      var item = array[i][0];
      var cost = array[i][1];
      this.payIndividualSkillItemCost(item, cost);
    }
};

Game_BattlerBase.prototype.payIndividualSkillItemCost = function(item, cost) {
};

Game_BattlerBase.prototype.numItems = function(item) {
    return $gameParty.maxItems(item);
};

Game_BattlerBase.prototype.maxItems = function(item) {
    return $gameParty.maxItems(item);
};

Game_BattlerBase.prototype.applySkillItemReplace = function(item) {
    var type = '';
    if (DataManager.isItem(item)) type = 'ITEM ' + item.id;
    if (DataManager.isWeapon(item)) type = 'WEAPON ' + item.id;
    if (DataManager.isArmor(item)) type = 'ARMOR ' + item.id;
    var substitute = this.makeSkillItemReplace(type);
    return substitute || item;
};

Game_BattlerBase.prototype.makeSkillItemReplace = function(type) {
    var max = this.states().length;
    for (var i = 0; i < max; ++i) {
      var state = this.states()[i];
      if (state && this.hasSkillItemReplace(state, type)) {
        return this.getSkillItemReplace(state, type);
      }
    }
    return null;
};

Game_BattlerBase.prototype.hasSkillItemReplace = function(obj, type) {
    if (obj.replaceItemCost) {
      return obj.replaceItemCost[type];
    }
    return false;
};

Game_BattlerBase.prototype.getSkillItemReplace = function(obj, type) {
    if (obj.replaceItemCost) {
      var text = obj.replaceItemCost[type];
      if (text.match(/ITEM[ ](\d+)/i)) {
        return $dataItems[parseInt(RegExp.$1)];
      } else if (text.match(/WEAPON[ ](\d+)/i)) {
        return $dataWeapons[parseInt(RegExp.$1)];
      } else if (text.match(/ARMOR[ ](\d+)/i)) {
        return $dataArmors[parseInt(RegExp.$1)];
      }
    }
    return null;
};

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

Game_Actor.prototype.canPaySkillItemCost = function(skill) {
    var array = this.skillItemCost(skill);
    var max = array.length;
    for (var i = 0; i < max; ++i) {
      var item = array[i][0];
      var cost = array[i][1];
      if (this.numItems(item) < cost) return false;
    }
    return Game_BattlerBase.prototype.canPaySkillItemCost.call(this, skill);
};

Game_Actor.prototype.skillItemCost = function(skill) {
    var array = Game_BattlerBase.prototype.skillItemCost.call(this, skill);
    array = array.concat(this.extractSkillItemCost(skill.useItemCost, 0));
    array = array.concat(this.extractSkillItemCost(skill.useWeaponCost, 1));
    array = array.concat(this.extractSkillItemCost(skill.useArmorCost, 2));
    array = this.combineSkillItemCostEntries(array);
    return array;
};

Game_Actor.prototype.payIndividualSkillItemCost = function(item, cost) {
    $gameParty.loseItem(item, cost, false);
};

Game_Actor.prototype.numItems = function(item) {
    return $gameParty.numItems(item);
};

Game_Actor.prototype.maxItems = function(item) {
    return $gameParty.maxItems(item);
};

Game_Actor.prototype.getSkillItemCostRate = function(item) {
    var rate = Game_Battler.prototype.getSkillItemCostRate.call(this, item);
    rate *= this.getSkillItemCostObjRate(item, this.actor());
    rate *= this.getSkillItemCostObjRate(item, this.currentClass());
    var max = this.equips().length;
    for (var i = 0; i < max; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      rate *= this.getSkillItemCostObjRate(item, equip);
    }
    return rate;
};

Game_Actor.prototype.getSkillItemCostSet = function(item) {
    var bonus = Game_Battler.prototype.getSkillItemCostSet.call(this, item);
    bonus += this.getSkillItemCostObjSet(item, this.actor());
    bonus += this.getSkillItemCostObjSet(item, this.currentClass());
    var max = this.equips().length;
    for (var i = 0; i < max; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      bonus += this.getSkillItemCostObjSet(item, equip);
    }
    return bonus;
};

Game_Actor.prototype.makeSkillItemReplace = function(type) {
    var state = Game_Battler.prototype.makeSkillItemReplace.call(this, type);
    if (state) return state;
    var max = this.equips().length;
    for (var i = 0; i < max; ++i) {
      var equip = this.equips()[i];
      if (equip && this.hasSkillItemReplace(equip, type)) {
        return this.getSkillItemReplace(equip, type);
      }
    }
    if (this.hasSkillItemReplace(this.currentClass(), type)) {
      return this.getSkillItemReplace(this.currentClass(), type);
    }
    if (this.hasSkillItemReplace(this.actor(), type)) {
      return this.getSkillItemReplace(this.actor(), type);
    }
    return null;
};

//=============================================================================
// Window_Base
//=============================================================================

Yanfly.SCI.Window_Base_drawActorHp = Window_Base.prototype.drawActorHp;
Window_Base.prototype.drawActorHp = function(actor, x, y, width) {
    if (actor.gauge1().match(/(?:ITEM|WEAPON|ARMOR)[ ](\d+)/i)) {
      this.drawItemGaugeSwap(actor, 1, x, y, width);
    } else {
      Yanfly.SCI.Window_Base_drawActorHp.call(this, actor, x, y, width);
    }
};

Yanfly.SCI.Window_Base_drawActorMp = Window_Base.prototype.drawActorMp;
Window_Base.prototype.drawActorMp = function(actor, x, y, width) {
    if (actor.gauge2().match(/(?:ITEM|WEAPON|ARMOR)[ ](\d+)/i)) {
      this.drawItemGaugeSwap(actor, 2, x, y, width);
    } else {
      Yanfly.SCI.Window_Base_drawActorMp.call(this, actor, x, y, width);
    }
};

Yanfly.SCI.Window_Base_drawActorTp = Window_Base.prototype.drawActorTp;
Window_Base.prototype.drawActorTp = function(actor, x, y, width) {
    if (actor.gauge3().match(/(?:ITEM|WEAPON|ARMOR)[ ](\d+)/i)) {
      this.drawItemGaugeSwap(actor, 3, x, y, width);
    } else {
      Yanfly.SCI.Window_Base_drawActorTp.call(this, actor, x, y, width);
    }
};

Window_Base.prototype.drawItemGaugeSwap = function(actor, id, wx, wy, ww) {
    ww = ww || 186;
    if (id === 1) text = actor.gauge1();
    if (id === 2) text = actor.gauge2();
    if (id === 3) text = actor.gauge3();
    if (text.match(/ITEM[ ](\d+)/i)) {
      var item = $dataItems[parseInt(RegExp.$1)];
    } else if (text.match(/WEAPON[ ](\d+)/i)) {
      var item = $dataWeapons[parseInt(RegExp.$1)];
    } else if (text.match(/ARMOR[ ](\d+)/i)) {
      var item = $dataArmors[parseInt(RegExp.$1)];
    }
    var icon = item.iconIndex;
    if (id === 1 && actor.gaugeIcon1() > 0) icon = actor.gaugeIcon1();
    if (id === 2 && actor.gaugeIcon2() > 0) icon = actor.gaugeIcon2();
    if (id === 3 && actor.gaugeIcon3() > 0) icon = actor.gaugeIcon3();
    this.drawItemGaugeMain(actor, item, wx, wy, ww);
    var iw = this.drawItemGaugeIcon(icon, wx, wy);
    wx += iw;
    ww -= iw;
    var size = this.contents.fontSize;
    this.drawItemGaugeName(actor, item, wx, wy, ww);
    this.contents.fontSize = size;
    var cur = actor.numItems(item);
    var max = actor.maxItems(item);
    var color = this.normalColor();
    this.drawCurrentAndMax(cur, max, wx, wy, ww, color, color);
};

Window_Base.prototype.drawItemGaugeName = function(actor, item, wx, wy, ww) {
    ww -= this.textWidth(Yanfly.Util.toGroup(actor.numItems(item)));
    ww -= this.textWidth(Yanfly.Util.toGroup(actor.maxItems(item)));
    ww -= this.textWidth('/');
    var text = item.itemGaugeText;
    for (;;) {
      var nameWidth = this.textWidth(text);
      if (nameWidth > ww) {
        this.contents.fontSize -= 1;
      } else {
        break;
      }
      if (this.contents.fontSize < 1) break;
    }
    this.changeTextColor(this.textColor(item.itemGaugeTextColor));
    this.drawText(text, wx, wy, ww);
};

Window_Base.prototype.drawItemGaugeMain = function(actor, item, wx, wy, ww) {
    var color1 = this.textColor(item.itemGaugeColor1);
    var color2 = this.textColor(item.itemGaugeColor2);
    var rate = actor.numItems(item) / actor.maxItems(item);
    this.drawGauge(wx, wy, ww, rate, color1, color2);
};

Window_Base.prototype.drawItemGaugeIcon = function(icon, wx, wy) {
    this.drawIcon(icon, wx, wy);
    return Window_Base._iconWidth + 4;
};

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

Yanfly.SCI.Window_SkillList_drawTpCost = Window_SkillList.prototype.drawTpCost;
Window_SkillList.prototype.drawTpCost = function(skill, wx, wy, dw) {
    dw = this.drawSkillItemCost(skill, wx, wy, dw);
    return Yanfly.SCI.Window_SkillList_drawTpCost.call(this, skill, wx, wy, dw);
};

Window_SkillList.prototype.drawSkillItemCost = function(skill, wx, wy, dw) {
    if (Yanfly.Param.SCICostStyle === 0) return dw;
    var array = this._actor.skillItemCost(skill);
    var max = array.length;
    if (max <= 0) return dw;
    this.contents.fontSize = Yanfly.Param.SCIFontSize;
    dw -= 2;
    for (var i = 0; i < max; ++i) {
      var arr = array[max - i - 1];
      var item = arr[0];
      var cost = arr[1];
      dw = this.drawSoloItemCost(item, cost, wx, wy, dw);
    }
    var returnWidth = dw - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.drawSoloItemCost = function(item, cost, wx, wy, dw) {
    var x = wx + dw - Window_Base._iconWidth;
    this.drawIcon(item.iconIndex, x, wy + 2);
    var amt1 = Yanfly.Util.toGroup(cost);
    var amt2 = Yanfly.Util.toGroup(this._actor.numItems(item));
    var fmt = Yanfly.Param.SCIAmountFmt;
    var text = fmt.format(amt1, amt2);
    if (Yanfly.Param.SCICostStyle === 1) {
      var iconWidth = Window_Base._iconWidth + 4;
      this.drawText(text, wx, wy + Yanfly.Param.SCIYBuffer, dw, 'right');
      dw -= Math.max(iconWidth, this.textWidth(text));
    } else if (Yanfly.Param.SCICostStyle === 2) {
      var iconWidth = Window_Base._iconWidth;
      dw -= iconWidth;
      this.drawText(text, wx, wy + Yanfly.Param.SCIYBuffer, dw, 'right');
      dw -= this.textWidth(text);
    }
    return dw;
};

//=============================================================================
// 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
//=============================================================================
};