code:
//=============================================================================
// Yanfly Engine Plugins - Equip Core
// YEP_EquipCore.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.Equip = Yanfly.Equip || {};

//=============================================================================
/*:
* @plugindesc v1.11 Allows for the equipment system to be more flexible to
* allow for unique equipment slots per class.
* @author Yanfly Engine Plugins
*
* @param ---General---
* @default
*
* @param Text Align
* @desc How to align the text for the command window.
* left     center     right
* @default center
*
* @param Finish Command
* @desc The command text used for exiting the equip scene.
* @default Finish
*
* @param Remove Text
* @desc The text used to display the "Remove" command in the equip
* item list.
* @default Remove
*
* @param Remove Icon
* @desc The icon used to display next to the "Remove" command in
* the equip item list.
* @default 16
*
* @param Empty Text
* @desc The text used to display an "Empty" piece of equipment.
* @default <Empty>
*
* @param Empty Icon
* @desc The icon used to display next to the "Empty" piece of
* equipment in the equipment list.
* @default 16
*
* @param ---Rules---
* @default
*
* @param Non-Removable Types
* @desc These types must always have an item equipped and cannot
* be empty. Separate the type ID's by a space.
* @default 1
*
* @param Non-Optimized Types
* @desc These types will be ignored when the actor optimizes
* equips. Separate the type ID's by a space.
* @default 5
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* This plugin alters various aspects regarding equipment handling. The changes
* are as listed:
*
* 1. Scene_Equip
* Scene_Equip has been modified to look differently. This is primarily done to
* make the main menu scenes look uniform and keep everything familiar for
* players. Furthermore, the command window has been adjusted to be better fit
* for extension plugins in the future that may add commands to the command
* window and/or the scene.
*
* 2. Equipment Type Handling
* Characters will no longer have one universal equipment slot setting. Now,
* different classes can use different setups by simply adding a few notetags
* to the class notebox. Furthermore, equipment types in the past with matching
* names would be treated as separate types. Now, equipment types with matching
* names will be treated as the same type.
*
* 3. Equipment Rulings
* Now, certain equipment types can or cannot be removed. For example, this
* plugin can set it so that the Weapon slot must always have something
* equipped and that the player cannot manually leave it empty (the game, on
* the other hand, can achieve this through events). In addition to that,
* optimizing equipment can be restricted for certain equipment types, which
* are better off being decided manually (such as accessories).
*
* 4. Parameter Control
* Equipment parameters can now to be adjusted through notetags to have a large
* value or customized value (through code). This allows for equipment to no
* longer be static items, but instead, equipment can now be dynamic and may
* change over the course of the game.
*
* Note: Item Core Users
* For users using the Item Core plugin and the new Item Scene layout option,
* the Item Info Window is now added to the Equip Scene. Pressing Left/Right
* will toggle the stat comparison window with the info window. Pressing Tab on
* the keyboard will also switch them as well as clicking on those windows.
*
* ============================================================================
* Notetags
* ============================================================================
*
* You can use the following notetags to change a class's equipment setup.
*
* Class Notetags:
*   <Equip Slot: x>      Example: <Equip Slot: 1, 2, 3, 4, 5, 5, 5, 5>
*   <Equip Slot: x, x, x>
*   Changes this class's equipment slots to x. Using repeating numbers makes
*   it so that equipment type is duplicated and that the class can equip
*   multiple equipment of that type. To find the Equipment Type ID, go to your
*   database's Types tab and look for the ID type.
*
*   If you don't like the above method for setting equipment slots, you can
*   use the following notetags instead:
*
*   <Equip Slot>         Example: <Equip Slot>
*    string                        Weapon
*    string                        Armor
*    string                        Accessory
*    string                        Accessory
*   </Equip Slot>                 </Equip Slot>
*   Replace 'string' with the Equipment type's name entry. This is case
*   sensitive so if the string does not match a name entry perfectly, the slot
*   will not be granted to the class. Multiple copies of a name entry would
*   mean the class can equip multiple equipment of that type. Everything works
*   the same as the previous notetag.
*
* Weapon and Armor Notetags:
*   <stat: +x>
*   <stat: -x>
*   Allows the piece of weapon or armor to gain or lose x amount of stat.
*   Replace "stat" with "hp", "mp", "atk", "def", "mat", "mdf", "agi", or
*   "luk" to alter that specific stat. This allows the piece of equipment
*   to go past the editor's default limitation so long as the maximum value
*   allows for it. Changes made here alter the base parameters.
*
* ============================================================================
* Lunatic Mode - Custom Parameters
* ============================================================================
*
*   <Custom Parameters>  Example: <Custom Parameters>
*    code                          atk = $gameVariables.value(1);
*    code                          mat = atk / 2;
*    code                          all = $gameParty.members().length;
*    code                         </Custom Parameters>
*   </Code Parameters>
*   Allows for parameters to have custom rates adjusted by code. The following
*   parameters are defined: 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf',
*   'agi', 'luk', and 'all'. The 'all' parameter will affect all parameters.
*   Changes made here do not alter the base parameters, but instead, are added
*   onto the base parameters.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.11:
* - Updated for RPG Maker MV version 1.1.0.
*
* Version 1.10:
* - Fixed a bug that did not clear changes made to an actor's stats after
* having unequipped them and then switching actors.
*
* Version 1.09:
* - For users using the Item Core plugin and the new Item Scene layout option,
* the Item Info Window is now added to the Equip Scene. Pressing Left/Right
* will toggle the stat comparison window with the info window. Pressing Tab on
* the keyboard will also switch them as well as clicking on those windows.
*
* Version 1.08:
* - Fixed a bug where changing an actor's equips would revive them if dead.
*
* Version 1.07:
* - Fixed a bug with 'Optimize' and 'Remove All' not refreshing windows.
*
* Version 1.06:
* - Fixed a bug with 'Change Equipment' event where it would only change the
* slot of the marked equipment rather than the slot type.
*
* Version 1.05:
* - Fixed an issue where unequipping items can kill actors.
*
* Version 1.04a:
* - Fixed a bug and rewrote the initializing equipment process.
*
* Version 1.03:
* - Fixed an bug that resulted in null object errors.
*
* Version 1.02:
* - Fixed an issue that did not keep HP and MP rates the same when using the
* optimize and clear commands.
*
* Version 1.01:
* - Fixed a bug that did not update the stats properly when compared.
*
* Version 1.00:
* - Finished plugin!
*/

/*:ja
* @plugindesc ver 1.11 クラスごとに独自の装備スロットを提供し、
* 装備のシステムをより柔軟なものにできます。
* @author Yanfly Engine Plugins
*
* @param ---一般---
* @default
*
* @param Text Align
* @desc コマンドウィンドウでのテキストの配置を変更します。
* left(左)    center(中央)    right(右)
* @default center
*
* @param Finish Command
* @desc 装備シーンから出るときのテキストを指定します。
* @default 終了
*
* @param Remove Text
* @desc 装備アイテムリストで"外す"を表すテキストを指定します。
* @default 外す
*
* @param Remove Icon
* @desc 装備アイテムリストで"外す"を表すアイコンを指定します。
* @default 16
*
* @param Empty Text
* @desc 装備リストで、装備品が空であることを表すテキストを指定します。
* @default <空き>
*
* @param Empty Icon
* @desc 装備リストで、装備品が空であることを表すアイコンを指定します。
* @default 16
*
* @param ---ルール---
* @default
*
* @param Non-Removable Types
* @desc ここで指定したタイプは常に何かアイテムを装備していなければなりません。
* 複数のタイプIDを指定する場合はスペースで区切ってください。
* @default 1
*
* @param Non-Optimized Types
* @desc 最強装備の機能使用時に、ここで指定したタイプを無視させます。
* 複数のタイプIDを指定する場合はスペースで区切ってください。
* @default 5
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* このプラグインでは、装備のハンドリングに関するいくつかの要素を変更します。
* 詳細は下記を参照してください:
*
* 1. Scene_Equip
* Scene_Equipは見た目の変更を行います。主にメインメニューの見た目を統一して
* プレイヤーにとって親しみやすいものへと変更します。更に、今後リリースされる
* 拡張プラグインにもきちんと対応できるように、コマンドウィンドウについても
* 最適化されています。
*
* 2. 装備タイプの扱い
* 職業のノートにいくつかNotetagを加えるだけで、異なる職業がそれぞれの
* セッティングを持つことができるようになります。以前は、マッチした名前を持った
* 装備タイプは、単独としてバラバラに扱われていました。このプラグインでは、
* 同じタイプの物として扱うことができます。
*
* 3. 装備ルール
* 特定の装備タイプは外すことができなくなります。例として、このプラグインでは
* 「武器スロットには常に何かしら装備していなくてはならない」というような設定が
* 可能で、プレイヤーは武器を勝手に外すことはできなくなります。(イベントを通して
* 解除させることもできます。) それに加えて、特定の装備タイプを指定して、
* 最強装備を制限することもできます。アクセサリーのような装備品タイプに関しては
* 手動で決定させた方が良いでしょう。
*
* 4. パラメータコントロール
* Notetagを用いることで、装備パラメータに、大きな値やカスタマイズされた値を
* 付与することができます。(コードを通して実行されます)
* 装備品は固定の性能を持ったアイテムではなくなり、これにより、ゲームを通して
* 性能が変動するようなものとなります。
*
* Note: アイテムコア（Item Core）を使用してる方々へ
* アイテムコアのプラグイン、または更新されてるItem Sceneレイアウトオプション
* を使っている方へ。「Item Info Window」は「Equip Scene」に移動されました。
* 左・右キー、タブキー、またはそれぞれのウィンドウをクリックするとパラメータを
* 比べるウィンドウとInfoウィンドウが表示されます。
*
* ============================================================================
* Notetags
* ============================================================================
*
* 職業の装備設定を変更するには、下記のNotetagを用いてください。
*
* 職業のNotetags:
*   <Equip Slot: x>      例: <Equip Slot: 1, 2, 3, 4, 5, 5, 5, 5>
*   <Equip Slot: x, x, x>
*   職業の装備スロットを x に変更してください。繰り返し同じ番号を使うことにより
*   装備タイプを複製し、その職業は同タイプの装備を複数着けることができます。
*   タイプIDを見つけるには、データベースのタイプタブを参照してください。
*
*   上記の方法が気に入らない場合は、下記のNotetagを代わりに用いてください。
*
*   <Equip Slot>            例: <Equip Slot>
*    string                        Weapon
*    string                        Armor
*    string                        Accessory
*    string                        Accessory
*   </Equip Slot>                 </Equip Slot>
*   'string'を装備タイプの名前に変えてください。非常に正確な照合のため、
*   名前欄が完璧にマッチしない場合は、スロットはその職業と認められません。
*   複数コピーされた名前欄は、その職業がそのタイプの装備を複数持てることを
*   表しています。全て、前述のNotetagと同様に動作します。
*
* 武器と防具のNotetags:
*   <stat: +x>
*   <stat: -x>
*   武器もしくは防具のステータスを、 x だけ増加・減少させます。
*   "stat"の部分を"hp", "mp", "atk", "def", "mat", "mdf", "agi", "luk"
*   のような特定のステータスに変更してください。この機能は、デフォルトの
*   最大値の上限を無視して使うことができます。
*   ここで成された変更は、ベースのパラメータを上書きします。
*
* ============================================================================
* Lunatic Mode - Custom Parameters
* ============================================================================
*
*   <Custom Parameters>  　　例: <Custom Parameters>
*    code                          atk = $gameVariables.value(1);
*    code                          mat = atk / 2;
*    code                          all = $gameParty.members().length;
*    code                         </Custom Parameters>
*   </Code Parameters>
*   パラメータに、コードによって適用されたレートを設定することができます。
*   次のパラメータが定義されます: 'maxhp', 'maxmp', 'atk', 'def', 'mat', 'mdf',
*   'agi', 'luk', and 'all'
*   'all' のパラメータは、全てのパラメータに作用します。
*   ここでの変更はベースのパラメータを上書きしませんが、追加保存されます。
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.11:
* - Updated for RPG Maker MV version 1.1.0.
*
* Version 1.10:
* - Fixed a bug that did not clear changes made to an actor's stats after
* having unequipped them and then switching actors.
*
* Version 1.09:
* - For users using the Item Core plugin and the new Item Scene layout option,
* the Item Info Window is now added to the Equip Scene. Pressing Left/Right
* will toggle the stat comparison window with the info window. Pressing Tab on
* the keyboard will also switch them as well as clicking on those windows.
*
* Version 1.08:
* - Fixed a bug where changing an actor's equips would revive them if dead.
*
* Version 1.07:
* - Fixed a bug with 'Optimize' and 'Remove All' not refreshing windows.
*
* Version 1.06:
* - Fixed a bug with 'Change Equipment' event where it would only change the
* slot of the marked equipment rather than the slot type.
*
* Version 1.05:
* - Fixed an issue where unequipping items can kill actors.
*
* Version 1.04a:
* - Fixed a bug and rewrote the initializing equipment process.
*
* Version 1.03:
* - Fixed an bug that resulted in null object errors.
*
* Version 1.02:
* - Fixed an issue that did not keep HP and MP rates the same when using the
* optimize and clear commands.
*
* Version 1.01:
* - Fixed a bug that did not update the stats properly when compared.
*
* Version 1.00:
* - Finished plugin!
*/

