code:
//=============================================================================
// Yanfly Engine Plugins - Shop Menu Core
// YEP_ShopMenuCore.js
//=============================================================================

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

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

//=============================================================================
 /*:
 * @plugindesc v1.05 Revamps the shop menu appearance and provides the
 * framework for many new shop options.
 * @author Yanfly Engine Plugins
 *
 * @param ---General---
 * @default
 *
 * @param Command Order
 * @parent ---General---
 * @desc This is the order in which the command menu will appear. Use
 * a space to separate the individual commands.
 * @default Buy Sell Equip Custom Cancel
 *
 * @param Shop List Width
 * @parent ---General---
 * @desc This allows you to adjust the formula to determine the window width
 * for the main shop list windows.
 * @default Graphics.boxWidth / 2 + Graphics.boxWidth / 10
 *
 * @param Command Alignment
 * @parent ---General---
 * @type combo
 * @option left
 * @option center
 * @option right
 * @desc Text alignment used for the command windows.
 * left     center     right
 * @default center
 *
 * @param ---Status Window---
 * @default
 *
 * @param Default Mode
 * @parent ---Status Window---
 * @type combo
 * @option default
 * @option actor
 * @desc Display a comparison for all actors per stat or per actor?
 * default - All Actors     actor - Individual Actors
 * @default actor
 *
 * @param Stat Switching
 * @parent ---Status Window---
 * @type boolean
 * @on Enable
 * @off Disable
 * @desc Enable stat comparison switching by pressing left/right?
 * NO - false     YES - true
 * @default true
 *
 * @param Cannot Equip
 * @parent ---Status Window---
 * @desc If an actor cannot equip an item, this text is shown.
 * @default Can't Equip
 *
 * @param Stat Font Size
 * @parent ---Status Window---
 * @desc The font size used for stat comparisons.
 * Default: 28
 * @default 20
 *
 * @param Cannot Equip Font Size
 * @parent ---Status Window---
 * @type number
 * @min 1
 * @desc The font size used for cannot equip text.
 * Default: 28
 * @default 20
 *
 * @param ---Info Window---
 * @default
 *
 * @param Show Icon
 * @parent ---Info Window---
 * @type boolean
 * @on Show
 * @off Hide
 * @desc Show the icon in the info window?
 * NO - false     YES - true
 * @default true
 *
 * @param Icon Size
 * @parent ---Info Window---
 * @type number
 * @min 0
 * @desc This will be the width and height of the icon to be drawn.
 * This is normally 4x the default Icon Width and Icon Height.
 * @default 128
 *
 * @param Font Size
 * @parent ---Info Window---
 * @type number
 * @min 1
 * @desc This changes the font size for description items.
 * Default: 28
 * @default 20
 *
 * @param Recovery Format
 * @parent ---Info Window---
 * @desc This is the text format for HP/MP Recovery.
 * @default %1 Heal
 *
 * @param Add State
 * @parent ---Info Window---
 * @desc This is the text for adding states.
 * @default +State
 *
 * @param Add Buff
 * @parent ---Info Window---
 * @desc This is the text for adding buffs.
 * @default +Buff
 *
 * @param Remove State
 * @parent ---Info Window---
 * @desc This is the text for remove states.
 * @default -State
 *
 * @param Remove Buff
 * @parent ---Info Window---
 * @desc This is the text for remove buffs.
 * @default -Buff
 *
 * @param Maximum Icons
 * @parent ---Info Window---
 * @type number
 * @min 0
 * @desc Maximum number of icons drawn for states and buffs.
 * @default 4
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * The shop menu in RPG Maker MV is the same as it was in RPG Maker VX and RPG
 * Maker VX Ace. It's relatively basic and provides adequate information, but
 * not really enough to let the player know what they're actually buying or
 * even selling. This plugin enables shops to show more than just the basic
 * information displayed in RPG Maker MV and even allows for custom commands to
 * be inserted into the command window.
 *
 * This plugin also gives the player the option to tab between a parameter
 * comparison mode with the whole party displaying individual stats at a time
 * or individual actors displaying all stats at a time. The player can switch
 * between the two modes by pressing the 'tab' button on the keyboard or with
 * touch input on the name of the actor or parameter.
 *
 * ============================================================================
 * Instructions
 * ============================================================================
 *
 * You can add and remove commands from the Command Window by changing the
 * 'Command Order' parameter. Here is a list of commands you may use:
 *
 *   Buy
 *   - This is the buy item command.
 *
 *   Sell
 *   - This is the sell item command.
 *
 *   Equip
 *   - This is the equip command to directly access an actor's equipment.
 *
 *   Custom
 *   - If you have any custom shop menu items, they will be displayed here.
 *
 *   Cancel
 *   - This exits the shop.
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * You can use the following notetag to alter various shop aspects
 *
 * Item, Weapon, and Armor Notetag:
 *
 *   <Price: x>
 *   This notetag allows you to exceed the default editor limit for item prices
 *   of 999,999 gold.
 *
 *   <Sell Price: x>
 *   This sets the selling price of the item to x.
 *
 *   <Cannot Sell>
 *   This makes it so that the item cannot be sold.
 *
 *   <Can Sell>
 *   This makes it so that the item can be sold even if it is at 0 gold.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.05:
 * - Updated for RPG Maker MV version 1.5.0.
 *
 * Version 1.04:
 * - Compatibility Update with YEP_X_ItemPictureImg.js
 *
 * Version 1.03:
 * - Updated for RPG Maker MV version 1.1.0.
 *
 * Version 1.02:
 * - Fixed a visual bug that listed actor stats in the wrong order.
 *
 * Version 1.01a:
 * - Disabled LEFT/RIGHT movement from the status window while inputting an
 * item quantity to buy.
 * - Added a font reset on the number window upon refresh.
 * - Fixed a visual error with MP recovery displaying a 0 instead of ---.
 *
 * Version 1.00:
 * - Finished Plugin!
 */
//=============================================================================

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

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

Yanfly.Param.ShopCommandOrder = String(Yanfly.Parameters['Command Order']);
Yanfly.Param.ShopListWidth = String(Yanfly.Parameters['Shop List Width']);
Yanfly.Param.ShopCommandAlign = String(Yanfly.Parameters['Command Alignment']);

Yanfly.Param.ShopDefaultMode = String(Yanfly.Parameters['Default Mode']);
Yanfly.Param.ShopDefaultMode = Yanfly.Param.ShopDefaultMode.toLowerCase();
Yanfly.Param.ShopStatSwitch = eval(String(Yanfly.Parameters['Stat Switching']));
Yanfly.Param.ShopCantEquip = String(Yanfly.Parameters['Cannot Equip']);
Yanfly.Param.ShopStatFontSize = Number(Yanfly.Parameters['Stat Font Size']);
Yanfly.Param.ShopCantSize = Number(Yanfly.Parameters['Cannot Equip Font Size']);

if (!Imported.YEP_ItemCore) {
  Yanfly.Param.ItemFontSize = Number(Yanfly.Parameters['Font Size']);
  Yanfly.Param.ItemShowIcon = String(Yanfly.Parameters['Show Icon']);
  Yanfly.Param.ItemIconSize = Number(Yanfly.Parameters['Icon Size']);
  Yanfly.Param.ItemRecoverFmt = String(Yanfly.Parameters['Recovery Format']);
  Yanfly.Param.ItemAddState = String(Yanfly.Parameters['Add State']);
  Yanfly.Param.ItemAddBuff = String(Yanfly.Parameters['Add Buff']);
  Yanfly.Param.ItemRemoveState = String(Yanfly.Parameters['Remove State']);
  Yanfly.Param.ItemRemoveBuff = String(Yanfly.Parameters['Remove Buff']);
  Yanfly.Param.ItemMaxIcons = Number(Yanfly.Parameters['Maximum Icons']);
};

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

Yanfly.Shop.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.Shop.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_ShopMenuCore) {
    this.processShopNotetags($dataItems);
    this.processShopNotetags($dataWeapons);
    this.processShopNotetags($dataArmors);
    Yanfly._loaded_YEP_ShopMenuCore = true;
  }
  return true;
};

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

    obj.cannotSell = false;
    obj.canSell = false;
    obj.sellPrice = undefined;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:PRICE):[ ](\d+)>/i)) {
        obj.price = parseInt(RegExp.$1);
      } else if (line.match(/<(?:SELL PRICE|SELLING PRICE):[ ](\d+)>/i)) {
        obj.sellPrice = parseInt(RegExp.$1);
      } else if (line.match(/<(?:CANNOT SELL)>/i)) {
        obj.cannotSell = true;
      } else if (line.match(/<(?:CAN SELL)>/i)) {
        obj.canSell = true;
      }
    }
  }
};

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

Game_Temp.prototype.registerShopGoods = function() {
    var scene = SceneManager._scene;
    this._shopGoods = scene._goods;
    this._shopPurchaseOnly = scene._purchaseOnly;
};

Game_Temp.prototype.clearShopGoods = function() {
    this._shopGoods = undefined;
    this._shopPurchaseOnly = undefined;
};

//=============================================================================
// Window_ShopCommand
//=============================================================================

Window_ShopCommand.prototype.windowWidth = function() {
    return 240;
};

Window_ShopCommand.prototype.maxCols = function() {
    return 1;
};

Window_ShopCommand.prototype.numVisibleRows = function() {
    return 4;
};

Window_ShopCommand.prototype.makeCommandList = function() {
    this._commandOrder = Yanfly.Param.ShopCommandOrder.split(' ');
    for (var i = 0; i < this._commandOrder.length; ++i) {
      var command = this._commandOrder[i];
      this.createCommand(command);
    }
};

Window_ShopCommand.prototype.createCommand = function(command) {
    command = command.toUpperCase();
    if (command === 'BUY') {
      this.addCommand(TextManager.buy, 'buy');
    } else if (command === 'SELL') {
      this.addCommand(TextManager.sell, 'sell', !this._purchaseOnly);
    } else if (command === 'CANCEL') {
      this.addCommand(TextManager.cancel, 'cancel');
    } else if (['CUSTOM', 'ORIGINAL'].contains(command)) {
      this.addCustomCommands();
    } else if (command === 'EQUIP') {
      this.addCommand(TextManager.equip, 'equip');
    }
};

Window_ShopCommand.prototype.addCustomCommands = function() {
};

Window_ShopCommand.prototype.itemTextAlign = function() {
    return Yanfly.Param.ShopCommandAlign;
};

//=============================================================================
// Window_ShopInfo
//=============================================================================

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

Window_ShopInfo.prototype = Object.create(Window_Base.prototype);
Window_ShopInfo.prototype.constructor = Window_ShopInfo;

Window_ShopInfo.prototype.initialize = function(x, y, width, height) {
    Window_Base.prototype.initialize.call(this, x, y, width, height);
    this._item = null;
    this.deactivate();
    this.refresh();
};

Window_ShopInfo.prototype.setItem = function(item) {
    if (this._item === item) return;
    this._item = item;
    this.refresh();
};

Window_ShopInfo.prototype.refresh = function() {
    this.contents.clear();
    this.drawDarkRectEntries();
    if (!this._item) return;
    this.contents.fontSize = Yanfly.Param.ItemFontSize;
    this.drawItemEntry();
};

