code:
//=============================================================================
// Yanfly Engine Plugins - Battle Engine Extension - Visual HP Gauge
// YEP_X_VisualHpGauge.js
//=============================================================================

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

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

//=============================================================================
/*:
* @plugindesc v1.06 (Requires YEP_BattleEngineCore.js) Reveal HP Gauges
* when a battler is selected or takes damage in battle.
* @author Yanfly Engine Plugins
*
* @param ---General---
* @default
*
* @param Display Actor
* @desc Do you wish to display the HP Gauge for actors?
* NO - false     YES - true
* @default true
*
* @param Defeat First
* @desc Enemies must be defeated first before showing the HP Gauge.
* NO - false     YES - true
* @default false
*
* @param Always Visible
* @desc HP Gauge is always visible and doesn't fade away.
* NO - false     YES - true
* @default false
*
* @param ---Appearance---
* @default
*
* @param Minimum Gauge Width
* @desc This is the minimum width in pixels for HP Gauges.
* @default 144
*
* @param Gauge Height
* @desc This is the height in pixels for HP Gauges.
* @default 18
*
* @param Back Color
* @desc This is the text color used for the back of HP Gauges.
* @default 19
*
* @param HP Color 1
* @desc This is the text color used for the 1st part of HP Gauges.
* @default 20
*
* @param HP Color 2
* @desc This is the text color used for the 2nd part of HP Gauges.
* @default 21
*
* @param Gauge Duration
* @desc This is the frames the HP gauge will continue to show after
* it finishes draining or filling.
* @default 30
*
* @param Gauge Position
* @desc Where do you wish to show the HP gauge?
* BELOW - false     ABOVE - true
* @default false
*
* @param Y Buffer
* @desc How much do you wish to shift the gauge Y position?
* @default -16
*
* @param Use Thick Gauges
* @desc Use the thick gauges provided by this plugin?
* Default - false     Thick - true
* @default true
*
* @param ---Text Display---
* @default
*
* @param Show HP
* @desc Show the actual 'HP' text.
* NO - false     YES - true
* @default false
*
* @param Show Value
* @desc Show the HP value.
* NO - false     YES - true
* @default false
*
* @param Show Max
* @desc Show the MaxHP value if value is shown?
* NO - false     YES - true
* @default false
*
* @help
* ============================================================================
* Introduction
* ============================================================================
*
* This plugin requires YEP_BattleEngineCore.
* Make sure this plugin is located under YEP_BattleEngineCore in the plugin
* list.
*
* This plugin shows the HP Gauges of enemies as they're selected or while they
* take damage. You can also opt for actors to show their HP Gauge as well.
* Adjust the parameters to change the way you want the HP Gauges to appear.
*
* By default, enemies would need to be defeated first in order for the gauges
* to show up. This can be changed within the parameter settings. However,
* during battle test, the HP gauges are always shown unless the enemy has a
* hidden HP gauge.
*
* ============================================================================
* Notetags
* ============================================================================
*
* Class and Enemy Notetags:
*   <Hide HP Gauge>
*   This HP gauge will always be hidden if this notetag is present.
*
*   <Show HP Gauge>
*   This HP gauge will always be shown if this notetag is present while the
*   target is selected or taking damage.
*
*   <HP Gauge Width: x>
*   This will set the battler's HP Gauge width to x pixels. However, if this
*   width is less than the minimum width, minimum width will take priority.
*
*   <HP Gauge Height: x>
*   This set's the HP Gauge height to x pixels.
*
*   <HP Gauge Back Color: x>
*   This changes the HP Gauge's back color to x text color.
*
*   <HP Gauge Color 1: x>
*   This changes the HP Gauge's color 1 to x text color.
*
*   <HP Gauge Color 2: x>
*   This changes the HP Gauge's color 2 to x text color.
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 1.06:
* - Compatibility update with State Categories.
*
* Version 1.05:
* - Updated for RPG Maker MV version 1.1.0.
*
* Version 1.04:
* - Optimization update.
*
* Version 1.03:
* - Fixed a bug when Escape skill-effects are used on battlers.
*
* Version 1.02:
* - Fixed a bug with gauge height not adjusting.
*
* Version 1.01b:
* - Fixed a bug regarding dependancy checks.
* - Fixed many bugs regarding stacking errors.
*
* Version 1.01:
* - Rewrote the good majority of plugin to accomodate the following features:
* ---'Always Visible' parameter.
* ---'Gauge Position' parameter.
* ---'Y Buffer' parameter.
* ---'Use Thick Gauges' parameter.
* ---'Show HP' parameter.
* ---'Show Value' parameter.
* ---'Show Max' parameter.
*
* Version 1.00:
* - Finished Plugin!
*/
//=============================================================================