//=============================================================================

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

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

Yanfly.Param.EquipTextAlign = String(Yanfly.Parameters['Text Align']);
Yanfly.Param.EquipFinishCmd = String(Yanfly.Parameters['Finish Command']);
Yanfly.Param.EquipRemoveText = String(Yanfly.Parameters['Remove Text']);
Yanfly.Icon.RemoveEquip = Number(Yanfly.Parameters['Remove Icon']);
Yanfly.Param.EquipEmptyText = String(Yanfly.Parameters['Empty Text']);
Yanfly.Icon.EmptyEquip = Number(Yanfly.Parameters['Empty Icon']);
Yanfly.Data = String(Yanfly.Parameters['Non-Removable Types']);
Yanfly.Data = Yanfly.Data.split(' ');
Yanfly.Param.EquipNonRemove = [];
for (Yanfly.i = 0; Yanfly.i < Yanfly.Data.length; ++Yanfly.i) {
  Yanfly.Param.EquipNonRemove.push(parseInt(Yanfly.Data[Yanfly.i]));
};
Yanfly.Data = String(Yanfly.Parameters['Non-Optimized Types']);
Yanfly.Data = Yanfly.Data.split(' ');
Yanfly.Param.EquipNonOptimized = [];
for (Yanfly.i = 0; Yanfly.i < Yanfly.Data.length; ++Yanfly.i) {
  Yanfly.Param.EquipNonOptimized.push(parseInt(Yanfly.Data[Yanfly.i]));
};

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

Yanfly.Equip.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
DataManager.isDatabaseLoaded = function () {
  if (!Yanfly.Equip.DataManager_isDatabaseLoaded.call(this)) return false;
  if (!Yanfly._loaded_YEP_EquipCore) {
    DataManager.processEquipNotetags1($dataClasses);
    DataManager.processEquipNotetags2($dataWeapons);
    DataManager.processEquipNotetags2($dataArmors);
    Yanfly._loaded_YEP_EquipCore = true;
  }
  return true;
};

DataManager.processEquipNotetags1 = function (group) {
  var note1 = /<(?:EQUIP SLOT|equip slots):[ ]*(\d+(?:\s*,\s*\d+)*)>/i;
  var note2 = /<(?:EQUIP SLOT|equip slots)>/i;
  var note3 = /<\/(?:EQUIP SLOT|equip slots)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.equipSlots = [];
    var equipSlots = false;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        var array = JSON.parse('[' + RegExp.$1.match(/\d+/g) + ']');
        obj.equipSlots = obj.equipSlots.concat(array);
      } else if (line.match(note2)) {
        equipSlots = true;
      } else if (line.match(note3)) {
        equipSlots = false;
      } else if (equipSlots && line.match(/[ ]*(.*)/i)) {
        var name = String(RegExp.$1);
        var slotId = $dataSystem.equipTypes.indexOf(name);
        if (slotId >= 0) obj.equipSlots.push(slotId);
      }
    }
    if (obj.equipSlots.length <= 0) this.setDefaultEquipSlots(obj);
  }
};

DataManager.setDefaultEquipSlots = function (obj) {
  for (var i = 1; i < $dataSystem.equipTypes.length; ++i) {
    var name = $dataSystem.equipTypes[i];
    var slotId = $dataSystem.equipTypes.indexOf(name);
    if (slotId >= 0) obj.equipSlots.push(slotId);
  }
};

DataManager.processEquipNotetags2 = function (group) {
  var note1 = /<(?:PARAMETER EVAL|custom parameter|custom parameters)>/i;
  var note2 = /<\/(?:PARAMETER EVAL|custom parameter|custom parameters)>/i;
  var note3 = /<(.*):[ ]([\+\-]\d+)>/i;
  for (var n = 1; n < group.length; n++) {
    var obj = group[n];
    var notedata = obj.note.split(/[\r\n]+/);

    obj.parameterEval = '';
    var parameterEval = false;

    for (var i = 0; i < notedata.length; i++) {
      var line = notedata[i];
      if (line.match(note1)) {
        parameterEval = true;
      } else if (line.match(note2)) {
        parameterEval = false;
      } else if (parameterEval) {
        obj.parameterEval = obj.parameterEval + line + '\n';
      } else if (line.match(note3)) {
        var stat = String(RegExp.$1).toUpperCase();
        var value = parseInt(RegExp.$2);
        switch (stat) {
          case 'HP':
          case 'MAXHP':
          case 'MAX HP':
            obj.params[0] = value;
            break;
          case 'MP':
          case 'MAXMP':
          case 'MAX MP':
          case 'SP':
          case 'MAXSP':
          case 'MAX SP':
            obj.params[1] = value;
            break;
          case 'ATK':
          case 'STR':
            obj.params[2] = value;
            break;
          case 'DEF':
            obj.params[3] = value;
            break;
          case 'MAT':
          case 'INT' || 'SPI':
            obj.params[4] = value;
            break;
          case 'MDF':
          case 'RES':
            obj.params[5] = value;
            break;
          case 'AGI':
          case 'SPD':
            obj.params[6] = value;
            break;
          case 'LUK':
            obj.params[7] = value;
            break;
        }
      }
    }
  }
};

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

Game_Actor.prototype.initEquips = function (equips) {
  var equips = this.convertInitEquips(equips);
  this.equipInitEquips(equips);
  this.releaseUnequippableItems(true);
  this.recoverAll();
  this.refresh();
};

Game_Actor.prototype.convertInitEquips = function (equips) {
  var items = [];
  for (var i = 0; i < equips.length; ++i) {
    var equipId = equips[i];
    if (equipId <= 0) continue;
    var equipType = $dataSystem.equipTypes[i + 1];
    if (equipType === $dataSystem.equipTypes[1] ||
      (i === 1 && this.isDualWield())) {
      var equip = $dataWeapons[equipId];
    } else {
      var equip = $dataArmors[equipId];
    }
    items.push(equip);
  }
  return items;
};

Game_Actor.prototype.equipInitEquips = function (equips) {
  var slots = this.equipSlots();
  var maxSlots = slots.length;
  this._equips = [];
  for (var i = 0; i < maxSlots; ++i) {
    this._equips[i] = new Game_Item();
  }
  for (var i = 0; i < maxSlots; ++i) {
    var slotType = slots[i];
    var equip = this.grabInitEquips(equips, slotType);
    if (this.canEquip(equip)) this._equips[i].setObject(equip);
  }
};

Game_Actor.prototype.grabInitEquips = function (equips, slotType) {
  var item = null;
  for (var i = 0; i < equips.length; ++i) {
    var equip = equips[i];
    if (!equip) continue;
    if (slotType === 1 && DataManager.isWeapon(equip)) {
      item = equip;
      break;
    } else if (equip.etypeId === slotType) {
      item = equip;
      break;
    }
  }
  if (item) equips[i] = null;
  return item;
};

Game_Actor.prototype.equipSlots = function () {
  var slots = this.currentClass().equipSlots.slice();
  if (slots.length >= 2 && this.isDualWield()) slots[1] = 1;
  return slots;
};

Yanfly.Equip.Game_Actor_equips = Game_Actor.prototype.equips;
Game_Actor.prototype.equips = function () {
  for (var i = 0; i < this.currentClass().equipSlots.length; ++i) {
    if (this._equips[i] === undefined || this._equips[i] === null) {
      this._equips[i] = new Game_Item();
    }
  }
  return Yanfly.Equip.Game_Actor_equips.call(this);
};

Yanfly.Equip.Game_Actor_changeEquip = Game_Actor.prototype.changeEquip;
Game_Actor.prototype.changeEquip = function (slotId, item) {
  if (!this._equips[slotId]) this._equips[slotId] = new Game_Item();
  Yanfly.Equip.Game_Actor_changeEquip.call(this, slotId, item);
};

Yanfly.Equip.Game_Actor_forceChangeEquip =
  Game_Actor.prototype.forceChangeEquip;
Game_Actor.prototype.forceChangeEquip = function (slotId, item) {
  if (!this._equips[slotId]) {
    this._equips[slotId] = new Game_Item();
    this._equips[slotId].setEquip(this.equipSlots()[slotId] === 1, 0);
  }
  Yanfly.Equip.Game_Actor_forceChangeEquip.call(this, slotId, item);
};

Yanfly.Equip.Game_Actor_isEquipChangeOk = Game_Actor.prototype.isEquipChangeOk;
Game_Actor.prototype.isEquipChangeOk = function (slotId) {
  if ($gameTemp._clearEquipments) {
    var typeId = this.equipSlots()[slotId];
    if (Yanfly.Param.EquipNonRemove.contains(typeId)) return false;
  }
  if ($gameTemp._optimizeEquipments) {
    var typeId = this.equipSlots()[slotId];
    if (Yanfly.Param.EquipNonOptimized.contains(typeId)) return false;
  }
  return Yanfly.Equip.Game_Actor_isEquipChangeOk.call(this, slotId);
};

Yanfly.Equip.Game_Actor_paramPlus = Game_Actor.prototype.paramPlus;
Game_Actor.prototype.paramPlus = function (paramId) {
  value = Yanfly.Equip.Game_Actor_paramPlus.call(this, paramId);
  var equips = this.equips();
  for (var i = 0; i < equips.length; i++) {
    var item = equips[i];
    if (!item) continue;
    value += this.customParamPlus(item, paramId);
    value += this.evalParamPlus(item, paramId);
  }
  return value;
};

Game_Actor.prototype.customParamPlus = function (item, paramId) {
  return 0;
};