Window_ShopInfo.prototype.drawDarkRectEntries = function() {
    var rect = new Rectangle();
    if (eval(Yanfly.Param.ItemShowIcon)) {
      rect.width = Window_Base._faceWidth;
      rect.height = Window_Base._faceHeight;
      this.drawDarkRect(rect.x, rect.y, rect.width, rect.height);
      rect.width = (this.contents.width - Window_Base._faceWidth) / 2;
    } else {
      rect.width = this.contents.width / 2;
    }
    rect.height = this.lineHeight();
    for (var i = 0; i < 8; ++i) {
      rect = this.getRectPosition(rect, i);
      this.drawDarkRect(rect.x, rect.y, rect.width, rect.height);
    }
};

Window_ShopInfo.prototype.drawDarkRect = function(dx, dy, dw, dh) {
    var color = this.gaugeBackColor();
    this.changePaintOpacity(false);
    this.contents.fillRect(dx + 1, dy + 1, dw - 2, dh - 2, color);
    this.changePaintOpacity(true);
};

Window_ShopInfo.prototype.getRectPosition = function(rect, i) {
    if (i % 2 === 0) {
      if (eval(Yanfly.Param.ItemShowIcon)) {
        rect.x = Window_Base._faceWidth;
      } else {
        rect.x = 0;
      }
      rect.y = i / 2 * this.lineHeight();
    } else {
      if (eval(Yanfly.Param.ItemShowIcon)) {
        rect.x = Window_Base._faceWidth + rect.width;
      } else {
        rect.x = rect.width;
      }
    }
    return rect;
};

Window_ShopInfo.prototype.drawItemEntry = function() {
    var item = this._item;
    if (eval(Yanfly.Param.ItemShowIcon)) this.drawItemIcon(item);
    if (DataManager.isItem(item)) this.drawItemInfo(item);
    if (DataManager.isWeapon(item)) this.drawEquipInfo(item);
    if (DataManager.isArmor(item)) this.drawEquipInfo(item);
};

Window_ShopInfo.prototype.drawItemIcon = function() {
    this.drawLargeIcon();
};

if (Imported.YEP_X_ItemPictureImg) {

Yanfly.IPI.Window_ShopInfo_drawItemIcon =
  Window_ShopInfo.prototype.drawItemIcon;
Window_ShopInfo.prototype.drawItemIcon = function() {
  if (this.itemHasPictureImage()) {
    this.readyItemPictureImage(this._item);
  } else {
    Yanfly.IPI.Window_ShopInfo_drawItemIcon.call(this);
  }
};

Window_ShopInfo.prototype.itemHasPictureImage = function() {
  if (!this._item) return false;
  var filename = ItemManager.getItemPictureImageFilename(this._item);
  return filename !== '';
};

Window_ShopInfo.prototype.readyItemPictureImage = function(item) {
  if (item !== this._item) return;
  var bitmap = ItemManager.getItemPictureImage(item);
  if (bitmap.width <= 0) {
    return setTimeout(this.readyItemPictureImage.bind(this, item), 250);
  } else {
    this.drawItemPictureImage(bitmap);
  }
};

Window_ShopInfo.prototype.drawItemPictureImage = function(bitmap) {
  var pw = bitmap.width;
  var ph = bitmap.height;
  var sx = 0;
  var sy = 0;
  var dw = pw;
  var dh = ph;
  if (dw > Yanfly.Param.ItemImageMaxWidth) {
    var rate = Yanfly.Param.ItemImageMaxWidth / dw;
    dw = Math.floor(dw * rate);
    dh = Math.floor(dh * rate);
  }
  if (dh > Yanfly.Param.ItemImageMaxHeight) {
    var rate = Yanfly.Param.ItemImageMaxHeight / dh;
    dw = Math.floor(dw * rate);
    dh = Math.floor(dh * rate);
  }
  var dx = (Window_Base._faceWidth - dw) / 2;
  var dy = (Window_Base._faceHeight - dh) / 2;
  this.contents.blt(bitmap, sx, sy, pw, ph, dx, dy, dw, dh);
};

}; // Imported.YEP_X_ItemPictureImg

Window_ShopInfo.prototype.drawLargeIcon = function() {
    var iconIndex = this._item.iconIndex;
    var bitmap = ImageManager.loadSystem('IconSet');
    var pw = Window_Base._iconWidth;
    var ph = Window_Base._iconHeight;
    var sx = iconIndex % 16 * pw;
    var sy = Math.floor(iconIndex / 16) * ph;
    var dw = Yanfly.Param.ItemIconSize;
    var dh = Yanfly.Param.ItemIconSize;
    var dx = (Window_Base._faceWidth - dw) / 2;
    var dy = (Window_Base._faceHeight - dh) / 2;
    this.contents._context.imageSmoothingEnabled = false;
    this.contents.blt(bitmap, sx, sy, pw, ph, dx, dy, dw, dh);
    this.contents._context.imageSmoothingEnabled = true;
};

Window_ShopInfo.prototype.drawEquipInfo = function(item) {
    var rect = new Rectangle();
    if (eval(Yanfly.Param.ItemShowIcon)) {
      rect.width = (this.contents.width - Window_Base._faceWidth) / 2;
    } else {
      rect.width = this.contents.width / 2;
    }
    for (var i = 0; i < 8; ++i) {
      rect = this.getRectPosition(rect, i);
      var dx = rect.x + this.textPadding();
      var dw = rect.width - this.textPadding() * 2;
      this.changeTextColor(this.systemColor());
      this.drawText(TextManager.param(i), dx, rect.y, dw);
      this.changeTextColor(this.paramchangeTextColor(item.params[i]));
      var text = Yanfly.Util.toGroup(item.params[i]);
      if (item.params[i] >= 0) text = '+' + text;
      if (text === '+0') this.changePaintOpacity(false);
      this.drawText(text, dx, rect.y, dw, 'right');
      this.changePaintOpacity(true);
    }
};

Window_ShopInfo.prototype.drawItemInfo = function(item) {
    var rect = new Rectangle();
    if (eval(Yanfly.Param.ItemShowIcon)) {
      rect.width = (this.contents.width - Window_Base._faceWidth) / 2;
    } else {
      rect.width = this.contents.width / 2;
    }
    for (var i = 0; i < 8; ++i) {
      rect = this.getRectPosition(rect, i);
      var dx = rect.x + this.textPadding();
      var dw = rect.width - this.textPadding() * 2;
      this.changeTextColor(this.systemColor());
      var text = this.getItemInfoCategory(i);
      this.drawText(text, dx, rect.y, dw);
      this.drawItemData(i, dx, rect.y, dw);
    }
};

Window_ShopInfo.prototype.getItemInfoCategory = function(i) {
    var fmt = Yanfly.Param.ItemRecoverFmt;
    if (i === 0) return fmt.format(TextManager.param(0));
    if (i === 1) return fmt.format(TextManager.hp);
    if (i === 2) return fmt.format(TextManager.param(1));
    if (i === 3) return fmt.format(TextManager.mp);
    if (i === 4) return Yanfly.Param.ItemAddState;
    if (i === 5) return Yanfly.Param.ItemRemoveState;
    if (i === 6) return Yanfly.Param.ItemAddBuff;
    if (i === 7) return Yanfly.Param.ItemRemoveBuff;
    return '';
};

Window_ShopInfo.prototype.drawItemData = function(i, dx, dy, dw) {
    if (!this._item) return;
    var effect;
    var value = '---';
    var pre = '';
    var text = '';
    var icons = [];
    if (i === 0) {
      effect = this.getEffect(Game_Action.EFFECT_RECOVER_HP);
      value = (effect) ? effect.value1 : '---';
      if (value === 0) value = '---';
      if (value !== '---' && value !== 0) value *= 100;
    }
    if (i === 1) {
      effect = this.getEffect(Game_Action.EFFECT_RECOVER_HP);
      value = (effect) ? effect.value2 : '---';
      if (value === 0) value = '---';
    }
    if (i === 2) {
      effect = this.getEffect(Game_Action.EFFECT_RECOVER_MP);
      value = (effect) ? effect.value1 : '---';
      if (value === 0) value = '---';
      if (value !== '---' && value !== 0) value *= 100;
    }
    if (i === 3) {
      effect = this.getEffect(Game_Action.EFFECT_RECOVER_MP);
      value = (effect) ? effect.value2 : '---';
      if (value === 0) value = '---';
    }
    if (i >= 4) {
      icons = this.getItemIcons(i, icons);
    }
    this.changeTextColor(this.normalColor());
    if (value === '---') {
      this.changePaintOpacity(false);
    } else if (i < 4) {
      if (value > 0) pre = '+';
      value = Yanfly.Util.toGroup(parseInt(value));
      if ([0, 2].contains(i)) text = '%';
    }
    if (icons.length > 0) {
      this.changePaintOpacity(true);
      dx = dx + dw - icons.length * Window_Base._iconWidth;
      dx += this.textPadding() - 2;
      for (var j = 0; j < icons.length; ++j) {
        var icon = icons[j];
        this.drawIcon(icon, dx, dy + 2);
        dx += Window_Base._iconWidth;
      }
    } else {
      text = pre + value + text;
      this.drawText(text, dx, dy, dw, 'right');
      this.changePaintOpacity(true);
    }
};

Window_ShopInfo.prototype.getEffect = function(code) {
    var targetEffect;
    this._item.effects.forEach(function(effect) {
      if (effect.code === code) targetEffect = effect;
    }, this);
    return targetEffect;
};

Window_ShopInfo.prototype.getItemIcons = function(i, array) {
    this._item.effects.forEach(function(effect) {
      if (i === 4 && effect.code === Game_Action.EFFECT_ADD_STATE) {
        var state = $dataStates[effect.dataId];
        if (state && state.iconIndex !== 0) array.push(state.iconIndex);
      }
      if (i === 5 && effect.code === Game_Action.EFFECT_REMOVE_STATE) {
        var state = $dataStates[effect.dataId];
        if (state && state.iconIndex !== 0) array.push(state.iconIndex);
      }
      if (i === 6 && effect.code === Game_Action.EFFECT_ADD_BUFF) {
        var icon = Game_BattlerBase.ICON_BUFF_START + effect.dataId;
        array.push(icon);
      }
      if (i === 6 && effect.code === Game_Action.EFFECT_ADD_DEBUFF) {
        var icon = Game_BattlerBase.ICON_DEBUFF_START + effect.dataId;
        array.push(icon);
      }
      if (i === 7 && effect.code === Game_Action.EFFECT_REMOVE_BUFF) {
        var icon = Game_BattlerBase.ICON_BUFF_START + effect.dataId;
        array.push(icon);
      }
      if (i === 7 && effect.code === Game_Action.EFFECT_REMOVE_DEBUFF) {
        var icon = Game_BattlerBase.ICON_DEBUFF_START + effect.dataId;
        array.push(icon);
      }
    }, this);
    array = array.slice(0, Yanfly.Param.ItemMaxIcons);
    return array;
};

//=============================================================================
// Window_ShopNumber
//=============================================================================

Window_ShopNumber.prototype.windowWidth = function() {
    return Math.ceil(eval(Yanfly.Param.ShopListWidth));
};

