//=============================================================================
// TMPlugin - マップＨＰゲージ
// バージョン: 1.4.4
// 最終更新日: 2019/11/04
// 配布元　　: https://hikimoki.sakura.ne.jp/
//-----------------------------------------------------------------------------
// Copyright (c) 2016 tomoaky
// Released under the MIT license.
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @plugindesc マップシーンに顔グラフィックとＨＰゲージを表示します。
 * 必要に応じてＭＰや変数などをゲージで表示することもできます。
 *
 * @author tomoaky (https://hikimoki.sakura.ne.jp/)
 *
 * @param gaugeWindowX
 * @type number
 * @min -1000
 * @desc ＨＰゲージウィンドウのＸ座標
 * 初期値: 0
 * @default 0
 *
 * @param gaugeWindowY
 * @type number
 * @min -1000
 * @desc ＨＰゲージウィンドウのＹ座標
 * 初期値: 0
 * @default 0
 *
 * @param gaugeWindowWidth
 * @type number
 * @desc ＨＰゲージウィンドウの幅
 * 初期値: 288
 * @default 288
 *
 * @param gaugeWindowHeight
 * @type number
 * @desc ＨＰゲージウィンドウの高さ
 * 初期値: 64
 * @default 64
 *
 * @param gaugeA
 * @type struct<Gauge>
 * @desc ゲージＡのパラメータ
 * @default {"type":"HP","x":"12","y":"12","width":"144","height":"36","fontSize":"28","param":"0","max":"0","name":"AP","color":"#ff60c0 #ffa0e0"}
 *
 * @param gaugeB
 * @type struct<Gauge>
 * @desc ゲージＢのパラメータ
 * @default {"type":"","x":"12","y":"12","width":"144","height":"36","fontSize":"28","param":"0","max":"0","name":"AP","color":"#ff60c0 #ffa0e0"}
 *
 * @param gaugeC
 * @type struct<Gauge>
 * @desc ゲージＣのパラメータ
 * @default {"type":"","x":"12","y":"12","width":"144","height":"36","fontSize":"28","param":"0","max":"0","name":"AP","color":"#ff60c0 #ffa0e0"}
 *
 * @param gaugeD
 * @type struct<Gauge>
 * @desc ゲージＤのパラメータ
 * @default {"type":"","x":"12","y":"12","width":"144","height":"36","fontSize":"28","param":"0","max":"0","name":"AP","color":"#ff60c0 #ffa0e0"}
 *
 * @param faceOffsetX
 * @type number
 * @min -1000
 * @desc 顔グラフィックのＸ座標補正値
 * 初期値: -4 ( -1000 で顔グラフィックを使用しない)
 * @default -4
 *
 * @param faceOffsetY
 * @type number
 * @min -1000
 * @desc 顔グラフィックのＹ座標補正値
 * 初期値: -4
 * @default -4
 *
 * @param stateIconMax
 * @type number
 * @desc ステートアイコンを表示する個数
 * 初期値: 4
 * @default 4
 *
 * @param stateIconX
 * @type number
 * @min -1000
 * @desc ステートアイコンのＸ座標
 * 初期値: 156
 * @default 156
 *
 * @param stateIconY
 * @type number
 * @min -1000
 * @desc ステートアイコンのＹ座標
 * 初期値: 24
 * @default 24
 *
 * @param stateIconScale
 * @type number
 * @desc ステートアイコンの拡大率（ % ）
 * 初期値: 100
 * @default 100
 *
 * @param stateIconOpacity
 * @type number
 * @desc ステートアイコンの不透明度（ 0 ~ 255 ）
 * 初期値: 255
 * @default 255
 *
 * @param goldWidth
 * @type number
 * @desc 所持金表示の幅
 * 初期値: 0 ( 0 で非表示 )
 * @default 0
 *
 * @param goldX
 * @type number
 * @min -9999
 * @desc 所持金表示のＸ座標
 * 初期値: 12
 * @default 12
 *
 * @param goldY
 * @type number
 * @min -1000
 * @desc 所持金表示のＹ座標
 * 初期値: 12
 * @default 12
 *
 * @param vnMax
 * @type boolean
 * @desc ゲージタイプ VN の最大値を表示するかどうか
 * 初期値: OFF ( true = ON 表示 / false = OFF 非表示 )
 * @default false
 *
 * @param shakeTime
 * @type number
 * @desc ダメージを受けたときにウィンドウを揺らす時間（フレーム）
 * 初期値: 20 ( 0 で揺らさない )
 * @default 20
 *
 * @param startVisible
 * @type boolean
 * @desc ゲーム開始時の表示状態
 * 初期値: ON（ true = ON 表示 / false = OFF 非表示 ）
 * @default true
 *
 * @param windowOpacity
 * @type number
 * @desc ＨＰゲージウィンドウの不透明度
 * 初期値: 255
 * @default 255
 *
 * @param collideOpacity
 * @type number
 * @max 255
 * @desc プレイヤーと重なったときの不透明度
 * 初期値: 128（ 0 ～ 255 ）
 * @default 128
 *
 * @param messageBusyHide
 * @type boolean
 * @desc メッセージウィンドウ表示中はＨＰゲージウィンドウを隠す
 * 初期値: ON ( true = ON 隠す / false = OFF 隠さない )
 * @default true
 *
 * @param eventBusyHide
 * @type boolean
 * @desc イベント起動中はＨＰゲージウィンドウを隠す
 * 初期値: ON（ true = ON 隠す / false = OFF 隠さない )
 * @default true
 *
 * @param useBattleScene
 * @type boolean
 * @desc 戦闘シーンでもＨＰゲージウィンドウを表示する。
 * 初期値: OFF（ true = ON 表示 / false = OFF 非表示 )
 * @default false
 *
 * @param gaugeWindowBattleX
 * @type number
 * @min -1000
 * @desc 戦闘シーンのＨＰゲージウィンドウのＸ座標
 * 初期値: 0
 * @default 0
 *
 * @param gaugeWindowBattleY
 * @type number
 * @min -1000
 * @desc 戦闘シーンのＨＰゲージウィンドウのＹ座標
 * 初期値: 0
 * @default 0
 *
 * @help
 * TMPlugin - マップＨＰゲージ ver1.4.4
 *
 * 使い方:
 *
 *   プラグインパラメータをいじってお好みのＨＰゲージを表示してください。
 *
 *   このプラグインは RPGツクールMV Version 1.6.2 で動作確認をしています。
 *
 *   このプラグインはMITライセンスのもとに配布しています、商用利用、
 *   改造、再配布など、自由にお使いいただけます。
 *
 *
 * プラグインコマンド:
 *
 *   showHpGauge
 *     ＨＰゲージウィンドウを表示します。
 *     プラグインパラメータ startVisible が 0 の場合、
 *     このコマンドが実行されるまでＨＰゲージは表示されません。
 *
 *   showHpGauge A
 *     ゲージＡを表示します。プラグインパラメータでタイプが設定されている場合、
 *     ゲーム開始時に自動的に表示状態になります。
 *
 *   hideHpGauge
 *     ＨＰゲージウィンドウを隠します。showHpGauge コマンドが実行されるまで
 *     表示されないままです。
 *
 *   hideHpGauge B
 *     ゲージＢを隠します。showHpGauge B コマンドが実行されるまで
 *     表示されないままです。
 *
 *   moveHpGaugeWindow 100 200
 *     ＨＰゲージウィンドウの位置を X座標 = 100 / Y座標 = 200 の位置へ
 *     移動します。
 *
 *
 * プラグインパラメータ補足:
 *
 *   gaugeA ～ gaugeD
 *
 *     param
 *       ゲージのタイプが VN の場合に、ゲージの現在値として扱う
 *       ゲーム変数番号を設定してください。
 *
 *     max
 *       ゲージのタイプが VN の場合に、ゲージの最大値として扱う
 *       ゲーム変数番号を指定してください。
 *       このパラメータに設定した番号のゲーム変数に値を代入することで、
 *       初めて最大値として機能します。
 *       この設定はゲージの長さにのみ影響します、変数の値が最大値を
 *       超えなくなるような機能はありません。
 *
 *   windowOpacity / collideOpacity
 *     windowOpacity はウィンドウフレーム及び背景に影響し、collideOpacity
 *     はゲージや顔グラフィックにも影響します。
 *     windowOpacity の値が collideOpacity よりも低い場合、プレイヤーと
 *     重なった際の不透明度として windowOpacity の値が適用されます。
 *     ただし、ゲージと顔グラフィックに関しては通常どおり collideOpacity の
 *     値が適用されます。
 *
 *   faceOffsetX
 *     この値を -1000 に設定すると顔グラフィックが非表示となります。
 *
 *   vnMax
 *     値が true なら最大値も表示しますが、現在値と最大値を表示するための
 *     スペースが足りない（ゲージの長さが短い）場合は vnMax の設定に関わらず
 *     強制的に現在値のみの表示になります。
 */