if (Imported.YEP_BattleEngineCore) {

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

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

  Yanfly.Param.VHGDisplayActor = String(Yanfly.Parameters['Display Actor']);
  Yanfly.Param.VHGDefeatFirst = String(Yanfly.Parameters['Defeat First']);
  Yanfly.Param.VHGAlwaysShow = eval(String(Yanfly.Parameters['Always Visible']));

  Yanfly.Param.VHGMinHpWidth = Number(Yanfly.Parameters['Minimum Gauge Width']);
  Yanfly.Param.VHGGaugeHeight = Number(Yanfly.Parameters['Gauge Height']);
  Yanfly.Param.VHGBackColor = Number(Yanfly.Parameters['Back Color']);
  Yanfly.Param.VHGHpColor1 = Number(Yanfly.Parameters['HP Color 1']);
  Yanfly.Param.VHGHpColor2 = Number(Yanfly.Parameters['HP Color 2']);
  Yanfly.Param.VHGGaugeDuration = Number(Yanfly.Parameters['Gauge Duration']);
  Yanfly.Param.VHGGaugePos = eval(String(Yanfly.Parameters['Gauge Position']));
  Yanfly.Param.VHGBufferY = Number(Yanfly.Parameters['Y Buffer']);
  Yanfly.Param.VHGThick = eval(String(Yanfly.Parameters['Use Thick Gauges']));

  Yanfly.Param.VHGShowHP = eval(String(Yanfly.Parameters['Show HP']));
  Yanfly.Param.VHGShowValue = eval(String(Yanfly.Parameters['Show Value']));
  Yanfly.Param.VHGShowMax = eval(String(Yanfly.Parameters['Show Max']));

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

  Yanfly.VHG.DataManager_isDatabaseLoaded = DataManager.isDatabaseLoaded;
  DataManager.isDatabaseLoaded = function () {
    if (!Yanfly.VHG.DataManager_isDatabaseLoaded.call(this)) return false;
    if (!Yanfly._loaded_YEP_X_VisualHpGauge) {
      this.processVHGNotetags($dataClasses);
      this.processVHGNotetags($dataEnemies);
      Yanfly._loaded_YEP_X_VisualHpGauge = true;
    }
    return true;
  };

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

      obj.hideHpGauge = false;
      obj.showHpGauge = false;
      obj.hpGaugeWidth = 0;
      obj.hpGaugeHeight = Yanfly.Param.VHGGaugeHeight;
      obj.hpGaugeBackColor = Yanfly.Param.VHGBackColor;
      obj.hpGaugeColor1 = Yanfly.Param.VHGHpColor1;
      obj.hpGaugeColor2 = Yanfly.Param.VHGHpColor2;

      for (var i = 0; i < notedata.length; i++) {
        var line = notedata[i];
        if (line.match(/<(?:HIDE HP GAUGE)>/i)) {
          obj.hideHpGauge = true;
        } else if (line.match(/<(?:SHOW HP GAUGE)>/i)) {
          obj.showHpGauge = true;
        } else if (line.match(/<(?:HP GAUGE WIDTH):[ ](\d+)>/i)) {
          obj.hpGaugeWidth = parseInt(RegExp.$1);
        } else if (line.match(/<(?:HP GAUGE HEIGHT):[ ](\d+)>/i)) {
          obj.hpGaugeHeight = parseInt(RegExp.$1);
        } else if (line.match(/<(?:HP GAUGE BACK COLOR):[ ](\d+)>/i)) {
          obj.hpGaugeBackColor = parseInt(RegExp.$1);
        } else if (line.match(/<(?:HP GAUGE COLOR 1):[ ](\d+)>/i)) {
          obj.hpGaugeColor1 = parseInt(RegExp.$1);
        } else if (line.match(/<(?:HP GAUGE COLOR 2):[ ](\d+)>/i)) {
          obj.hpGaugeColor2 = parseInt(RegExp.$1);
        }
      }
    }
  };

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

  Yanfly.VHG.Game_System_initialize = Game_System.prototype.initialize;
  Game_System.prototype.initialize = function () {
    Yanfly.VHG.Game_System_initialize.call(this);
    this.initShownHpGauge();
  };

  Game_System.prototype.initShownHpGauge = function () {
    this._shownHpGauge = [];
  };

  Game_System.prototype.showHpGaugeEnemy = function (id) {
    if (this._shownHpGauge === undefined) this.initShownHpGauge();
    if (!eval(Yanfly.Param.VHGDefeatFirst)) return true;
    return this._shownHpGauge.contains(id);
  };

  Game_System.prototype.addHpGaugeEnemy = function (id) {
    if (this._shownHpGauge === undefined) this.initShownHpGauge();
    if (this._shownHpGauge.contains(id)) return;
    this._shownHpGauge.push(id);
  };

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

  Yanfly.VHG.Game_BattlerBase_die = Game_BattlerBase.prototype.die;
  Game_BattlerBase.prototype.die = function () {
    Yanfly.VHG.Game_BattlerBase_die.call(this);
    if (!this.isEnemy()) return;
    if (eval(Yanfly.Param.VHGDefeatFirst)) {
      if (!$gameSystem.showHpGaugeEnemy(this._enemyId)) this._noHpGauge = true;
    }
    $gameSystem.addHpGaugeEnemy(this._enemyId);
  };

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

  Game_Battler.prototype.hpGaugeVisible = function () {
    if (this._noHpGauge) return false;
    if (this.isHidden()) return false;
    return true;
  };

  Game_Battler.prototype.hpGaugeWidth = function () {
    var width = Math.max(this.spriteWidth(), Yanfly.Param.VHGMinHpWidth);
    return (width & 1) ? width + 1 : width;
  };

  Game_Battler.prototype.hpGaugeHeight = function () {
    return Yanfly.Param.VHGGaugeHeight;
  };

  Game_Battler.prototype.hpGaugeBackColor = function () {
    return Yanfly.Param.VHGBackColor;
  };

  Game_Battler.prototype.hpGaugeColor1 = function () {
    return Yanfly.Param.VHGHpColor1;
  };

  Game_Battler.prototype.hpGaugeColor2 = function () {
    return Yanfly.Param.VHGHpColor2;
  };

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

  Game_Actor.prototype.hpGaugeVisible = function () {
    if (this.isHidden()) return false;
    if (this.currentClass().showHpGauge) return true;
    if (!eval(Yanfly.Param.VHGDisplayActor)) return false;
    if (this.currentClass().hideHpGauge) return false;
    return Game_Battler.prototype.hpGaugeVisible.call(this);
  };

  Game_Actor.prototype.hpGaugeWidth = function () {
    if (this.currentClass().hpGaugeWidth > 0) {
      var width = this.currentClass().hpGaugeWidth;
    } else {
      var width = this.spriteWidth();
    }
    width = Math.max(width, Yanfly.Param.VHGMinHpWidth);
    return (width & 1) ? width + 1 : width;
  };

  Game_Actor.prototype.hpGaugeHeight = function () {
    return this.currentClass().hpGaugeHeight;
  };

  Game_Actor.prototype.hpGaugeBackColor = function () {
    return this.currentClass().hpGaugeBackColor;
  };

  Game_Actor.prototype.hpGaugeColor1 = function () {
    return this.currentClass().hpGaugeColor1;
  };

  Game_Actor.prototype.hpGaugeColor2 = function () {
    return this.currentClass().hpGaugeColor2;
  };

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

  Game_Enemy.prototype.hpGaugeVisible = function () {
    if (this.isHidden()) return false;
    if (this.enemy().hideHpGauge) return false;
    if (BattleManager.isBattleTest()) return true;
    if (this.enemy().showHpGauge) return true;
    if (!$gameSystem.showHpGaugeEnemy(this._enemyId)) return false;
    return Game_Battler.prototype.hpGaugeVisible.call(this);
  };

  Yanfly.VHG.Game_Enemy_revive = Game_Enemy.prototype.revive;
  Game_Enemy.prototype.revive = function () {
    if (this._hp === 0) this._noHpGauge = false;
    Yanfly.VHG.Game_Enemy_revive.call(this);
  };

  Game_Enemy.prototype.hpGaugeWidth = function () {
    if (this.enemy().hpGaugeWidth > 0) {
      var width = this.enemy().hpGaugeWidth;
    } else {
      var width = this.spriteWidth();
    }
    width = Math.max(width, Yanfly.Param.VHGMinHpWidth);
    return (width & 1) ? width + 1 : width;
  };

  Game_Enemy.prototype.hpGaugeHeight = function () {
    return this.enemy().hpGaugeHeight;
  };

  Game_Enemy.prototype.hpGaugeBackColor = function () {
    return this.enemy().hpGaugeBackColor;
  };

  Game_Enemy.prototype.hpGaugeColor1 = function () {
    return this.enemy().hpGaugeColor1;
  };

  Game_Enemy.prototype.hpGaugeColor2 = function () {
    return this.enemy().hpGaugeColor2;
  };

  //=============================================================================
  // Sprite_Battler
  //=============================================================================

  Yanfly.VHG.Sprite_Battler_update = Sprite_Battler.prototype.update;
  Sprite_Battler.prototype.update = function () {
    Yanfly.VHG.Sprite_Battler_update.call(this);
    this.createVisualHpGaugeWindow();
  };

  Sprite_Battler.prototype.createVisualHpGaugeWindow = function () {
    if (this._createdVisualHpGaugeWindow) return;
    if (!this._battler) return;
    if (this.checkVisualATBGauge()) {
      if (!this._visualATBWindow) return;
      if (!this.parent.parent.children.contains(this._visualATBWindow)) return;
    }
    this._createdVisualHpGaugeWindow = true;
    this._visualHpGauge = new Window_VisualHPGauge();
    this._visualHpGauge.setBattler(this._battler);
    this.parent.parent.addChild(this._visualHpGauge);
  };

  Sprite_Battler.prototype.checkVisualATBGauge = function () {
    if (!Imported.YEP_X_BattleSysATB) return false;
    if (!BattleManager.isATB()) return false;
    if (!Imported.YEP_X_VisualATBGauge) return false;
    return this._battler.isEnemy();
  };

  Yanfly.VHG.Sprite_Battler_setBattler = Sprite_Battler.prototype.setBattler;
  Sprite_Battler.prototype.setBattler = function (battler) {
    Yanfly.VHG.Sprite_Battler_setBattler.call(this, battler);
    if (this._visualHpGauge) this._visualHpGauge.setBattler(battler);
  };

  //=============================================================================
  // Window_VisualHPGauge
  //=============================================================================

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

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

  Window_VisualHPGauge.prototype.initialize = function () {
    this._opacitySpeed = 255 / Yanfly.Param.VHGGaugeDuration;
    this._dropSpeed = 0;
    this._visibleCounter = 0;
    Window_Base.prototype.initialize.call(this, 0, 0, 1, 1);
    this._battler = null;
    this._requestRefresh = false;
    this._currentHpValue = 0;
    this._displayedValue = 0;
    this.contentsOpacity = 0;
    this.opacity = 0;
  };

  Window_VisualHPGauge.prototype.setBattler = function (battler) {
    if (this._battler === battler) return;
    this._battler = battler;
    this._currentHpValue = this._battler ? this._battler.hp : 0;
    this._displayedValue = this._battler ? this._battler.hp : 0;
  };

  Window_VisualHPGauge.prototype.update = function () {
    Window_Base.prototype.update.call(this);
    if (!this._battler) return;
    this.updateWindowAspects();
  };

  Window_VisualHPGauge.prototype.updateWindowAspects = function () {
    this.updateWindowSize();
    this.updateWindowPosition();
    this.updateOpacity();
    this.updateHpPosition();
    this.updateRefresh();
  };

  Window_VisualHPGauge.prototype.updateWindowSize = function () {
    var spriteWidth = this._battler.hpGaugeWidth();
    var width = spriteWidth + this.standardPadding() * 2;
    width = Math.min(width, Graphics.boxWidth + this.standardPadding() * 2);
    var height = Math.max(this.lineHeight(), this.gaugeHeight() + 4);
    height += this.standardPadding() * 2;
    if (width === this.width && height === this.height) return;
    this.width = width;
    this.height = height;
    this.createContents();
    this._requestRefresh = true;
    this.makeWindowBoundaries();
  };

  Window_VisualHPGauge.prototype.makeWindowBoundaries = function () {
    if (!this._requestRefresh) return;
    this._minX = -1 * this.standardPadding();
    this._maxX = Graphics.boxWidth - this.width + this.standardPadding();
    this._minY = -1 * this.standardPadding();
    this._maxY = Graphics.boxHeight - this.height + this.standardPadding();
    this._maxY -= SceneManager._scene._statusWindow.height;
  };

  Window_VisualHPGauge.prototype.updateWindowPosition = function () {
    if (!this._battler) return;
    var battler = this._battler;
    this.x = battler.spritePosX();
    this.x -= Math.ceil(this.width / 2);
    this.x = this.x.clamp(this._minX, this._maxX);
    this.y = battler.spritePosY();
    if (Yanfly.Param.VHGGaugePos) {
      this.y -= battler.spriteHeight();
    } else {
      this.y -= this.standardPadding();
    }
    this.y = this.y.clamp(this._minY, this._maxY);
    this.y += Yanfly.Param.VHGBufferY;
  };

  Window_VisualHPGauge.prototype.updateOpacity = function () {
    if (this.isShowWindow()) {
      this.contentsOpacity += 32;
    } else {
      this.contentsOpacity -= 32;
    }
  };

  Window_VisualHPGauge.prototype.isShowWindow = function () {
    if (!this._battler.isAppeared()) return false;
    if (!this._battler.hpGaugeVisible()) return false;
    if (Yanfly.Param.VHGAlwaysShow && !this._battler.isDead()) return true;
    if (this._currentHpValue !== this._displayedValue) return true;
    if (this._battler.isSelected()) return true;
    --this._visibleCounter;
    return this._visibleCounter > 0;
  };

  Window_VisualHPGauge.prototype.updateHpPosition = function () {
    if (!this._battler) return;
    if (this._currentHpValue !== this._battler.hp) {
      this._visibleCounter = Yanfly.Param.VHGGaugeDuration;
      this._currentHpValue = this._battler.hp;
      var difference = Math.abs(this._displayedValue - this._battler.hp);
      this._dropSpeed = Math.ceil(difference / Yanfly.Param.VHGGaugeDuration);
    }
    this.updateDisplayCounter();
  };

  Window_VisualHPGauge.prototype.updateDisplayCounter = function () {
    if (this._battler._barrierAltered) {
      this._battler._barrierAltered = false;
    } else if (this._currentHpValue === this._displayedValue) {
      return;
    }
    var d = this._dropSpeed;
    var c = this._currentHpValue;
    if (this._displayedValue > this._currentHpValue) {
      this._displayedValue = Math.max(this._displayedValue - d, c);
    } else if (this._displayedValue < this._currentHpValue) {
      this._displayedValue = Math.min(this._displayedValue + d, c);
    }
    this._requestRefresh = true;
  };

  Window_VisualHPGauge.prototype.updateRefresh = function () {
    if (this._requestRefresh) this.refresh();
  };

  Window_VisualHPGauge.prototype.refresh = function () {
    this.contents.clear();
    if (!this._battler) return;
    this._requestRefresh = false;
    var wy = this.contents.height - this.lineHeight();
    var ww = this.contents.width;
    this.drawActorHp(this._battler, 0, wy, ww);
  };

  Window_VisualHPGauge.prototype.gaugeBackColor = function () {
    return this.textColor(this._battler.hpGaugeBackColor());
  };

  Window_VisualHPGauge.prototype.hpGaugeColor1 = function () {
    return this.textColor(this._battler.hpGaugeColor1());
  };

  Window_VisualHPGauge.prototype.hpGaugeColor2 = function () {
    return this.textColor(this._battler.hpGaugeColor2());
  };

  Window_VisualHPGauge.prototype.drawActorHp = function (actor, x, y, width) {
    width = width || 186;
    var color1 = this.hpGaugeColor1();
    var color2 = this.hpGaugeColor2();
    var rate = this._displayedValue / actor.mhp;
    if (Imported.YEP_AbsorptionBarrier && actor.barrierPoints() > 0) {
      ww = this.drawBarrierGauge(actor, x, y, width);
    } else {
      this.drawGauge(x, y, width, rate, color1, color2);
    }
    if (Yanfly.Param.VHGShowHP) {
      this.changeTextColor(this.systemColor());
      this.drawText(TextManager.hpA, x, y, 44);
    }
    if (Yanfly.Param.VHGShowValue) {
      var val = this._displayedValue
      var max = actor.mhp;
      var w = width;
      var color = this.hpColor(actor);
      this.drawCurrentAndMax(val, max, x, y, w, color, this.normalColor());
    }
  };

  Window_VisualHPGauge.prototype.drawCurrentAndMax = function (current, max, x, y,
    width, color1, color2) {
    if (Yanfly.Param.VHGShowMax) {
      Window_Base.prototype.drawCurrentAndMax.call(this, current, max,
        x, y, width, color1, color2);
    } else {
      var align = Yanfly.Param.VHGShowHP ? 'right' : 'center';
      var text = Yanfly.Util.toGroup(current);
      this.changeTextColor(color1);
      this.drawText(text, x, y, width, align);
    }
  };

  Window_VisualHPGauge.prototype.gaugeHeight = function () {
    if (!this._battler) return Window_Base.prototype.gaugeHeight.call(this);
    return this._battler.hpGaugeHeight();
  };

  if (Imported.YEP_CoreEngine && Yanfly.Param.VHGThick) {

    Window_VisualHPGauge.prototype.drawGauge =
      function (dx, dy, dw, rate, color1, color2) {
        var color3 = this.gaugeBackColor();
        var fillW = Math.floor(dw * rate).clamp(0, dw);
        var gaugeH = this.gaugeHeight();
        var gaugeY = dy + this.lineHeight() - gaugeH - 2;
        if (eval(Yanfly.Param.GaugeOutline)) {
          color3.paintOpacity = this.translucentOpacity();
          this.contents.fillRect(dx, gaugeY, dw, gaugeH, color3);
          dx += 2;
          gaugeY += 2;
          fillW = Math.max(0, fillW - 4);
          gaugeH -= 4;
        } else {
          var fillW = Math.floor(dw * rate);
          var gaugeY = dy + this.lineHeight() - gaugeH - 2;
          this.contents.fillRect(dx, gaugeY, dw, gaugeH, color3);
        }
        this.contents.gradientFillRect(dx, gaugeY, fillW, gaugeH, color1, color2);
      };

  } // Imported.YEP_CoreEngine

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

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

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

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