Window_ShopNumber.prototype.refresh = function() {
    this.contents.clear();
    this._index = 0;
    this.resetFontSettings();
    this.drawItemName(this._item, 0, this.lineHeight(), this.contents.width);
    this.drawMultiplicationSign();
    this.drawNumber();
    this.drawTotalPrice();
};

Window_ShopNumber.prototype.itemY = function() {
    return this.lineHeight() * 2;
};

Window_ShopNumber.prototype.drawTotalPrice = function() {
    var ww = this.contents.width - this.textPadding();
    var wy = this.itemY();
    this.drawHorzLine(this.lineHeight() * 3);
    this.drawTotalCurrency(ww, wy + this.lineHeight() * 1);
    this.drawTotalCost(ww, wy + this.lineHeight() * 2);
    this.drawHorzLine(wy + this.lineHeight() * 3);
    this.drawTotalAfter(ww, wy + this.lineHeight() * 3);
};

Window_ShopNumber.prototype.drawTotalCurrency = function(ww, wy) {
    var value = Yanfly.Util.toGroup(this.getTotalCurrency());
    this.drawCurrencyValue(value, this._currencyUnit, 0, wy, ww);
};

Window_ShopNumber.prototype.getTotalCurrency = function() {
    if (this._currencyUnit === TextManager.currencyUnit) {
      return $gameParty.gold();
    }
    return 0;
};

Window_ShopNumber.prototype.drawTotalCost = function(ww, wy) {
    var value = this._price * this._number;
    if (!this.isSelling()) value *= -1;
    value = Yanfly.Util.toGroup(value);
    if (this.isSelling()) value = '+' + value;
    this.drawCurrencyValue(value, this._currencyUnit, 0, wy, ww);
};

Window_ShopNumber.prototype.drawHorzLine = function(y) {
  this.contents.paintOpacity = 128;
  this.contents.fillRect(0, y, this.contentsWidth(), 2, this.normalColor());
  this.contents.paintOpacity = 255;
};

Window_ShopNumber.prototype.drawTotalAfter = function(ww, wy) {
    var value = this.getTotalCurrency();
    value += (this._price * this._number) * (!this.isSelling() ? -1 : 1);
    value = Yanfly.Util.toGroup(value);
    this.drawCurrencyValue(value, this._currencyUnit, 0, wy, ww);
};

Window_ShopNumber.prototype.isSelling = function() {
    var scene = SceneManager._scene;
    return scene.isSelling();
};

Window_ShopNumber.prototype.cursorWidth = function() {
    this.resetFontSettings();
    var item = this._item
    if (this._item && this._item.proxyBuy) {
      var id = this._item.proxyBuy;
      if (DataManager.isItem(this._item)) item = $dataItems[id];
      if (DataManager.isWeapon(this._item)) item = $dataWeapons[id];
      if (DataManager.isArmor(this._item)) item = $dataArmors[id];
    }
    var value = $gameParty.maxItems(item);
    var digitWidth = this.textWidth(Yanfly.Util.toGroup(value));
    return digitWidth + this.textPadding() * 2;
};

//=============================================================================
// Window_ShowBuy
//=============================================================================

Window_ShopBuy.prototype.windowWidth = function() {
    return Math.ceil(eval(Yanfly.Param.ShopListWidth));
};

Window_ShopBuy.prototype.setInfoWindow = function(infoWindow) {
    this._infoWindow = infoWindow;
    this.callUpdateHelp();
};

Yanfly.Shop.Window_ShopBuy_updateHelp = Window_ShopBuy.prototype.updateHelp;
Window_ShopBuy.prototype.updateHelp = function() {
    Yanfly.Shop.Window_ShopBuy_updateHelp.call(this);
    if (this._infoWindow) this._infoWindow.setItem(this.item());
};

//=============================================================================
// Window_ShopCategory
//=============================================================================

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

Window_ShopCategory.prototype = Object.create(Window_ItemCategory.prototype);
Window_ShopCategory.prototype.constructor = Window_ShopCategory;

Window_ShopCategory.prototype.initialize = function() {
    Window_ItemCategory.prototype.initialize.call(this);
};

Window_ShopCategory.prototype.windowWidth = function() {
    return 240;
};

Window_ShopCategory.prototype.numVisibleRows = function() {
    return 4;
};

Window_ShopCategory.prototype.maxCols = function() {
    return 1;
};

Window_ShopCategory.prototype.itemTextAlign = function() {
    return Yanfly.Param.ShopCommandAlign;
};

//=============================================================================
// Window_ShopBuy
//=============================================================================

Window_ShopBuy.prototype.drawItem = function(index) {
    var item = this._data[index];
    var rect = this.itemRect(index);
    rect.width -= this.textPadding();
    this.changePaintOpacity(this.isEnabled(item));
    this.drawBuyItem(item, rect);
    this.drawBuyPrice(item, rect);
    this.changePaintOpacity(true);
    this.resetFontSettings();
};

Window_ShopBuy.prototype.drawBuyItem = function(item, rect) {
    this.drawItemName(item, rect.x, rect.y, rect.width);
};

Window_ShopBuy.prototype.drawBuyPrice = function(item, rect) {
    if (Imported.YEP_CoreEngine) {
      this.contents.fontSize = Yanfly.Param.GoldFontSize;
    }
    var itemPrice = Yanfly.Util.toGroup(this.price(item));
    this.drawCurrencyValue(itemPrice, this.currencyUnit(), rect.x, rect.y,
        rect.width);
};

Window_ShopBuy.prototype.currencyUnit = function() {
    return TextManager.currencyUnit;
};

//=============================================================================
// Window_ShopSell
//=============================================================================

Window_ShopSell.prototype.maxCols = function() {
    return 1;
};

Window_ShopSell.prototype.setInfoWindow = function(infoWindow) {
    this._infoWindow = infoWindow;
    this.callUpdateHelp();
};

Window_ShopSell.prototype.setStatusWindow = function(statusWindow) {
    this._statusWindow = statusWindow;
    this.callUpdateHelp();
};

Yanfly.Shop.Window_ShopSell_updateHelp = Window_ShopSell.prototype.updateHelp;
Window_ShopSell.prototype.updateHelp = function() {
    Yanfly.Shop.Window_ShopSell_updateHelp.call(this);
    if (this._infoWindow) this._infoWindow.setItem(this.item());
    if (this._statusWindow) this._statusWindow.setItem(this.item());
};

Yanfly.Shop.Window_ShopSell_isEnabled = Window_ShopSell.prototype.isEnabled;
Window_ShopSell.prototype.isEnabled = function(item) {
    if (item) {
      if ($gamePlayer.isDebugThrough()) return true;
      if (item.cannotSell) return false;
      if (item.canSell) return true;
    }
    return Yanfly.Shop.Window_ShopSell_isEnabled.call(this, item);
};

//=============================================================================
// Window_ShopStatus
//=============================================================================

Yanfly.Shop.Window_ShopStatus_initialize =
    Window_ShopStatus.prototype.initialize;
Window_ShopStatus.prototype.initialize = function(x, y, width, height) {
    Yanfly.Shop.Window_ShopStatus_initialize.call(this, x, y, width, height);
    if (Yanfly.Param.ShopStatSwitch) this._paramId = 2;
    this._displayMode = Yanfly.Param.ShopDefaultMode;
    this._actorIndex = 0;
    this._maxActorIndex = $gameParty.members().length - 1;
    this._clickZoneX = this.textWidth('<<') + this.standardPadding();
    this._clickZoneY = this.standardPadding() + this.lineHeight() * 2;
};

Window_ShopStatus.prototype.displayMode = function() {
    return this._displayMode;
};

Window_ShopStatus.prototype.setDisplayMode = function(mode) {
    this._displayMode = mode;
};

Window_ShopStatus.prototype.isDefaultMode = function() {
    return this.displayMode() === 'default';
};

Window_ShopStatus.prototype.isActorMode = function() {
    return this.displayMode() === 'actor';
};

Window_ShopStatus.prototype.refresh = function() {
    this.contents.clear();
    if (!this._item) return;
    this.resetTextColor();
    this.resetFontSettings();
    var x = this.textPadding();
    this.drawPossession(x, 0);
    if (!this.isEquipItem()) return;
    this.resetTextColor();
    this.resetFontSettings();
    if (this.isDefaultMode()) this.drawDefaultData();
    if (this.isActorMode()) this.drawActorData();
};

Window_ShopStatus.prototype.drawDefaultData = function() {
    this.drawStatDisplayed();
    this.drawEquipInfo(this.textPadding(), this.lineHeight() * 2);
};

Window_ShopStatus.prototype.drawStatDisplayed = function() {
    var paramId = this.paramId();
    var text = TextManager.param(paramId);
    this.changeTextColor(this.normalColor());
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'center');
    if (!Yanfly.Param.ShopStatSwitch) return;
    this.changeTextColor(this.systemColor());
    var text = '<<';
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'left');
    var text = '>>';
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'right');
};

Window_ShopStatus.prototype.drawActorData = function() {
    var actor = this.getActor();
    this.drawActorDisplayed(actor);
    this.drawDarkRectEntries();
    this.drawActorStatInfo(actor);
};

Window_ShopStatus.prototype.getActor = function() {
    return $gameParty.members()[this._actorIndex];
};

Window_ShopStatus.prototype.drawActorDisplayed = function(actor) {
    var text = actor.name();
    this.changeTextColor(this.normalColor());
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'center');
    this.changeTextColor(this.systemColor());
    var text = '<<';
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'left');
    var text = '>>';
    this.drawText(text, 0, this.lineHeight(), this.contents.width, 'right');
};

Window_ShopStatus.prototype.drawDarkRectEntries = function() {
    for (var i = 0; i < 8; ++i) {
      var rect = this.getRectPosition(i);
      this.drawDarkRect(rect.x, rect.y, rect.width, rect.height);
    }
};

Window_ShopStatus.prototype.getRectPosition = function(index) {
    var rect = new Rectangle();
    rect.width = Math.floor(this.contents.width / 2);
    rect.height = this.lineHeight();
    rect.x = index % 2 === 0 ? 0 : rect.width;
    rect.y = Math.floor(index / 2) * this.lineHeight() + this.lineHeight() * 2;
    return rect;
};

Window_ShopStatus.prototype.drawDarkRect = function(dx, dy, dw, dh) {
    var color = this.gaugeBackColor();
    this.changePaintOpacity(false);
    this.contents.fillRect(dx + 1, dy + 1, dw - 2, dh - 2, color);
    this.changePaintOpacity(true);
};

Window_ShopStatus.prototype.drawActorStatInfo = function(actor) {
    this.contents.fontSize = Yanfly.Param.ShopStatFontSize;
    var item1 = this.currentEquippedItem(actor, this._item.etypeId);
    var canEquip = actor.canEquip(this._item);
    for (var i = 0; i < 8; ++i) {
      this.changePaintOpacity(true);
      var rect = this.getRectPosition(i);
      rect.x += this.textPadding();
      rect.width -= this.textPadding() * 2;
      this.changeTextColor(this.systemColor());
      var text = TextManager.param(i);
      this.drawText(text, rect.x, rect.y, rect.width);
      if (!canEquip) this.drawActorCantEquip(actor, rect);
      if (canEquip) this.drawActorChange(actor, rect, item1, i);
    }
    this.changePaintOpacity(true);
};