Game_Actor.prototype.evalParamPlus = function (item, paramId) {
  if (!item) return 0;
  if (!item.parameterEval || item.parameterEval === '') return 0;
  var value = 0;
  var hp = 0;
  var maxhp = 0;
  var mhp = 0;
  var mp = 0;
  var maxmp = 0;
  var mmp = 0;
  var sp = 0;
  var maxsp = 0;
  var msp = 0;
  var atk = 0;
  var str = 0;
  var def = 0;
  var mat = 0;
  var int = 0;
  var spi = 0;
  var mdf = 0;
  var res = 0;
  var agi = 0;
  var spd = 0;
  var luk = 0;
  var all = 0;
  var a = this;
  var user = this;
  var s = $gameSwitches._data;
  var v = $gameVariables._data;
  eval(item.parameterEval);
  switch (paramId) {
    case 0:
      value += hp + maxhp + mhp;
      break;
    case 1:
      value += mp + maxmp + mmp + sp + maxsp + msp;
      break;
    case 2:
      value += atk + str;
      break;
    case 3:
      value += def;
      break;
    case 4:
      value += mat + int + spi;
      break;
    case 5:
      value += mdf + res;
      break;
    case 6:
      value += agi + spd;
      break;
    case 7:
      value += luk;
      break;
  }
  return value + all;
};

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

// Change Equipment
Game_Interpreter.prototype.command319 = function () {
  var actor = $gameActors.actor(this._params[0]);
  if (!actor) return true;
  var index = actor.equipSlots().indexOf(this._params[1]) + 1;
  actor.changeEquipById(index, this._params[2]);
  return true;
};

//=============================================================================
// Window_EquipCommand
//=============================================================================

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

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

Window_EquipCommand.prototype.windowHeight = function () {
  return this.fittingHeight(this.numVisibleRows());
};

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

Window_EquipCommand.prototype.itemTextAlign = function () {
  return Yanfly.Param.EquipTextAlign;
};

Yanfly.Equip.Window_EquipCommand_makeCommandList =
  Window_EquipCommand.prototype.makeCommandList;
Window_EquipCommand.prototype.makeCommandList = function () {
  Yanfly.Equip.Window_EquipCommand_makeCommandList.call(this);
  this.addCustomCommand();
  this.addFinishCommand();
};

Window_EquipCommand.prototype.addCustomCommand = function () {
};

Window_EquipCommand.prototype.addFinishCommand = function () {
  this.addCommand(Yanfly.Param.EquipFinishCmd, 'cancel');
};

//=============================================================================
// Window_EquipSlot
//=============================================================================

Yanfly.Equip.Window_EquipSlot_setActor = Window_EquipSlot.prototype.setActor;
Window_EquipSlot.prototype.setActor = function (actor) {
  this.setSlotNameWidth(actor);
  Yanfly.Equip.Window_EquipSlot_setActor.call(this, actor);
};

Window_EquipSlot.prototype.isEnabled = function (index) {
  if (this._actor) {
    return Yanfly.Equip.Game_Actor_isEquipChangeOk.call(this._actor, index);
  } else {
    return false;
  }
};

Window_EquipSlot.prototype.drawItem = function (index) {
  if (!this._actor) return;
  var rect = this.itemRectForText(index);
  this.changeTextColor(this.systemColor());
  this.changePaintOpacity(this.isEnabled(index));
  var ww1 = this._nameWidth;
  this.drawText(this.slotName(index), rect.x, rect.y, ww1);
  var ww2 = rect.width - ww1;
  var item = this._actor.equips()[index];
  if (item) {
    this.drawItemName(item, rect.x + ww1, rect.y, ww2);
  } else {
    this.drawEmptySlot(rect.x + ww1, rect.y, ww2);
  }
  this.changePaintOpacity(true);
};

Window_EquipSlot.prototype.setSlotNameWidth = function (actor) {
  if (!actor) return;
  this._nameWidth = 0;
  for (var i = 0; i < actor.equipSlots().length; ++i) {
    var text = $dataSystem.equipTypes[actor.equipSlots()[i]] + ' ';
    this._nameWidth = Math.max(this._nameWidth, this.textWidth(text));
  }
};

Window_EquipSlot.prototype.drawEmptySlot = function (wx, wy, ww) {
  this.changePaintOpacity(false);
  var ibw = Window_Base._iconWidth + 4;
  this.resetTextColor();
  this.drawIcon(Yanfly.Icon.EmptyEquip, wx + 2, wy + 2);
  var text = Yanfly.Param.EquipEmptyText;
  this.drawText(text, wx + ibw, wy, ww - ibw);
};

Window_EquipSlot.prototype.setInfoWindow = function (infoWindow) {
  this._infoWindow = infoWindow;
  this.update();
};

Yanfly.Equip.Window_ItemList_updateHelp = Window_EquipSlot.prototype.updateHelp;
Window_EquipSlot.prototype.updateHelp = function () {
  Yanfly.Equip.Window_ItemList_updateHelp.call(this);
  if (SceneManager._scene instanceof Scene_Equip && this._infoWindow) {
    this._infoWindow.setItem(this.item());
  }
};

//=============================================================================
// Window_EquipItem
//=============================================================================

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

Yanfly.Equip.Window_EquipItem_setSlotId = Window_EquipItem.prototype.setSlotId;
Window_EquipItem.prototype.setSlotId = function (slotId) {
  // do nothing
};

Yanfly.Equip.Window_EquipItem_includes = Window_EquipItem.prototype.includes;
Window_EquipItem.prototype.includes = function (item) {
  if (item === null && this._actor && this._data.length > 0) {
    var typeId = this._actor.equipSlots()[this._slotId];
    if (Yanfly.Param.EquipNonRemove.contains(typeId)) return false;
  }
  return Yanfly.Equip.Window_EquipItem_includes.call(this, item);
};

Yanfly.Equip.Window_EquipItem_isEnabled =
  Window_EquipItem.prototype.isEnabled;
Window_EquipItem.prototype.isEnabled = function (item) {
  if (item === null && this._actor) {
    var typeId = this._actor.equipSlots()[this._slotId];
    if (Yanfly.Param.EquipNonRemove.contains(typeId)) return false;
  }
  return Yanfly.Equip.Window_EquipItem_isEnabled.call(this, item);
};

Yanfly.Equip.Window_EquipItem_drawItem = Window_EquipItem.prototype.drawItem;
Window_EquipItem.prototype.drawItem = function (index) {
  var item = this._data[index];
  if (item === null) {
    this.drawRemoveEquip(index);
  } else {
    Yanfly.Equip.Window_EquipItem_drawItem.call(this, index);
  }
};

Window_EquipItem.prototype.drawRemoveEquip = function (index) {
  if (!this.isEnabled(null)) return;
  var rect = this.itemRect(index);
  rect.width -= this.textPadding();
  this.changePaintOpacity(true);
  var ibw = Window_Base._iconWidth + 4;
  this.resetTextColor();
  this.drawIcon(Yanfly.Icon.RemoveEquip, rect.x + 2, rect.y + 2);
  var text = Yanfly.Param.EquipRemoveText;
  this.drawText(text, rect.x + ibw, rect.y, rect.width - ibw);
};

Window_EquipItem.prototype.setInfoWindow = function (infoWindow) {
  this._infoWindow = infoWindow;
  this.update();
};

Yanfly.Equip.Window_ItemList_updateHelp = Window_EquipItem.prototype.updateHelp;
Window_EquipItem.prototype.updateHelp = function () {
  Yanfly.Equip.Window_ItemList_updateHelp.call(this);
  if (SceneManager._scene instanceof Scene_Equip && this._infoWindow) {
    this._infoWindow.setItem(this.item());
  }
};

//=============================================================================
// Window_StatCompare
//=============================================================================

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

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

Window_StatCompare.prototype.initialize = function (wx, wy, ww, wh) {
  Window_Base.prototype.initialize.call(this, wx, wy, ww, wh);
  this._actor = null;
  this._tempActor = null;
  this.refresh();
};

Window_StatCompare.prototype.createWidths = function () {
  this._paramNameWidth = 0;
  this._paramValueWidth = 0;
  this._arrowWidth = this.textWidth('\u2192' + ' ');
  var buffer = this.textWidth(' ');
  for (var i = 0; i < 8; ++i) {
    var value1 = this.textWidth(TextManager.param(i));
    var value2 = this.textWidth(Yanfly.Util.toGroup(this._actor.paramMax(i)));
    this._paramNameWidth = Math.max(value1, this._paramNameWidth);
    this._paramValueWidth = Math.max(value2, this._paramValueWidth);
  }
  this._bonusValueWidth = this._paramValueWidth;
  this._bonusValueWidth += this.textWidth('(+)') + buffer;
  this._paramNameWidth += buffer;
  this._paramValueWidth;
  if (this._paramNameWidth + this._paramValueWidth * 2 + this._arrowWidth +
    this._bonusValueWidth > this.contents.width) this._bonusValueWidth = 0;
};

Window_StatCompare.prototype.setActor = function (actor) {
  if (this._actor === actor) return;
  this._actor = actor;
  this.createWidths();
  this.refresh();
};

Window_StatCompare.prototype.refresh = function () {
  this.contents.clear();
  if (!this._actor) return;
  for (var i = 0; i < 8; ++i) {
    this.drawItem(0, this.lineHeight() * i, i);
  }
};

Window_StatCompare.prototype.setTempActor = function (tempActor) {
  if (this._tempActor === tempActor) return;
  this._tempActor = tempActor;
  this.refresh();
};

Window_StatCompare.prototype.drawItem = function (x, y, paramId) {
  this.drawDarkRect(x, y, this.contents.width, this.lineHeight());
  this.drawParamName(y, paramId);
  this.drawCurrentParam(y, paramId);
  this.drawRightArrow(y);
  if (!this._tempActor) return;
  this.drawNewParam(y, paramId);
  this.drawParamDifference(y, paramId);
};

Window_StatCompare.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_StatCompare.prototype.drawParamName = function (y, paramId) {
  var x = this.textPadding();
  this.changeTextColor(this.systemColor());
  this.drawText(TextManager.param(paramId), x, y, this._paramNameWidth);
};

Window_StatCompare.prototype.drawCurrentParam = function (y, paramId) {
  var x = this.contents.width - this.textPadding();
  x -= this._paramValueWidth * 2 + this._arrowWidth + this._bonusValueWidth;
  this.resetTextColor();
  var actorparam = Yanfly.Util.toGroup(this._actor.param(paramId));
  this.drawText(actorparam, x, y, this._paramValueWidth, 'right');
};

Window_StatCompare.prototype.drawRightArrow = function (y) {
  var x = this.contents.width - this.textPadding();
  x -= this._paramValueWidth + this._arrowWidth + this._bonusValueWidth;
  var dw = this.textWidth('\u2192' + ' ');
  this.changeTextColor(this.systemColor());
  this.drawText('\u2192', x, y, dw, 'center');
};

Window_StatCompare.prototype.drawNewParam = function (y, paramId) {
  var x = this.contents.width - this.textPadding();
  x -= this._paramValueWidth + this._bonusValueWidth;
  var newValue = this._tempActor.param(paramId);
  var diffvalue = newValue - this._actor.param(paramId);
  var actorparam = Yanfly.Util.toGroup(newValue);
  this.changeTextColor(this.paramchangeTextColor(diffvalue));
  this.drawText(actorparam, x, y, this._paramValueWidth, 'right');
};

Window_StatCompare.prototype.drawParamDifference = function (y, paramId) {
  var x = this.contents.width - this.textPadding();
  x -= this._bonusValueWidth;
  var newValue = this._tempActor.param(paramId);
  var diffvalue = newValue - this._actor.param(paramId);
  if (diffvalue === 0) return;
  var actorparam = Yanfly.Util.toGroup(newValue);
  this.changeTextColor(this.paramchangeTextColor(diffvalue));
  var text = Yanfly.Util.toGroup(diffvalue);
  if (diffvalue > 0) {
    text = ' (+' + text + ')';
  } else {
    text = ' (' + text + ')';
  }
  this.drawText(text, x, y, this._bonusValueWidth, 'left');
};

//=============================================================================
// Scene_Equip
//=============================================================================