code:
//============================================================================
// YKNR_SaveThumbnail.js - ver.1.2.0
// ---------------------------------------------------------------------------
// Copyright (c) 2019 Yakinori
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
//============================================================================
/*:
 * ===========================================================================
 * @plugindesc セーブファイルにサムネイル用の画像を保存し、
 * セーブ/ロード画面でファイル毎にサムネイルを表示する
 * @author 焼きノリ
 * ===========================================================================
 *
 * @param AutoSnapForThumbnail
 * @text サムネイルの自動生成
 * @desc マップ画面からメニュー画面に切り替えたタイミングで
 * サムネイル用の画像を撮影するかを設定します。
 * @type boolean
 * @default true
 *
 * @param FastLoadingData
 * @text 読み込み速度高速化
 * @desc セーブ/ロード画面に入ったときやファイルリストを
 * スクロールしたときの読み込み速度を改善します。
 * @type boolean
 * @default true
 *
 * @param SnapSettings
 * @text サムネイルの保存設定
 * @desc 階層分けのために用意したパラメータなので、
 * ここには何も設定しないでください。
 *
 * @param ThumbQuality
 * @text 画質の設定
 * @desc 保存するサムネイルの画質を設定します。
 * 値が小さいほどデータサイズを小さくできます。
 * @type number
 * @min 0
 * @max 100
 * @default 90
 * @parent SnapSettings
 *
 * @param ThumbSaveWidth
 * @text サイズの設定：幅
 * @desc 保存するサムネイルの幅を設定します。
 * 値が小さいほどデータサイズを小さくできます。
 * @type number
 * @min 0
 * @default 122
 * @parent SnapSettings
 *
 * @param ThumbSaveHeight
 * @text サイズの設定：高さ
 * @desc 保存するサムネイルの高さを設定します。
 * 値が小さいほどデータサイズを小さくできます。
 * @type number
 * @min 0
 * @default 94
 * @parent SnapSettings
 *
 * @param ShowInSavefileList
 * @text ファイルリスト内に表示
 * @desc リストの項目にサムネイルを表示するか設定します。
 * @type boolean
 * @on 表示する
 * @off 表示しない
 * @default true
 *
 * @param ThumbItemPosX
 * @text サムネイルのX座標
 * @desc 描画するX座標をJavascriptで設定します。
 * rect = 項目の範囲, width = サムネイル幅
 * @type string
 * @default rect.x + rect.width - width;
 * @parent ShowInSavefileList
 *
 * @param ThumbItemPosY
 * @text サムネイルのY座標
 * @desc 描画するY座標をJavascriptで設定します。
 * rect = 項目の範囲, height = サムネイル高さ
 * @type string
 * @default rect.y + 5
 * @parent ShowInSavefileList
 *
 * @param ThumbItemScale
 * @text サムネイルのスケール値
 * @desc 描画するスケールを設定します。
 * 「サムネイルの保存設定」で設定した幅/高さを 1 とします。
 * @type number
 * @min 0
 * @decimals 2
 * @default 1.00
 * @parent ShowInSavefileList
 *
 * @param OtherWindowClass
 * @text 別ウィンドウの表示設定
 * @desc 別ウィンドウにサムネイルを表示したいときに設定します。
 * 対象となるウィンドウクラス名を記入します。
 * @type string
 * @default
 *
 * @param ThumbOWPosX
 * @text サムネイルのX座標
 * @desc 別ウィンドウに描画するX座標をJavascriptで設定します。
 * rect = ウィンドウ内の範囲, width = サムネイル幅
 * @type string
 * @default rect.x + rect.width - width;
 * @parent OtherWindowClass
 *
 * @param ThumbOWPosY
 * @text サムネイルのY座標
 * @desc 別ウィンドウに描画するY座標をJavascriptで設定します。
 * rect = ウィンドウ内の範囲, height = サムネイル高さ
 * @type string
 * @default rect.y + 5
 * @parent OtherWindowClass
 *
 * @param ThumbOWScale
 * @text サムネイルのスケール値
 * @desc 別ウィンドウに描画するスケールを設定します。
 * 「サムネイルの保存設定」で設定した幅/高さを 1 とします。
 * @type number
 * @min 0
 * @decimals 2
 * @default 1.00
 * @parent OtherWindowClass
 *
 * @help
 * ===========================================================================
 *【！注意！】
 * ※ツクールMV本体のバージョンが 1.6.1 未満の場合、動作できません。
 * ===========================================================================
 *【機能紹介】
 * セーブデータにマップの現在地の画像をサムネイルとして保存し、
 * セーブ画面/ロード画面のリストにそのサムネイルを表示する機能を追加します。
 *
 * サムネイル撮影のタイミングは、メニュー画面を開くときに自動に撮影されます。
 *
 * community-1.3 の「オートセーブ機能」でセーブされたデータには、
 * サムネイルは表示しない仕様となっています。
 *
 * ---------------------------------------------------------------------------
 *【パラメータ説明】
 * ・「サムネイルの自動生成」
 *   false にした場合、サムネイルの撮影は手動で行うことになります。
 *   イベントコマンドの「スクリプト」から以下を呼び出してください。
 * -------------------------------------
 * SceneManager.snapForThumbnail();
 * -------------------------------------
 *
 * ・「画質の設定」「サイズの設定：幅」「サイズの設定：高さ」
 *   保存するデータサイズに関わる設定です。
 *   サイズを大きく画質を良くすれば、サムネイルの品質は良くなりますが、
 *   データが肥大化するので注意が必要です。
 *
 * ・「ファイルリスト内に表示」
 *   デフォルトのリストのウィンドウ内にサムネイルを表示します。
 *   ここに表示する必要性が無ければ false にしてください。
 *
 * ・「別ウィンドウの表示設定」
 *   ファイルリスト内ではなく、他プラグインによって追加された
 *   任意のウィンドウに表示することも可能です。
 *   表示したいウィンドウのクラス名を設定することで表示できます。
 *   例えば、Window_Help と設定すると
 *   ヘルプウィンドウ内に選択中のセーブデータのサムネイルが表示されます。
 *   (SceneManager._scene._listWindow を参照しているため、
 *    これが存在しない場合は正常に動作しません。)
 *
 * ---------------------------------------------------------------------------
 *【更新履歴】
 * [2019/01/04] [1.0.0] 公開
 * [2019/12/02] [1.1.0] 「ファイルリスト内に表示」、「別ウィンドウの表示設定」
 *   が機能していない問題の修正
 * [2020/05/28] [1.1.1] デプロイメント時に「画像の暗号化」にチェックを入れて
 *   出力されたゲームでサムネイル表示時にエラーが出ていた問題の修正
 * [2021/02/16] [1.1.2] Window_SavefileListでのサムネイルのコンテナ数の調整
 * [2021/02/18] [1.2.0] サムネイル表示処理の修正。「読み込み速度高速化」を追加
 *
 * ===========================================================================
 * [Blog]   : http://mata-tuku.ldblog.jp/
 * [Twitter]: https://twitter.com/Noritake0424
 * [Github] : https://github.com/Yakinori0424/RPGMakerMVPlugins
 * ---------------------------------------------------------------------------
 * 本プラグインは MITライセンス のもとで配布されています。
 * 利用はどうぞご自由に。
 * http://opensource.org/licenses/mit-license.php
*/