Window_ShopStatus.prototype.drawActorCantEquip = function(actor, rect) {
    this.changePaintOpacity(false);
    this.resetTextColor();
    this.contents.fontSize = Yanfly.Param.ShopCantSize;
    var text = '-';
    this.drawText(text, rect.x, rect.y, rect.width, 'right');
};

Window_ShopStatus.prototype.drawActorChange = function(actor, rect, item1, i) {
    var change = this._item.params[i]
    change -= (item1 ? item1.params[i] : 0);
    this.changePaintOpacity(change !== 0);
    this.changeTextColor(this.paramchangeTextColor(change));
    var text = (change > 0 ? '+' : '') + Yanfly.Util.toGroup(change);
    this.drawText(text, rect.x, rect.y, rect.width, 'right');
};

Window_ShopStatus.prototype.drawEquipInfo = function(x, y) {
    var members = this.statusMembers();
    for (var i = 0; i < members.length; i++) {
      var wy = y;
      wy += i * this.lineHeight();
      this.drawActorEquipInfo(x, wy, members[i]);
    }
};

Window_ShopStatus.prototype.drawActorEquipInfo = function(x, y, actor) {
    var enabled = actor.canEquip(this._item);
    this.changePaintOpacity(enabled);
    this.resetTextColor();
    this.resetFontSettings();
    this.drawText(actor.name(), x, y, this.contents.width - x);
    var item1 = this.currentEquippedItem(actor, this._item.etypeId);
    if (enabled) {
      this.contents.fontSize = Yanfly.Param.ShopStatFontSize;
      this.drawActorParamChange(x, y, actor, item1);
    } else {
      this.contents.fontSize = Yanfly.Param.ShopCantSize;
      var ww = this.contents.width - this.textPadding();
      this.drawText(Yanfly.Param.ShopCantEquip, x, y, ww, 'right');
    }
    this.changePaintOpacity(true);
};

Window_ShopStatus.prototype.drawActorParamChange =
function(x, y, actor, item1) {
    var width = this.contents.width - this.textPadding() - x;
    var paramId = this.paramId();
    var change = this._item.params[paramId]
    change -= (item1 ? item1.params[paramId] : 0);
    this.changeTextColor(this.paramchangeTextColor(change));
    var text = (change > 0 ? '+' : '') + Yanfly.Util.toGroup(change);
    this.drawText(text, x, y, width, 'right');
};

Yanfly.Shop.Window_ShopStatus_update = Window_ShopStatus.prototype.update;
Window_ShopStatus.prototype.update = function() {
    Yanfly.Shop.Window_ShopStatus_update.call(this);
    if (this.isUpdateTrigger()) this.updateParamSwitch();
};

Window_ShopStatus.prototype.isUpdateTrigger = function() {
    if (this.isDefaultMode() && Yanfly.Param.ShopStatSwitch) return true;
    if (this.isActorMode()) return true;
    return false;
};

Window_ShopStatus.prototype.updateParamSwitch = function() {
    if (!this.isEquipItem()) return;
    if (this.isTouched(-1) || this.getInput('left')) {
      SoundManager.playCursor();
      this.adjustLeft();
      this.refresh();
    } else if (this.isTouched(1) || this.getInput('right')) {
      SoundManager.playCursor();
      this.adjustRight();
      this.refresh();
    } else if (Input.isRepeated('tab') || this.isTouched(0)) {
      SoundManager.playCursor();
      this.adjustMode();
      this.refresh();
    }
};

Window_ShopStatus.prototype.getInput = function(input) {
    if (SceneManager._scene._numberWindow.active) return false;
    return Input.isRepeated(input)
};

Window_ShopStatus.prototype.adjustLeft = function() {
    if (this.isDefaultMode()) {
      this._paramId -= 1;
      if (this._paramId < 0) this._paramId = 7;
    } else if (this.isActorMode()) {
      this._actorIndex -= 1;
      if (this._actorIndex < 0) this._actorIndex = this._maxActorIndex;
    }
};

Window_ShopStatus.prototype.adjustRight = function() {
    if (this.isDefaultMode()) {
      this._paramId += 1;
      if (this._paramId > 7) this._paramId = 0;
    } else if (this.isActorMode()) {
      this._actorIndex += 1;
      if (this._actorIndex > this._maxActorIndex) this._actorIndex = 0;
    }
};

Window_ShopStatus.prototype.adjustMode = function() {
    if (this.isDefaultMode()) {
      this.setDisplayMode('actor');
    } else if (this.isActorMode()) {
      this.setDisplayMode('default');
    }
};

Window_ShopStatus.prototype.isTouched = function(position) {
    if (!TouchInput.isTriggered()) return false;
    if (!this.isTouchedInsideFrame()) return false;
    var y = this.canvasToLocalY(TouchInput.y);
    if (y > this._clickZoneY) return false;
    var x = this.canvasToLocalX(TouchInput.x);
    if (position === -1 && x < this._clickZoneX) return true;
    if (position === 1 && x > this.width - this._clickZoneX) return true;
    if (position === 0) return true;
    return false;
};

Yanfly.Shop.Window_ShopStatus_paramId = Window_ShopStatus.prototype.paramId;
Window_ShopStatus.prototype.paramId = function() {
    if (Yanfly.Param.ShopStatSwitch) return this._paramId;
    return Yanfly.Shop.Window_ShopStatus_paramId.call(this);
};

Window_ShopStatus.prototype.isPageChangeRequested = function() {
    if (Input.isTriggered('shift')) return true;
    return false;
};

//=============================================================================
// Scene_Shop
//=============================================================================

Scene_Shop.prototype.failSafeGoods = function() {
  if (this._goods === undefined) {
    var goods = $gameTemp._shopGoods;
    var purchaseOnly = $gameTemp._shopPurchaseOnly;
    this.prepare(goods, purchaseOnly);
  }
  $gameTemp.clearShopGoods();
};

Scene_Shop.prototype.create = function() {
    Scene_MenuBase.prototype.create.call(this);
    this.failSafeGoods();
    this.createHelpWindow();
    this.createCommandWindow();
    this.createInfoWindow();
    this.createDummyWindow();
    this.createNumberWindow();
    this.createBuyWindow();
    this.createCategoryWindow();
    this.createSellWindow();
    this.createGoldWindow();
    this.createStatusWindow();
    this.createActorWindow();
};

Scene_Shop.prototype.createCommandWindow = function() {
    this._commandWindow = new Window_ShopCommand(0, this._purchaseOnly);
    this._commandWindow.y = this._helpWindow.height;
    this.addWindow(this._commandWindow);
    this.setCommandWindowHandlers();
};

Scene_Shop.prototype.setCommandWindowHandlers = function() {
    this._commandWindow.setHandler('buy',    this.commandBuy.bind(this));
    this._commandWindow.setHandler('sell',   this.commandSell.bind(this));
    this._commandWindow.setHandler('cancel', this.popScene.bind(this));
    this._commandWindow.setHandler('equip',  this.commandEquip.bind(this));
};

Scene_Shop.prototype.createInfoWindow = function() {
    var wx = this._commandWindow.width;
    var wy = this._commandWindow.y;
    var ww = Graphics.boxWidth - wx;
    var wh = this._commandWindow.height;
    this._infoWindow = new Window_ShopInfo(wx, wy, ww, wh);
    this.addWindow(this._infoWindow);
};

Scene_Shop.prototype.createDummyWindow = function() {
    var wy = this._commandWindow.y + this._commandWindow.height;
    var wh = Graphics.boxHeight - wy;
    var ww = Math.ceil(eval(Yanfly.Param.ShopListWidth));
    this._dummyWindow = new Window_Base(0, wy, ww, wh);
    this.addWindow(this._dummyWindow);
};

Scene_Shop.prototype.createBuyWindow = function() {
    var wy = this._dummyWindow.y;
    var wh = this._dummyWindow.height;
    this._buyWindow = new Window_ShopBuy(0, wy, wh, this._goods);
    this._buyWindow.setHelpWindow(this._helpWindow);
    this._buyWindow.setInfoWindow(this._infoWindow);
    this._buyWindow.hide();
    this._buyWindow.setHandler('ok',     this.onBuyOk.bind(this));
    this._buyWindow.setHandler('cancel', this.onBuyCancel.bind(this));
    this.addWindow(this._buyWindow);
};

Scene_Shop.prototype.createCategoryWindow = function() {
    this._categoryWindow = new Window_ShopCategory();
    this._categoryWindow.setHelpWindow(this._helpWindow);
    this._categoryWindow.y = this._commandWindow.y;
    this._categoryWindow.hide();
    this._categoryWindow.deactivate();
    this._categoryWindow.setHandler('ok',     this.onCategoryOk.bind(this));
    this._categoryWindow.setHandler('cancel', this.onCategoryCancel.bind(this));
    this.addWindow(this._categoryWindow);
};

Scene_Shop.prototype.createSellWindow = function() {
    var wy = this._dummyWindow.y;
    var ww = this._dummyWindow.width;
    var wh = this._dummyWindow.height;
    this._sellWindow = new Window_ShopSell(0, wy, ww, wh);
    this._sellWindow.setHelpWindow(this._helpWindow);
    this._sellWindow.hide();
    this._sellWindow.setInfoWindow(this._infoWindow);
    this._sellWindow.setHandler('ok',     this.onSellOk.bind(this));
    this._sellWindow.setHandler('cancel', this.onSellCancel.bind(this));
    this._categoryWindow.setItemWindow(this._sellWindow);
    this.addWindow(this._sellWindow);
};

Scene_Shop.prototype.createGoldWindow = function() {
    this._goldWindow = new Window_Gold(0, 0);
    this._goldWindow.x = this._buyWindow.width;
    this._goldWindow.y = Graphics.boxHeight - this._goldWindow.height;
    this._goldWindow.width = Graphics.boxWidth - this._goldWindow.x;
    this._goldWindow.createContents();
    this._goldWindow.refresh();
    this.addWindow(this._goldWindow);
};

Scene_Shop.prototype.createStatusWindow = function() {
    var wx = this._dummyWindow.width;
    var wy = this._dummyWindow.y;
    var ww = Graphics.boxWidth - wx;
    var wh = this._dummyWindow.height - this._goldWindow.height;
    this._statusWindow = new Window_ShopStatus(wx, wy, ww, wh);
    this.addWindow(this._statusWindow);
    this._buyWindow.setStatusWindow(this._statusWindow);
    this._sellWindow.setStatusWindow(this._statusWindow);
};

Yanfly.Shop.Scene_Shop_onBuyCancel = Scene_Shop.prototype.onBuyCancel;
Scene_Shop.prototype.onBuyCancel = function() {
    Yanfly.Shop.Scene_Shop_onBuyCancel.call(this);
    this._statusWindow.show();
    this._infoWindow.setItem(null);
};

Scene_Shop.prototype.doBuy = function(number) {
    if (Imported.YEP_ItemCore) $gameTemp.enableVarianceStock();
    this.doBuyGold(number);
    this.doBuyItem(number);
    if (Imported.YEP_ItemCore) $gameTemp.disableVarianceStock();
};