Scene_Equip.prototype.create = function () {
  Scene_MenuBase.prototype.create.call(this);
  this.createHelpWindow();
  this.createCommandWindow();
  this.createStatusWindow();
  this.createSlotWindow();
  this.createItemWindow();
  this.createCompareWindow();
  this._lowerRightVisibility = true;
  this.updateLowerRightWindows();
  this.refreshActor();
};

Scene_Equip.prototype.createCommandWindow = function () {
  var wy = this._helpWindow.height;
  this._commandWindow = new Window_EquipCommand(0, wy, 240);
  this._commandWindow.setHelpWindow(this._helpWindow);
  this._commandWindow.setHandler('equip', this.commandEquip.bind(this));
  this._commandWindow.setHandler('optimize', this.commandOptimize.bind(this));
  this._commandWindow.setHandler('clear', this.commandClear.bind(this));
  this._commandWindow.setHandler('cancel', this.popScene.bind(this));
  this._commandWindow.setHandler('pagedown', this.nextActor.bind(this));
  this._commandWindow.setHandler('pageup', this.previousActor.bind(this));
  this.addWindow(this._commandWindow);
};

Scene_Equip.prototype.createStatusWindow = function () {
  var wx = this._commandWindow.width;
  var wy = this._helpWindow.height;
  var ww = Graphics.boxWidth - wx;
  var wh = this._commandWindow.height;
  this._statusWindow = new Window_SkillStatus(wx, wy, ww, wh);
  this.addWindow(this._statusWindow);
};

Scene_Equip.prototype.createSlotWindow = function () {
  var wy = this._commandWindow.y + this._commandWindow.height;
  var ww = Graphics.boxWidth / 2;
  var wh = Graphics.boxHeight - wy;
  this._slotWindow = new Window_EquipSlot(0, wy, ww, wh);
  this._slotWindow.setHelpWindow(this._helpWindow);
  this._slotWindow.setHandler('ok', this.onSlotOk.bind(this));
  this._slotWindow.setHandler('cancel', this.onSlotCancel.bind(this));
  this.addWindow(this._slotWindow);
};

Scene_Equip.prototype.createItemWindow = function () {
  var wy = this._slotWindow.y;
  var ww = Graphics.boxWidth / 2;
  var wh = Graphics.boxHeight - wy;
  this._itemWindow = new Window_EquipItem(0, wy, ww, wh);
  this._itemWindow.setHelpWindow(this._helpWindow);
  this._itemWindow.setHandler('ok', this.onItemOk.bind(this));
  this._itemWindow.setHandler('cancel', this.onItemCancel.bind(this));
  this._slotWindow.setItemWindow(this._itemWindow);
  this.addWindow(this._itemWindow);
  this._itemWindow.hide();
};

Scene_Equip.prototype.createCompareWindow = function () {
  this._lowerRightWindows = [];
  var wx = this._itemWindow.width;
  var wy = this._itemWindow.y;
  var ww = Graphics.boxWidth - wx;
  var wh = Graphics.boxHeight - wy;
  this._compareWindow = new Window_StatCompare(wx, wy, ww, wh);
  this._slotWindow.setStatusWindow(this._compareWindow);
  this._itemWindow.setStatusWindow(this._compareWindow);
  this.addWindow(this._compareWindow);
  this._lowerRightWindows.push(this._compareWindow);
  if (Imported.YEP_ItemCore && eval(Yanfly.Param.ItemSceneItem)) {
    this.createItemInfoWindow();
  }
};

Scene_Equip.prototype.createItemInfoWindow = function () {
  var wx = this._itemWindow.width;
  var wy = this._itemWindow.y;
  var ww = Graphics.boxWidth - wx;
  var wh = this._itemWindow.height;
  this._infoWindow = new Window_ItemInfo(wx, wy, ww, wh);
  this._slotWindow.setInfoWindow(this._infoWindow);
  this._itemWindow.setInfoWindow(this._infoWindow);
  this.addWindow(this._infoWindow);
  this._lowerRightWindows.push(this._infoWindow);
};

Yanfly.Equip.Scene_Equip_refreshActor = Scene_Equip.prototype.refreshActor;
Scene_Equip.prototype.refreshActor = function () {
  Yanfly.Equip.Scene_Equip_refreshActor.call(this);
  this._compareWindow.setActor(this.actor());
};

Yanfly.Equip.Scene_Equip_commandOptimize =
  Scene_Equip.prototype.commandOptimize;
Scene_Equip.prototype.commandOptimize = function () {
  $gameTemp._optimizeEquipments = true;
  var hpRate = this.actor().hp / Math.max(1, this.actor().mhp);
  var mpRate = this.actor().mp / Math.max(1, this.actor().mmp);
  Yanfly.Equip.Scene_Equip_commandOptimize.call(this);
  $gameTemp._optimizeEquipments = false;
  var max = this.actor().isDead() ? 0 : 1;
  var hpAmount = Math.max(max, parseInt(this.actor().mhp * hpRate));
  this.actor().setHp(hpAmount);
  this.actor().setMp(parseInt(this.actor().mmp * mpRate));
  this._compareWindow.refresh();
  this._statusWindow.refresh();
  this.refreshActor();
};

Yanfly.Equip.Scene_Equip_commandClear = Scene_Equip.prototype.commandClear;
Scene_Equip.prototype.commandClear = function () {
  $gameTemp._clearEquipments = true;
  var hpRate = this.actor().hp / Math.max(1, this.actor().mhp);
  var mpRate = this.actor().mp / Math.max(1, this.actor().mmp);
  Yanfly.Equip.Scene_Equip_commandClear.call(this);
  $gameTemp._clearEquipments = false;
  var max = this.actor().isDead() ? 0 : 1;
  var hpAmount = Math.max(max, parseInt(this.actor().mhp * hpRate));
  this.actor().setHp(hpAmount);
  this.actor().setMp(parseInt(this.actor().mmp * mpRate));
  this._compareWindow.refresh();
  this._statusWindow.refresh();
  this.refreshActor();
};

Yanfly.Equip.Scene_Equip_onSlotOk = Scene_Equip.prototype.onSlotOk;
Scene_Equip.prototype.onSlotOk = function () {
  this._itemWindow._slotId = -1;
  var slotId = this._slotWindow.index();
  Yanfly.Equip.Window_EquipItem_setSlotId.call(this._itemWindow, slotId);
  Yanfly.Equip.Scene_Equip_onSlotOk.call(this);
  this._itemWindow.show();
};

Yanfly.Equip.Scene_Equip_onSlotCancel = Scene_Equip.prototype.onSlotCancel;
Scene_Equip.prototype.onSlotCancel = function () {
  Yanfly.Equip.Scene_Equip_onSlotCancel.call(this);
  if (this._infoWindow) this._infoWindow.setItem(null);
  this._compareWindow.setTempActor(null);
};

Yanfly.Equip.Scene_Equip_onItemOk = Scene_Equip.prototype.onItemOk;
Scene_Equip.prototype.onItemOk = function () {
  var hpRate = this.actor().hp / Math.max(1, this.actor().mhp);
  var mpRate = this.actor().mp / Math.max(1, this.actor().mmp);
  Yanfly.Equip.Scene_Equip_onItemOk.call(this);
  var max = this.actor().isDead() ? 0 : 1;
  var hpAmount = Math.max(max, parseInt(this.actor().mhp * hpRate));
  this.actor().setHp(hpAmount);
  this.actor().setMp(parseInt(this.actor().mmp * mpRate));
  this._itemWindow.hide();
  this._statusWindow.refresh();
};

Yanfly.Equip.Scene_Equip_onItemCancel = Scene_Equip.prototype.onItemCancel;
Scene_Equip.prototype.onItemCancel = function () {
  Yanfly.Equip.Scene_Equip_onItemCancel.call(this);
  this._itemWindow.hide();
};

Scene_Equip.prototype.update = function () {
  Scene_MenuBase.prototype.update.call(this);
  this.updateLowerRightWindowTriggers()
};

Scene_Equip.prototype.updateLowerRightWindowTriggers = function () {
  if (!this._lowerRightVisibility) return;
  if (Input.isRepeated('right')) {
    this.shiftLowerRightWindows();
  } else if (Input.isRepeated('left')) {
    this.unshiftLowerRightWindows();
  } else if (Input.isRepeated('tab')) {
    this.shiftLowerRightWindows();
  } else if (this.isLowerWindowTouched()) {
    this.shiftLowerRightWindows();
  }
};

Scene_Equip.prototype.isLowerWindowTouched = function () {
  if (!TouchInput.isTriggered()) return false;
  var x = TouchInput.x;
  var y = TouchInput.y;
  var rect = new Rectangle();
  rect.x = this._compareWindow.x;
  rect.y = this._compareWindow.y;
  rect.width = this._compareWindow.x + this._compareWindow.width;
  rect.height = this._compareWindow.y + this._compareWindow.height;
  return (x >= rect.x && y >= rect.y && x < rect.width && y < rect.height);
};

Scene_Equip.prototype.updateLowerRightWindows = function () {
  var length = this._lowerRightWindows.length;
  for (var i = 0; i < length; ++i) {
    var win = this._lowerRightWindows[i];
    win.visible = false;
  }
  this._lowerRightWindows[0].visible = this._lowerRightVisibility;
};

Scene_Equip.prototype.shiftLowerRightWindows = function () {
  var win = this._lowerRightWindows.shift();
  this._lowerRightWindows.push(win);
  this.updateLowerRightWindows();
  this.playLowerRightWindowSound();
};

Scene_Equip.prototype.unshiftLowerRightWindows = function () {
  var win = this._lowerRightWindows.pop();
  this._lowerRightWindows.unshift(win);
  this.updateLowerRightWindows();
  this.playLowerRightWindowSound();
};

Scene_Equip.prototype.playLowerRightWindowSound = function () {
  if (this._lowerRightWindows.length <= 1) return;
  SoundManager.playCursor();
};

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

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

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

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

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// Yanfly Engine Plugins - Event Chase Player
// YEP_EventChasePlayer.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.ECP = Yanfly.ECP || {};

//=============================================================================
/*:
* @plugindesc v1.03 When a player is in the proximity of a certain event,
* the event will start chasing or fleeing from the player.
* @author Yanfly Engine Plugins
*
* @param Sight Lock
* @desc This is the number of frames for how long an event chases
* the player if 'this._seePlayer = true' is used.
* @default 300
*
* @param See Player
* @desc Does the event have to be able to see the player by default?
* NO - false     YES - true
* @default true
*
* @param Alert Timer
* @desc This is the number of frames that must occur before the
* alert balloon will show up on the same event.
* @default 120
*
* @param Alert Balloon
* @desc This is the default balloon used when the player is seen.
* Refer to balloon ID's.
* @default 1
*
* @param Alert Sound
* @desc This is the default sound played when the player is seen.
* @default Attack1
*
* @param Alert Common Event
* @desc The default common event played when the player is seen.
* Use 0 if you do not wish to use a Common Event.
* @default 0
*
* @param Return After
* @desc After chasing/fleeing from a player, the event returns
* to its original spot. NO - false   YES - true
* @default true
*
* @param Return Wait
* @desc The frames to wait after finishing a chase/flee.
* @default 180
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* This plugin allows you to make events that will chase the player or flee
* from the player when the player enters within range of the event or when the
* event sees the player.
*
* ============================================================================
* How to Use
* ============================================================================
*
* Insert these lines into the script call window within the Movement Route
* event to give an event the chase or flee flag.
*
* Note: This doesn’t work with players.
*
* Script Call lines
*  this._chaseRange = x       Event will chase player if reaching x range.
*  this._fleeRange = x        Event will flee from player if reaching x range.
*  this._chaseSpeed = x       Event's movement speed when chasing.
*  this._fleeSpeed = x        Event's movement speed when fleeing.
*  this._sightLock = x        Event will flee/chase player for x frames.
*  this._seePlayer = true     Requires the event to be able to see player.
*  this._seePlayer = false    Doesn't require event to be able to see player.
*  this._alertBalloon = x     This balloon will play when player is seen.
*  this._alertSound = x       This sound will play when player is seen.
*  this._alertSoundVol = x    The volume used by the alert sound.
*  this._alertSoundPitch = x  The pitch used by the alert sound.
*  this._alertSoundPan = x    The pan used by the alert sound.
*  this._alertCommonEvent = x This event will play when player is seen.
*  this._returnAfter = true   Returns the event back to its original spot.
*  this._returnAfter = false  Event stays where it is when finished chasing.
*  this._returnWait = x       How long event waits after finishing chase/flee.
*
* It is best to play this inside of a custom move route for the event at a
* high frequency rate. Keep in mind these effects only occur after the setting
* is made and ran, which means upon loading a map, if the event with a low
* frequency hasn't loaded up 'this._chaseRange = x' in its movement queue yet,
* the event will not chase the player just yet.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.03:
* - Improved pathfinding for chasing events. They will get stuck less by walls
* and/or events that may be blocking the event.
* - Added random factor for fleeing events. Fleeing events won't simply just
* run away 180 degrees away from the player. They will sometimes move in a
* random direction.
*
* Version 1.02:
* - Added 'Return After' parameter where events will return to their original
* spot after chasing/fleeing from a player.
* - Added 'Return Wait' parameter to determine how long an event will wait in
* place before returning after a finished chase/flee.
* - Added 'this._returnAfter' and 'this._returnWait' to the list of available
* movement route script calls.
*
* Version 1.01:
* - Added 'this._alertSoundPitch' 'this._alertSoundVol' 'this._alertSoundPan'
* to the settings you can alter to adjust the alert sound.
*
* Version 1.00:
* - Finished Plugin!
*/