/*~struct~Gauge:
 *
 * @param type
 * @type select
 * @option なし
 * @value
 * @option HP
 * @option MP
 * @option TP
 * @option LV
 * @option VN
 * @desc ゲージのタイプ（HP / MP / TP / LV / VN）
 * 初期値: HP
 * @default HP
 *
 * @param x
 * @type number
 * @min -1000
 * @desc ゲージのＸ座標（ウィンドウ内の左端が 0 ）
 * 初期値: 12
 * @default 12
 *
 * @param y
 * @type number
 * @min -1000
 * @desc ゲージのＹ座標（ウィンドウ内の上端が 0 ）
 * 初期値: 12
 * @default 12
 *
 * @param width
 * @type number
 * @desc ゲージの長さ
 * 初期値: 144
 * @default 144
 *
 * @param height
 * @type number
 * @desc ゲージの表示領域（数値とゲージ合わせて）の高さ
 * 初期値: 36
 * @default 36
 *
 * @param fontSize
 * @type number
 * @desc フォントサイズ
 * 初期値: 28
 * @default 28
 *
 * @param param
 * @type variable
 * @desc ゲージのタイプが VN のときに現在値とするゲーム変数番号
 * 初期値: 0
 * @default 0
 *
 * @param max
 * @type variable
 * @desc ゲージのタイプが VN のときに最大値とするゲーム変数番号
 * 初期値: 0
 * @default 0
 *
 * @param name
 * @type string
 * @desc ゲージのタイプが VN のときに表示するパラメータ名
 * 初期値: AP
 * @default AP
 *
 * @param color
 * @type string
 * @desc ゲージのタイプが LV / VN のときのゲージカラー
 * 初期値: #ff60c0 #ffa0e0
 * @default #ff60c0 #ffa0e0
 */

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