Scene_Shop.prototype.doBuyGold = function(number) {
    $gameParty.loseGold(number * this.buyingPrice());
};

Scene_Shop.prototype.doBuyItem = function(number) {
    $gameParty.gainItem(this._item, number);
};

Scene_Shop.prototype.doSell = function(number) {
    this.doSellGold(number);
    this.doSellItem(number);
    if (!Imported.YEP_ItemCore) return;
    if (!DataManager.isIndependent(this._item)) return;
    DataManager.removeIndependentItem(this._item);
};

Scene_Shop.prototype.doSellGold = function(number) {
    $gameParty.gainGold(number * this.sellingPrice());
};

Scene_Shop.prototype.doSellItem = function(number) {
    $gameParty.loseItem(this._item, number);
};

Yanfly.Shop.Scene_Shop_activateSellWindow =
    Scene_Shop.prototype.activateSellWindow;
Scene_Shop.prototype.activateSellWindow = function() {
    Yanfly.Shop.Scene_Shop_activateSellWindow.call(this);
    this._statusWindow.show();
};

Yanfly.Shop.Scene_Shop_onSellCancel = Scene_Shop.prototype.onSellCancel;
Scene_Shop.prototype.onSellCancel = function() {
    Yanfly.Shop.Scene_Shop_onSellCancel.call(this);
    this._infoWindow.setItem(null);
};

Scene_Shop.prototype.isSelling = function() {
    return this._commandWindow.currentSymbol() === 'sell';
};

Scene_Shop.prototype.createActorWindow = function() {
    this._actorWindow = new Window_MenuActor();
    this._actorWindow.setHandler('ok',     this.onActorOk.bind(this));
    this._actorWindow.setHandler('cancel', this.onActorCancel.bind(this));
    this.addWindow(this._actorWindow);
};

Scene_Shop.prototype.commandEquip = function() {
    this._actorWindow.activate();
    this._actorWindow.show();
    this._actorWindow.select(0);
};

Scene_Shop.prototype.onActorOk = function() {
    this.onActorCommon();
    if (this._commandWindow.currentSymbol() === 'equip') {
      SceneManager.push(Scene_Equip);
    }
};

Scene_Shop.prototype.onActorCancel = function() {
    this._actorWindow.hide();
    this._actorWindow.deselect();
    this._commandWindow.activate();
};

Scene_Shop.prototype.onActorCommon = function() {
    $gameTemp.registerShopGoods();
    var index = this._actorWindow.index();
    var actor = $gameParty.members()[index];
    $gameParty.setMenuActor(actor);
    SoundManager.playOk();
};

Yanfly.Shop.Scene_Shop_sellingPrice = Scene_Shop.prototype.sellingPrice;
Scene_Shop.prototype.sellingPrice = function() {
    if (this._item && this._item.sellPrice !== undefined) {
      return this._item.sellPrice;
    }
    return Yanfly.Shop.Scene_Shop_sellingPrice.call(this);
};

//=============================================================================
// 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
// YEP_SkillCore.js
//=============================================================================

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

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

//=============================================================================
/*:
 * @plugindesc v1.12 Skills are now given more functions and the ability
 * to require different types of costs.
 * @author Yanfly Engine Plugins
 *
 * @param ---General---
 * @default
 *
 * @param Cost Padding
 * @parent ---General---
 * @type number
 * @min 0
 * @desc If a skill has multiple costs, this is the amount of pixels
 * used as padding in between the costs.
 * @default 4
 *
 * @param Command Alignment
 * @parent ---General---
 * @type combo
 * @option left
 * @option center
 * @option right
 * @desc Adjusts the text alignment of the skill type window.
 * left     center     right
 * @default center
 *
 * @param Window Columns
 * @parent ---General---
 * @type number
 * @min 1
 * @desc Choose how many columns to use for the skill window.
 * Default: 2
 * @default 2
 *
 * @param ---HP Costs---
 * @default
 *
 * @param HP Format
 * @parent ---HP Costs---
 * @desc Adjusts the way HP cost appears in the skill list window.
 * %1 - Cost     %2 - HP
 * @default %1%2
 *
 * @param HP Font Size
 * @parent ---HP Costs---
 * @type number
 * @min 1
 * @desc Adjusts the font size used to display HP.
 * Default: 28
 * @default 20
 *
 * @param HP Text Color
 * @parent ---HP Costs---
 * @type number
 * @min 0
 * @max 31
 * @desc Adjusts the text color used from the Window skin for HP.
 * Default: 21
 * @default 18
 *
 * @param HP Icon
 * @parent ---HP Costs---
 * @type number
 * @min 0
 * @desc Choose what icon to use to represent HP costs.
 * Use 0 if you wish to not use an icon.
 * @default 162
 *
 * @param ---MP Costs---
 * @default
 *
 * @param MP Format
 * @parent ---MP Costs---
 * @desc Adjusts the way MP cost appears in the skill list window.
 * %1 - Cost     %2 - MP
 * @default %1%2
 *
 * @param MP Font Size
 * @parent ---MP Costs---
 * @type number
 * @min 1
 * @desc Adjusts the font size used to display MP.
 * Default: 28
 * @default 20
 *
 * @param MP Text Color
 * @parent ---MP Costs---
 * @type number
 * @min 0
 * @max 31
 * @desc Adjusts the text color used from the Window skin for MP.
 * Default: 23
 * @default 23
 *
 * @param MP Icon
 * @parent ---MP Costs---
 * @type number
 * @min 0
 * @desc Choose what icon to use to represent MP costs.
 * Use 0 if you wish to not use an icon.
 * @default 165
 *
 * @param ---TP Costs---
 * @default
 *
 * @param TP Format
 * @parent ---TP Costs---
 * @desc Adjusts the way TP cost appears in the skill list window.
 * %1 - Cost     %2 - TP
 * @default %1%2
 *
 * @param TP Font Size
 * @parent ---TP Costs---
 * @type number
 * @min 1
 * @desc Adjusts the font size used to display TP.
 * Default: 28
 * @default 20
 *
 * @param TP Text Color
 * @parent ---TP Costs---
 * @type number
 * @min 0
 * @max 31
 * @desc Adjusts the text color used from the Window skin for TP.
 * Default: 29
 * @default 29
 *
 * @param TP Icon
 * @parent ---TP Costs---
 * @type number
 * @min 0
 * @desc Choose what icon to use to represent TP costs.
 * Use 0 if you wish to not use an icon.
 * @default 164
 *
 * @help
 * ============================================================================
 * Introduction
 * ============================================================================
 *
 * Skills in RPG's consist of three main components: Costs, Damage, and
 * Effects. Although not all components are required for a skill, they
 * certainly make up a good chunk of it. Damage will be handled by another
 * plugin, but this plugin will provide a core handling for skill costs and
 * skill effects.
 *
 * This plugin also includes the ability for battlers to swap their HP, MP,
 * and/or TP gauges for something different if it would fit the character
 * better (for example, some classes don't use MP and/or TP).
 *
 * ============================================================================
 * Notetags
 * ============================================================================
 *
 * These notetags can adjust either skill costs or special skill effects.
 *
 * Skill Notetags:
 *   <HP Cost: x>
 *   Changes the skill to have x as its HP cost. RPG Maker MV's editor lacks
 *   HP cost functions so this would allow skills to use HP as their cost.
 *
 *   <HP Cost: x%>
 *   Changes the skill to cost a percentage of the character's MaxHP value.
 *
 *   <MP Cost: x>
 *   Changes the skill to have x as its MP cost.
 *   This helps bypass the database's hard limit of 9999.
 *
 *   <MP Cost: x%>
 *   Changes the skill to cost a percentage of the character's MaxMP value.
 *
 *   <TP Cost: x>
 *   Changes the skill to have x as its TP cost.
 *   This helps bypass the database's hard limit of 99.
 *
 *   <TP Cost: x%>
 *   Changes the skill to cost a percentage of the character's MaxTP value.
 *   Although the default MaxTP is 100, this tag will be useful for any
 *   plugins that will alter a character's MaxTP values.
 *
 *   <Hide in Battle>
 *   This will hide and disable the skill during battle.
 *
 *   <Hide in Field>
 *   This will hide and disable the skill outside of battle.
 *
 *   <Hide if Learned Skill: x>
 *   <Hide if Learned Skill: x, x, x>
 *   <Hide if Learned Skill: x to y>
 *   Will hide and disable this skill if skill x has been learned. If multiple
 *   skills are listed, the skill will be hidden and disabled if any one of the
 *   listed skills have been learned. This will ONLY apply to skills that have
 *   been learned and not skills added through traits.
 *
 * ============================================================================
 * Gauge Swapping
 * ============================================================================
 *
 * This plugin also lets you swap around the HP, MP, and TP Gauges to any order
 * you want assuming that all the plugins you use will keep the same order of
 * HP, MP, and TP and does not override the default gauge drawing process. If
 * you use any plugin extensions, they can be swaped in as well.
 *
 * Note: If you do not have 'Display TP in Battle' checked under the System tab
 * in the database, nothing will be shown for the third slot.
 *
 * Class Notetag:
 *   <Swap Gauge x: y>
 *   This will change gauge x (1, 2, or 3) to y. Replace y with 'HP', 'MP', or
 *   'TP' to have it display that gauge type in that gauge slot. If you wish
 *   for that slot to display nothing, insert 'Nothing' or 'Null' in place of
 *   y in the notetag.
 *
 * Weapon, Armor, and State Notetags:
 *   <Swap Gauge x: y>
 *   Actors with equipment or states  that contain these notetags or enemies
 *   with states that contain these notetags will display those swapped gauges
 *   in place of the default settings or settings defined by the Class or
 *   Enemy notetags.
 *
 *   Priority will go in the following order:
 *     Weapons, Armors, States, Class, Enemy
 *
 * ============================================================================
 * Lunatic Mode - Skill Costs
 * ============================================================================
 *
 * For users who want more control over skill costs and skill effects, there
 * exists notetags that allow you to apply code to the costs and/or effects of
 * a skill. For effects, this will also extend towards item control, as well.
 *
 *   <Custom HP Cost>       Example: <Custom HP Cost>
 *    code                            cost += $gameVariables.value(1);
 *    code                           </Custom HP Cost>
 *   </Custom HP Cost>
 *   This allows the skill to have a custom HP cost based off of code. For the
 *   piece of code, 'cost' is a variable already predefined with the HP Cost
 *   and the HP percentage cost.
 *
 *   <Custom MP Cost>       Example: <Custom MP Cost>
 *    code                            cost += $gameVariables.value(1);
 *    code                           </Custom MP Cost>
 *   </Custom MP Cost>
 *   This allows the skill to have a custom MP cost based off of code. For the
 *   piece of code, 'cost' is a variable already predefined with the MP Cost
 *   and the MP percentage cost.
 *
 *   <Custom TP Cost>       Example: <Custom TP Cost>
 *    code                            cost += $gameVariables.value(1);
 *    code                           </Custom TP Cost>
 *   </Custom TP Cost>
 *   This allows the skill to have a custom TP cost based off of code. For the
 *   piece of code, 'cost' is a variable already predefined with the TP Cost
 *   and the TP percentage cost.
 *
 * ============================================================================
 * Lunatic Mode - Custom Show Requirements
 * ============================================================================
 *
 * For those who would like to show certain skills and disable them under any
 * custom conditions using their JavaScript knowledge, use the following:
 *
 * Skill Notetag:
 *   <Custom Show Eval>
 *   if (user.level > 50) {
 *     visible = true;
 *   } else {
 *     visible = false;
 *   }
 *   </Custom Show Eval>
 *   If the visible is set to true, the skill is shown (not hidden) and enabled
 *   if all other conditions are met. If visible is set to false, the skill is
 *   disabled and hidden from the list.
 *
 * ============================================================================
 * Lunatic Mode - Custom Requirements and Execution
 * ============================================================================
 *
 * For those with a bit of JavaScript experience, you can use the following
 * notetags to restrict a skill and what kind of code to process when executing
 * the said skill.
 *
 * Skill Notetags:
 *
 *   <Custom Requirement>
 *    if ($gameParty.gold() > 1000) {
 *      value = true;
 *    } else {
 *      value = false;
 *    }
 *   </Custom Requirement>
 *   If value is set to true, the skill will be useable provided that all other
 *   requirements have been met. If the value is set to false, the skill won't
 *   be useable.
 *
 *   <Custom Execution>
 *    $gameParty.loseGold(1000);
 *   </Custom Execution>
 *   This runs the code between the notetags upon using the skill.
 *
 * ============================================================================
 * Lunatic Mode - Custom Cost Display
 * ============================================================================
 *
 * For those with a bit of JavaScript experience, you can add new ways to
 * display the skill cost.
 *
 * Skill Notetags:
 *
 *   <Cost Display Eval>
 *    var variableId = 1;
 *    var value = 1000;
 *    $gameVariables.setValue(variableId, value);
 *   </Cost Display Eval>
 *   This notetag runs an eval before displaying the skill's cost. This is so
 *   you can set up variables and whatnot for your skill cost display text.
 *
 *   <Custom Cost Display>
 *    \c[4]\v[1]\c[0] Gold
 *   </Custom Cost Display>
 *   This is the custom text displayed before the rest of the skill costs. You
 *   can use text codes with this notetag.
 *
 * ============================================================================
 * Lunatic Mode - The Skill Phases
 * ============================================================================
 *
 * For this skill, multiple effects are applied and at different phases. The
 * various phases are as follows:
 *
 *    Before Effect Phase (influenced by this plugin)
 *    if skill successfully lands:
 *    - Pre-Damage Effect Phase (influenced by this plugin)
 *    - Damage Phase
 *    - Post-Damage Effect Phase (influenced by this plugin)
 *    - Item Trait Effects Phase
 *    After Effect Phase (influenced by this plugin)
 *
 * There's four phases which can be influenced by this plugin. Two of which do
 * not matter if the effect successfully lands or not, two of which do matter
 * if the skill does land.
 *
 * Skill and Item Notetags:
 *   <Before Eval>
 *    code
 *    code
 *   </Before Eval>
 *
 *   <Pre-Damage Eval>
 *    code
 *    code
 *   </Pre-Damage Eval>
 *
 *   <Post-Damage Eval>
 *    code
 *    code
 *   </Post-Damage Eval>
 *
 *   <After Eval>
 *    code
 *    code
 *   </After Eval>
 *   If you wish to use custom effects for your skill, you can insert the
 *   respective notetags into the skill (or item) noteboxes and it will run the
 *   code that appears in between the tags. However, using any form of comments
 *   in this tag will block out code that follows.
 *
 *   Those using the <Pre-Damage Eval> and <Post-Damage Eval> are able to make
 *   use of the damage to be dealt and the damage that has been dealt through
 *   the 'value' variable. The <Pre-Damage Eval> notetag is capable of altering
 *   the 'value' variable and return it to have damage affected by its code.
 *
 * ============================================================================
 * Changelog
 * ============================================================================
 *
 * Version 1.12:
 * - Updated for RPG Maker MV version 1.5.0.
 *
 * Version 1.11a:
 * - Lunatic Mode fail safes added.
 * - Documentation fix for the help file. Lunatic Mode tags didn't end right.
 * The help file is now updated to show the correct notetags.
 *
 * Version 1.10b:
 * - Fixed a visual bug when using text code font changing for custom skill
 * cost display.
 * - <Hide if Learned Skill: x> documentation updated.
 * - Compatibility update for future plugins.
 *
 * Version 1.09:
 * - The <Pre-Damage Eval> notetag now has the ability alter damage dealt. The
 * 'value' variable refers to and returns the damage affected by the action.
 *
 * Version 1.08:
 * - Updated for RPG Maker MV version 1.1.0.
 *
 * Version 1.07:
 * - Fixed a bug that prevented immortal actors at 0 HP from using skills.
 *
 * Version 1.06a:
 * - Added <Hide in Battle> and <Hide in Field> notetags.
 * - Added a failsafe to check for undefined skills.
 *
 * Version 1.05:
 * - Added <Hide if Learned Skill: x> notetags.
 * - Added <Custom Show Eval> Lunatic Mode notetag.
 *
 * Version 1.04:
 * - Added four Lunatic Modes notetags: Custom Requirement, Custom Execution,
 * Cost Display Eval, Custom Cost Display.
 *
 * Version 1.03:
 * - Fixed a bug with the Lunatic Mode notetags not working.
 *
 * Version 1.02:
 * - Added 'Window Columns' parameter to let users adjust the number of columns
 * used for the skill window.
 *
 * Version 1.01:
 * - Fixed a mathematical error for skill cost padding.
 * - Added return for drawSkillCost to assist others scripters when making
 * compatibility notes.
 *
 * Version 1.00:
 * - Finished plugin!
 */