/*:ja
* @plugindesc v1.03 プレイヤーが特定のイベントに近づくと、イベントがプレイヤーを追いかけたりプレイヤーから逃げます
* @author Yanfly Engine Plugins
*
* @param Sight Lock
* @desc 'SeePlayer'がtrueの時、イベントがプレイヤーを追いかける
* 時間を設定します(フレーム単位)
* @default 300
*
* @param See Player
* @desc イベントがプレイヤーを認識する必要があるかを設定します
* 不要 - false     必要 - true
* @default true
*
* @param Alert Timer
* @desc 同じイベント上でフキダシが表示されるまでにかかるフレーム数を指定します
* @default 120
*
* @param Alert Balloon
* @desc プレイヤーが認識された際に表示される、フキダシを指定します
* (フキダシのIDで指定します)
* @default 1
*
* @param Alert Sound
* @desc プレイヤーが認識された際に表示される、サウンドを指定します
* @default Attack1
*
* @param Alert Common Event
* @desc 認識された際に再生されるコモンイベントを指定します
* 利用しない場合は、0のままにしてください
* @default 0
*
* @param Return After
* @desc 追跡または逃走した後に、イベントがもとの位置に戻ります
* いいえ - false   はい - true
* @default true
*
* @param Return Wait
* @desc 追跡または逃走したあとに、待機するフレーム数を指定します
* @default 180
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* このプラグインでは、プレイヤーを追いかけるイベント、もしくは
* プレイヤーから逃げるイベントを作成することができます。
* プレイヤーがイベントから一定の距離範囲内に入った時や
* イベントがプレイヤーを認識した際に発動させることができます。
*
* ============================================================================
* How to Use
* ============================================================================
*
* 下記のコードをスクリプトコールウィンドウ内の、
* Movement Routeイベント内に挿入することで、そのイベントに
* 追跡もしくは逃走のフラグを付与することができます。
*
* 注＊プレイヤーに対しては無効です。
*
* Script Call lines
*  this._chaseRange = x
*              →x の距離内に入った時、イベントがプレイヤーを追いかけます
*  this._fleeRange = x
*              →x の距離内に入った時、イベントはプレイヤーから逃げます
*  this._chaseSpeed = x
*              →追いかける時のイベントの速度 x を決定します
*  this._fleeSpeed = x
*              →逃げる時のイベントの速度 x を決定します
*  this._sightLock = x
*              →イベントは、フレーム数 x だけ追跡/逃走を行います
*  this._seePlayer = true
*              →イベントはプレイヤーを認識する必要があります
*  this._seePlayer = false
*              →イベントはプレイヤーを認識する必要がありません
*  this._alertBalloon = x
*              →プレイヤーが認識されると、x というフキダシを表示します
*  this._alertSound = x
*              →プレイヤーが認識されると、x というサウンドを再生します
*  this._alertSoundVol = x
*              →プレイヤーが認識されたときに再生される音の音量を指定します
*  this._alertSoundPitch = x
*              →プレイヤーが認識されたときに再生される音のピッチを指定します
*  this._alertSoundPan = x
*              →プレイヤーが認識されたときに再生される音のパンを指定します
*  this._alertCommonEvent = x
*              →プレイヤーが認識されると、x というイベントを再生します
*  this._returnAfter = true
*              →イベントを元の位置に戻します
*  this._returnAfter = false
*              →追跡/逃走が終わってもイベントはそこにとどまります
*  this._returnWait = x
*              →追跡/逃走が終わったあと x の間待機します
*
* カスタムした移動ルート内でイベントを再生させる際は、
* 移動頻度はなるべく高く設定するようにしてください。
* 設定が完了し有効になるまでは、これらのエフェクトは発動しません。
* 移動頻度の低いイベントですと、マップロード中に'this._chaseRange = x'の
* 読み込みを完了できず、プレイヤーを追いかけなくなってしまう可能性があります。
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.03:
* - Improved pathfinding for chasing events. They will get stuck less by walls
* and/or events that may be blocking the event.
* - Added random factor for fleeing events. Fleeing events won't simply just
* run away 180 degrees away from the player. They will sometimes move in a
* random direction.
*
* Version 1.02:
* - Added 'Return After' parameter where events will return to their original
* spot after chasing/fleeing from a player.
* - Added 'Return Wait' parameter to determine how long an event will wait in
* place before returning after a finished chase/flee.
* - Added 'this._returnAfter' and 'this._returnWait' to the list of available
* movement route script calls.
*
* Version 1.01:
* - Added 'this._alertSoundPitch' 'this._alertSoundVol' 'this._alertSoundPan'
* to the settings you can alter to adjust the alert sound.
*
* Version 1.00:
* - Finished Plugin!
*/
//=============================================================================

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

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

Yanfly.Param.ECPSightLock = Number(Yanfly.Parameters['Sight Lock']);
Yanfly.Param.ECPSeePlayer = String(Yanfly.Parameters['See Player']);
Yanfly.Param.ECPAlertTimer = Number(Yanfly.Parameters['Alert Timer']);
Yanfly.Param.ECPAlertBalloon = Number(Yanfly.Parameters['Alert Balloon']);
Yanfly.Param.ECPAlertSound = String(Yanfly.Parameters['Alert Sound']);
Yanfly.Param.ECPAlertEvent = Number(Yanfly.Parameters['Alert Common Event']);
Yanfly.Param.ECPReturn = eval(String(Yanfly.Parameters['Return After']));
Yanfly.Param.ECPReturnWait = Number(Yanfly.Parameters['Return Wait']);

//=============================================================================
// Main Code
//=============================================================================

Yanfly.ECP.Game_Event_setupPage = Game_Event.prototype.setupPage;
Game_Event.prototype.setupPage = function () {
  Yanfly.ECP.Game_Event_setupPage.call(this);
  this.clearChaseSettings();
};

Game_Event.prototype.clearChaseSettings = function () {
  this._alertBalloon = Yanfly.Param.ECPAlertBalloon;
  this._alertCommonEvent = Yanfly.Param.ECPAlertEvent;
  this._alertLock = 0;
  this._alertPlayer = false;
  this._alertSound = Yanfly.Param.ECPAlertSound;
  this._alertSoundVol = 100;
  this._alertSoundPitch = 100;
  this._alertSoundPan = 0;
  this._alertTimer = 0;
  this._chasePlayer = false;
  this._chaseRange = 0;
  this._chaseSpeed = this._moveSpeed;
  this._defaultSpeed = this._moveSpeed;
  this._fleePlayer = false;
  this._fleeRange = 0;
  this._fleeSpeed = this._moveSpeed;
  this._seePlayer = eval(Yanfly.Param.ECPSeePlayer);
  this._sightLock = eval(Yanfly.Param.ECPSightLock);
  this._returnAfter = Yanfly.Param.ECPReturn;
  this._returnWait = Yanfly.Param.ECPReturnWait;
  this._returnPhase = false;
  this._returnFrames = 0;
  this._startLocationX = this.x;
  this._startLocationY = this.y;
  this._startLocationDir = this._direction;
};

Yanfly.ECP.Game_Event_updateSelfMovement =
  Game_Event.prototype.updateSelfMovement;
Game_Event.prototype.updateSelfMovement = function () {
  if (Imported.YEP_StopAllMove && $gameSystem.isEventMoveStopped()) return;
  this.updateChaseDistance();
  this.updateFleeDistance();
  this.updateChaseMovement();
};

Yanfly.ECP.Game_Event_update = Game_Event.prototype.update;
Game_Event.prototype.update = function () {
  Yanfly.ECP.Game_Event_update.call(this);
  this.updateAlert();
  this.updateReturnPhase();
};

Game_Event.prototype.canSeePlayer = function () {
  if (!this._seePlayer) return false;
  var sx = this.deltaXFrom($gamePlayer.x);
  var sy = this.deltaYFrom($gamePlayer.y);
  if (Math.abs(sx) > Math.abs(sy)) {
    var direction = (sx > 0) ? 4 : 6;
  } else {
    var direction = (sy > 0) ? 8 : 2;
  }
  if (direction === this.direction()) {
    this._alertLock = this._sightLock;
    return true;
  }
  return false;
};

Game_Event.prototype.updateChaseDistance = function () {
  if (this._erased) return;
  if (this._chaseRange <= 0) return;
  var dis = Math.abs(this.deltaXFrom($gamePlayer.x));
  dis += Math.abs(this.deltaYFrom($gamePlayer.y));
  if (this.chaseConditions(dis)) {
    this.startEventChase();
  } else if (this._chasePlayer) {
    this.endEventChase();
  }
};

Game_Event.prototype.chaseConditions = function (dis) {
  if (this._alertLock > 0) return true;
  if (dis <= this._chaseRange && this.canSeePlayer()) return true;
  if (dis <= this._chaseRange && !this._seePlayer) {
    this._alertLock = this._sightLock;
    return true;
  }
  return false;
};

Game_Event.prototype.startEventChase = function () {
  this._chasePlayer = true;
  this.setMoveSpeed(this._chaseSpeed);
};

Game_Event.prototype.endEventChase = function () {
  this._chasePlayer = false;
  this.setMoveSpeed(this._defaultSpeed);
  if (this._alertTimer <= 0) this._alertPlayer = false;
  this.startReturnPhase();
};

Game_Event.prototype.updateFleeDistance = function () {
  if (this._erased) return;
  if (this._fleeRange <= 0) return;
  var dis = Math.abs(this.deltaXFrom($gamePlayer.x));
  dis += Math.abs(this.deltaYFrom($gamePlayer.y));
  if (this.fleeConditions(dis)) {
    this.startEventFlee();
  } else if (this._fleePlayer) {
    this.endEventFlee();
  }
};

Game_Event.prototype.fleeConditions = function (dis) {
  if (this._alertLock > 0) return true;
  if (dis <= this._fleeRange && this.canSeePlayer()) return true;
  if (dis <= this._fleeRange && !this._seePlayer) {
    this._alertLock = this._sightLock;
    return true;
  }
  return false;
};