(function () {
    'use strict';

    //------------------------------------------------------------------------

    /**
     * 対象のオブジェクト上の関数を別の関数に差し替えます.
     *
     * @method monkeyPatch
     * @param {Object} target 対象のオブジェクト
     * @param {String} methodName オーバーライドする関数名
     * @param {Function} newMethod 新しい関数を返す関数
     */
    function monkeyPatch(target, methodName, newMethod) {
        target[methodName] = newMethod(target[methodName]);
    };

    //------------------------------------------------------------------------

    /**
     * Jsonをパースし, プロパティの値を変換して返す
     *
     * @method jsonParamsParse
     * @param {String} json JSON文字列
     * @return {Object} パース後のオブジェクト
     */
    function jsonParamsParse(json) {
        return JSON.parse(json, parseRevive);
    };

    function parseRevive(key, value) {
        if (key === '') { return value; }
        try {
            return JSON.parse(value, parseRevive);
        } catch (e) {
            return value;
        }
    };

    /**
     * Jsonをパースして変換後, 配列ならば連想配列に変換して返す
     *
     * @method jsonParamsParse
     * @param {String} json JSON文字列
     * @param {String} keyName 連想配列のキーとする要素のあるプロパティ名
     * @param {String} valueName 連想配列の値とする要素のあるプロパティ名
     * @return {Object} パース後の連想配列
     */
    function parseArrayToHash(json, keyName, valueName) {
        let hash = {};
        const array = jsonParamsParse(json);
        if (Array.isArray(array)) {
            for (let i = 0, l = array.length; i < l; i++) {
                const key = array[i][keyName];
                if (key && key !== '') {
                    hash[key] = array[i][valueName] || null;
                }
            }
        }
        return hash;
    };

    //------------------------------------------------------------------------
    // パラメータを受け取る.
    const pluginName = 'YKNR_SaveThumbnail';
    const parameters = PluginManager.parameters(pluginName);
    const isAutoSnap = parameters['AutoSnapForThumbnail'] === 'true';
    const isFastLoadingData = parameters['FastLoadingData'] === 'true';
    const thumbQuality = parseInt(parameters['ThumbQuality']);
    const thumbSaveWidth = parseInt(parameters['ThumbSaveWidth']);
    const thumbSaveHeight = parseInt(parameters['ThumbSaveHeight']);
    const isShowInList = parameters['ShowInSavefileList'] === 'true';
    const thumbItemPosX = parameters['ThumbItemPosX'] || '0';
    const thumbItemPosY = parameters['ThumbItemPosY'] || '0';
    const thumbItemScale = parseFloat(parameters['ThumbItemScale']);
    const otherWindowClass = parameters['OtherWindowClass'];
    const thumbOtherPosX = parameters['ThumbOWPosX'] || '0';
    const thumbOtherPosY = parameters['ThumbOWPosY'] || '0';
    const thumbOtherScale = parseFloat(parameters['ThumbOWScale']);

    //------------------------------------------------------------------------

    /**
     * セーブデータのサムネイルで使用するユニークなキーを返します
     *
     * @param {number} savefileId セーブファイルのID
     * @return {string}
    */
    function generateThumbUniqueKey(savefileId) {
        if (DataManager.isThisGameFile(savefileId)) {
            const info = DataManager.loadSavefileInfo(savefileId);
            return savefileId + ':' + info.timestamp;
        }
        return undefined;
    };

    //------------------------------------------------------------------------

    /**
     * Takes a snapshot of the game screen and returns a new bitmap object.\
     * 出力するビットマップの幅と高さを指定できるよう, Bitmap.snap を元に拡張しています.\
     * 幅/高さが未指定の場合は, 従来のように Graphics.width, Graphics.height となります.\
     * また, 出力前の元々の幅と高さをさらに指定することで,\
     * その値を元にビットマップの幅と高さに合わせて拡大率を調整します.\
     * こちらの指定がない場合は, ビットマップの幅と高さと同値となり, 拡大率を変えません.
     *
     * @static
     * @param {Stage} stage The stage object
     * @param {number} dw 出力するビットマップの幅
     * @param {number} dh 出力するビットマップの高さ
     * @param {number} cw 元の幅
     * @param {number} ch 元の高さ
     * @return {Bitmap} リサイズされたビットマップ
     */
    Bitmap.snap2 = function (stage, dw = Graphics.width, dh = Graphics.height, cw = dw, ch = dh) {
        const bitmap = new Bitmap(dw, dh);
        if (stage) {
            const context = bitmap._context;
            const renderTexture = PIXI.RenderTexture.create(dw, dh);
            const last_sx = stage.scale.x;
            const last_sy = stage.scale.y;
            stage.scale.x = dw / cw;
            stage.scale.y = dh / ch;
            Graphics._renderer.render(stage, renderTexture);
            stage.worldTransform.identity();
            stage.scale.x = last_sx;
            stage.scale.y = last_sy;
            let canvas = null;
            if (Graphics.isWebGL()) {
                canvas = Graphics._renderer.extract.canvas(renderTexture);
            } else {
                canvas = renderTexture.baseTexture._canvasRenderTarget.canvas;
            }
            context.drawImage(canvas, 0, 0);
            renderTexture.destroy({ destroyBase: true });
            bitmap._setDirty();
        }
        return bitmap;
    };

    //------------------------------------------------------------------------

    monkeyPatch(Decrypter, 'checkImgIgnore', function ($) {
        return function (url) {
            // Base64形式なら暗号化の対象外にする
            if (url.includes('data:image/jpeg;base64')) {
                return true;
            }
            return $.call(this, url);
        };
    });

    //------------------------------------------------------------------------

    /**
     * セーブファイルがこのゲームの何番目のものか取得します.
     *
     * @param {Object} info セーブデータ
     * @return {number}
     */
    DataManager.getSavefileId = function (info) {
        const globalInfo = this.loadGlobalInfo();
        if (globalInfo) {
            for (let id = 1, l = globalInfo.length; id < l; id++) {
                if (this.isThisGameFile(id)) {
                    if (this.isEqualSavefile(info, globalInfo[id])) {
                        return id;
                    }
                }
            }
        }
        return -1;
    };

    /**
     * セーブファイルが同じものか判定します.
     *
     * @param {Object} a セーブデータA
     * @param {Object} b セーブデータB
     * @return {boolean}
     */
    DataManager.isEqualSavefile = function (a, b) {
        // NOTE : thumbnailは長くなりがちなので比較しなくてよいかなという判断
        return (a.globalId === b.globalId
            && a.title === b.title
            && a.timestamp === b.timestamp
            && a.playtime === b.playtime
            // && a.thumbnail === b.thumbnail
            && a.characters.equals(b.characters)
            && a.faces.equals(b.faces)
        );
    };

    //------------------------------------------------------------------------

    /**
     * Base64形式用のキャッシュキーを返します.\
     * データURIは長くなるので, ユニークなキーを指定して代用します.
     *
     * @param {number|string} cacheKey 任意のキー
     * @param {number} hue 色相
     * @return {string}
     */
    ImageManager._generateBase64CacheKey = function (cacheKey, hue) {
        return 'Base64:' + cacheKey + ':' + hue;
    };

    /**
     * ビットマップをjpgのBase64形式文字列に変換します
     *
     * @param {Bitmap} bitmap ビットマップ
     * @return {string} Base64形式の文字列を返します
     */
    ImageManager.toBase64 = function (bitmap) {
        const minetype = 'image/jpeg';
        const quality = thumbQuality / 100;
        return bitmap._canvas.toDataURL(minetype, quality);
    };

    /**
     * Base64形式の文字列からビットマップをロードします.\
     * キャッシュに対応しています.
     *
     * @param {string} src Base64形式の文字列
     * @param {number|string} cacheKey キャッシュに使用する任意のキー
     * @param {number} hue 色相
     * @return {Bitmap}
     */
    ImageManager.loadBase64Bitmap = function (src, cacheKey, hue = 0) {
        const b64cacheKey = this._generateBase64CacheKey(cacheKey, hue);
        let bitmap = this._imageCache.get(b64cacheKey);
        if (!bitmap) {
            bitmap = Bitmap.load(src);
            if (this._callCreationHook) {
                // community-1.3 の プログレスバー 対応
                this._callCreationHook(bitmap);
            }
            bitmap.addLoadListener(function () {
                bitmap.rotateHue(hue);
            });
            this._imageCache.add(b64cacheKey, bitmap);
        } else if (!bitmap.isReady()) {
            bitmap.decode();
        }
        return bitmap;
    };

    /**
     * Base64形式の文字列からビットマップをリクエストします.\
     * キャッシュに対応しています.
     *
     * @param {string} src Base64形式の文字列
     * @param {number|string} cacheKey キャッシュに使用する任意のキー
     * @param {number} hue 色相
     * @return {Bitmap}
     */
    ImageManager.requestBase64Bitmap = function (src, cacheKey, hue = 0) {
        const b64cacheKey = this._generateBase64CacheKey(cacheKey, hue);
        let bitmap = this._imageCache.get(b64cacheKey);
        if (!bitmap) {
            bitmap = Bitmap.request(src);
            if (this._callCreationHook) {
                // community-1.3 の プログレスバー 対応
                this._callCreationHook(bitmap);
            }
            bitmap.addLoadListener(function () {
                bitmap.rotateHue(hue);
            });
            this._imageCache.add(b64cacheKey, bitmap);
            this._requestQueue.enqueue(b64cacheKey, bitmap);
        } else {
            this._requestQueue.raisePriority(b64cacheKey);
        }
        return bitmap;
    };

    //------------------------------------------------------------------------

    /**
     * セーブファイルからサムネイルをロードします.
     *
     * @param {number} savefileId セーブファイルのID
     * @param {object} info セーブデータ
     * @param {number} hue 色相
     * @return {Bitmap}
     */
    ImageManager.loadThumbnail = function (savefileId, info, hue) {
        const cacheKey = generateThumbUniqueKey(savefileId);
        if (info && info.thumbnail && cacheKey) {
            return ImageManager.loadBase64Bitmap(info.thumbnail, cacheKey, hue);
        }
        return this.loadEmptyBitmap();
    };

    /**
     * セーブファイルからサムネイルをリクエストします.
     *
     * @param {number} savefileId セーブファイルのID
     * @param {object} info セーブデータ
     * @param {number} hue 色相
     * @return {Bitmap}
     */
    ImageManager.requestThumbnail = function (savefileId, info, hue) {
        const cacheKey = generateThumbUniqueKey(savefileId);
        if (info && info.thumbnail && cacheKey) {
            return this.requestBase64Bitmap(info.thumbnail, cacheKey, hue);
        }
        return this.loadEmptyBitmap();
    };

    /**
     * セーブ/ロード画面用のサムネイル読み込み中のビットマップを返します.
     *
     * @param {number} width
     * @param {number} height
     * @return {Bitmap}
     */
    ImageManager.loadBusyThumbBitmap = function (width, height) {
        const cacheKey = 'busyThumb:' + width + '_' + height;
        let empty = this._imageCache.get(cacheKey);
        if (!empty) {
            empty = new Bitmap(width, height);
            empty.fillAll('#000000');
            this._imageCache.add(cacheKey, empty);
        }
        return empty;
    };

    /**
     * サムネイルの自動撮影を行うか判定.
     *
     * @return {boolean}
     */
    SceneManager.isAutoSnapForThumbnail = function () {
        if (!isAutoSnap || !$gameSystem.isSaveEnabled()) {
            return false;
        }
        // 現在のシーンがマップ画面以外であれば false.
        if (!this._scene || this._scene.constructor !== Scene_Map) {
            return false;
        }
        // 次のシーンが指定のいずれかであれば true.
        //const scenes = [Scene_Menu, Scene_Load, Scene_Save];
        const scenes = [Scene_Menu];
        return scenes.some((scene) => this.isNextScene(scene));
    };

    monkeyPatch(SceneManager, 'snapForBackground', function ($) {
        return function () {
            $.call(this);
            if (this.isAutoSnapForThumbnail()) {
                this.snapForThumbnail();
            }
        };
    });

    /**
     * マップ画面を指定のサイズのビットマップを保存します.
     */
    SceneManager.snapForThumbnail = function () {
        if (this._scene) {
            const cw = Graphics.width;
            const ch = Graphics.height;
            this._thumbnailBitmap = Bitmap.snap2(this._scene, thumbSaveWidth, thumbSaveHeight, cw, ch);
        }
    };

    /**
     * サムネイルのビットマップを削除します.
     */
    SceneManager.clearThumbnail = function () {
        this._thumbnailBitmap = null;
    };

    /**
     * サムネイル用に保存したビットマップのBase64形式の文字列を返します.
     *
     * @return {string}
     */
    SceneManager.thumbnailBase64 = function () {
        if (this._thumbnailBitmap) {
            return ImageManager.toBase64(this._thumbnailBitmap);
        }
        return '';
    };

    monkeyPatch(DataManager, 'makeSavefileInfo', function ($) {
        return function () {
            let info = $.call(this);
            info.thumbnail = SceneManager.thumbnailBase64();
            if (!info.thumbnail) {
                delete info.thumbnail;
            }
            return info;
        };
    });

    monkeyPatch(DataManager, 'loadSavefileImages', function ($) {
        return function (info) {
            $.call(this, info);
            if (info.thumbnail) {
                ImageManager.requestThumbnail(info);
            }
        };
    });

    //------------------------------------------------------------------------

    /**
     * Base64形式の文字列データから画像を読み込んで描画する.
     *
     * @param {string} src Base64形式の文字列
     * @param {number|string} cacheKey キャッシュに使用する任意のキー
     * @param {number} x 描画 X 座標
     * @param {number} y 描画 Y 座標
     * @param {number} width 描画する幅
     * @param {number} height 描画する高さ
     * @param {Function} onDrawAfter 描画後の処理
     */
    Window_Base.prototype.drawBase64Data = function (src, cacheKey, x, y, width = 0, height = 0, onDrawAfter = null) {
        const bitmap = ImageManager.loadBase64Bitmap(src, cacheKey);
        const lastOpacity = this.contents.paintOpacity;
        if (!bitmap.isReady() && width > 0 && height > 0) {
            this.contents.fillRect(x, y, width, height, '#000000');
        }
        bitmap.addLoadListener(() => {
            this._onLoadBase64Data(bitmap, x, y, lastOpacity, width, height, onDrawAfter);
        });
    };

    /**
     * drawBase64Data のイベントリスナー関数.
     *
     * @param {Bitmap} bitmap Base64形式から生成されたビットマップ
     * @param {number} x 描画 X 座標
     * @param {number} y 描画 Y 座標
     * @param {number} lastOpacity 描画前の透明度
     * @param {number} width 描画する幅
     * @param {number} height 描画する高さ
     * @param {Function} onDrawAfter 描画後の処理
     */
    Window_Base.prototype._onLoadBase64Data = function (bitmap, x, y, lastOpacity, width, height, onDrawAfter = null) {
        const bw = bitmap.width;
        const bh = bitmap.height;
        width = width || bw;
        height = height || bh;
        //const lastOpacity = this.contents.paintOpacity;
        this.contents.paintOpacity = lastOpacity;
        this.contents.blt(bitmap, 0, 0, bw, bh, x, y, width, height);
        if (onDrawAfter) {
            onDrawAfter();
        }
        //this.contents.paintOpacity = lastOpacity;
    };

    /**
     * Base64形式の文字列データから画像を読み込んで描画する.\
     * 読み込みの遅延により描画が遅れると, 高速スクロールさせることで\
     * 描画位置や透明度がずれることがあるのでその対策込みで再定義.
     *
     * @param {string} src Base64形式の文字列
     * @param {number|string} cacheKey キャッシュに使用する任意のキー
     * @param {number} x 描画 X 座標
     * @param {number} y 描画 Y 座標
     * @param {number} width 描画する幅
     * @param {number} height 描画する高さ
     * @param {Function} onDrawAfter 描画後の処理
     */
    Window_Selectable.prototype.drawBase64Data = function (src, cacheKey, x, y, width = 0, height = 0, onDrawAfter = null) {
        const bitmap = ImageManager.loadBase64Bitmap(src, cacheKey);
        const lastOpacity = this.contents.paintOpacity;
        const lastTopRow = this.topRow();
        const lastLeftCol = Math.floor(this._scrollX / this.itemWidth());
        if (!bitmap.isReady() && width > 0 && height > 0) {
            this.contents.fillRect(x, y, width, height, '#000000');
        }
        bitmap.addLoadListener(() => {
            if (this.topRow() !== lastTopRow || Math.floor(this._scrollX / this.itemWidth()) !== lastLeftCol) {
                return;
            }
            this._onLoadBase64Data(bitmap, x, y, lastOpacity, width, height, onDrawAfter);
        });
    };

    //------------------------------------------------------------------------

    // Scene_File 上での DataManager.loadGlobalInfo の実行回数を減らすための対応
    if (isFastLoadingData) {
        /** @type {Object[]} */
        let _globalInfo;

        monkeyPatch(DataManager, 'loadGlobalInfo', function ($) {
            return function () {
                return _globalInfo ? _globalInfo : $.call(this);
            };
        });

        monkeyPatch(Scene_File.prototype, 'initialize', function ($) {
            return function () {
                _globalInfo = DataManager.loadGlobalInfo();
                $.call(this);
            };
        });

        monkeyPatch(Scene_File.prototype, 'terminate', function ($) {
            return function () {
                $.call(this);
                _globalInfo = null;
            };
        });
    }

    //------------------------------------------------------------------------

    // リストウィンドウ内に, サムネイル表示を行う処理を追加します
    if (isShowInList) {
        Window_SavefileList.prototype.thumbnailX = eval('(function(rect, width) { return %1; });'.format(thumbItemPosX));
        Window_SavefileList.prototype.thumbnailY = eval('(function(rect, height) { return %1; });'.format(thumbItemPosY));

        monkeyPatch(Window_SavefileList.prototype, 'initialize', function ($) {
            return function (x, y, width, height) {
                $.call(this, x, y, width, height);
                this.createThumbnail();
            };
        });

        Window_SavefileList.prototype.createThumbnail = function () {
            const contentsIndex = this.children.indexOf(this._windowContentsSprite);
            this._thumbContainer = new PIXI.Container();
            this.addChildAt(this._thumbContainer, contentsIndex);
            let thumb;
            let maxVisibleRows = this.maxItems();
            //let maxVisibleRows = this.maxVisibleItems();
            for (let i = 0, l = maxVisibleRows; i < l; i++) {
                thumb = new Sprite();
                thumb.scale.x = thumbItemScale;
                thumb.scale.y = thumbItemScale;
                thumb.bitmap = null;
                thumb.visible = false;
                this._thumbContainer.addChild(thumb);
            }
            this.refreshThumbnailParts();
        };

        monkeyPatch(Window_SavefileList.prototype, '_refreshContents', function ($) {
            return function () {
                $.call(this);
                this.refreshThumbnailParts();
            };
        });

        Window_SavefileList.prototype.refreshThumbnailParts = function () {
            if (this._thumbContainer) {
                this._thumbContainer.x = this.padding;
                this._thumbContainer.y = this.padding;
            }
        };

        Window_SavefileList.prototype.bottomIndex = function () {
            return this.topIndex() + this.maxPageItems() - 1;
        };

        monkeyPatch(Window_SavefileList.prototype, 'refresh', function ($) {
            return function () {
                this.clearThumbnail();
                $.call(this);
            };
        });

        Window_SavefileList.prototype.clearThumbnail = function () {
            const thumbs = this._thumbContainer.children;
            let thumb;
            for (let i = 0, l = thumbs.length; i < l; i++) {
                thumb = thumbs[i];
                thumb.bitmap = null;
                thumb.visible = false;
            }
        };

        monkeyPatch(Window_SavefileList.prototype, 'drawContents', function ($) {
            return function (info, rect, valid) {
                $.call(this, info, rect, valid);
                let thumbRect = new Rectangle();
                thumbRect.width = Math.floor(thumbSaveWidth * thumbItemScale);
                thumbRect.height = Math.floor(thumbSaveHeight * thumbItemScale);
                thumbRect.x = this.thumbnailX(rect, thumbRect.width);
                thumbRect.y = this.thumbnailY(rect, thumbRect.height);
                this.drawThumbnail(info, thumbRect, valid);
            };
        });

        /**
         * サムネイルを描画する
         *
         * @param {Object} info セーブファイルのインフォデータ
         * @param {Rectangle} thumbRect
         * @param {boolean} valid
         */
        Window_SavefileList.prototype.drawThumbnail = function (info, thumbRect, valid) {
            const savefileId = DataManager.getSavefileId(info);
            const listIndex = savefileId - 1;
            if (savefileId > 0 && info.thumbnail) {
                let sprite = this._thumbContainer.children[listIndex];
                sprite.visible = true;
                sprite.x = thumbRect.x;
                sprite.y = thumbRect.y;
                const thunmbBitmap = ImageManager.loadThumbnail(savefileId, info);
                if (!thunmbBitmap.isReady()) {
                    // 読み込み終わるまで別のビットマップを表示
                    const empty = ImageManager.loadBusyThumbBitmap(thumbRect.width, thumbRect.height);
                    sprite.bitmap = empty;
                }
                thunmbBitmap.addLoadListener(() => {
                    // 読み込み終わったときにリスト表示範囲内であれば描画
                    if (this.topIndex() <= listIndex && this.bottomIndex() >= listIndex) {
                        sprite.visible = true;
                        sprite.bitmap = thunmbBitmap;
                        sprite.bitmap.paintOpacity = valid ? 255 : this.translucentOpacity();
                    } else {
                        sprite.visible = false;
                    }
                });
            }
        };
    }

    // 任意のウィンドウに, サムネイル表示を行う処理を追加します
    if (otherWindowClass) {
        /** @type {Window_Base} */
        const AnyWindowClass = eval(otherWindowClass);

        if (!AnyWindowClass || !AnyWindowClass.prototype || !(AnyWindowClass.prototype instanceof Window_Base)) {
            throw new Error(AnyWindowClass + ': This is not a class extended \'Window_Base\' class');
        }

        AnyWindowClass.prototype._thumbnailX = eval('(function(rect, width) { return %1; });'.format(thumbOtherPosX));
        AnyWindowClass.prototype._thumbnailY = eval('(function(rect, height) { return %1; });'.format(thumbOtherPosY));

        monkeyPatch(AnyWindowClass.prototype, 'initialize', function ($) {
            return function () {
                $.call(this, ...arguments);
                if (SceneManager._scene instanceof Scene_File) {
                    this._createThumbnail();
                }
            };
        });

        AnyWindowClass.prototype._createThumbnail = function () {
            const contentsIndex = this.children.indexOf(this._windowContentsSprite);
            this._thumbContainer = new PIXI.Container();
            this.addChildAt(this._thumbContainer, contentsIndex);
            this._thumbSprite = new Sprite();
            this._thumbSprite.scale.x = thumbItemScale;
            this._thumbSprite.scale.y = thumbItemScale;
            this._thumbSprite.bitmap = null;
            this._thumbSprite.visible = false;
            this._thumbContainer.addChild(this._thumbSprite);
            // contents からはみ出ないためのマスクをつける
            this._maskGraphic = new PIXI.Graphics();
            this._thumbContainer.addChild(this._maskGraphic);
            this._thumbContainer.mask = this._maskGraphic;
            this._refreshThumbnailParts();
        };

        monkeyPatch(AnyWindowClass.prototype, '_refreshContents', function ($) {
            return function () {
                $.call(this);
                this._refreshThumbnailParts();
            };
        });

        AnyWindowClass.prototype._refreshThumbnailParts = function () {
            if (this._thumbContainer) {
                this._thumbContainer.x = this.padding;
                this._thumbContainer.y = this.padding;
            }
            if (this._maskGraphic) {
                this._maskGraphic.clear();
                this._maskGraphic.beginFill('#000000');
                this._maskGraphic.drawRect(0, 0, this.contentsWidth(), this.contentsHeight());
                this._maskGraphic.endFill();
            }
        };

        monkeyPatch(AnyWindowClass.prototype, 'update', function ($) {
            return function () {
                if ($) {
                    $.call(this);
                }
                if (SceneManager._scene instanceof Scene_File) {
                    this._updateThumbnail();
                }
            };
        });

        AnyWindowClass.prototype._updateThumbnail = function () {
            /** @type {Window_SavefileList} */
            const list = SceneManager._scene._listWindow;
            if (list) {
                const savefileId = list.index() + 1;
                if (savefileId !== this._savefileId) {
                    this._savefileId = savefileId;
                    const rect = new Rectangle(0, 0, this.contentsWidth(), this.contentsHeight());
                    let thumbRect = new Rectangle();
                    thumbRect.width = Math.floor(thumbSaveWidth * thumbOtherScale);
                    thumbRect.height = Math.floor(thumbSaveHeight * thumbOtherScale);
                    thumbRect.x = this._thumbnailX(rect, thumbRect.width);
                    thumbRect.y = this._thumbnailY(rect, thumbRect.height);
                    this._drawThumbnail(thumbRect);
                }
            }
        };

        AnyWindowClass.prototype._drawThumbnail = function (thumbRect) {
            const savefileId = this._savefileId;
            const info = DataManager.loadSavefileInfo(savefileId);
            if (this._savefileId > 0 && info && info.thumbnail) {
                const valid = DataManager.isThisGameFile(savefileId);
                this._thumbSprite.visible = true;
                this._thumbSprite.x = thumbRect.x;
                this._thumbSprite.y = thumbRect.y;
                const thunmbBitmap = ImageManager.loadThumbnail(savefileId, info);
                if (!thunmbBitmap.isReady()) {
                    // 読み込み終わるまで別のビットマップを表示
                    const empty = ImageManager.loadBusyThumbBitmap(thumbRect.width, thumbRect.height);
                    this._thumbSprite.bitmap = empty;
                }
                thunmbBitmap.addLoadListener(() => {
                    // 読み込み終わって位置が変わっていないなら描画
                    if (savefileId === this._savefileId) {
                        this._thumbSprite.bitmap = thunmbBitmap;
                        this._thumbSprite.bitmap.paintOpacity = valid ? 255 : this.translucentOpacity();
                    }
                });
            } else {
                this._thumbSprite.visible = false;
                this._thumbSprite.bitmap = null;
            }
        };
    }

    //------------------------------------------------------------------------

    // community-1.3 の オートセーブ 対応
    if (DataManager.autoSaveGame) {
        monkeyPatch(DataManager, 'autoSaveGame', function ($) {
            return function () {
                if (this._autoSaveFileId !== 0 && !this.isEventTest() && $gameSystem.isSaveEnabled()) {
                    SceneManager.clearThumbnail();
                }
                $.call(this);
            };
        });
    }

})();

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// メッセージボックス中央揃い・右揃いプラグイン
// aligncenter.js
// Copyright (c) 2018 村人Ａ
//=============================================================================