//=============================================================================

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

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

Yanfly.Param.SCCCostPadding = Number(Yanfly.Parameters['Cost Padding']);
Yanfly.Param.SCCTextAlign = String(Yanfly.Parameters['Command Alignment']);
Yanfly.Param.SCCWindowCol = Number(Yanfly.Parameters['Window Columns']);
Yanfly.Param.SCCTpFormat = String(Yanfly.Parameters['TP Format']);
Yanfly.Param.SCCTpFontSize = Number(Yanfly.Parameters['TP Font Size']);
Yanfly.Param.SCCTpTextColor = Number(Yanfly.Parameters['TP Text Color']);
Yanfly.Icon.Tp = Number(Yanfly.Parameters['TP Icon']);
Yanfly.Param.SCCMpFormat = String(Yanfly.Parameters['MP Format']);
Yanfly.Param.SCCMpFontSize = Number(Yanfly.Parameters['MP Font Size']);
Yanfly.Param.SCCMpTextColor = Number(Yanfly.Parameters['MP Text Color']);
Yanfly.Icon.Mp = Number(Yanfly.Parameters['MP Icon']);
Yanfly.Param.SCCHpFormat = String(Yanfly.Parameters['HP Format']);
Yanfly.Param.SCCHpFontSize = Number(Yanfly.Parameters['HP Font Size']);
Yanfly.Param.SCCHpTextColor = Number(Yanfly.Parameters['HP Text Color']);
Yanfly.Icon.Hp = Number(Yanfly.Parameters['HP Icon']);

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

Yanfly.Skill.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function() {
  if (!Yanfly.Skill.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_SkillCore) {
    this.processSkillNotetags($dataSkills);
    this.processObjectNotetags($dataSkills);
    this.processObjectNotetags($dataItems);
    this.processGSCNotetags1($dataClasses);
    this.processGSCNotetags1($dataEnemies);
    this.processGSCNotetags2($dataWeapons);
    this.processGSCNotetags2($dataArmors);
    this.processGSCNotetags2($dataStates);
    Yanfly._loaded_YEP_SkillCore = true;
  }
  return true;
};

DataManager.processSkillNotetags = function(group) {
  var note1 = /<(?:MP COST):[ ](\d+)>/i;
  var note2 = /<(?:MP COST):[ ](\d+)([%％])>/i;
  var note3 = /<(?:TP COST):[ ](\d+)>/i;
  var note4 = /<(?:TP COST):[ ](\d+)([%％])>/i;
  var note5 = /<(?:HP COST):[ ](\d+)>/i;
  var note6 = /<(?:HP COST):[ ](\d+)([%％])>/i;
  var note7a = /<(?:HIDE IF LEARNED SKILL):[ ]*(\d+(?:\s*,\s*\d+)*)>/i;
  var note7b = /<(?:HIDE IF LEARNED SKILL):[ ](\d+)[ ](?:THROUGH|to)[ ](\d+)>/i;
  var note8a = /<(?:HIDE IN BATTLE|hide during battle)>/i;
  var note8b = /<(?:HIDE IN FIELD|hide during field)>/i;
  var noteMpEval1 = /<(?:MP COST EVAL|custom mp cost)>/i;
  var noteMpEval2 = /<\/(?:MP COST EVAL|custom mp cost)>/i;
  var noteTpEval1 = /<(?:TP COST EVAL|custom tp cost)>/i;
  var noteTpEval2 = /<\/(?:TP COST EVAL|custom tp cost)>/i;
  var noteHpEval1 = /<(?:HP COST EVAL|custom hp cost)>/i;
  var noteHpEval2 = /<\/(?:HP COST EVAL|custom hp cost)>/i;
  var noteEvalReq1 = /<(?:EVAL REQUIREMENT|custom requirement)>/i;
  var noteEvalReq2 = /<\/(?:EVAL REQUIREMENT|custom requirement)>/i;
  var noteEvalExe1 = /<(?:EVAL EXECUTION|custom execution)>/i;
  var noteEvalExe2 = /<\/(?:EVAL EXECUTION|custom execution)>/i;
  var noteCostEval1 = /<(?:COST DISPLAY EVAL|display cost eval)>/i;
  var noteCostEval2 = /<\/(?:COST DISPLAY EVAL|display cost eval)>/i;
  var noteCostText1 = /<(?:CUSTOM COST DISPLAY|custom display cost)>/i;
  var noteCostText2 = /<\/(?:CUSTOM COST DISPLAY|custom display cost)>/i;
  var noteShowEval1 = /<(?:CUSTOM SHOW EVAL)>/i;
  var noteShowEval2 = /<\/(?:CUSTOM SHOW EVAL)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.hpCost = 0;
    obj.hpCostPer = 0.0;
    obj.mpCostPer = 0.0;
    obj.tpCostPer = 0.0;
    obj.hideInBattle = false;
    obj.hideInField = false;
    obj.hideIfLearnedSkill = [];
    var evalMode = 'none';
    obj.hpCostEval = '';
    obj.mpCostEval = '';
    obj.tpCostEval = '';
    obj.requireEval = '';
    obj.executeEval = '';
    obj.costdisplayEval = '';
    obj.costShowEval = '';
    obj.customCostText = '';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        obj.mpCost = parseInt(RegExp.$1);
      } else if (line.match(note2)) {
        obj.mpCostPer = parseFloat(RegExp.$1 * 0.01);
      } else if (line.match(note3)) {
        obj.tpCost = parseInt(RegExp.$1);
      } else if (line.match(note4)) {
        obj.tpCostPer = parseFloat(RegExp.$1 * 0.01);
      } else if (line.match(note5)) {
        obj.hpCost = parseInt(RegExp.$1);
      } else if (line.match(note6)) {
        obj.hpCostPer = parseFloat(RegExp.$1 * 0.01);
      } else if (line.match(note7a)) {
        var array = JSON.parse('[' + RegExp.$1.match(/\d+/g) + ']');
        obj.hideIfLearnedSkill = obj.hideIfLearnedSkill.concat(array);
      } else if (line.match(note7b)) {
        var array = JSON.parse('[' + RegExp.$1.match(/\d+/g) + ']');
        var range = Yanfly.Util.getRange(parseInt(RegExp.$1),
          parseInt(RegExp.$2));
        obj.hideIfLearnedSkill = obj.hideIfLearnedSkill.concat(range);
      } else if (line.match(note8a)) {
        obj.hideInBattle = true;
      } else if (line.match(note8b)) {
        obj.hideInField = true;
      } else if (line.match(noteMpEval1)) {
        evalMode = 'mp';
      } else if (line.match(noteMpEval2)) {
        evalMode = 'none';
      } else if (line.match(noteTpEval1)) {
        evalMode = 'tp';
      } else if (line.match(noteTpEval2)) {
        evalMode = 'none';
      } else if (line.match(noteHpEval1)) {
        evalMode = 'hp';
      } else if (line.match(noteHpEval2)) {
        evalMode = 'none';
      } else if (line.match(noteEvalReq1)) {
        evalMode = 'custom requirement';
      } else if (line.match(noteEvalReq2)) {
        evalMode = 'none';
      } else if (line.match(noteEvalExe1)) {
        evalMode = 'custom execute';
      } else if (line.match(noteEvalExe2)) {
        evalMode = 'none';
      } else if (line.match(noteCostEval1)) {
        evalMode = 'display cost eval';
      } else if (line.match(noteCostEval2)) {
        evalMode = 'none';
      } else if (line.match(noteCostText1)) {
        evalMode = 'custom display cost';
      } else if (line.match(noteCostText2)) {
        evalMode = 'none';
      } else if (line.match(noteShowEval1)) {
        evalMode = 'custom show eval';
      } else if (line.match(noteShowEval2)) {
        evalMode = 'none';
      } else if (evalMode === 'mp') {
        obj.mpCostEval = obj.mpCostEval + line + '\n';
      } else if (evalMode === 'tp') {
        obj.tpCostEval = obj.tpCostEval + line + '\n';
      } else if (evalMode === 'hp') {
        obj.hpCostEval = obj.hpCostEval + line + '\n';
      } else if (evalMode === 'custom requirement') {
        obj.requireEval = obj.requireEval + line + '\n';
      } else if (evalMode === 'custom execute') {
        obj.executeEval = obj.executeEval + line + '\n';
      } else if (evalMode === 'display cost eval') {
        obj.costdisplayEval = obj.costdisplayEval + line + '\n';
      } else if (evalMode === 'custom display cost') {
        obj.customCostText = obj.customCostText + line;
      } else if (evalMode === 'custom show eval') {
        obj.costShowEval = obj.costShowEval + line + '\n';
      }
    }
  }
};