Game_Event.prototype.startEventFlee = function () {
  this._fleePlayer = true;
  this.setMoveSpeed(this._fleeSpeed);
};

Game_Event.prototype.endEventFlee = function () {
  this._fleePlayer = false;
  this.setMoveSpeed(this._defaultSpeed);
  if (this._alertTimer <= 0) this._alertPlayer = false;
  this.startReturnPhase();
};

Game_Event.prototype.updateChaseMovement = function () {
  if (this._stopCount > 0 && this._chasePlayer) {
    var direction = this.findDirectionTo($gamePlayer.x, $gamePlayer.y);
    if (direction > 0) this.moveStraight(direction);
  } else if (this._stopCount > 0 && this._fleePlayer) {
    this.updateFleeMovement();
  } else if (this._returnPhase) {
    this.updateMoveReturnAfter();
  } else {
    Yanfly.ECP.Game_Event_updateSelfMovement.call(this);
  }
};

Game_Event.prototype.updateFleeMovement = function () {
  switch (Math.randomInt(6)) {
    case 0: case 1: case 2: case 3: case 4:
      this.moveAwayFromPlayer();
      break;
    case 5:
      this.moveRandom();
      break;
  }
};

Game_Event.prototype.updateAlert = function () {
  if (this._erased) return;
  this._alertLock--;
  if (this.alertConditions()) this.activateAlert();
  if (this._alertPlayer) this._alertTimer--;
};

Game_Event.prototype.alertConditions = function () {
  return (this._chasePlayer || this._fleePlayer) && !this._alertPlayer;
};

Game_Event.prototype.activateAlert = function () {
  if (this._alertBalloon >= 0) this.requestBalloon(this._alertBalloon);
  this._alertPlayer = true;
  this._alertTimer = Yanfly.Param.ECPAlertTimer;
  this.playAlertSound();
  this.playAlertCommonEvent();
};

Game_Event.prototype.playAlertSound = function () {
  if (this._alertSound === '') return;
  var sound = {
    name: this._alertSound,
    volume: this._alertSoundVol,
    pitch: this._alertSoundPitch,
    pan: this._alertSoundPan
  };
  AudioManager.playSe(sound);
};

Game_Event.prototype.playAlertCommonEvent = function () {
  if (this._alertCommonEvent <= 0) return;
  $gameTemp.reserveCommonEvent(this._alertCommonEvent);
};

Game_Event.prototype.startReturnPhase = function () {
  if (!this._returnAfter) return;
  this._returnPhase = true;
  this._returnFrames = this._returnWait;
};

Game_Event.prototype.updateReturnPhase = function () {
  if (this._returnPhase) this._returnFrames--;
};

Game_Event.prototype.updateMoveReturnAfter = function () {
  if (this._returnFrames > 0) return;
  var sx = this.deltaXFrom(this._startLocationX);
  var sy = this.deltaYFrom(this._startLocationY);
  if (Math.abs(sx) > Math.abs(sy)) {
    if (Math.randomInt(6) <= 4) {
      this.moveStraight(sx > 0 ? 4 : 6);
      if (!this.isMovementSucceeded() && sy !== 0) {
        this.moveStraight(sy > 0 ? 8 : 2);
      }
    } else {
      this.moveRandom();
    }
  } else if (sy !== 0) {
    if (Math.randomInt(6) <= 4) {
      this.moveStraight(sy > 0 ? 8 : 2);
      if (!this.isMovementSucceeded() && sx !== 0) {
        this.moveStraight(sx > 0 ? 4 : 6);
      }
    } else {
      this.moveRandom();
    }
  }
  if (sx === 0 && sy === 0) {
    this._returnPhase = false;
    this._returnFrames = 0;
    this._direction = this._startLocationDir;
  }
};

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


code:
//=============================================================================
// Yanfly Engine Plugins - Template
// YEP_GabWindow.js
//=============================================================================

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

var Yanfly = Yanfly || {};
Yanfly.Gab = Yanfly.Gab || {};

//=============================================================================
/*:
* @plugindesc v1.03a The Gab Window functions as a window for random
* jibber jabber that does not require a message window.
* @author Yanfly Engine Plugins
*
* @param ---General---
* @default
*
* @param Gab Font Name
* @desc The font name used for the text of the Gab Window.
* Default: GameFont
* @default GameFont
*
* @param Gab Font Size
* @desc The font size used for the text of the Gab Window.
* Default: 28
* @default 28
*
* @param Character X Pos
* @desc X position of the character.
* Default: 36
* @default 36
*
* @param Character Y Pos
* @desc Y position of the character.
* Default: 60
* @default 60
*
* @param Base Wait Time
* @desc Minimum frames the Gab Window stays visible.
* Default: 90
* @default 90
*
* @param Time Per Character
* @desc Frames added per Text Character.
* Default: 4
* @default 4
*
* @param Fade Rate
* @desc Is is how fast the gab window fades away.
* Default: 16
* @default 16
*
* @param Anti-Repeat
* @desc Stops gabs of the same settings from being queued.
* NO - false     YES - true
* @default true
*
* @param ---Map---
* @default
*
* @param Map Y Location
* @desc This is the Y location of the Gab Window.
* Default: 72
* @default 72
*
* @param Map Dim Color 1
* @desc This is the dim color 1 used for maps.
* Default: rgba(0, 0, 0, 0.6)
* @default rgba(0, 0, 0, 0.6)
*
* @param Map Dim Color 2
* @desc This is the dim color 2 used for maps.
* Default: rgba(0, 0, 0, 0.3)
* @default rgba(0, 0, 0, 0.3)
*
* @param ---Battle---
* @default
*
* @param Battle Y Location
* @desc This is the Y location of the Gab Window.
* Default: 108
* @default 108
*
* @param Battle Dim Color 1
* @desc This is the dim color 1 used for battles.
* Default: rgba(0, 0, 0, 0.6)
* @default rgba(0, 0, 0, 0.6)
*
* @param Battle Dim Color 2
* @desc This is the dim color 2 used for battles.
* Default: rgba(0, 0, 0, 0)
* @default rgba(0, 0, 0, 0)
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* Sometimes there's random jibber jabber that does not warrant a message box.
* The Gab Window fulfills that jibber jabber by placing such text outside of
* the message window box and at the corner of the screen. The gab text will
* appear briefly and then disappear, not showing up again until the gab text
* is updated with something else.
*
* New to the MV version is the ability to play sounds for your Gab Window in
* addition to queueing multiple gabs together to have them form a conversation
* of sorts. When queued up, the currently playing gab will continue showing
* until it fades out before loading up the next gab.
*
* ============================================================================
* Instructions
* ============================================================================
*
* Using the Gab Window is quite simple. By default, it can be used in either
* the map scene or the battle scene. To call upon it, you will to use a few
* Plugin Commands to set up what you wish for the Gab Window to display.
*
* Plugin Commands:
*
* --- Setup Commands ---
*
* GabText text
* This will set the gab window to type out the above text. Text codes can be
* used for the Gab Window.
*
* GabFaceName filename
* If you wish to display a face graphic, use this plugin command to have it
* display a face from the filename.
*
* GabFaceIndex x
* Used in combination with the above plugin command to define which index the
* face will use.
*
* GabSpriteName filename
* If you wish to display a particular character sprite, use this plugin
* command to have it display a sprite from the filename.
*
* GabSpriteIndex x
* Used in combination with the above plugin command to define which index the
* sprite will use.
*
* GabActor x
* GabActorFace x
* This will display actor x's face graphic where x is the actor's ID.
*
* GabActorSprite x
* This will display actor x's sprite graphic where x is the actor's ID.
*
* GabParty x
* GabPartyFace x
* This will display party member x's face graphic where x is the position.
*
* GabPartySprite x
* This will display party member x's sprite graphic where x is the position.
*
* GabSound filename
* This will play a sound from the SE folder under that particular filename.
*
* GabSwitch x
* This will enable switch x when this gab finishes playing.
*
* --- Display Commands ---
*
* ShowGab
* Once the above settings are complete, use this Plugin Command to launch the
* Gab Window and display the above data. This will put the gab data into a
* queue which means if there's another gab playing, this will be next in line.
*
* *Note If multiple ShowGabs are used, they will be queued up. The current
* playing gab will finish playing before moving onto the next. If it so
* happens that the inputted Gab would have the same exact settings as a
* previously loaded gab within the same queue, it will not be inserted to
* prevent any redundancy amongst the conversation.
*
* ForceGab
* Once the above settings are complete, use this Plugin Command to clear all
* the other gabs in the Gab Window and display the above data.
*
* ClearGab
* This clears out the Gab Window of the current gab and any gabs queued.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.03a:
* - Fixed a bug with GabSound that didn't load the proper sound filenames.
* - Fixed the time count for Gabs to not include text codes.
*
* Version 1.02a:
* - Added functionality for battle gabs to be saved when going into other
* scenes and returning to battle.
* - Added GabSwitch x to enable switch x when the gab finishes playing.
*
* Version 1.01:
* - Added 'GabParty x' and 'GabPartySprite x' plugin commands to help with
* those without dynamic party setups.
*
* Version 1.00:
* - Finished Plugin!
*
*/
/*:ja
* @plugindesc v1.03a "Gab Window"はメッセージウィンドウ無しで画面上におしゃべりを表示できるプラグインです。
* @author Yanfly Engine Plugins
*
* @param ---一般---
* @default
*
* @param Gab Font Name
* @desc Gab Windowで使われるフォント名を指定してください
* デフォルト: GameFont
* @default GameFont
*
* @param Gab Font Size
* @desc Gab Windowで使われるフォントサイズを指定してください
* デフォルト: 28
* @default 28
*
* @param Character X Pos
* @desc キャラクター表示のX座標を指定してください
* デフォルト: 36
* @default 36
*
* @param Character Y Pos
* @desc キャラクター表示のY座標を指定してください
* デフォルト: 60
* @default 60
*
* @param Base Wait Time
* @desc Gab Windowの表示が続く最小フレーム数を指定してください
* デフォルト: 90
* @default 90
*
* @param Time Per Character
* @desc テキストキャラクターごとに追加されるフレーム数を指定してください
* デフォルト: 4
* @default 4
*
* @param Fade Rate
* @desc Gab Windowがフェードアウトする速さを指定してください
* デフォルト: 16
* @default 16
*
* @param Anti-Repeat
* @desc 同じ設定のGab Windowがキュー処理されるのを防ぎますか？
* いいえ - false     はい - true
* @default true
*
* @param ---マップ時---
* @default
*
* @param Map Y Location
* @desc Gab Window表示のY座標を指定してください。
* デフォルト: 72
* @default 72
*
* @param Map Dim Color 1
* @desc マップ時に用いられる、背景色1 を指定してください。
* デフォルト: rgba(0, 0, 0, 0.6)
* @default rgba(0, 0, 0, 0.6)
*
* @param Map Dim Color 2
* @desc マップ時に用いられる、背景色2 を指定してください。
* デフォルト: rgba(0, 0, 0, 0.3)
* @default rgba(0, 0, 0, 0.3)
*
* @param ---戦闘---
* @default
*
* @param Battle Y Location
* @desc Gab Window表示のY座標を指定してください。
* Default: 108
* @default 108
*
* @param Battle Dim Color 1
* @desc 戦闘時に用いられる、背景色1 を指定してください。
* デフォルト: rgba(0, 0, 0, 0.6)
* @default rgba(0, 0, 0, 0.6)
*
* @param Battle Dim Color 2
* @desc 戦闘時に用いられる、背景色2 を指定してください。
* デフォルト: rgba(0, 0, 0, 0)
* @default rgba(0, 0, 0, 0)
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* ウィンドウを必要とするまでもないような、おしゃべりを表示させたいですか？
* "Gab Window"はメッセージウィンドウ外、画面の隅で、そのようなおしゃべりを表示
* させることができます。テキストは一時的に画面上に表示され、その後消えます。
* 何か他の要因が介入しない限りは、また表れることもありません。
*
* MVでの新しい要素としては、あなたのゲーム内のGab Windowに音を付けることが
* できます。また、複数のおしゃべりをまとめてキュー処理し、会話のようにつなげる
* こともできます。その際、現在表示されているおしゃべりは、次のおしゃべりが
* ロードされるタイミングでフェードアウトします。
*
* ============================================================================
* Instructions
* ============================================================================
*
* "Gab Window"の使い方はとってもシンプルです。デフォルト設定では、マップでも
* バトルシーンでも使うことができるようになっています。表示の指示・設定をする
* には、下記のプラグインコマンドを用いてください。
*
* プラグインコマンド:
*
* --- セットアップコマンド ---
*
* GabText text
* Gab Windowに、このテキストを表示させます。Gab Window内では
* テキストコードを使うこともできます。
*
* GabFaceName filename
* 顔グラフィックを表示させたい場合は、このコマンドを用いてファイル名を指定
* してください。
*
* GabFaceIndex x
* 上記のコマンドと一緒に用いることで、その顔グラフィックがどのインデックスを
* 使うかを指定します。
*
* GabSpriteName filename
* 特定のキャラクタースプライトを表示させたい時は、このコマンドを使って
* ファイル名を指定してください。
*
* GabSpriteIndex x
* 上記のコマンドと一緒に用いることで、そのスプライトがどのインデックスを
* 使うかを指定します。
*
* GabActor x
* GabActorFace x
* アクター x の顔グラフィックを表示させます。（xにはIDを入れてください)
*
* GabActorSprite x
* アクター x のスプライトを表示させます。（xにはIDを入れてください)
*
* GabParty x
* GabPartyFace x
* パーティメンバー x の顔グラフィックを表示させます。（xにはポジションを
* 入れてください)
*
* GabPartySprite x
* パーティメンバー x のスプライトを表示させます。（xにはポジションを
* 入れてください)
*
* GabSound filename
* SEフォルダから、filenameで指定したサウンドを再生します。
*
* GabSwitch x
* おしゃべりの再生が終了したときに、スイッチ x を有効にします。
*
* --- Display Commands ---
*
* ShowGab
* 一旦上記の設定が完了したら、このプラグインコマンドを使ってGab Windowを
* 起動し、上記のデータを表示させます。これによりおしゃべりがキューに追加され、
* もし他のおしゃべりが再生されている場合は、そのうしろに並ぶようになります。
*
* *注意：複数の"ShowGabs"が使用されると、それらは一列に並びます。現在再生され
* ているおしゃべりは、次のおしゃべりに移る前に終了します。新たに追加しようと
* したおしゃべりが、たまたまロード済のおしゃべりと全く同じ設定だった場合、
* 会話内の重複を防ぐため、新規追加は行われません。
*
* ForceGab
* 一旦上記の設定が完了したら、このプラグインコマンドを使って他の全ての他の
* おしゃべりを消去し、上記のデータを表示させます。
*
* ClearGab
* 現在のおしゃべりのGab Windowと、待機中のおしゃべりを全て消去します。
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.03a:
* - Fixed a bug with GabSound that didn't load the proper sound filenames.
* - Fixed the time count for Gabs to not include text codes.
*
* Version 1.02a:
* - Added functionality for battle gabs to be saved when going into other
* scenes and returning to battle.
* - Added GabSwitch x to enable switch x when the gab finishes playing.
*
* Version 1.01:
* - Added 'GabParty x' and 'GabPartySprite x' plugin commands to help with
* those without dynamic party setups.
*
* Version 1.00:
* - Finished Plugin!
*
*/
//=============================================================================

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

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