(function () {
  var parameters = PluginManager.parameters("TMMapHpGauge");
  var gaugeWindowX = +(parameters["gaugeWindowX"] || 0);
  var gaugeWindowY = +(parameters["gaugeWindowY"] || 0);
  var gaugeWindowWidth = +(parameters["gaugeWindowWidth"] || 288);
  var gaugeWindowHeight = +(parameters["gaugeWindowHeight"] || 64);
  var gauges = [];
  ["A", "B", "C", "D"].forEach(function (code, i) {
    gauges[i] = JSON.parse(parameters["gauge" + code]);
    gauges[i].x = +gauges[i].x;
    gauges[i].y = +gauges[i].y;
    gauges[i].width = +gauges[i].width;
    gauges[i].height = +gauges[i].height;
    gauges[i].fontSize = +gauges[i].fontSize;
    gauges[i].param = +gauges[i].param;
    gauges[i].max = +gauges[i].max;
    gauges[i].color = gauges[i].color.split(" ");
  });
  var faceOffsetX = +(parameters["faceOffsetX"] || -4);
  var faceOffsetY = +(parameters["faceOffsetY"] || -4);
  var stateIconMax = +(parameters["stateIconMax"] || 4);
  var stateIconX = +(parameters["stateIconX"] || 156);
  var stateIconY = +(parameters["stateIconY"] || 24);
  var stateIconScale = +(parameters["stateIconScale"] || 100);
  var stateIconOpacity = +(parameters["stateIconOpacity"] || 255);
  var goldWidth = +(parameters["goldWidth"] || 0);
  var goldX = +(parameters["goldX"] || 0);
  var goldY = +(parameters["goldY"] || 0);
  var vnMax = JSON.parse(parameters["vnMax"] || "false");
  var shakeTime = +(parameters["shakeTime"] || 20);
  var collideOpacity = +(parameters["collideOpacity"] || 128);
  var startVisible = JSON.parse(parameters["startVisible"] || "true");
  var windowOpacity = +(parameters["windowOpacity"] || 255);
  var messageBusyHide = JSON.parse(parameters["messageBusyHide"] || "true");
  var eventBusyHide = JSON.parse(parameters["eventBusyHide"] || "true");
  var useBattleScene = JSON.parse(parameters["useBattleScene"] || "false");
  var gaugeWindowBattleX = +(parameters["gaugeWindowBattleX"] || 0);
  var gaugeWindowBattleY = +(parameters["gaugeWindowBattleY"] || 0);

  //-----------------------------------------------------------------------------
  // Game_System
  //

  Game_System.prototype.isVisibleMapHpGauge = function () {
    if (this._visibleMapHpGauge == null) this._visibleMapHpGauge = startVisible;
    return this._visibleMapHpGauge;
  };

  Game_System.prototype.setVisibleMapHpGauge = function (flag) {
    this._visibleMapHpGauge = flag;
  };

  Game_System.prototype.isVisibleMapHpGauges = function (gaugeId) {
    if (this._visibleMapHpGauges == null) {
      this._visibleMapHpGauges = [];
      for (var i = 0; i < gauges.length; i++) {
        this._visibleMapHpGauges[i] = gauges[i].type !== "";
      }
    }
    return this._visibleMapHpGauges[gaugeId];
  };

  Game_System.prototype.setVisibleMapHpGauges = function (gaugeId, flag) {
    this._visibleMapHpGauges[gaugeId] = flag;
  };

  //-----------------------------------------------------------------------------
  // Game_Interpreter
  //

  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    if (command === "showHpGauge") {
      if (args[0]) {
        var gaugeId = ["A", "B", "C", "D"].indexOf(args[0]);
        $gameSystem.setVisibleMapHpGauges(gaugeId, true);
      } else {
        $gameSystem.setVisibleMapHpGauge(true);
      }
    } else if (command === "hideHpGauge") {
      if (args[0]) {
        var gaugeId = ["A", "B", "C", "D"].indexOf(args[0]);
        $gameSystem.setVisibleMapHpGauges(gaugeId, false);
      } else {
        $gameSystem.setVisibleMapHpGauge(false);
      }
    } else if (command === "moveHpGaugeWindow") {
      $gameSystem._mapHpGaugeWindowX = +args[0];
      $gameSystem._mapHpGaugeWindowY = +args[1];
      if (SceneManager._scene._mapHpGaugeWindow) {
        SceneManager._scene._mapHpGaugeWindow.x = +args[0];
        SceneManager._scene._mapHpGaugeWindow.y = +args[1];
        SceneManager._scene._mapHpGaugeWindow._baseX = +args[0];
      }
    }
  };

  //-----------------------------------------------------------------------------
  // Window_MapHpGauge
  //

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

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

  Window_MapHpGauge.prototype.initialize = function () {
    if (SceneManager.isNextScene(Scene_Battle)) {
      var x = gaugeWindowBattleX;
      var y = gaugeWindowBattleY;
    } else {
      var x =
        $gameSystem._mapHpGaugeWindowX != null
          ? $gameSystem._mapHpGaugeWindowX
          : gaugeWindowX;
      var y =
        $gameSystem._mapHpGaugeWindowY != null
          ? $gameSystem._mapHpGaugeWindowY
          : gaugeWindowY;
    }
    var wight = gaugeWindowWidth;
    var height = gaugeWindowHeight;
    Window_Base.prototype.initialize.call(this, x, y, wight, height);
    this.openness = $gameSystem.isVisibleMapHpGauge() ? 255 : 0;
    this.opacity = windowOpacity;
    this._gaugeParams = [];
    this._gaugeVisible = [];
    for (var i = 0; i < gauges.length; i++) {
      this._gaugeParams.push({ param: -1, max: -1 });
      this._gaugeVisible[i] = $gameSystem.isVisibleMapHpGauges(i);
    }
    this._icons = [];
    this._gold = 0;
    this._actorId = -1;
    this._faceName = "";
    this._faceIndex = "";
    this._shakeDuration = 0;
    this._baseX = x;
    this._needFaceRefresh = false;
    this._hideCount = 0;
  };

  Window_MapHpGauge.prototype.lineHeight = function () {
    return this._lineHeight || 36;
  };

  Window_MapHpGauge.prototype.standardPadding = function () {
    return 0;
  };

  Window_MapHpGauge.prototype.setShake = function (power) {
    this._shakeDuration = power;
  };

  Window_MapHpGauge.prototype.update = function () {
    Window_Base.prototype.update.call(this);
    if (this.updateVisibility()) {
      this.open();
      if (this.isNeedRefresh()) {
        var actor = $gameParty.leader();
        for (var i = 0; i < gauges.length; i++) {
          this._gaugeVisible[i] = $gameSystem.isVisibleMapHpGauges(i);
          var gauge = gauges[i];
          if (gauge.type === "HP") {
            this._gaugeParams[i].param = actor.hp;
            this._gaugeParams[i].max = actor.mhp;
          } else if (gauge.type === "MP") {
            this._gaugeParams[i].param = actor.mp;
            this._gaugeParams[i].max = actor.mmp;
          } else if (gauge.type === "TP") {
            this._gaugeParams[i].param = actor.tp;
            this._gaugeParams[i].max = actor.maxTp();
          } else if (gauge.type === "LV") {
            this._gaugeParams[i].param = actor.currentExp();
            this._gaugeParams[i].max = actor.nextLevelExp();
            this._gaugeParams[i].subParam = actor.level;
          } else if (gauge.type === "VN") {
            this._gaugeParams[i].param = $gameVariables.value(gauge.param);
            this._gaugeParams[i].max = $gameVariables.value(gauge.max);
          }
        }
        this._icons = actor.stateIcons().concat(actor.buffIcons());
        this._gold = $gameParty.gold();
        this._actorId = actor.actorId();
        this._faceName = actor.faceName();
        this._faceIndex = actor.faceIndex();
        this.refresh();
      }
      this.updateShake();
      this.updateOpacity();
    } else {
      this.close();
    }
  };

  Window_MapHpGauge.prototype.updateVisibility = function () {
    if (!$gameSystem.isVisibleMapHpGauge()) {
      return false;
    }
    if ($gameParty.inBattle()) {
      return true;
    }
    if (
      (eventBusyHide && $gameMap.isEventRunning()) ||
      (messageBusyHide && $gameMessage.isBusy())
    ) {
      this._hideCount++;
    } else {
      this._hideCount = 0;
    }
    return this._hideCount < 10 && $gameParty.leader();
  };

  Window_MapHpGauge.prototype.isNeedRefresh = function () {
    var actor = $gameParty.leader();
    if (actor) {
      var result = false;
      if (this._actorId !== actor.actorId()) {
        this.setShake(1);
        return true;
      }
      for (var i = 0; i < gauges.length; i++) {
        if (this._gaugeVisible[i] !== $gameSystem.isVisibleMapHpGauges(i)) {
          result = true;
        }
        var gauge = gauges[i];
        var gaugeParam = this._gaugeParams[i];
        if (gauge.type === "HP") {
          if (gaugeParam.param !== actor.hp || gaugeParam.max !== actor.mhp) {
            if (gaugeParam.param > actor.hp) {
              this.setShake(shakeTime);
            }
            result = true;
          }
        } else if (gauge.type === "MP") {
          if (gaugeParam.param !== actor.mp || gaugeParam.max !== actor.mmp) {
            result = true;
          }
        } else if (gauge.type === "TP") {
          if (
            gaugeParam.param !== actor.tp ||
            gaugeParam.max !== actor.maxTp()
          ) {
            result = true;
          }
        } else if (gauge.type === "LV") {
          if (
            gaugeParam.param !== actor.currentExp() ||
            gaugeParam.max !== actor.nextLevelExp() ||
            gaugeParam.subParam !== actor.level
          ) {
            result = true;
          }
        } else if (gauge.type === "VN") {
          if (
            gaugeParam.param !== $gameVariables.value(gauge.param) ||
            gaugeParam.max !== $gameVariables.value(gauge.max)
          ) {
            result = true;
          }
        }
      }
      if (stateIconMax > 0) {
        var icons = actor.stateIcons().concat(actor.buffIcons());
        if (this._icons.toString() !== icons.toString()) {
          result = true;
        }
      }
      if (goldWidth > 0 && this._gold !== $gameParty.gold()) {
        result = true;
      }
    }
    if (this._needFaceRefresh) {
      this.refreshFace();
      if (!this._needFaceRefresh) {
        result = true;
      }
    }
    return result;
  };

  Window_MapHpGauge.prototype.updateShake = function () {
    if (this._shakeDuration > 0) {
      this._shakeDuration--;
      this.x = this._baseX;
      if (this._shakeDuration > 0) {
        this.x += Math.floor(
          Math.sin(((this._shakeDuration % 10) * Math.PI) / 5) * 8
        );
      }
    }
  };

  Window_MapHpGauge.prototype.updateOpacity = function () {
    if (
      this.x < $gamePlayer.screenX() + 24 &&
      this.x + gaugeWindowWidth > $gamePlayer.screenX() - 24 &&
      this.y < $gamePlayer.screenY() &&
      this.y + gaugeWindowHeight > $gamePlayer.screenY() - 48
    ) {
      this.opacity = Math.min(collideOpacity, windowOpacity);
      this.contentsOpacity = collideOpacity;
    } else {
      this.opacity = windowOpacity;
      this.contentsOpacity = 255;
    }
  };

  Window_MapHpGauge.prototype.refresh = function () {
    this.contents.clear();
    var actor = $gameParty.leader();
    if (actor) {
      this.refreshFace();
      for (var i = 0; i < gauges.length; i++) {
        if (!$gameSystem.isVisibleMapHpGauges(i)) {
          continue;
        }
        var gauge = gauges[i];
        this._lineHeight = gauge.height;
        this.contents.fontSize = gauge.fontSize;
        if (gauge.type === "HP") {
          this.drawActorHp(actor, gauge.x, gauge.y, gauge.width);
        } else if (gauge.type === "MP") {
          this.drawActorMp(actor, gauge.x, gauge.y, gauge.width);
        } else if (gauge.type === "TP") {
          this.drawActorTp(actor, gauge.x, gauge.y, gauge.width);
        } else if (gauge.type === "LV") {
          this.drawLvGauge(actor, gauge);
        } else if (gauge.type === "VN") {
          this.drawVnGauge(this._gaugeParams[i], gauge);
        }
      }
      for (var i = 0; i < stateIconMax; i++) {
        if (!this._icons[i]) break;
        var x =
          stateIconX +
          i * Math.floor((Window_Base._iconWidth * stateIconScale) / 100);
        this.drawIcon(this._icons[i], x, stateIconY);
      }
      if (goldWidth > 0) {
        this.drawCurrencyValue(
          this._gold,
          TextManager.currencyUnit,
          goldX,
          goldY,
          goldWidth
        );
      }
      this._lineHeight = 36;
    }
  };

  Window_MapHpGauge.prototype.drawIcon = function (iconIndex, x, y) {
    var bitmap = ImageManager.loadSystem("IconSet");
    var pw = Window_Base._iconWidth;
    var ph = Window_Base._iconHeight;
    var sx = (iconIndex % 16) * pw;
    var sy = Math.floor(iconIndex / 16) * ph;
    var dw = Math.floor((pw * stateIconScale) / 100);
    var dh = Math.floor((ph * stateIconScale) / 100);
    var lastPaintOpacity = this.contents.paintOpacity;
    this.contents.paintOpacity = stateIconOpacity;
    this.contents.blt(bitmap, sx, sy, pw, ph, x, y, dw, dh);
    this.contents.paintOpacity = lastPaintOpacity;
  };

  Window_MapHpGauge.prototype.drawLvGauge = function (actor, gauge) {
    if (actor.isMaxLevel()) {
      var value1 = "-------";
      var value2 = "-------";
      var rate = 1;
    } else {
      var n = actor.currentLevelExp();
      var value1 = actor.currentExp() - n;
      var value2 = actor.nextLevelExp() - n;
      var rate = value1 / value2;
    }
    this.drawGauge(
      gauge.x,
      gauge.y,
      gauge.width,
      rate,
      gauge.color[0],
      gauge.color[1]
    );
    this.changeTextColor(this.systemColor());
    this.drawText(TextManager.levelA, gauge.x, gauge.y, 44);
    var color = this.normalColor();
    this.changeTextColor(color);
    var width = this.textWidth(TextManager.levelA) + 4;
    this.drawText(actor.level, gauge.x + width, gauge.y, 44);
    width = gauge.width - width - this.textWidth("" + actor.level);
    this.drawCurrentAndMax(
      value1,
      value2,
      gauge.x + gauge.width - width,
      gauge.y,
      width,
      color,
      color
    );
  };

  Window_MapHpGauge.prototype.drawVnGauge = function (params, gauge) {
    var rate = params.max === 0 ? 0 : params.param / params.max;
    this.drawGauge(
      gauge.x,
      gauge.y,
      gauge.width,
      rate,
      gauge.color[0],
      gauge.color[1]
    );
    this.changeTextColor(this.systemColor());
    this.drawText(gauge.name, gauge.x, gauge.y, this.textWidth(gauge.name));
    this.changeTextColor(this.normalColor());
    if (vnMax) {
      this.drawVnCurrentAndMax(
        gauge.name,
        params.param,
        params.max,
        gauge.x,
        gauge.y,
        gauge.width
      );
    } else {
      this.drawText(
        params.param,
        gauge.x + gauge.width - 64,
        gauge.y,
        64,
        "right"
      );
    }
  };

  Window_MapHpGauge.prototype.drawVnCurrentAndMax = function (
    name,
    current,
    max,
    x,
    y,
    width
  ) {
    var labelWidth = this.textWidth(name);
    var valueWidth = this.textWidth("0" + max);
    var slashWidth = this.textWidth("/");
    var x1 = x + width - valueWidth;
    var x2 = x1 - slashWidth;
    var x3 = x2 - valueWidth;
    this.changeTextColor(this.normalColor());
    if (x3 >= x + labelWidth) {
      this.drawText(current, x3, y, valueWidth, "right");
      this.drawText("/", x2, y, slashWidth, "right");
      this.drawText(max, x1, y, valueWidth, "right");
    } else {
      this.drawText(current, x1, y, valueWidth, "right");
    }
  };

  Window_MapHpGauge.prototype.refreshFace = function () {
    if (faceOffsetX === -1000) {
      return;
    }
    var actor = $gameParty.leader();
    var bitmap = ImageManager.loadFace(actor.faceName());
    this._needFaceRefresh = bitmap.width === 0;
    if (!this._needFaceRefresh) {
      var x = gaugeWindowWidth - 144 + faceOffsetX;
      var y = faceOffsetY;
      var height = Math.min(gaugeWindowHeight, 144);
      this.drawFace(actor.faceName(), actor.faceIndex(), x, y, 144, height);
    }
  };

  //-----------------------------------------------------------------------------
  // Scene_Base
  //

  Scene_Base.prototype.createMapHpGaugeWindow = function () {
    this._mapHpGaugeWindow = new Window_MapHpGauge();
    this.addChild(this._mapHpGaugeWindow);
  };

  //-----------------------------------------------------------------------------
  // Scene_Map
  //

  var _Scene_Map_createDisplayObjects =
    Scene_Map.prototype.createDisplayObjects;
  Scene_Map.prototype.createDisplayObjects = function () {
    _Scene_Map_createDisplayObjects.call(this);
    this.createMapHpGaugeWindow();
  };

  var _Scene_Map_terminate = Scene_Map.prototype.terminate;
  Scene_Map.prototype.terminate = function () {
    if (!SceneManager.isNextScene(Scene_Battle)) this._mapHpGaugeWindow.hide();
    _Scene_Map_terminate.call(this);
    this.removeChild(this._mapHpGaugeWindow);
  };

  var _Scene_Map_launchBattle = Scene_Map.prototype.launchBattle;
  Scene_Map.prototype.launchBattle = function () {
    this._mapHpGaugeWindow.hide();
    _Scene_Map_launchBattle.call(this);
  };

  //-----------------------------------------------------------------------------
  // Scene_Battle
  //

  var _Scene_Battle_createDisplayObjects =
    Scene_Battle.prototype.createDisplayObjects;
  Scene_Battle.prototype.createDisplayObjects = function () {
    _Scene_Battle_createDisplayObjects.call(this);
    if (useBattleScene) {
      this.createMapHpGaugeWindow();
    }
  };

  var _Scene_Battle_terminate = Scene_Battle.prototype.terminate;
  Scene_Battle.prototype.terminate = function () {
    _Scene_Battle_terminate.call(this);
    if (this._mapHpGaugeWindow) {
      this.removeChild(this._mapHpGaugeWindow);
    }
  };
})();