DataManager.processObjectNotetags = function(group) {
  var note1 = /<(?:BEFORE EVAL)>/i;
  var note2 = /<\/(?:BEFORE EVAL)>/i;
  var note3 = /<(?:PRE-DAMAGE EVAL)>/i;
  var note4 = /<\/(?:PRE-DAMAGE EVAL)>/i;
  var note5 = /<(?:POST-DAMAGE EVAL)>/i;
  var note6 = /<\/(?:POST-DAMAGE EVAL)>/i;
  var note7 = /<(?:AFTER EVAL)>/i;
  var note8 = /<\/(?:AFTER EVAL)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    var customMode = 'none';
    obj.customBeforeEval = '';
    obj.customPreDamageEval = '';
    obj.customPostDamageEval = '';
    obj.customAfterEval = '';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        customMode = 'before';
      } else if (line.match(note2)) {
        customMode = 'none';
      } else if (line.match(note3)) {
        customMode = 'pre-damage';
      } else if (line.match(note4)) {
        customMode = 'none';
      } else if (line.match(note5)) {
        customMode = 'post-damage';
      } else if (line.match(note6)) {
        customMode = 'none';
      } else if (line.match(note7)) {
        customMode = 'after';
      } else if (line.match(note8)) {
        customMode = 'none';
      } else if (customMode === 'before') {
        obj.customBeforeEval = obj.customBeforeEval + line + '\n';
      } else if (customMode === 'pre-damage') {
        obj.customPreDamageEval = obj.customPreDamageEval + line + '\n';
      } else if (customMode === 'post-damage') {
        obj.customPostDamageEval = obj.customPostDamageEval + line + '\n';
      } else if (customMode === 'after') {
        obj.customAfterEval = obj.customAfterEval + line + '\n';
      }
    }
  }
};

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

    obj.gauge1 = 'HP';
    obj.gauge2 = 'MP';
    obj.gauge3 = 'TP';

    obj.gaugeIcon1 = 0;
    obj.gaugeIcon2 = 0;
    obj.gaugeIcon3 = 0;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:SWAP GAUGE|gauge)[ ](\d+):[ ](.*)>/i)) {
        var gauge = parseInt(RegExp.$1);
        var text = String(RegExp.$2).toUpperCase();
        if (['HP', 'MP', 'TP', 'NOTHING', 'NULL'].contains(text)) {
          if (gauge === 1) obj.gauge1 = text;
          if (gauge === 2) obj.gauge2 = text;
          if (gauge === 3) obj.gauge3 = text;
        }
      }
    }
  }
};

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

    obj.gauge1 = 'UNDEFINED';
    obj.gauge2 = 'UNDEFINED';
    obj.gauge3 = 'UNDEFINED';

    obj.gaugeIcon1 = 'UNDEFINED';
    obj.gaugeIcon2 = 'UNDEFINED';
    obj.gaugeIcon3 = 'UNDEFINED';

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(/<(?:SWAP GAUGE|gauge)[ ](\d+):[ ](.*)>/i)) {
        var gauge = parseInt(RegExp.$1);
        var text = String(RegExp.$2).toUpperCase();
        if (['HP', 'MP', 'TP', 'NOTHING', 'NULL'].contains(text)) {
          if (gauge === 1) obj.gauge1 = text;
          if (gauge === 2) obj.gauge2 = text;
          if (gauge === 3) obj.gauge3 = text;
        }
      }
    }
  }
};

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

Yanfly.Skill.Game_BattlerBase_mSC =
    Game_BattlerBase.prototype.meetsSkillConditions;
Game_BattlerBase.prototype.meetsSkillConditions = function(skill) {
    if (!Yanfly.Skill.Game_BattlerBase_mSC.call(this, skill)) return false;
    if (!skill) return false;
    if (!this.noHiddenSkillConditionsMet(skill) && !skill.hasTag('HideOnly')) return false;
    return this.meetsSkillConditionsEval(skill);
};

Game_BattlerBase.prototype.noHiddenSkillConditionsMet = function(skill) {
    if (!skill) return false;
    if (this.isEnemy()) return true;
    if (skill.hideIfLearnedSkill) {
      for (var i = 0; i < skill.hideIfLearnedSkill.length; ++i) {
        var skillId = skill.hideIfLearnedSkill[i];
        if (this.isLearnedSkill(skillId)) return false;
      }
    }
    if (skill.hideInBattle && $gameParty.inBattle()) return false;
    if (skill.hideInField && !$gameParty.inBattle()) return false;
    if (!this.meetsCustomShowEval(skill)) return false;
    return true;
};

Game_BattlerBase.prototype.meetsCustomShowEval = function(skill) {
    if (skill.costShowEval === '') return true;
    var visible = true;
    var item = skill;
    var a = this;
    var user = this;
    var subject = this;
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = skill.costShowEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'SKILL CUSTOM SHOW EVAL ERROR');
    }
    return visible;
};

Game_BattlerBase.prototype.meetsSkillConditionsEval = function(skill) {
    if (skill.requireEval === '') return true;
    var value = true;
    var item = skill;
    var a = this;
    var user = this;
    var subject = this;
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = skill.requireEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'SKILL CUSTOM REQUIRE EVAL ERROR');
    }
    return value;
};

Game_BattlerBase.prototype.skillHpCost = function(skill) {
  var cost = skill.hpCost;
  var item = skill;
  var a = this;
  var user = this;
  var subject = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  cost += this.mhp * skill.hpCostPer;
  var code = skill.hpCostEval;
  try {
    eval(code);
  } catch (e) {
    Yanfly.Util.displayError(e, code, 'SKILL CUSTOM HP COST ERROR');
  }
  return Math.max(0, Math.floor(cost));
};

Game_BattlerBase.prototype.skillMpCost = function(skill) {
  var cost = skill.mpCost;
  var item = skill;
  var a = this;
  var user = this;
  var subject = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  cost += this.mmp * skill.mpCostPer;
  var code = skill.mpCostEval;
  try {
    eval(code);
  } catch (e) {
    Yanfly.Util.displayError(e, code, 'SKILL CUSTOM MP COST ERROR');
  }
  return Math.max(0, Math.floor(cost * this.mcr));
};

Game_BattlerBase.prototype.skillTpCost = function(skill) {
  var cost = skill.tpCost;
  var item = skill;
  var a = this;
  var user = this;
  var subject = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  cost += this.maxTp() * skill.tpCostPer;
  var code = skill.tpCostEval;
  try {
    eval(code);
  } catch (e) {
    Yanfly.Util.displayError(e, code, 'SKILL CUSTOM TP COST ERROR');
  }
  return Math.max(0, Math.floor(cost));
};

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

Game_BattlerBase.prototype.canPaySkillHpCost = function(skill) {
    var cost = this.skillHpCost(skill);
    if (cost <= 0) return true;
    return this._hp > cost;
};

Yanfly.Skill.Game_BattlerBase_paySkillCost =
    Game_BattlerBase.prototype.paySkillCost
Game_BattlerBase.prototype.paySkillCost = function(skill) {
	if(!skill.hasTag('DisplayCostOnly')) {
		Yanfly.Skill.Game_BattlerBase_paySkillCost.call(this, skill);
		this.paySkillHpCost(skill);
		this.paySkillEvalCost(skill);
	}
};

Game_BattlerBase.prototype.paySkillHpCost = function(skill) {
    this._hp -= this.skillHpCost(skill);
};

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

Game_BattlerBase.prototype.gauge1 = function() {
    return 'HP';
};

Game_BattlerBase.prototype.gauge2 = function() {
    return 'MP';
};

Game_BattlerBase.prototype.gauge3 = function() {
    return 'TP';
};

Game_BattlerBase.prototype.gaugeIcon1 = function() {
    return 0;
};

Game_BattlerBase.prototype.gaugeIcon2 = function() {
    return 0;
};

Game_BattlerBase.prototype.gaugeIcon3 = function() {
    return 0;
};

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

Game_Actor.prototype.gauge1 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gauge1 === 'UNDEFINED') continue;
      return equip.gauge1;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge1 === 'UNDEFINED') continue;
      return state.gauge1;
    }
    return this.currentClass().gauge1;
};