Yanfly.Param.GabFontName = String(Yanfly.Parameters['Gab Font Name']);
Yanfly.Param.GabFontSize = Number(Yanfly.Parameters['Gab Font Size']);
Yanfly.Param.GabCharPosX = Number(Yanfly.Parameters['Character X Pos']);
Yanfly.Param.GabCharPosY = Number(Yanfly.Parameters['Character Y Pos']);
Yanfly.Param.GabBaseTime = Number(Yanfly.Parameters['Base Wait Time']);
Yanfly.Param.GabTimePerChar = Number(Yanfly.Parameters['Time Per Character']);
Yanfly.Param.GabFadeRate = Number(Yanfly.Parameters['Fade Rate']);
Yanfly.Param.GabAntiRepeat = Boolean(Yanfly.Parameters['Anti-Repeat']);

Yanfly.Param.GabMapYLoc = Number(Yanfly.Parameters['Map Y Location']);
Yanfly.Param.GabMapDim1 = String(Yanfly.Parameters['Map Dim Color 1']);
Yanfly.Param.GabMapDim2 = String(Yanfly.Parameters['Map Dim Color 2']);

Yanfly.Param.GabBattleYLoc = Number(Yanfly.Parameters['Battle Y Location']);
Yanfly.Param.GabBattleDim1 = String(Yanfly.Parameters['Battle Dim Color 1']);
Yanfly.Param.GabBattleDim2 = String(Yanfly.Parameters['Battle Dim Color 2']);

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

Yanfly.Gab.Game_Interpreter_clear = Game_Interpreter.prototype.clear;
Game_Interpreter.prototype.clear = function () {
  Yanfly.Gab.Game_Interpreter_clear.call(this);
  this.clearGabInformation();
};

Yanfly.Gab.Game_Interpreter_pluginCommand =
  Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
  Yanfly.Gab.Game_Interpreter_pluginCommand.call(this, command, args)
  if (command === 'GabText') this.setGabText(args);
  if (command === 'GabSpriteName') this.setGabSpriteName(args);
  if (command === 'GabSpriteIndex') this.setGabSpriteIndex(args);
  if (command === 'GabFaceName') this.setGabFaceName(args);
  if (command === 'GabFaceIndex') this.setGabFaceIndex(args);
  if (command === 'GabActorSprite') this.setGabActorSprite(args);
  if (command === 'GabActor') this.setGabActorFace(args);
  if (command === 'GabActorFace') this.setGabActorFace(args);
  if (command === 'GabPartySprite') this.setGabPartySprite(args);
  if (command === 'GabParty') this.setGabPartyFace(args);
  if (command === 'GabPartyFace') this.setGabPartyFace(args);
  if (command === 'GabSound') this.setGabSound(args);
  if (command === 'GabSwitch') this.setGabSwitch(args);
  if (command === 'ShowGab') this.showGab();
  if (command === 'ForceGab') this.forceGab();
  if (command === 'ClearGab') this.clearGab();
};

Game_Interpreter.prototype.clearGabInformation = function () {
  this._gabText = '';
  this._gabGraphicType = 'none';
  this._gabGraphicName = '';
  this._gabGraphicIndex = 0;
  this._gabSoundName = '';
  this._gabSwitch = 0;
};

Game_Interpreter.prototype.setGabText = function (args) {
  var text = '';
  for (var i = 0; i < args.length; ++i) {
    text = text + args[i] + ' ';
  }
  this._gabText = text;
};

Game_Interpreter.prototype.setGabSpriteName = function (args) {
  this._gabGraphicType = 'character';
  var text = '';
  if (args.length === 1) return this._gabGraphicName = String(args[0]);
  for (var i = 0; i < args.length; ++i) {
    text = text + ' ' + args[i];
  }
  this._gabGraphicName = text;
};

Game_Interpreter.prototype.setGabSpriteIndex = function (args) {
  this._gabGraphicType = 'character';
  this._gabGraphicIndex = parseInt(args[0]);
};

Game_Interpreter.prototype.setGabFaceName = function (args) {
  this._gabGraphicType = 'face';
  var text = '';
  if (args.length === 1) return this._gabGraphicName = String(args[0]);
  for (var i = 0; i < args.length; ++i) {
    text = text + ' ' + args[i];
  }
  this._gabGraphicName = text;
};

Game_Interpreter.prototype.setGabFaceIndex = function (args) {
  this._gabGraphicType = 'face';
  this._gabGraphicIndex = parseInt(args[0]);
};

Game_Interpreter.prototype.setGabActorSprite = function (args) {
  var actorId = parseInt(args[0]);
  var actor = $gameActors.actor(actorId);
  if (!actor) return;
  this._gabGraphicType = 'character';
  this._gabGraphicName = actor.characterName();
  this._gabGraphicIndex = actor.characterIndex();
};

Game_Interpreter.prototype.setGabPartySprite = function (args) {
  var position = parseInt(args[0]);
  if (position <= 0) return;
  position -= 1;
  var actor = $gameParty.members()[position];
  if (!actor) return;
  var actorId = actor._actorId;
  this.setGabActorSprite([actorId]);
};

Game_Interpreter.prototype.setGabActorFace = function (args) {
  var actorId = parseInt(args[0]);
  var actor = $gameActors.actor(actorId);
  if (!actor) return;
  this._gabGraphicType = 'face';
  this._gabGraphicName = actor.faceName();
  this._gabGraphicIndex = actor.faceIndex();
};

Game_Interpreter.prototype.setGabPartyFace = function (args) {
  var position = parseInt(args[0]);
  if (position <= 0) return;
  position -= 1;
  var actor = $gameParty.members()[position];
  if (!actor) return;
  var actorId = actor._actorId;
  this.setGabActorFace([actorId]);
};

Game_Interpreter.prototype.setGabSound = function (args) {
  var text = '';
  if (args.length === 1) return this._gabSoundName = String(args[0]);
  for (var i = 0; i < args.length; ++i) {
    if (i === 0) {
      text = args[0];
      continue;
    }
    text = text + ' ' + args[i];
  }
  this._gabSoundName = text;
};

Game_Interpreter.prototype.setGabSwitch = function (args) {
  this._gabSwitch = parseInt(args[0]);
};

Game_Interpreter.prototype.showGab = function () {
  if (!this._gabText) return;
  var gabData = [
    this._gabText,
    this._gabGraphicType,
    this._gabGraphicName,
    this._gabGraphicIndex,
    this._gabSoundName,
    this._gabSwitch
  ];
  var scene = SceneManager._scene;
  if (scene._gabWindow) scene.startGabWindow(gabData);
  this.clearGabInformation();
};

Game_Interpreter.prototype.forceGab = function () {
  if (!this._gabText) return;
  var gabData = [
    this._gabText,
    this._gabGraphicType,
    this._gabGraphicName,
    this._gabGraphicIndex,
    this._gabSoundName,
    this._gabSwitch
  ];
  var scene = SceneManager._scene;
  if (scene._gabWindow) scene.forceGabWindow(gabData);
  this.clearGabInformation();
};

Game_Interpreter.prototype.clearGab = function () {
  var scene = SceneManager._scene;
  if (scene._gabWindow) scene.clearGabWindow();
  this.clearGabInformation();
};

//=============================================================================
// Window_Gab
//=============================================================================

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

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

Window_Gab.prototype.initialize = function (battle) {
  this._battle = battle;
  var wx = this.standardPadding() * -1;
  if (battle) {
    var wy = Yanfly.Param.GabBattleYLoc - this.standardPadding();
  } else {
    var wy = Yanfly.Param.GabMapYLoc - this.standardPadding();
  }
  var ww = Graphics.boxWidth + this.standardPadding() * 2;
  var wh = this.fittingHeight(2);
  this._gabSwitch = 0;
  this._showCount = 0;
  this._ignoreMask = true;
  this._gabQueue = [];
  this._currentGab = [];
  this._gabSwitchedOn = false;
  Window_Base.prototype.initialize.call(this, wx, wy, ww, wh);
  this.restoreGabs();
  this.clear();
};