/*:ja
 * @plugindesc メッセージボックスの文字を中央揃い、右揃いにするプラグインです。
 * @author 村人A
 *
 * @help
 *
 * メッセージ内で指定の行の冒頭で「\#」で中央揃い、[\_]で右揃いにします。
 * ex)メッセージ入力時
 *
 * ここはデフォルト（左揃い）
 * \#ここは中央ぞろい
 * \_ここは右揃い
 * ここはデフォルト（左揃い）
 *
 * となります。
 *
 * 拡大・縮小文字を揃えたい場合はや「\#」や「\_」の前に指定特殊文字「\{」や「\}」を
 * 入力してください。
 * ex)メッセージ入力時
 *
 * ここはデフォルト（左揃い）
 * \{\#ここは一段階大きな文字を中央ぞろい
 * \}}\_ここは一段階小さい文字を右揃い
 * ここは一段階小さい文字を左揃い
 *
 */

(function () {
	var _Window_Base_initialize = Window_Base.prototype.initialize;
	Window_Base.prototype.initialize = function (x, y, width, height) {
		_Window_Base_initialize.call(this, x, y, width, height);
		this.villaA_paddingleft = 0;
		this.villaA_procLine = 0;
	}

	Window_Base.prototype.obtainEscapeCode = function (textState) {
		textState.index++;
		var regExp = /^[\$\.\|\^!><\{\}\\\#\_]|^[A-Z]+/i;
		var arr = regExp.exec(textState.text.slice(textState.index));
		if (arr) {
			textState.index += arr[0].length;
			return arr[0].toUpperCase();
		} else {
			return '';
		}
	};

	Window_Message.prototype.processEscapeCharacter = function (code, textState) {
		switch (code) {
			case '$':
				this._goldWindow.open();
				break;
			case '.':
				this.startWait(15);
				break;
			case '|':
				this.startWait(60);
				break;
			case '!':
				this.startPause();
				break;
			case '>':
				this._lineShowFast = true;
				break;
			case '<':
				this._lineShowFast = false;
				break;
			case '^':
				this._pauseSkip = true;
				break;
			case '\#':
				var linelenght = textState.text.split(/\r\n|\r|\n/)
				this.villaA_paddingleft = (this.width - this.textWidth(linelenght[this.villaA_procLine]) - this.newLineX()) / 2;
				break;
			case '\_':
				var linelenght = textState.text.split(/\r\n|\r|\n/)
				this.villaA_paddingleft = this.width - this.textWidth(linelenght[this.villaA_procLine]) - 20 - this.newLineX();
				break;
			default:
				Window_Base.prototype.processEscapeCharacter.call(this, code, textState);
				break;
		}
	};

	Window_Base.prototype.processCharacter = function (textState) {
		switch (textState.text[textState.index]) {
			case '\n':
				this.processNewLine(textState);
				this.villaA_procLine++;
				break;
			case '\f':
				this.processNewPage(textState);
				break;
			case '\x1b':
				this.processEscapeCharacter(this.obtainEscapeCode(textState), textState);
				break;
			default:
				this.processNormalCharacter(textState);
				break;
		}
	};

	Window_Base.prototype.processNormalCharacter = function (textState) {
		var c = textState.text[textState.index++];
		var w = this.textWidth(c);
		this.contents.drawText(c, textState.x + this.villaA_paddingleft, textState.y, w * 2, textState.height);
		textState.x += w;
	};

	var _Window_Base_processNewLine = Window_Base.prototype.processNewLine
	Window_Base.prototype.processNewLine = function (textState) {
		_Window_Base_processNewLine.call(this, textState);
		this.villaA_paddingleft = 0;

	};

	var _Window_Message_startMessage = Window_Message.prototype.startMessage
	Window_Message.prototype.startMessage = function () {
		_Window_Message_startMessage.call(this);
		this.villaA_procLine = 0;
	};

	var _Window_Message_clearFlags = Window_Message.prototype.clearFlags
	Window_Message.prototype.clearFlags = function () {
		_Window_Message_clearFlags.call(this);
		this.villaA_paddingleft = 0;
	};
})();


code:
//=============================================================================
// AnimatedSVEnemies.js
// Version: 1.15.5.1 - The Re-Remake
//=============================================================================

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

var Rexal = Rexal || {};
Rexal.ASVE = Rexal.ASVE || {};
/*:
 * @plugindesc Version: 1.15.5.1 - The Re-Remake
 * - Lets enemies be animated!
 * @author Rexal
 *

  * @param Debug
 * @desc Log to the Console(F8)?
 * @default true

 * @param No Movement
 * @desc Prevents enemies from moving whenever they perform an action.
 * @default false

 * @param Enemies Celebrate
 * @desc Enemies will celebrate over your demise.
 * @default true

  * @param SV Enemies Collapse
 * @desc All SV Enemies will collapse after death.
 * @default false

 * @param Static Enemies Breathe
 * @desc Static Enemies have a breathing effect
 * @default true

 * @param AGI Effects Breathing
 * @desc Static Enemies with a higher AGI stat will breathe faster.
 * @default true

 * @param Scale Statics by Distance
 * @desc Static Enemies will be smaller the further away they are in the background
 * @default true

  * @param Damage Slows Down Breathing
 * @desc Breathing slows down the more damage they take
 * @default true

  * @help

 --------------------------------------------------------------------------------
 Notetags
 ================================================================================

 ---------------------------[SV Battlers]---------------------------------

 [SV Animated]
 - Sets the enemy to use the an SV Actor sprite. These are located in the sv_actors
 folder. Make sure that there's a sprite in that folder that matches the name
 of the enemy's image you used.

 [Collapse]
 - Lets the SV Enemy use collapse animations regardless of parameter settings.

 [No Collapse]
 - Prevents the SV Enemy from using collapse animations regardless of parameter settings.

 SV Motion: motion
 - Sets the enemy to use this motion when attacking. If you don't know what motions
 you can use, refer to the motion list at the bottom of the help section.

  SV Weapon: id
 - "Equips" the enemy with this weapon.

 Ex: SV Weapon: 1

    SV Weapon Scale: amount
     multiplies the size of the weapon by this amount.

     SV Weapon Anchor: x,y
     sets the weapon's anchor point to this.

Ex. SV Weapon Anchor: .5,1

       SV Anchor: x,y
     sets the battler's anchor point to this.

Ex. SV Anchor: .5,1

  ----------------------------[Static Battlers]---------------------------------

 [Breathless]
 -This enemy doesn't breathe. Useful for golems and evil walls.

 [Float]
 -Makes enemies have a floating effect similar to rm2k3's.

 Breath Control: speedScale,xScale,yScale
 -Sets the speed of the sine wave and how many times the size of the sprite it's
  allowed to go width-wise and height-wise.

  You'll have to play around with the values a bit until it looks right. The
  example below is the default settings.

 Ex: Breath Control: 50,5,25

 -----------------------------------[Both]---------------------------------------

 Enemy Scale: amount

 multiplies the size of the enemy by this amount.

 --------------------------------------------------------------------------------
 Version Log
 ================================================================================

 v1 - Initial Version

 v1.05 - Many fixes
 - Fixed issue with enemies not playing the right animations when more than one
 enemy is on the screen.
 - Misc. Fixes that I've forgotten about.
 - Added SV Weapon, which lets you play a weapon animation(currently backwards).
 This is not yet compatible with my other script: Sprite Weapons Enhanced.
 - Added a param that stops enemies from moving.

  v1.075 - Deep breaths
 - Static enemies breathe now!
 - Added a bunch of stuff to control the breathing. (notetags do not work!)

   v1.08 - Fixed Breathing
 - The breathing notetags work now! Yay!
 - Added [Float]

   v1.1 - Live and Reloaded

  -Breathing slows down the less hp an enemy has. (orignally they just breathed less)
  - Added an option that lets enemies scale down the further into the background they are.
  - Fixed the weapons!
  - Enemies can celebrate your demise.
  - Fixed the Flash Target bug.
  - SV Enemies can collapse.
  - SV Enemies will properly appear
  - Enemies have a proper escape animation.
  - Enemies are now properly positioned.
  - You can now scale the enemies however you want.

   v1.101 -

   - Added a parameter to prevent enemies from breathing slower the more damage they take.

   v1.11 -

   - Fixed the positioning. SORRY!

   v1.111 -
   - No comment.
      v1.113 -
   Fixed the weapons.

   v1.12 -
   - Completely rewrote crucial portions of the script.
   - Note tags are no longer case-sensitive.
   - Fixed the positioning officially.
   - Fixed the floating issue.

   v1.15 - The Re-Remake
   - Massive cleanup that should make it much more compatible.

    v1.15.1 -
    -Solved the issue with damage numbers not popping up.
    v1.15.3
    -Fixed Some stuff.
    v1.15.5
    -Added some stuff. =m=

    v1.15.5.1
    -Should be more compatible with stuff

 --------------------------------------------------------------------------------
 Motion List
 ================================================================================
 walk - Ready Animation
 wait - The Idle Animation
 chant - Magic Ready animation
 guard - The Guard Animation
 damage - Damage Animation
 evade - Miss! Animation
 thrust - Stabbing Animation
 swing - Swinging Animation
 missile - Shooting Animation
 skill - Physical Skill Use Animation
 spell - Magical Skill Use Animation
 item - Item Use Animation
 escape - Escape Animation
 victory - Victory Animation
 dying - The "Danger" Animation
 abnormal - The State Affected Animation
 sleep - The Sleeping Animation
 dead - The Dead Animation

 */

Rexal.ASVE.Parameters = PluginManager.parameters('animatedSVEnemies');
Rexal.ASVE.Debug = eval(String(Rexal.ASVE.Parameters['Debug']));
Rexal.ASVE.NoMovement = eval(String(Rexal.ASVE.Parameters['No Movement']));
Rexal.ASVE.Breathe = eval(String(Rexal.ASVE.Parameters['Static Enemies Breathe']));
Rexal.ASVE.AGIB = eval(String(Rexal.ASVE.Parameters['AGI Effects Breathing']));
Rexal.ASVE.Celebration = eval(String(Rexal.ASVE.Parameters['Enemies Celebrate']));
Rexal.ASVE.DoCollapse = eval(String(Rexal.ASVE.Parameters['SV Enemies Collapse']));
Rexal.ASVE.DamageSlow = eval(String(Rexal.ASVE.Parameters['Damage Slows Down Breathing']));
Rexal.ASVE.ScaleStatics = eval(String(Rexal.ASVE.Parameters['Scale Statics by Distance']));

//-----------------------------------------------------------------------------
//Original Functions Storage
//=============================================================================
Rexal.ASVE.Game_Enemy_makeActions = Game_Enemy.prototype.makeActions;
Rexal.ASVE.Game_Enemy_performDamage = Game_Enemy.prototype.performDamage;
Rexal.ASVE.Sprite_Enemy_updateBitmap = Sprite_Enemy.prototype.updateBitmap;
Rexal.ASVE.seupdateappear = Sprite_Enemy.prototype.updateAppear;
Rexal.ASVE.processDefeat = BattleManager.processDefeat;
Rexal.ASVE.spriteactorupdatebitmap = Sprite_Actor.prototype.updateBitmap;
Rexal.ASVE.setupweaponanimation = Sprite_Actor.prototype.setupWeaponAnimation;
Rexal.ASVE.setactorhome = Sprite_Actor.prototype.setActorHome;
//-----------------------------------------------------------------------------
// BattleManager
//=============================================================================

if (Rexal.ASVE.Celebration) {

    BattleManager.processDefeat = function () {
        Rexal.ASVE.processDefeat.call(this);
        if (Rexal.ASVE.Celebration) $gameTroop.performVictory();
        this.displayDefeatMessage();
        this.playDefeatMe();
        if (this._canLose) {
            this.replayBgmAndBgs();
        } else {
            AudioManager.stopBgm();
        }
        this.endBattle(2);
    };
}

//-----------------------------------------------------------------------------
// Game_Enemy
//=============================================================================

Game_Enemy.prototype.weapons = function () {

    if (this._animated) return [$dataWeapons[this._weaponId]];
    else return [1];
};

Game_Enemy.prototype.performAttack = function () {
    Game_Actor.prototype.performAttack.call(this);
};

Game_Enemy.prototype.attackAnimationId1 = function () {
    Game_Actor.prototype.attackAnimationId1.call(this);
};

Game_Enemy.prototype.attackAnimationId2 = function () {
    Game_Actor.prototype.attackAnimationId2.call(this);
};

Game_Enemy.prototype.bareHandsAnimationId = function () {
    Game_Actor.prototype.bareHandsAnimationId.call(this);
};

Game_Enemy.prototype.hasNoWeapons = function () {
    if (this._animated && this._weaponId != 0)
        return false;
    else return true;
}

Game_Enemy.prototype.performAction = function (action) {
    Game_Actor.prototype.performAction.call(this, action);
};

Game_Enemy.prototype.performDamage = function () {
    Rexal.ASVE.Game_Enemy_performDamage.call(this);
    this.requestMotion('damage');
};

Game_Enemy.prototype.actor = function () {
    return $dataEnemies[this._enemyId];
};

Game_Enemy.prototype.performEvasion = function () {
    Game_Battler.prototype.performEvasion.call(this);
    this.requestMotion('evade');
};

Game_Enemy.prototype.performMagicEvasion = function () {
    Game_Battler.prototype.performMagicEvasion.call(this);
    this.requestMotion('evade');
};

Game_Enemy.prototype.performCounter = function () {
    Game_Battler.prototype.performCounter.call(this);
    this.performAttack();
};

Game_Enemy.prototype.performVictory = function () {
    if (this.canMove()) {
        this.requestMotion('victory');
    }
};

Game_Enemy.prototype.makeActions = function () {
    Rexal.ASVE.Game_Enemy_makeActions.call(this);
    this.setActionState('undecided');
};

Game_Enemy.prototype.performEscape = function () {
    if (this.canMove()) {
        this.requestMotion('escape');
    }
};

//-----------------------------------------------------------------------------
// Game_Troop
//=============================================================================
Game_Troop.prototype.performVictory = function () {
    this.members().forEach(function (enemy) {
        enemy.performVictory();
    });
};
//-----------------------------------------------------------------------------
// Sprite_Enemy
//=============================================================================

Sprite_Enemy.prototype.setBattler = function (battler) {
    Sprite_Battler.prototype.setBattler.call(this, battler);
    this._enemy = battler;
    this.setHome(battler.screenX(), battler.screenY());
    this._stateIconSprite.setup(battler);
};

Sprite_Enemy.prototype.updateBitmap = function () {

    Rexal.ASVE.Sprite_Enemy_updateBitmap.call(this);

    if (!this._enemy._breathless && Rexal.ASVE.Breathe) {

        var a = 1;
        if (Rexal.ASVE.AGIB) a = this._enemy.agi / 100 + 1;
        var breathS = this._enemy._breath[0] / 1000;
        if (Rexal.ASVE.DamageSlow) breathS *= (this._enemy.hp / this._enemy.mhp) + .1;
        var breathY = Math.cos(Graphics.frameCount * breathS * a) * (this._enemy._breath[2] / 1000);
        var breathX = Math.cos(Graphics.frameCount * breathS) * (this._enemy._breath[1] / 1000);

        if (Rexal.ASVE.DamageSlow) breathY *= (this._enemy.hp / this._enemy.mhp);
        var ss = Graphics.boxHeight / 624 + .1;
        if (Rexal.ASVE.ScaleStatics) var s = ss * (this._homeY / Graphics.boxHeight) * this._enemy._scale;
        else var s = this._enemy._scale;

        this.smooth = true;

        this.scale.y = s + breathY;
        this.scale.x = s + breathX;

    }

    if (this._enemy._floating && !this.isBusy) {
        var f = Math.cos(Graphics.frameCount / 50) * 20;
        this.setHome(this._enemy.screenX(), this._enemy.screenY() + f);
    }

};

Sprite_Enemy.prototype.stepForward = function () {
    if (!Rexal.ASVE.NoMovement) this.startMove(48, 0, 12);
};

Sprite_Enemy.prototype.setHome = function (x, y) {

    var dX = Graphics.boxWidth / 816;
    var dY = Graphics.boxHeight / 624;

    y *= dY;
    x *= dX;

    this._homeX = x;
    this._homeY = y + (Graphics.boxHeight - 624) / 3;
    this.updatePosition();
};

//-----------------------------------------------------------------------------
// Sprite_EnemyRex
//=============================================================================

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

Sprite_EnemyRex.prototype = Object.create(Sprite_Actor.prototype);
Sprite_EnemyRex.prototype.constructor = Sprite_EnemyRex;

Sprite_EnemyRex.prototype.createWeaponSprite = function () {

    this._weaponSprite = new Sprite_Weapon();

    this.addChild(this._weaponSprite);
};

Sprite_EnemyRex.prototype.updateSelectionEffect = function () {

    var target = this._effectTarget;
    if (this._battler.isSelected()) {
        this._selectionEffectCount++;
        if (this._selectionEffectCount % 30 < 15) {
            target.setBlendColor([255, 255, 255, 64]);
        } else {
            target.setBlendColor([0, 0, 0, 0]);
        }
    } else if (this._selectionEffectCount > 0) {
        this._selectionEffectCount = 0;
        target.setBlendColor([0, 0, 0, 0]);
    }

}

Sprite_EnemyRex.prototype.loadBitmap = function (name, hue) {

    this.bitmap = ImageManager.loadSvActor(name, hue);
};

Sprite_EnemyRex.prototype.setBattler = function (battler) {
    Sprite_Battler.prototype.setBattler.call(this, battler);
    var changed = (battler !== this._actor);
    if (changed) {
        this._actor = battler;
        this._enemy = battler;
        if (battler) {
            this.setActorHome(battler);
        }
        this.startEntryMotion();
        this._stateSprite.setup(battler);
    }
};

Sprite_EnemyRex.prototype.updateBitmap = function () {
    Rexal.ASVE.spriteactorupdatebitmap.call(this);
    this.updateEffect();
    var hue = this._actor.battlerHue();
    var name = this._actor.battlerName();
    this._mainSprite.bitmap = ImageManager.loadSvActor(name, hue);
    this._mainSprite.scale.x = -this._actor._scale;
    this._mainSprite.scale.y = this._actor._scale;
    this._mainSprite.anchor.x = this._actor._anchor[0];
    this._mainSprite.anchor.y = this._actor._anchor[1];

};

Sprite_EnemyRex.prototype.setupWeaponAnimation = function () {

    Rexal.ASVE.setupweaponanimation.call(this);
    if (!this._weaponSprite._positioned) {

        var scale = this._actor._scale + this._actor._weaponScale;

        this._weaponSprite.scale.x = -scale;
        this._weaponSprite.scale.y = scale;
        this._weaponSprite.x = -this._weaponSprite.x * scale;

        this._weaponSprite.anchor.x = this._actor._weaponAnchor[0];
        this._weaponSprite.anchor.y = this._actor._weaponAnchor[1];

        this._weaponSprite._positioned = true;
    }

};

Sprite_EnemyRex.prototype.setActorHome = function (battler) {
    Rexal.ASVE.setactorhome.call(this);
    var dX = Graphics.boxWidth / 816;
    var dY = Graphics.boxHeight / 624;

    var x = battler.screenX() * dX;
    var y = battler.screenY() * dY;

    this._homeX = x;
    this._homeY = y + (Graphics.boxHeight - 624) / 3;
    this.updatePosition();
};

Sprite_EnemyRex.prototype.stepForward = function () {
    if (!Rexal.ASVE.NoMovement) this.startMove(48, 0, 12);
};

Sprite_EnemyRex.prototype.stepBack = function () {
    if (!Rexal.ASVE.NoMovement) this.startMove(0, 0, 12);
};

Sprite_EnemyRex.prototype.retreat = function () {
    this.startMove(300, 0, 30);
};

Sprite_EnemyRex.prototype.initVisibility = function () {
    this._appeared = this._actor.isAlive();
    if (!this._appeared) {
        this.opacity = 0;
    }
};

Sprite_EnemyRex.prototype.setupEffect = function () {
    this._enemy = this._actor;
    Sprite_Enemy.prototype.setupEffect.call(this);
};

Sprite_EnemyRex.prototype.startEffect = function (effectType) {

    this._effectType = effectType;
    switch (this._effectType) {
        case 'appear':
            this.startAppear();
            break;
        case 'disappear':
            this.startDisappear();
            break;
        case 'whiten':
            this.startWhiten();
            break;
        case 'blink':
            this.startBlink();
            break;
        case 'collapse':
            if (this._actor._collapse) this.startCollapse();
            break;
        case 'bossCollapse':
            this.startBossCollapse();
            break;
        case 'instantCollapse':
            this.startInstantCollapse();
            break;
    }
    this.revertToNormal();
};

Sprite_EnemyRex.prototype.startAppear = function () {
    Sprite_Enemy.prototype.startAppear.call(this);
};

Sprite_EnemyRex.prototype.startDisappear = function () {
    Sprite_Enemy.prototype.startDisappear.call(this);
};

Sprite_EnemyRex.prototype.startWhiten = function () {
    Sprite_Enemy.prototype.startWhiten.call(this);
};

Sprite_EnemyRex.prototype.startBlink = function () {
    Sprite_Enemy.prototype.startBlink.call(this);
};

Sprite_EnemyRex.prototype.startCollapse = function () {
    Sprite_Enemy.prototype.startCollapse.call(this);
};

Sprite_EnemyRex.prototype.startBossCollapse = function () {
    Sprite_Enemy.prototype.startBossCollapse.call(this);
};

Sprite_EnemyRex.prototype.startInstantCollapse = function () {
    Sprite_Enemy.prototype.startInstantCollapse.call(this);
};

Sprite_EnemyRex.prototype.updateEffect = function () {

    this.setupEffect();
    if (this._effectDuration > 0) {
        this._effectDuration--;
        switch (this._effectType) {
            case 'whiten':
                this.updateWhiten();
                break;
            case 'blink':
                this.updateBlink();
                break;
            case 'appear':
                this.updateAppear();
                break;
            case 'disappear':
                this.updateDisappear();
                break;
            case 'collapse':
                if (this._actor._collapse) this.updateCollapse();
                break;
            case 'bossCollapse':
                if (this._actor._collapse) this.updateBossCollapse();
                break;
            case 'instantCollapse':
                if (this._actor._collapse) this.updateInstantCollapse();
                break;
        }
        if (this._effectDuration === 0) {
            this._effectType = null;
        }
    }
};

Sprite_EnemyRex.prototype.isEffecting = function () {
    Sprite_Enemy.prototype.isEffecting.call(this);
};

Sprite_EnemyRex.prototype.revertToNormal = function () {
    Sprite_Enemy.prototype.revertToNormal.call(this);
};

Sprite_EnemyRex.prototype.updateWhiten = function () {
    Sprite_Enemy.prototype.updateWhiten.call(this);
};

Sprite_EnemyRex.prototype.updateBlink = function () {
    Sprite_Enemy.prototype.updateBlink.call(this);
};

Rexal.ASVE.seupdateappear = Sprite_Enemy.prototype.updateAppear;
Sprite_Enemy.prototype.updateAppear = function () {
    Rexal.ASVE.seupdateappear.call(this);
    this.setHome(this._homeX, this._homeY);
};

Rexal.ASVE.seupdatedisappear = Sprite_Enemy.prototype.updateDisappear;

Sprite_Enemy.prototype.updateDisappear = function () {
    Rexal.ASVE.seupdatedisappear.call(this);
    this.setHome(this._homeX - 10, this._homeY);
};

Sprite_EnemyRex.prototype.updateAppear = function () {
    Sprite_Enemy.prototype.updateAppear.call(this);
};

Sprite_EnemyRex.prototype.updateDisappear = function () {
    Sprite_Enemy.prototype.updateDisappear.call(this);
};

Sprite_EnemyRex.prototype.updateCollapse = function () {
    Sprite_Enemy.prototype.updateCollapse.call(this);
};

Sprite_EnemyRex.prototype.updateBossCollapse = function () {
    Sprite_Enemy.prototype.updateBossCollapse.call(this);
};

Sprite_EnemyRex.prototype.updateInstantCollapse = function () {
    Sprite_Enemy.prototype.updateInstantCollapse.call(this);
};
//-----------------------------------------------------------------------------
// Spriteset_Battle
//=============================================================================

Spriteset_Battle.prototype.createEnemies = function () {

    var enemies = $gameTroop.members();
    var sprites = [];
    for (var i = 0; i < enemies.length; i++) {
        var enemy = enemies[i];
        var baseEnemy = $dataEnemies[enemies[i].enemyId()];

        Rexal.ASVE.processEnemyNoteTag(baseEnemy);
        Rexal.ASVE.processEnemyData(enemy, baseEnemy);

        if (enemy._animated) {
            sprites[i] = new Sprite_EnemyRex(enemies[i]);
            sprites[i].opacity = 0;
        }
        else
            sprites[i] = new Sprite_Enemy(enemies[i]);

    }

    sprites.sort(this.compareEnemySprite.bind(this));
    for (var j = 0; j < sprites.length; j++) {
        this._battleField.addChild(sprites[j]);
    }
    this._enemySprites = sprites;
};

//-----------------------------------------------------------------------------
// Rex Functions
//=============================================================================

Object.defineProperties(Game_Enemy.prototype, {
    animated: { get: function () { return this._animated; }, configurable: true },
    motion: { get: function () { return this._motion; }, configurable: true },
    weaponid: { get: function () { return this._weaponId; }, configurable: true },
    breathless: { get: function () { return this._breathless; }, configurable: true },
    floating: { get: function () { return this._float; }, configurable: true },
    scale: { get: function () { return this._scale; }, configurable: true },
    weaponscale: { get: function () { return this._weaponscale; }, configurable: true },
    weaponanchor: { get: function () { return this._weaponanchor; }, configurable: true },
    anchor: { get: function () { return this._anchor; }, configurable: true },
    collapse: { get: function () { return this._collapse; }, configurable: true },
    breath: { get: function () { return this._breath; }, configurable: true }
});

Rexal.log = function (message, type) {
    if (!Rexal.ASVE.Debug) return;
    if (!type) type = 'log';

    switch (type) {

        case 'log':
            console.log(message);
            break;

        case 'info':
            console.debug(message);
            break;

        case 'warn':
            console.warn(message);
            break;

        case 'error':
            console.error(message);
            break;
    }

}

Rexal.ASVE.processEnemyData = function (obj, obj2) {
    obj._breath = [];
    obj._weaponAnchor = [];
    obj._anchor = [];
    obj._animated = obj2.animated;
    obj._motion = obj2.motion;
    obj._weaponId = obj2.weaponid;
    obj._breathless = obj2.breathless;
    obj._floating = obj2.floating;
    obj._scale = obj2.scale;
    obj._breath[0] = obj2.breath[0];
    obj._breath[1] = obj2.breath[1];
    obj._breath[2] = obj2.breath[2];
    obj._collapse = obj2.collapse;
    obj._weaponScale = obj2.weaponscale;
    obj._weaponAnchor = obj2.weaponanchor;
    obj._anchor = obj2.anchor;
}

Rexal.ASVE.processEnemyNoteTag = function (obj) {

    Rexal.log('reading ' + obj.name + '...');

    obj.motion = 'thrust';
    obj.weaponid = 0;
    obj.collapse = Rexal.ASVE.DoCollapse;
    obj.breath = [50, 5, 25];
    obj.scale = 1.0;
    obj.weaponscale = 0.0;
    obj.weaponanchor = [.5, 1];
    obj.anchor = [.5, 1];

    if (obj == null) return;

    var notedata = obj.note.split(/[\r\n]+/);

    for (var i = 0; i < notedata.length; i++) {
        var line = notedata[i];
        var lines = line.split(': ');

        switch (lines[0].toLowerCase()) {

            case '[sv animated]':
                obj.animated = true;
                Rexal.log(obj.name + ' is using SV Battler sprites', 'info');
                break;

            case 'sv motion':
                obj.motion = lines[1].toLowerCase();
                Rexal.log(obj.name + "'s attack motion is:" + obj.motion, 'info');
                break;

            case 'sv weapon':
                obj.weaponid = parseInt(lines[1]);
                Rexal.log(obj.name + " has weapon " + $dataWeapons[obj.weaponid].name, 'info');
                break;

            case '[breathless]':
                obj.breathless = true;
                Rexal.log(obj.name + " is breathless.", 'info');
                break;

            case '[float]':
                obj.floating = true;
                Rexal.log(obj.name + " floats.", 'info');
                break;

            case '[collapse]':
                obj.collapse = true;
                Rexal.log(obj.name + " can collapse.", 'info');
                break;

            case '[no collapse]':
                obj.collapse = false;
                Rexal.log(obj.name + " cannot collapse.", 'info');
                break;

            case 'breath control':

                var lines2 = lines[1].split(',');
                obj.breath[0] = parseInt(lines2[0]);
                obj.breath[1] = parseInt(lines2[1]);
                obj.breath[2] = parseInt(lines2[2]);
                Rexal.log(obj.name + "'s breath control: " + obj.breath, 'info');
                break;

            case 'enemy scale':
                obj.scale = parseFloat(lines[1]);
                Rexal.log(obj.name + " is " + obj.scale + "x bigger than normal.", 'info');
                break;

            case 'sv weapon scale':
                obj.weaponscale = parseFloat(lines[1]) - 1;
                Rexal.log(obj.name + "'s weapon is " + obj.scale + "x bigger than normal.", 'info');
                break;

            case 'sv weapon anchor':

                var lines2 = lines[1].split(',');
                obj.weaponanchor[0] = parseFloat(lines2[0]);
                obj.weaponanchor[1] = parseFloat(lines2[1]);
                Rexal.log(obj.name + "'s weapon is anchored to " + obj.weaponanchor[0] + " and " + obj.weaponanchor[1], 'info');
                break;

            case 'sv anchor': //WIP

                var lines2 = lines[1].split(',');
                obj.anchor[0] = parseFloat(lines2[0]);
                obj.anchor[1] = parseFloat(lines2[1]);
                Rexal.log(obj.name + " is anchored to " + obj.anchor[0] + " and " + obj.anchor[1], 'info');
                break;

        }

    }
    return obj;
};


code:
//=============================================================================
// ダッシュ禁止プラグイン
// dashBan.js
// Copyright (c) 2018 村人Ａ
//=============================================================================

/*:ja
 * @plugindesc ダッシュを禁止するプラグインです
 * @author 村人A
 *
 * @help
 *　=======================================
 *
 *　バージョン管理
 *　2019/3/7 バージョン１.01 リリース
 *　         セーブ・ロード後もダッシュ禁止・許可が反映されているようにしました。
 *　2018/1/2 バージョン１.00 リリース
 *
 *　=======================================
 *
 * プレイヤーのダッシュをコマンドで禁止するプラグインです
 * ダッシュが許可されているマップに移動してもダッシュ禁止は
 * 継続されます。
 *
 * プラグインコマンド:
 *   ダッシュ禁止    # ダッシュを禁止
 *   ダッシュ許可    # ダッシュを許可
 */

(function () {
	villaA_dashBan = false;

	var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
	Game_Interpreter.prototype.pluginCommand = function (command, args) {
		_Game_Interpreter_pluginCommand.call(this, command, args);
		if (command === 'ダッシュ禁止') {
			$gamePlayer.villaA_dashBan = true;
		}

		if (command === 'ダッシュ許可') {
			$gamePlayer.villaA_dashBan = false;
		}
	};

	Game_Player.prototype.isDashing = function () {
		if ($gamePlayer.villaA_dashBan) {
			return false;
		} else {
			return this._dashing;
		}
	};
})();


code:
//=============================================================================
// df.js
//=============================================================================

/*:
 * @plugindesc Complete protection
 * @author karakasr_dool
 *
 * @param NO_GUARD
 * @desc Eliminate the defense command
 * @default false
 *
 * @param PROBABILITY
 * @desc Probability of complete protection (0~100)
 * @default 25
 *
 * @help
 *
 *
 */

/*:ja
 * @plugindesc 完全防御
 * @author karakasr_dool
 *
 * @param NO_GUARD
 * @desc 防御など不要!!
 * @default false
 *
 *
 * @param PROBABILITY
 * @desc 完全防御の確率 (0~100)
 * @default 25
 * @help
 *

 */

(function () {
	var parameters = PluginManager.parameters('df');
	var flag = parameters['NO_GUARD'] === "true";
	var n = parseInt(parameters['PROBABILITY'] || 25);

	if (flag) {
		Window_ActorCommand.prototype.addGuardCommand = function () {
			//this.addCommand(TextManager.guard, 'guard', this._actor.canGuard());
		};
	}

	Game_Action.prototype.applyGuard = function (damage, target) {
		var flag = target.isGuard();
		if (flag) {
			var rand = Math.floor(Math.random() * 100);
			if (rand < n) {
				return 0;
			}
		}
		return damage / (damage > 0 && flag ? 2 * target.grd : 1);
	};

})();


code:
//=============================================================================
// EnemyBars.js
//=============================================================================
//v1.1
/*:
 * @plugindesc Makes enemy hp bar appear in battle.
 * @author Jeremy Cannady
 *
 * @param High HP Color
 * @desc Insert the color code.
 * @default #009900
 *
 * @param Medium HP Color
 * @desc Insert the color code.
 * @default #ffcc00
 *
 * @param Low HP Color
 * @desc Insert the color code.
 * @default #ff6600
 *
 * @param Critical HP Color
 * @desc Insert the color code.
 * @default #ff3300
 *
 * @help
 * Put <hpBar> in the enemy note tag to activate the hp bar for that enemy
 during battle.
 *Put <hpBarSelectionOnly> to actiavte the hp bar only during selection.
 *Put<hpBarTurnASelection> to actiavet he bar during selection and attack.
 *Put <hpBarTurnOnly> to only show the bar during the attack phase.
 *PLEASE PUT ONLY ONE NOTETAG.
 * For the paramters use any html hex color codes.
 * A few color codes are:
 Green: #009900
 Yellow: #ffcc00
 Orange: #ff6600
 Red: #ff3300
 White: #ffffff
 Blue: #33ffff
 Purple: #660099
 *
*/

(function () {
	//=============================================================================
	// Create some variables and define the colors
	//=============================================================================
	Game_Enemy.prototype.battlerHeight = null;
	Game_Enemy.prototype.battlerWidth = null;
	var parameters = PluginManager.parameters('EnemyBars');
	var high = parameters['High HP Color'] || '#009900';
	var medium = parameters['Medium HP Color'] || '#ffcc00';
	var low = parameters['Low HP Color'] || '#ff6600';
	var critical = parameters['Critical HP Color'] || '#ff3300';

	//=============================================================================
	// Create the enemy hp window that displays all the hp bars
	//=============================================================================
	function Enemy_Bars() {
		this.initialize.apply(this, arguments);
	};

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

	Enemy_Bars.prototype.initialize = function (x, y, width, height) {
		Window_Base.prototype.initialize.call(this, x, y, width, height);
		this.deactivate();
		//Make the window transparent
		this.opacity = 0;
	};

	Enemy_Bars.prototype.update = function () {
		Window_Base.prototype.update.call(this);
		//Clear the window and re-draw the hp bars
		this.contents.clear();
		this.drawBar();
	};

	//FUNCTION: return the color the hp bar should be based on current hp
	Enemy_Bars.prototype.guageColor = function (rate) {
		if (rate > 0.75) {
			return high;//High hp color
		} else if (rate > 0.50) {
			return medium;//Medium hp color
		} else if (rate > 0.25) {
			return low;//Low hp color
		} else {
			return critical;//Critical hp color
		};
	};

	//FUNCTION: draw the hp guage
	Enemy_Bars.prototype.drawBar = function () {
		//Go through the enemies and draw the bars
		for (var i = 0; i < $gameTroop._enemies.length; i++) {
			var enemyId = $gameTroop._enemies[i]._enemyId;
			var selected = $gameTroop._enemies[i]._selected;
			if (BattleManager._phase === "action" || BattleManager._phase === "turn") {
				var turn = true
			} else {
				var turn = false
				console.log(BattleManager._phase)
			};

			var enabled = false;
			var meta = new Array(4);
			meta[0] = $dataEnemies[enemyId].meta.hpBar
			meta[1] = $dataEnemies[enemyId].meta.hpBarSelectionOnly
			meta[2] = $dataEnemies[enemyId].meta.hpBarTurnASelection
			meta[3] = $dataEnemies[enemyId].meta.hpBarTurnOnly

			if (meta[0]) {
				enabled = true;
			} else if (meta[1] && selected) {
				enabled = true;
			} else if (meta[2] && (selected || turn)) {
				enabled = true;
			} else if (meta[3] && turn) {
				enabled = true;
			} else {
				enabled = false;
			}

			//Current hp
			var currentHp = $gameTroop._enemies[i]._hp;
			//If the enemy hp is not zero then draw the hp bar
			if (currentHp > 0 && enabled) {
				//Max hp defined from the enemies parameters.
				var maxHp = $dataEnemies[enemyId].params[0];
				//Rate is the currnet hp compared to the max hp
				var rate = currentHp / maxHp;
				//Width of the bar
				var width = $dataEnemies[enemyId].battlerWidth;
				var xOffset = $dataEnemies[enemyId].battlerWidth / 2 + 16;
				var x = $gameTroop._enemies[i]._screenX - xOffset;
				var y = $gameTroop._enemies[i]._screenY - 32;
				//Draw the guage
				this.drawGauge(x, y, width, rate, this.guageColor(rate), this.guageColor(rate));
			};
		};
	};

	//=============================================================================
	// Alias the Scene_Battle createAllWindows to add the hp window
	//=============================================================================
	var battleWindows = Scene_Battle.prototype.createAllWindows;
	Scene_Battle.prototype.createAllWindows = function () {
		battleWindows.call(this)
		//Add the hp window to the battle scene
		this.Bar = new Enemy_Bars(0, 0, Graphics.width, Graphics.height);
		this.addChild(this.Bar);
	};

	//=============================================================================
	// Alias the Sprite_Enemy.updateFrame to return information back to the hp window.
	//=============================================================================
	var copyOfSprite_EnemyupdateFrame = Sprite_Enemy.prototype.updateFrame;
	Sprite_Enemy.prototype.updateFrame = function () {
		Sprite_Battler.prototype.updateFrame.call(this);
		copyOfSprite_EnemyupdateFrame.call(this);
		//As we are updating the enemy sprites return the bitmaps height and width
		$dataEnemies[this._enemy._enemyId].battlerHeight = this.bitmap.height;
		$dataEnemies[this._enemy._enemyId].battlerWidth = this.bitmap.width;
	};
})();


code:
//=============================================================================
// use_DI_Joypad.js
//=============================================================================
//Copyright (c) 2016 Trb
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
//
//twitter https://twitter.com/Trb_surasura
/*:
 * @plugindesc DirectInput方式のジョイパッドが使えるようになります
 * @author Trb
 * @version 1.15  2016/3/20 F5が押された時に実行する関数の位置を変更
 *          1.1   2016/3/11 F5でリロードすると動かなくなってしまう問題を修正
 *          1.001 2016/2/26 微修正
 *          1.00  2016/2/26 初版
 *
 * @help ジョイパッドにはDirect Input方式のものとX Input方式のものがあり、
 * ツクールMVでは通常はX Input方式のジョイパッドしか使えません。
 * それをどうにかDirect Inputのジョイパッドでも使えるようにしたプラグインです。
 *
 */
(function () {

    Input._updateGamepadState = function (gamepad) {
        var lastState = this._gamepadStates[gamepad.index] || [];
        var newState = [];
        var buttons = gamepad.buttons;
        var axes = gamepad.axes;
        var threshold = 0.5;
        newState[12] = false;//追加した部分　ここから
        newState[13] = false;//||
        newState[14] = false;//||
        newState[15] = false;//ここまで
        for (var i = 0; i < buttons.length; i++) {
            newState[i] = buttons[i].pressed;
        }
        if (axes[1] < -threshold) {
            newState[12] = true;    // up
        } else if (axes[1] > threshold) {
            newState[13] = true;    // down
        }
        if (axes[0] < -threshold) {
            newState[14] = true;    // left
        } else if (axes[0] > threshold) {
            newState[15] = true;    // right
        }
        for (var j = 0; j < newState.length; j++) {
            if (newState[j] !== lastState[j]) {
                var buttonName = this.gamepadMapper[j];
                if (buttonName) {
                    this._currentState[buttonName] = newState[j];
                }
            }
        }
        this._gamepadStates[gamepad.index] = newState;
    };

    /*ここからver 1.1追加分
    F5(キーコード116)を押した時にブラウザをリロードする処理を無くし、
    代わりに SceneManager.goto(Scene_Boot);で ゲームの開始地点に飛びます
    */
    var f5 = false;//f5を押したらtrueになる変数を用意

    SceneManager.onKeyDown = function (event) {
        if (!event.ctrlKey && !event.altKey) {
            switch (event.keyCode) {
                case 116: console.log('f5');
                    if (Utils.isNwjs()) {
                        //location.reload(false);本来の処理はカット
                        f5 = true;
                    }
                    break;
                case 119:   // F8
                    if (Utils.isNwjs() && Utils.isOptionValid('test')) {
                        require('nw.gui').Window.get().showDevTools();
                    }
                    break;
            }
        }
    };
    /*
    ↑のreloadの部分に SceneManager.goto を入れると
    F5を押すタイミングによってエラーが出てしまうことがあったので
    上では押した判定のみを取得するようにしました
    */

    //F5が押されていたらSceneBootに飛ぶ処理
    SceneManager.onKeyF5 = function () {
        if (f5 == true) {
            f5 = false;
            SceneManager.goto(Scene_Boot);
        }
    };

    var SMupdatescene = SceneManager.updateScene;
    SceneManager.updateScene = function () {
        SMupdatescene.call(this);
        this.onKeyF5();
    };

})();