Game_Actor.prototype.gauge2 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gauge2 === 'UNDEFINED') continue;
      return equip.gauge2;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge2 === 'UNDEFINED') continue;
      return state.gauge2;
    }
    return this.currentClass().gauge2;
};

Game_Actor.prototype.gauge3 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gauge3 === 'UNDEFINED') continue;
      return equip.gauge3;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge3 === 'UNDEFINED') continue;
      return state.gauge3;
    }
    return this.currentClass().gauge3;
};

Game_Actor.prototype.gaugeIcon1 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gaugeIcon1 === 'UNDEFINED') continue;
      return equip.gaugeIcon1;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon1 === 'UNDEFINED') continue;
      return state.gaugeIcon1;
    }
    return this.currentClass().gaugeIcon1;
};

Game_Actor.prototype.gaugeIcon2 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gaugeIcon2 === 'UNDEFINED') continue;
      return equip.gaugeIcon2;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon2 === 'UNDEFINED') continue;
      return state.gaugeIcon2;
    }
    return this.currentClass().gaugeIcon2;
};

Game_Actor.prototype.gaugeIcon3 = function() {
    for (var i = 0; i < this.equips().length; ++i) {
      var equip = this.equips()[i];
      if (!equip) continue;
      if (equip.gaugeIcon3 === 'UNDEFINED') continue;
      return equip.gaugeIcon3;
    }
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon3 === 'UNDEFINED') continue;
      return state.gaugeIcon3;
    }
    return this.currentClass().gaugeIcon3;
};

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

Game_Enemy.prototype.gauge1 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge1 === 'UNDEFINED') continue;
      return state.gauge1;
    }
    return this.enemy().gauge1;
};

Game_Enemy.prototype.gauge2 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge2 === 'UNDEFINED') continue;
      return state.gauge2;
    }
    return this.enemy().gauge2;
};

Game_Enemy.prototype.gauge3 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gauge1 === 'UNDEFINED') continue;
      return state.gauge1;
    }
    return this.enemy().gauge3;
};

Game_Enemy.prototype.gaugeIcon1 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon1 === 'UNDEFINED') continue;
      return state.gaugeIcon1;
    }
    return this.enemy().gaugeIcon1;
};

Game_Enemy.prototype.gaugeIcon2 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon2 === 'UNDEFINED') continue;
      return state.gaugeIcon2;
    }
    return this.enemy().gaugeIcon2;
};

Game_Enemy.prototype.gaugeIcon3 = function() {
    for (var i = 0; i < this.states().length; ++i) {
      var state = this.states()[i];
      if (!state) continue;
      if (state.gaugeIcon3 === 'UNDEFINED') continue;
      return state.gaugeIcon3;
    }
    return this.enemy().gaugeIcon3;
};

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_Action
//=============================================================================

Yanfly.Skill.Game_Action_apply = Game_Action.prototype.apply;
Game_Action.prototype.apply = function(target) {
    this.applyBeforeEffect(target);
    this.applyBeforeEval(target);
    Yanfly.Skill.Game_Action_apply.call(this, target);
    this.applyAfterEffect(target);
    this.applyAfterEval(target);
};

Game_Action.prototype.applyBeforeEffect = function(target) {
};

Game_Action.prototype.applyBeforeEval = function(target) {
    var item = this.item();
    var a = this.subject();
    var b = target;
    var user = this.subject();
    var subject = this.subject();
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = item.customBeforeEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'BEFORE EVAL ERROR');
    }
};

Game_Action.prototype.applyAfterEffect = function(target) {
};

Game_Action.prototype.applyAfterEval = function(target) {
    var item = this.item();
    var a = this.subject();
    var b = target;
    var user = this.subject();
    var subject = this.subject();
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = item.customAfterEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'AFTER EVAL ERROR');
    }
};

Yanfly.Skill.Game_Action_executeDamage = Game_Action.prototype.executeDamage;
Game_Action.prototype.executeDamage = function(target, value) {
    this.applyPreDamageEffect(target, value);
    value = this.applyPreDamageEval(target, value);
    Yanfly.Skill.Game_Action_executeDamage.call(this, target, value);
    this.applyPostDamageEffect(target, value);
    this.applyPostDamageEval(target, value);
};

Game_Action.prototype.applyPreDamageEffect = function(target, value) {
};

Game_Action.prototype.applyPreDamageEval = function(target, value) {
    var item = this.item();
    var a = this.subject();
    var b = target;
    var user = this.subject();
    var subject = this.subject();
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = item.customPreDamageEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'PRE-DAMAGE EVAL ERROR');
    }
    return value;
};

Game_Action.prototype.applyPostDamageEffect = function(target, value) {
};

Game_Action.prototype.applyPostDamageEval = function(target, value) {
    var item = this.item();
    var a = this.subject();
    var b = target;
    var user = this.subject();
    var subject = this.subject();
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = item.customPostDamageEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'POST-DAMAGE EVAL ERROR');
    }
};

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

Yanfly.Skill.Window_Base_drawActorHp = Window_Base.prototype.drawActorHp;
Window_Base.prototype.drawActorHp = function(actor, x, y, width) {
    if (actor.gauge1() === 'HP') {
      Yanfly.Skill.Window_Base_drawActorHp.call(this, actor, x, y, width);
    } else if (actor.gauge1() === 'MP') {
      Yanfly.Skill.Window_Base_drawActorMp.call(this, actor, x, y, width);
    } else if (actor.gauge1() === 'TP') {
      Yanfly.Skill.Window_Base_drawActorTp.call(this, actor, x, y, width);
    }
};

Yanfly.Skill.Window_Base_drawActorMp = Window_Base.prototype.drawActorMp;
Window_Base.prototype.drawActorMp = function(actor, x, y, width) {
    if (actor.gauge2() === 'HP') {
      Yanfly.Skill.Window_Base_drawActorHp.call(this, actor, x, y, width);
    } else if (actor.gauge2() === 'MP') {
      Yanfly.Skill.Window_Base_drawActorMp.call(this, actor, x, y, width);
    } else if (actor.gauge2() === 'TP') {
      Yanfly.Skill.Window_Base_drawActorTp.call(this, actor, x, y, width);
    }
};

Yanfly.Skill.Window_Base_drawActorTp = Window_Base.prototype.drawActorTp;
Window_Base.prototype.drawActorTp = function(actor, x, y, width) {
    if (actor.gauge3() === 'HP') {
      Yanfly.Skill.Window_Base_drawActorHp.call(this, actor, x, y, width);
    } else if (actor.gauge3() === 'MP') {
      Yanfly.Skill.Window_Base_drawActorMp.call(this, actor, x, y, width);
    } else if (actor.gauge3() === 'TP') {
      Yanfly.Skill.Window_Base_drawActorTp.call(this, actor, x, y, width);
    }
};

//=============================================================================
// Window_SkillType
//=============================================================================

Window_SkillType.prototype.itemTextAlign = function() {
    return Yanfly.Param.SCCTextAlign;
};

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

Window_SkillList.prototype.maxCols = function() {
    return Yanfly.Param.SCCWindowCol;
};

Yanfly.Skill.Window_SkillList_includes =
    Window_SkillList.prototype.includes;
Window_SkillList.prototype.includes = function(item) {
    if (this._actor) {
      if (!this._actor.noHiddenSkillConditionsMet(item)) return false;
    }
    return Yanfly.Skill.Window_SkillList_includes.call(this, item);
};

Window_SkillList.prototype.drawSkillCost = function(skill, wx, wy, width) {
    var dw = width;
    dw = this.drawTpCost(skill, wx, wy, dw);
    dw = this.drawMpCost(skill, wx, wy, dw);
    dw = this.drawHpCost(skill, wx, wy, dw);
    dw = this.drawCustomDisplayCost(skill, wx, wy, dw);
    dw = this.drawOtherCost(skill, wx, wy, dw);
    return dw;
};

Window_SkillList.prototype.drawTpCost = function(skill, wx, wy, dw) {
    if (this._actor.skillTpCost(skill) <= 0) return dw;
    if (Yanfly.Icon.Tp > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.Tp, iw, wy + 2);
      dw -= Window_Base._iconWidth + 2;
    }
    this.changeTextColor(this.textColor(Yanfly.Param.SCCTpTextColor));
    var fmt = Yanfly.Param.SCCTpFormat;
    var text = fmt.format(Yanfly.Util.toGroup(this._actor.skillTpCost(skill)),
      TextManager.tpA);
    this.contents.fontSize = Yanfly.Param.SCCTpFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.drawMpCost = function(skill, wx, wy, dw) {
    if (this._actor.skillMpCost(skill) <= 0) return dw;
    if (Yanfly.Icon.Mp > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.Mp, iw, wy + 2);
      dw -= Window_Base._iconWidth + 2;
    }
    this.changeTextColor(this.textColor(Yanfly.Param.SCCMpTextColor));
    var fmt = Yanfly.Param.SCCMpFormat;
    var text = fmt.format(Yanfly.Util.toGroup(this._actor.skillMpCost(skill)),
      TextManager.mpA);
    this.contents.fontSize = Yanfly.Param.SCCMpFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.drawHpCost = function(skill, wx, wy, dw) {
    if (this._actor.skillHpCost(skill) <= 0) return dw;
    if (Yanfly.Icon.Hp > 0) {
      var iw = wx + dw - Window_Base._iconWidth;
      this.drawIcon(Yanfly.Icon.Hp, iw, wy + 2);
      dw -= Window_Base._iconWidth + 2;
    }
    this.changeTextColor(this.textColor(Yanfly.Param.SCCHpTextColor));
    var fmt = Yanfly.Param.SCCHpFormat;
    var text = fmt.format(Yanfly.Util.toGroup(this._actor.skillHpCost(skill)),
      TextManager.hpA);
    this.contents.fontSize = Yanfly.Param.SCCHpFontSize;
    this.drawText(text, wx, wy, dw, 'right');
    var returnWidth = dw - this.textWidth(text) - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.textWidthEx = function(text) {
    return this.drawTextEx(text, 0, this.contents.height);
};

Window_SkillList.prototype.drawCustomDisplayCost = function(skill, wx, wy, dw) {
    this.runDisplayEvalCost(skill);
    if (skill.customCostText === '') return dw;
    var width = this.textWidthEx(skill.customCostText);
    this.resetFontSettings();
    this.drawTextEx(skill.customCostText, wx - width + dw, wy);
    var returnWidth = dw - width - Yanfly.Param.SCCCostPadding;
    this.resetFontSettings();
    return returnWidth;
};

Window_SkillList.prototype.runDisplayEvalCost = function(skill) {
    if (skill.costdisplayEval === '') return;
    var item = skill;
    var a = this._actor;
    var user = this._actor;
    var subject = this._actor;
    var s = $gameSwitches._data;
    var v = $gameVariables._data;
    var code = skill.costdisplayEval;
    try {
      eval(code);
    } catch (e) {
      Yanfly.Util.displayError(e, code, 'SKILL COST DISPLAY EVAL ERROR');
    }
};

Window_SkillList.prototype.drawOtherCost = function(skill, wx, wy, dw) {
    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
//=============================================================================