Window_Gab.prototype.clear = function () {
  this._gabLoaded = false;
  this._graphicLoading = false;
  this.opacity = 0;
  this.contentsOpacity = 0;
  this._text = '';
  this._graphicType = 'none';
  this._graphicName = '';
  this._graphicIndex = 0;
  this._soundName = '';
  this._graphicBitmap = undefined;
};

Window_Gab.prototype.standardFontFace = function () {
  return Yanfly.Param.GabFontName;
};

Window_Gab.prototype.standardFontSize = function () {
  return Yanfly.Param.GabFontSize;
};

Window_Gab.prototype.update = function () {
  Window_Base.prototype.update.call(this);
  if (this.isHideGabWindow()) {
    this.hide();
  } else if (this._gabLoaded) {
    if (this._graphicLoading && this._graphicBitmap.width <= 0) return;
    this.refresh();
  } else if (this._showCount > 0) {
    this.updateFadeIn();
    --this._showCount;
  } else if (this.contentsOpacity > 0) {
    this.updateFadeOut();
  } else if (this._gabQueue.length > 0) {
    this.processNewGabData()
  }
};

Window_Gab.prototype.isHideGabWindow = function () {
  if ($gameParty.inBattle() && BattleManager._victoryPhase) return true;
  return false;
};

Window_Gab.prototype.updateFadeIn = function () {
  this.contentsOpacity += Yanfly.Param.GabFadeRate;
};

Window_Gab.prototype.updateFadeOut = function () {
  this.contentsOpacity -= Yanfly.Param.GabFadeRate;
  if (this.contentsOpacity > 0) return;
  if (this._gabSwitchedOn) return;
  if (this._gabSwitch) {
    $gameSwitches.setValue(this._gabSwitch, true);
    this._gabSwitchedOn = true;
  }
};

Window_Gab.prototype.addGabData = function (gabData) {
  if (!gabData) return;
  if (this.checkDuplicateGab(gabData)) return;
  this._gabQueue.push(gabData);
};

Window_Gab.prototype.forceGabData = function (gabData) {
  if (!gabData) return;
  if (this.checkCurrentGab(gabData)) return;
  this._gabQueue = [];
  this._currentGab = [];
  this._showCount = 0;
  this._gabQueue.push(gabData);
};

Window_Gab.prototype.clearGabData = function () {
  this._gabQueue = [];
  this._currentGab = [];
  this._showCount = 0;
};

Window_Gab.prototype.checkDuplicateGab = function (gabData) {
  if (!Yanfly.Param.GabAntiRepeat) return false;
  if (this.checkCurrentGab(gabData)) return true;
  if (this.checkQueuedGabs(gabData)) return true;
  return false;
};

Window_Gab.prototype.checkCurrentGab = function (gabData) {
  var iteration = this._currentGab;
  if (iteration[0] !== gabData[0]) return false;
  if (iteration[1] !== gabData[1]) return false;
  if (iteration[2] !== gabData[2]) return false;
  if (iteration[3] !== gabData[3]) return false;
  if (iteration[4] !== gabData[4]) return false;
  if (iteration[5] !== gabData[5]) return false;
  return true;
};

Window_Gab.prototype.checkQueuedGabs = function (gabData) {
  for (var i = 0; i < this._gabQueue.length; ++i) {
    var iteration = this._gabQueue[i];
    if (iteration[0] !== gabData[0]) continue;
    if (iteration[1] !== gabData[1]) continue;
    if (iteration[2] !== gabData[2]) continue;
    if (iteration[3] !== gabData[3]) continue;
    if (iteration[4] !== gabData[4]) continue;
    if (iteration[5] !== gabData[5]) continue;
    return true;
  }
  return false;
};

Window_Gab.prototype.processNewGabData = function () {
  var gabData = this._gabQueue.shift();
  this._gabSwitchedOn = false;
  this._currentGab = gabData;
  this._text = gabData[0] || '';
  this._graphicType = gabData[1] || 'none';
  this._graphicName = gabData[2] || '';
  this._graphicIndex = gabData[3] || 0;
  this._soundName = gabData[4] || 0;
  this._gabSwitch = gabData[5] || 0;
  this.setupLoadGraphic();
  this._gabLoaded = true;
};

Window_Gab.prototype.setupLoadGraphic = function () {
  this._graphicLoading = false;
  if (this._graphicType === 'character') {
    this._graphicBitmap = ImageManager.loadCharacter(this._graphicName);
    this._graphicLoading = true;
  } else if (this._graphicType === 'face') {
    this._graphicBitmap = ImageManager.loadFace(this._graphicName);
    this._graphicLoading = true;
  }
};

Window_Gab.prototype.refresh = function () {
  this.contents.clear();
  this.startCountdown();
  this.drawGabBackground();
  this.drawGabCharacter();
  this.drawGabText();
  this.playSound();
  this.clear();
};

Yanfly.Gab.WindowLayer_webglMaskWindow =
  WindowLayer.prototype._webglMaskWindow;
WindowLayer.prototype._webglMaskWindow = function (renderSession, win) {
  if (win._ignoreMask) return;
  Yanfly.Gab.WindowLayer_webglMaskWindow.call(this, renderSession, win);
};

Window_Gab.prototype.startCountdown = function () {
  this._graphicLoading = false;
  this.contentsOpacity = 255;
  this._showCount = Yanfly.Param.GabBaseTime;
  var text = this._text.replace(/\\(.*?)\[(.*?)\]/gi, '');
  this._showCount += text.length * Yanfly.Param.GabTimePerChar;
};

Window_Gab.prototype.drawGabBackground = function () {
  var width = this.contentsWidth();
  this.drawBackground(0, 0, width, this.lineHeight() * 2);
};

Window_Gab.prototype.dimColor1 = function () {
  if ($gameParty.inBattle()) {
    return Yanfly.Param.GabBattleDim1;
  } else {
    return Yanfly.Param.GabMapDim1;
  }
};

Window_Gab.prototype.dimColor2 = function () {
  if ($gameParty.inBattle()) {
    return Yanfly.Param.GabBattleDim2;
  } else {
    return Yanfly.Param.GabMapDim2;
  }
};

Window_Gab.prototype.drawBackground = function (wx, wy, ww, wh) {
  var color1 = this.dimColor1();
  var color2 = this.dimColor2();
  var ww1 = Math.ceil(ww * 0.25)
  var ww2 = Math.ceil(ww * 0.75)
  this.contents.gradientFillRect(wx, wy, ww1, wh, color1, color1);
  this.contents.gradientFillRect(ww1, wy, ww2, wh, color1, color2);
};

Window_Gab.prototype.drawGabCharacter = function () {
  if (this._graphicName === '') return;
  if (this._graphicType === 'character') {
    var wx = Yanfly.Param.GabCharPosX;
    var wy = Yanfly.Param.GabCharPosY;
    this.drawCharacter(this._graphicName, this._graphicIndex, wx, wy);
  } else if (this._graphicType === 'face') {
    var wx = 0;
    var wy = 0;
    var ww = Window_Base._faceWidth;
    var wh = this.lineHeight() * 2;
    this.drawFace(this._graphicName, this._graphicIndex, wx, wy, ww, wh);
  }
};

Window_Gab.prototype.drawGabText = function () {
  var text = this._text;
  if (this._graphicType === 'character') {
    var wx = Yanfly.Param.GabCharPosX * 2;
  } else if (this._graphicType === 'face') {
    var wx = Window_Base._faceWidth + this.standardPadding();
  } else {
    var wx = this.standardPadding();
  }
  var wy = this.contents.height / 2 - this.lineHeight() / 2;
  this.drawTextEx(text, wx, wy);
};

Window_Gab.prototype.playSound = function () {
  var sound = {
    name: this._soundName,
    volume: 90,
    pitch: 100,
    pan: 0
  };
  AudioManager.playSe(sound);
};

Window_Gab.prototype.storeGabs = function () {
  if (this._battle) {
    this.storeBattleGabs();
  } else {
    this.storeMapGabs();
  }
};

Window_Gab.prototype.storeBattleGabs = function () {
  $gameTemp._storedBattleGabs = this._gabQueue.slice();
  if (this.contentsOpacity > 0) {
    $gameTemp._currentBattleGab = this._currentGab.slice();
  } else {
    $gameTemp._currentBattleGab = [];
  }
};

Window_Gab.prototype.storeMapGabs = function () {
  $gameTemp._storedMapGabs = this._gabQueue.slice();
  if (this.contentsOpacity > 0) {
    $gameTemp._currentMapGab = this._currentGab.slice();
  } else {
    $gameTemp._currentMapGab = [];
  }
};

Window_Gab.prototype.restoreGabs = function () {
  if (this._battle) {
    this.restoreBattleGabs();
  } else {
    this.restoreMapGabs();
  }
};

Window_Gab.prototype.restoreBattleGabs = function () {
  if ($gameTemp._storedBattleGabs) {
    this._gabQueue = $gameTemp._storedBattleGabs;
    $gameTemp._storedBattleGabs = undefined;
  }
  if ($gameTemp._currentBattleGab && $gameTemp._currentBattleGab.length > 0) {
    this._gabQueue.unshift($gameTemp._currentBattleGab);
    $gameTemp._currentBattleGab = undefined;
  }
};

Window_Gab.prototype.restoreMapGabs = function () {
  if ($gameTemp._storedMapGabs) {
    this._gabQueue = $gameTemp._storedMapGabs;
    $gameTemp._storedMapGabs = undefined;
  }
  if ($gameTemp._currentMapGab && $gameTemp._currentMapGab.length > 0) {
    this._gabQueue.unshift($gameTemp._currentMapGab);
    $gameTemp._currentMapGab = undefined;
  }
};

//=============================================================================
// SceneManager
//=============================================================================

Yanfly.Gab.SceneManager_push = SceneManager.push;
SceneManager.push = function (sceneClass) {
  if (this.isStoreGabs(sceneClass)) {
    this._scene._gabWindow.storeGabs();
  }
  Yanfly.Gab.SceneManager_push.call(this, sceneClass);
};

SceneManager.isStoreGabs = function (sceneClass) {
  if (!this.isSceneMap() && !this.isSceneBattle()) return false;
  if (sceneClass === Scene_Map) {
    if (this.isSceneMap()) return false;
  } else if (sceneClass === Scene_Battle) {
    if (this.isSceneMap()) return true;
  }
  return true;
};

SceneManager.isSceneMap = function () {
  return this._scene instanceof Scene_Map;
};

SceneManager.isSceneBattle = function () {
  return this._scene instanceof Scene_Battle;
};

//=============================================================================
// Scene_Base
//=============================================================================

Scene_Base.prototype.createGabWindow = function (battle) {
  this._gabWindow = new Window_Gab(battle);
  this.addChild(this._gabWindow);
};

Scene_Base.prototype.startGabWindow = function (gabData) {
  this._gabWindow.addGabData(gabData);
};

Scene_Base.prototype.forceGabWindow = function (gabData) {
  this._gabWindow.forceGabData(gabData);
};

Scene_Base.prototype.clearGabWindow = function () {
  this._gabWindow.clearGabData();
};

//=============================================================================
// Scene_Battle
//=============================================================================

Yanfly.Gab.Scene_Battle_createAllWindows =
  Scene_Battle.prototype.createAllWindows;
Scene_Battle.prototype.createAllWindows = function () {
  Yanfly.Gab.Scene_Battle_createAllWindows.call(this);
  this.createGabWindow(true);
};
//=============================================================================
// Scene_Map
//=============================================================================

Yanfly.Gab.Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
Scene_Map.prototype.createAllWindows = function () {
  Yanfly.Gab.Scene_Map_createAllWindows.call(this);
  this.createGabWindow(false);
};

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