code:
//=============================================================================
// BB_CustomSaveWindow.js
// Copyright (c) 2016 BB ENTERTAINMENT
//=============================================================================

/*:
 * @plugindesc セーブウインドウ改造プラグイン
 * @author ビービー
 *
 *
 * @param OutsideFrameColor
 * @desc 外枠の色を指定（テキストカラー0～31）
 * デフォルト：0
 * @default 0
 *
 * @param OutsideFrameOpacity
 * @desc 外枠の透明度を指定（0～255）
 * デフォルト：64
 * @default 64
 *
 * @param InsideFrameColor
 * @desc 内枠の色を指定（テキストカラー0～31）
 * デフォルト：0
 * @default 0
 *
 * @param InsideFrameOpacity
 * @desc 内枠の透明度を指定（0～255）
 * デフォルト：64
 * @default 64
 *
 * @param MaxItem
 * @desc 内枠の数を指定（1～4）
 * デフォルト：4（0で非表示）
 * @default 4
 *
 * @param Item0
 * @desc ファイルID右に表示される項目 0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * @default 1
 *
 * @param Item0Length
 * @desc ファイルID右に表示される項目の横幅（Item5(右上に表示される項目)に影響）
 * @default 300
 *
 * @param Item1title
 * @desc 右下に表示される項目のタイトル
 * デフォルト：プレイ時間
 * @default プレイ時間
 *
 * @param Item1
 * @desc 右下に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * @default 2
 *
 * @param Item2title
 * @desc 中央右に表示される項目のタイトル
 * デフォルト：現在地
 * @default 現在地
 *
 * @param Item2
 * @desc 中央右に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：3
 * @default 3
 *
 * @param Item3title
 * @desc 中央下に表示される項目のタイトル
 * デフォルト：所持金
 * @default 所持金
 *
 * @param Item3
 * @desc 中央下に表示される項  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：4
 * @default 4
 *
 * @param Item4title
 * @desc 中央に表示される項目のタイトル
 * デフォルト：セーブ回数
 * @default セーブ回数
 *
 * @param Item4
 * @desc 中央に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：5
 * @default 5
 *
 * @param Item5
 * @desc 右上に表示される項目  0=非表示 1=ﾀｲﾄﾙ 2=ﾌﾟﾚｲ時間 3=ﾏｯﾌﾟ名
 * 4=所持金 5=ｾｰﾌﾞ回数 6=変数項1 7=変数項2 8=変数項3 9=変数項4
 * デフォルト：6
 * @default 6
 *
 * @param ItemValue1
 * @desc 変数項目1に入れる変数のID
 * デフォルト：1
 * @default 1
 *
 * @param ItemValue2
 * @desc 変数項目2に入れる変数のID
 * デフォルト：2
 * @default 2
 *
 * @param ItemValue3
 * @desc 変数項目3に入れる変数のID
 * デフォルト：3
 * @default 3
 *
 * @param ItemValue4
 * @desc 変数項目4に入れる変数のID
 * デフォルト：4
 * @default 4
 *
 * @param ItemValue1unit
 * @desc 変数項目1の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue2unit
 * @desc 変数項目2の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue3unit
 * @desc 変数項目3の単位
 * デフォルト：無し
 * @default
 *
 * @param ItemValue4unit
 * @desc 変数項目4の単位
 * デフォルト：無し
 * @default
 *
 * @param TitleFramelength1
 * @desc 項目1のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength2
 * @desc 項目2のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength3
 * @desc 項目3のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param TitleFramelength4
 * @desc 項目4のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 * @default 110
 *
 * @param CharacterPositionY
 * @desc キャラクターグラフィックのy座標（下=6 中央=12 上=20）
 * デフォルト：6
 * @default 6
 *
 * @param CharacterOpacity
 * @desc パーティメンバーの内控えメンバーの不透明度を小さくします。
 * （0:控えメンバー非表示　1:不透明度255 2:不透明度160）
 * @default 2
 *
 * @param LevelPositionY
 * @desc レベルのy座標（下=72 上=23）
 * デフォルト：23
 * @default 23
 *
 * @param LevelOnOff
 * @desc レベルを表示するかしないかを指定（0＝非表示、1＝表示）
 * デフォルト：1
 * @default 1
 *
 * @help プラグインの説明
 *
 * ■各パラメータの説明
 * プラグイン内より少しだけ詳しくパラメータの説明をしていきます。
 *
 * OutsideFrameColor
 * 外枠の色をテキストカラーの0～31で指定できます。
 * デフォルト：0
 *
 * OutsideFrameOpacity
 * 外枠の透明度を0～255の数値で指定できます（0＝透明、255＝不透明）
 * デフォルト：64
 *
 * InsideFrameColor
 * 内枠の色をテキストカラーの0～31で指定できます。
 * デフォルト：0
 *
 * InsideFrameOpacity
 * 内枠の透明度を0～255の数値で指定できます（0＝透明、255＝不透明）
 * デフォルト：64
 *
 * MaxItem
 * 内枠の数を0から4のあいだで指定できます。
 * デフォルト：4（0で非表示）
 *
 * Item0
 * ファイルID右に表示される項目を0～9の数字で指定します。
 * 0＝非表示
 * 1＝ゲームタイトル
 * 2＝プレイ時間
 * 3＝マップ名
 * 4＝所持金（自動で通貨単位も表示されます）
 * 5＝セーブ回数
 * 6＝パラメータのItemValue1で指定した変数の値（パラメータのItemValue1unitで単位を指定できます）
 * 7＝パラメータのItemValue2で指定した変数の値（パラメータのItemValue2unitで単位を指定できます）
 * 8＝パラメータのItemValue3で指定した変数の値（パラメータのItemValue3unitで単位を指定できます）
 * 9＝パラメータのItemValue4で指定した変数の値（パラメータのItemValue4unitで単位を指定できます）
 *
 * Item0Length
 * ファイルID右に表示される項目の横幅を指定できます。（Item5(右上に表示される項目)に影響）
 * 指定したサイズより文字列の幅が大きい場合、指定したサイズに自動で文字幅が縮小されます。
 * default 300
 *
 * Item1title
 * 右下に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：プレイ時間
 *
 * Item1
 * 右下に表示される項目を0～9の数字で指定します。
 * デフォルト：2
 *
 * Item2title
 * 中央右に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：現在地
 *
 * Item2
 * 中央右に表示される項目を0～9の数字で指定します。
 * デフォルト：3
 *
 * Item3title
 * 中央下に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：所持金
 *
 * Item3
 * 中央下に表示される項を0～9の数字で指定します。
 * デフォルト：4
 *
 * Item4title
 * 中央に表示される項目のタイトルを好きな文字列で指定できます。
 * デフォルト：セーブ回数
 *
 * Item4
 * 中央に表示される項目を0～9の数字で指定します。
 * デフォルト：5
 *
 * Item5
 * 右上に表示される項目を0～9の数字で指定します。
 * デフォルト：6
 *
 * ItemValue1
 * 変数項目1に入れる変数のIDを指定します。
 * デフォルト：1
 *
 * ItemValue2
 * 変数項目2に入れる変数のIDを指定します。
 * デフォルト：2
 *
 * ItemValue3
 * 変数項目3に入れる変数のIDを指定します。
 * デフォルト：3
 *
 * ItemValue4
 * 変数項目4に入れる変数のIDを指定します。
 * デフォルト：4
 *
 * ItemValue1unit
 * 変数項目1の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue2unit
 * 変数項目2の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue3unit
 * 変数項目3の単位を指定します。
 * デフォルト：無し
 *
 * ItemValue4unit
 * 変数項目4の単位を指定します。
 * デフォルト：無し
 *
 * TitleFramelength1
 * 項目1のタイトル枠の横幅を0～274のあいだから指定します。
 * 文字数*20+10で文字の幅と同じ幅の枠を描画できます
 * 指定した枠幅より文字幅がはみ出る場合自動で文字幅が縮小されます。
 * デフォルト：110（5文字）
 *
 * TitleFramelength2
 * 項目2のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * TitleFramelength3
 * 項目3のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * TitleFramelength4
 * 項目4のタイトル枠の横幅（文字数*20+10）(0～274)
 * デフォルト：110
 *
 * CharacterPositionY
 * キャラクターグラフィックのy座標を指定します。
 * 下の方に表示したい場合は6、中央あたりなら12 上の方なら20が目安です。
 * デフォルト：6
 *
 * CharacterOpacity
 * パラメータの入力画面の説明の通りです。
 * デフォルト：1
 *
 * LevelPositionY
 * レベルのy座標を指定します。下の方なら72、上の方なら23が目安です。
 * レベルの表示はキャラクターグラフィックより手前に表示されます。
 * デフォルト：23
 *
 * LevelOnOff
 * レベルを表示するかしないかを指定（0＝非表示、1＝表示）
 * デフォルト：1
 *
 *
 * ■変数に文字列を代入する方法
 * 変数に文字列を代入するには
 * イベントコマンドの"タブ1"にある"ゲーム進行"内の"変数の操作"を実行し
 * 代入したい変数を選び、代入にチェックを入れ
 * スクリプトに書き込みます
 * このとき　'　←この記号ではじめと終わりを挟むのを忘れないでください。
 * （ ' ←この記号はキーボードが半角英数のときにshiftを押しながら７で打てます）
 * 例：'タケノコ'
 *
 * ■BB ENTERTAINMENT BLOGにて画像付きで解説しています。
 * 記事：http://bb-entertainment-blog.blogspot.jp/2016/11/blog-post_27.html#more
 *
 * バージョン：
 * 1.0.2 2016/12/01 レベルの表示、非表示を切り替えるパラメータを追加
 * 1.0.1 2016/11/29 ヘルプを追記
 * 1.0.0 2016/11/27 初版
 *
 * 利用規約：
 * このプラグインは、MITライセンスのもとで公開されています。
 * Copyright (c) 2016 BB ENTERTAINMENT
 * Released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * コンタクト：
 * BB ENTERTAINMENT Twitter: https://twitter.com/BB_ENTER/
 * BB ENTERTAINMENT BLOG   : http://bb-entertainment-blog.blogspot.jp/
 */

(function () {
  "use strict";
  //-----------------------------------------------------------------------------
  // プラグインパラメータ管理
  //-----------------------------------------------------------------------------
  var parameters = PluginManager.parameters("BB_CustomSaveWindow");
  var BBSWInFC = Number(parameters["InsideFrameColor"]);
  var BBSWInFO = Number(parameters["InsideFrameOpacity"]);
  var BBSWOutFC = Number(parameters["OutsideFrameColor"]);
  var BBSWOutFO = Number(parameters["OutsideFrameOpacity"]);
  var BBSWMaxItem = Number(parameters["MaxItem"]);
  var BBSWItem0 = Number(parameters["Item0"]);
  var BBSWItem0L = Number(parameters["Item0Length"]);
  var BBSWItem1T = String(parameters["Item1title"]);
  var BBSWItem1 = Number(parameters["Item1"]);
  var BBSWItem2T = String(parameters["Item2title"]);
  var BBSWItem2 = Number(parameters["Item2"]);
  var BBSWItem3T = String(parameters["Item3title"]);
  var BBSWItem3 = Number(parameters["Item3"]);
  var BBSWItem4T = String(parameters["Item4title"]);
  var BBSWItem4 = Number(parameters["Item4"]);
  var BBSWItem5 = Number(parameters["Item5"]);
  var BBSWV1 = Number(parameters["ItemValue1"]);
  var BBSWV2 = Number(parameters["ItemValue2"]);
  var BBSWV3 = Number(parameters["ItemValue3"]);
  var BBSWV4 = Number(parameters["ItemValue4"]);
  var BBSWV1u = String(parameters["ItemValue1unit"]);
  var BBSWV2u = String(parameters["ItemValue2unit"]);
  var BBSWV3u = String(parameters["ItemValue3unit"]);
  var BBSWV4u = String(parameters["ItemValue4unit"]);
  var BBSWTF1 = Number(parameters["TitleFramelength1"]);
  var BBSWTF2 = Number(parameters["TitleFramelength2"]);
  var BBSWTF3 = Number(parameters["TitleFramelength3"]);
  var BBSWTF4 = Number(parameters["TitleFramelength4"]);
  var BBSWCPY = Number(parameters["CharacterPositionY"]);
  var BBSWCOY = Number(parameters["CharacterOpacity"]);
  var BBSWLPY = Number(parameters["LevelPositionY"]);
  var BBSWLOO = Number(parameters["LevelOnOff"]);
  //-----------------------------------------------------------------------------
  // セーブデータに名前を定義
  //-----------------------------------------------------------------------------

  DataManager.makeSavefileInfo = function () {
    var info = {};
    info.globalId = this._globalId;
    info.title = $dataSystem.gameTitle;
    info.characters = $gameParty.charactersForSavefile();
    info.faces = $gameParty.facesForSavefile();
    info.playtime = $gameSystem.playtimeText();
    info.timestamp = Date.now();
    info.mapname = $gameMap.displayName();
    info.gold = $gameParty._gold;
    info.savecount = $gameSystem._saveCount;
    info.value1 = $gameVariables.value(BBSWV1);
    info.value2 = $gameVariables.value(BBSWV2);
    info.value3 = $gameVariables.value(BBSWV3);
    info.value4 = $gameVariables.value(BBSWV4);
    return info;
  };

  Game_Party.prototype.charactersForSavefile = function () {
    if (BBSWCOY) {
      var member = this.members();
    } else {
      var member = this.battleMembers();
    }
    return member.map(function (actor) {
      return [actor.characterName(), actor.characterIndex(), actor.level];
    });
  };

  Window_SavefileList.prototype.drawItem = function (index) {
    var id = index + 1;
    var valid = DataManager.isThisGameFile(id);
    var info = DataManager.loadSavefileInfo(id);
    var rect = this.itemRectForText(index);

    this.contents.fontSize = 20;
    this.contents.paintOpacity = BBSWInFO;
    this.contents.fillRect(
      rect.x - 5,
      rect.y + 2,
      rect.width + 10,
      2,
      this.textColor(BBSWInFC)
    ); //上の棒
    this.contents.fillRect(
      rect.x - 5,
      rect.y + rect.height - 3,
      rect.width + 10,
      2,
      this.textColor(BBSWInFC)
    ); //下の棒
    this.contents.fillRect(
      rect.x - 5,
      rect.y + 4,
      2,
      rect.height - 7,
      this.textColor(BBSWInFC)
    ); //左の棒
    this.contents.fillRect(
      rect.width + 9,
      rect.y + 4,
      2,
      rect.height - 7,
      this.textColor(BBSWInFC)
    ); //右の棒
    this.contents.fillRect(
      rect.x - 3,
      rect.y + 4,
      rect.width + 6,
      28,
      this.textColor(BBSWInFC)
    ); //タイトル背景

    this.contents.paintOpacity = BBSWOutFO;
    if (BBSWMaxItem >= 1) {
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 70,
        BBSWTF1,
        26,
        this.textColor(BBSWOutFC)
      ); //タイトル背景
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 68,
        276,
        2,
        this.textColor(BBSWOutFC)
      ); //上の棒
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 96,
        276,
        2,
        this.textColor(BBSWOutFC)
      ); //下の棒
      this.contents.fillRect(
        rect.x + rect.width - 278 + 274,
        rect.y + 70,
        2,
        26,
        this.textColor(BBSWOutFC)
      ); //右の棒
    }
    if (BBSWMaxItem >= 2) {
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 37,
        BBSWTF2,
        26,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 35,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 278,
        rect.y + 63,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 278 + 274,
        rect.y + 37,
        2,
        26,
        this.textColor(BBSWOutFC)
      );
    }
    if (BBSWMaxItem >= 3) {
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 70,
        BBSWTF3,
        26,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 68,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 96,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558 + 274,
        rect.y + 70,
        2,
        26,
        this.textColor(BBSWOutFC)
      );
    }
    if (BBSWMaxItem >= 4) {
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 37,
        BBSWTF4,
        26,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 35,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558,
        rect.y + 63,
        276,
        2,
        this.textColor(BBSWOutFC)
      );
      this.contents.fillRect(
        rect.x + rect.width - 558 + 274,
        rect.y + 37,
        2,
        26,
        this.textColor(BBSWOutFC)
      );
    }
    this.contents.paintOpacity = 255;
    this.resetTextColor();
    if (this._mode === "load") this.changePaintOpacity(valid);
    this.drawFileId(id, rect.x, rect.y);
    if (info) {
      this.changePaintOpacity(valid);
      this.drawContents(info, rect, valid);
      this.changePaintOpacity(true);
    }
  };

  Window_SavefileList.prototype.drawContents = function (info, rect, valid) {
    var bottom = rect.y + rect.height;
    if (rect.width >= 420) {
      //項目0------------------------------------------------------------------------
      if (BBSWItem0 == 1) {
        this.drawText(info.title, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 2) {
        this.drawText(info.playtime, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 3) {
        this.drawText(info.mapname, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x + 142,
          rect.y,
          BBSWItem0L
        );
      } else if (BBSWItem0 == 5) {
        this.drawText(info.savecount, rect.x + 142, rect.y, 312);
      } else if (BBSWItem0 == 6) {
        this.drawText(info.value1 + BBSWV1u, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 7) {
        this.drawText(info.value2 + BBSWV2u, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 8) {
        this.drawText(info.value3 + BBSWV3u, rect.x + 142, rect.y, BBSWItem0L);
      } else if (BBSWItem0 == 9) {
        this.drawText(info.value4 + BBSWV4u, rect.x + 142, rect.y, BBSWItem0L);
      }
      //-----------------------------------------------------------------------------
      if (valid) this.drawPartyCharacters(info, rect.x + 25, rect.y, bottom);
      //-----------------------------------------------------------------------------
    }
    var lineHeight = this.lineHeight();
    var y2 = bottom - lineHeight;
    /*
    this.contents.paintOpacity = 64;
//タイトルバック■
    this.contents.fillRect(rect.x + rect.width - 278, y2 + 30 - 28, BBSWTF1, 28, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 278, y2 - 2 - 28, BBSWTF2, 28, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 558, y2 + 30 - 28, BBSWTF3, 28, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 558, y2 - 2 - 28, BBSWTF4, 28, this.textColor(BBSWOutFC));
//アンダーバー
    this.contents.fillRect(rect.x + rect.width - 278, y2 + 30, 276, 2, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 278, y2 - 2, 276, 2, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 558, y2 + 30, 276, 2, this.textColor(BBSWOutFC));
    this.contents.fillRect(rect.x + rect.width - 558, y2 - 2, 276, 2, this.textColor(BBSWOutFC));

    this.contents.paintOpacity = 255;
*/
    if (y2 >= lineHeight) {
      //項目1 右下-------------------------------------------------------------------
      this.drawText(
        BBSWItem1T,
        rect.x + rect.width - 274,
        y2 - 2,
        BBSWTF1 - 10
      );
      if (BBSWItem1 == 1) {
        this.drawText(
          info.title,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        ); //rect.x - 7, y2 - 2, rect.width
      } else if (BBSWItem1 == 2) {
        this.drawText(
          info.playtime,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 3) {
        this.drawText(
          info.mapname,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 5) {
        this.drawText(
          info.savecount,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 6) {
        this.drawText(
          info.value1 + BBSWV1u,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 7) {
        this.drawText(
          info.value2 + BBSWV2u,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 8) {
        this.drawText(
          info.value3 + BBSWV3u,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      } else if (BBSWItem1 == 9) {
        this.drawText(
          info.value4 + BBSWV4u,
          rect.x + rect.width - 274 + BBSWTF1,
          y2 - 2,
          266 - BBSWTF1,
          "right"
        );
      }
      //-----------------------------------------------------------------------------
      //項目2 右上-------------------------------------------------------------------
      this.drawText(
        BBSWItem2T,
        rect.x + rect.width - 274,
        y2 - 34,
        BBSWTF2 - 10
      );
      if (BBSWItem2 == 1) {
        this.drawText(
          info.title,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        ); //rect.x - 7, y2 - 34, rect.width
      } else if (BBSWItem2 == 2) {
        this.drawText(
          info.playtime,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 3) {
        this.drawText(
          info.mapname,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 5) {
        this.drawText(
          info.savecount,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 6) {
        this.drawText(
          info.value1 + BBSWV1u,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 7) {
        this.drawText(
          info.value2 + BBSWV2u,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 8) {
        this.drawText(
          info.value3 + BBSWV3u,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      } else if (BBSWItem2 == 9) {
        this.drawText(
          info.value4 + BBSWV4u,
          rect.x + rect.width - 274 + BBSWTF2,
          y2 - 34,
          266 - BBSWTF2,
          "right"
        );
      }
      //-----------------------------------------------------------------------------
      //項目3 左下-------------------------------------------------------------------
      this.drawText(
        BBSWItem3T,
        rect.x + rect.width - 554,
        y2 - 2,
        BBSWTF3 - 10
      );
      if (BBSWItem3 == 1) {
        this.drawText(
          info.title,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        ); //rect.x - 287, y2 - 2, rect.width
      } else if (BBSWItem3 == 2) {
        this.drawText(
          info.playtime,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 3) {
        this.drawText(
          info.mapname,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 5) {
        this.drawText(
          info.savecount,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 6) {
        this.drawText(
          info.value1 + BBSWV1u,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 7) {
        this.drawText(
          info.value2 + BBSWV2u,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 8) {
        this.drawText(
          info.value3 + BBSWV3u,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      } else if (BBSWItem3 == 9) {
        this.drawText(
          info.value4 + BBSWV4u,
          rect.x + rect.width - 554 + BBSWTF3,
          y2 - 2,
          266 - BBSWTF3,
          "right"
        );
      }
      //-----------------------------------------------------------------------------
      //項目4 左上-------------------------------------------------------------------
      this.drawText(
        BBSWItem4T,
        rect.x + rect.width - 554,
        y2 - 34,
        BBSWTF4 - 10
      );
      if (BBSWItem4 == 1) {
        this.drawText(
          info.title,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        ); //rect.x - 287, y2 - 34, rect.width
      } else if (BBSWItem4 == 2) {
        this.drawText(
          info.playtime,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 3) {
        this.drawText(
          info.mapname,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 5) {
        this.drawText(
          info.savecount,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 6) {
        this.drawText(
          info.value1 + BBSWV1u,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 7) {
        this.drawText(
          info.value2 + BBSWV2u,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 8) {
        this.drawText(
          info.value3 + BBSWV3u,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      } else if (BBSWItem4 == 9) {
        this.drawText(
          info.value4 + BBSWV4u,
          rect.x + rect.width - 554 + BBSWTF4,
          y2 - 34,
          266 - BBSWTF4,
          "right"
        );
      }
      //-----------------------------------------------------------------------------
      //項目5 上部-------------------------------------------------------------------
      var L5 = 609 - BBSWItem0L;
      if (BBSWItem5 == 1) {
        this.drawText(
          info.title,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        ); //rect.x + 455, rect.y, 312,
      } else if (BBSWItem5 == 2) {
        this.drawText(
          info.playtime,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 3) {
        this.drawText(
          info.mapname,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 4) {
        this.drawText(
          info.gold + TextManager.currencyUnit,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 5) {
        this.drawText(
          info.savecount,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 6) {
        this.drawText(
          info.value1 + BBSWV1u,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 7) {
        this.drawText(
          info.value2 + BBSWV2u,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 8) {
        this.drawText(
          info.value3 + BBSWV3u,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      } else if (BBSWItem5 == 9) {
        this.drawText(
          info.value4 + BBSWV4u,
          rect.x - L5 + rect.width,
          rect.y,
          L5,
          "right"
        );
      }
    }
  };

  Window_SavefileList.prototype.drawPartyCharacters = function (
    info,
    x,
    y,
    bottom
  ) {
    if (info.characters) {
      this.contents.fontSize = 16;
      for (var i = 0; i < info.characters.length; i++) {
        var data = info.characters[i];
        var opa = BBSWCOY < 2 || i < $gameParty.battleMembers().length;
        this.changePaintOpacity(opa);
        this.drawCharacter(data[0], data[1], x + i * 48, bottom - BBSWCPY);
        if (!BBSWLOO) continue;
        this.drawText(
          TextManager.levelA + " " + data[2],
          12 + i * 48,
          y + BBSWLPY,
          40
        );
      }
      this.changePaintOpacity(true);
      this.contents.fontSize = 20;
    }
  };

  Window_SavefileList.prototype.drawFileId = function (id, x, y) {
    this.drawText(TextManager.file + " " + id, x, y, 120);
  };
})();


code:
//=============================================================================
// BattleBalloon.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015-2017 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.0.0 2017/02/25 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc BattleBalloonPlugin
 * @author triacontane
 *
 * @param BalloonSpeedRate
 * @desc フキダシを表示する速度倍率（レート）です。マップ画面のフキダシには影響しません。
 * @default 100
 *
 * @param BalloonWaitTime
 * @desc フキダシ表示後の待機時間(フレーム)です。マップ画面のフキダシには影響しません。
 * @default 12
 *
 * @param BalloonIdEvasion
 * @desc 回避時に表示するフキダシIDです。
 * @default 0
 *
 * @param BalloonIdCounter
 * @desc 反撃時に表示するフキダシIDです。
 * @default 0
 *
 * @param BalloonIdSubstitute
 * @desc 身代わり時に表示するフキダシIDです。
 * @default 0
 *
 * @param BalloonIdCounter
 * @desc 反射時に表示するフキダシIDです。
 * @default 0
 *
 * @help 戦闘中に様々なタイミングでフキダシ（バルーン）を表示できます。
 * さらにフキダシの速度や待機時間を調整できます。
 * 表示対象はアクターおよび敵キャラです。主に以下のタイミングで表示できます。
 *
 * 1. バトルイベント中にプラグインコマンドを実行
 * 　アクター、敵キャラ、スキル使用者を対象にできます。
 * 　スキル使用者を対象にする場合は、スキル実行後のコモンイベント等で
 * 　表示させてください。
 * 　フキダシ表示が完了するまでウェイトすることもできます。
 *
 * 2. 反撃や回避を行った際に自動発動
 * 　パラメータで指定しておけば反撃、回避、魔法反射、身代わりの瞬間に
 * 　指定したIDのバルーンを自動表示します。
 *
 * 3. スキル実行時に自動発動
 * 　スキルもしくはアイテム使用時に自動発動します。
 * 　メモ欄に以下の通り記述してください。
 *
 * <BB_決定時フキダシ:5> # スキル決定時にフキダシ[5]を表示(敵キャラのみ)(※1)
 * <BB_BalloonInput:5>   # 同上
 * <BB_使用時フキダシ:6> # スキル使用時にフキダシ[6]を表示
 * <BB_BalloonUsing:6>   # 同上
 * ※1 正確には敵キャラAIがスキルを決定したタイミングになります。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * BB_アクターにバルーン 3 1 ON # アクター[3]にバルーン[1]をウェイトありで表示
 * BB_BALLOON_FOR_ACTOR 3 1 ON  # 同上
 * BB_敵キャラにバルーン 1 2    # インデックス[1]の敵キャラにバルーン[2]を表示
 * BB_BALLOON_FOR_ENEMY 1 2     # 同上
 * BB_使用者にバルーン 3 ON     # スキルの使用者にバルーン[3]を表示
 * BB_BALLOON_FOR_USER 3 ON     # 同上
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc 戦闘中フキダシ表示プラグイン
 * @author トリアコンタン
 *
 * @param フキダシ速度倍率
 * @desc フキダシを表示する速度倍率（レート）です。マップ画面のフキダシには影響しません。
 * @default 100
 *
 * @param フキダシ待機時間
 * @desc フキダシ表示後の待機時間(フレーム)です。マップ画面のフキダシには影響しません。
 * @default 12
 *
 * @param 回避フキダシID
 * @desc 回避時に表示するフキダシIDです。
 * @default 0
 *
 * @param 反撃フキダシID
 * @desc 反撃時に表示するフキダシIDです。
 * @default 0
 *
 * @param 身代わりフキダシID
 * @desc 身代わり時に表示するフキダシIDです。
 * @default 0
 *
 * @param 反射フキダシID
 * @desc 反射時に表示するフキダシIDです。
 * @default 0
 *
 * @help 戦闘中に様々なタイミングでフキダシ（バルーン）を表示できます。
 * さらにフキダシの速度や待機時間を調整できます。
 * 表示対象はアクターおよび敵キャラです。主に以下のタイミングで表示できます。
 *
 * 1. バトルイベント中にプラグインコマンドを実行
 * 　アクター、敵キャラ、スキル使用者を対象にできます。
 * 　スキル使用者を対象にする場合は、スキル実行後のコモンイベント等で
 * 　表示させてください。
 * 　フキダシ表示が完了するまでウェイトすることもできます。
 *
 * 2. 反撃や回避を行った際に自動発動
 * 　パラメータで指定しておけば反撃、回避、魔法反射、身代わりの瞬間に
 * 　指定したIDのバルーンを自動表示します。
 *
 * 3. スキル実行時に自動発動
 * 　スキルもしくはアイテム使用時に自動発動します。
 * 　メモ欄に以下の通り記述してください。
 *
 * <BB_決定時フキダシ:5> # スキル決定時にフキダシ[5]を表示(敵キャラのみ)(※1)
 * <BB_BalloonInput:5>   # 同上
 * <BB_使用時フキダシ:6> # スキル使用時にフキダシ[6]を表示
 * <BB_BalloonUsing:6>   # 同上
 * ※1 正確には敵キャラAIがスキルを決定したタイミングになります。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * BB_アクターにバルーン 3 1 ON # アクター[3]にバルーン[1]をウェイトありで表示
 * BB_BALLOON_FOR_ACTOR 3 1 ON  # 同上
 * BB_敵キャラにバルーン 1 2    # インデックス[1]の敵キャラにバルーン[2]を表示
 * BB_BALLOON_FOR_ENEMY 1 2     # 同上
 * BB_使用者にバルーン 3 ON     # スキルの使用者にバルーン[3]を表示
 * BB_BALLOON_FOR_USER 3 ON     # 同上
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  var pluginName = "BattleBalloon";
  var metaTagPrefix = "BB_";

  //=============================================================================
  // ローカル関数
  //  プラグインパラメータやプラグインコマンドパラメータの整形やチェックをします
  //=============================================================================
  var getParamString = function (paramNames) {
    if (!Array.isArray(paramNames)) paramNames = [paramNames];
    for (var i = 0; i < paramNames.length; i++) {
      var name = PluginManager.parameters(pluginName)[paramNames[i]];
      if (name) return name;
    }
    return "";
  };

  var getParamNumber = function (paramNames, min, max) {
    var value = getParamString(paramNames);
    if (arguments.length < 2) min = -Infinity;
    if (arguments.length < 3) max = Infinity;
    return (parseInt(value) || 0).clamp(min, max);
  };

  var getArgNumber = function (arg, min, max) {
    if (arguments.length < 2) min = -Infinity;
    if (arguments.length < 3) max = Infinity;
    return (parseInt(arg) || 0).clamp(min, max);
  };

  var getMetaValue = function (object, name) {
    var metaTagName = metaTagPrefix + name;
    return object.meta.hasOwnProperty(metaTagName)
      ? convertEscapeCharacters(object.meta[metaTagName])
      : undefined;
  };

  var getMetaValues = function (object, names) {
    for (var i = 0, n = names.length; i < n; i++) {
      var value = getMetaValue(object, names[i]);
      if (value !== undefined) return value;
    }
    return undefined;
  };

  var convertEscapeCharacters = function (text) {
    if (text == null) text = "";
    var windowLayer = SceneManager._scene._windowLayer;
    return windowLayer
      ? windowLayer.children[0].convertEscapeCharacters(text)
      : text;
  };

  var convertAllArguments = function (args) {
    for (var i = 0; i < args.length; i++) {
      args[i] = convertEscapeCharacters(args[i]);
    }
    return args;
  };

  var setPluginCommand = function (commandName, methodName) {
    pluginCommandMap.set(metaTagPrefix + commandName, methodName);
  };

  //=============================================================================
  // パラメータの取得と整形
  //=============================================================================
  var param = {};
  param.balloonIdEvasion = getParamNumber([
    "BalloonIdEvasion",
    "回避フキダシID",
  ]);
  param.balloonIdReflection = getParamNumber([
    "BalloonIdReflection",
    "反射フキダシID",
  ]);
  param.balloonIdCounter = getParamNumber([
    "BalloonIdCounter",
    "反撃フキダシID",
  ]);
  param.balloonIdSubstitute = getParamNumber([
    "BalloonIdSubstitute",
    "身代わりフキダシID",
  ]);
  param.balloonSpeedRate = getParamNumber([
    "BalloonSpeedRate",
    "フキダシ速度倍率",
  ]);
  param.balloonWaitTime = getParamNumber([
    "BalloonWaitTime",
    "フキダシ待機時間",
  ]);

  var pluginCommandMap = new Map();
  setPluginCommand("アクターにバルーン", "requestBalloonActor");
  setPluginCommand("BALLOON_FOR_ACTOR", "requestBalloonActor");
  setPluginCommand("敵キャラにバルーン", "requestBalloonEnemy");
  setPluginCommand("BALLOON_FOR_ENEMY", "requestBalloonEnemy");
  setPluginCommand("使用者にバルーン", "requestBalloonUser");
  setPluginCommand("BALLOON_FOR_USER", "requestBalloonUser");

  //=============================================================================
  // Game_Interpreter
  //  プラグインコマンドを追加定義します。
  //=============================================================================
  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.apply(this, arguments);
    if (!$gameParty.inBattle()) return;
    var pluginCommandMethod = pluginCommandMap.get(command.toUpperCase());
    if (pluginCommandMethod) {
      this[pluginCommandMethod](convertAllArguments(args));
    }
  };

  var _Game_Interpreter_updateWaitMode =
    Game_Interpreter.prototype.updateWaitMode;
  Game_Interpreter.prototype.updateWaitMode = function () {
    var waiting = this.updateWaitModeForBattleBalloon();
    return waiting
      ? true
      : _Game_Interpreter_updateWaitMode.apply(this, arguments);
  };

  Game_Interpreter.prototype.updateWaitModeForBattleBalloon = function () {
    var waiting = false;
    if (this._waitMode === "battleBalloon") {
      waiting = this._battler.isBalloonPlaying();
    } else {
      this._battler = null;
    }
    return waiting;
  };

  Game_Interpreter.prototype.requestBalloonActor = function (args) {
    var actor = $gameActors.actor(getArgNumber(args[0]));
    if (actor && $gameParty.battleMembers().contains(actor)) {
      actor.requestBalloonIfNeed(getArgNumber(args[1], 1));
      this.setWaitForBalloon(args[2], actor);
    }
  };

  Game_Interpreter.prototype.requestBalloonEnemy = function (args) {
    var enemy = $gameTroop.members()[getArgNumber(args[0]) - 1];
    if (enemy) {
      enemy.requestBalloonIfNeed(getArgNumber(args[1], 1));
      this.setWaitForBalloon(args[2], enemy);
    }
  };

  Game_Interpreter.prototype.requestBalloonUser = function (args) {
    var user = BattleManager.getSkillUser();
    if (user) {
      user.requestBalloonIfNeed(getArgNumber(args[0], 1));
      this.setWaitForBalloon(args[1], user);
    }
  };

  Game_Interpreter.prototype.setWaitForBalloon = function (waitFlag, battler) {
    if (waitFlag && waitFlag.toUpperCase() !== "OFF") {
      this.setWaitMode("battleBalloon");
      this._battler = battler;
    }
  };

  //=============================================================================
  // BattleManager
  //  実行主体に対してバルーンスプライトの表示をリクエストします。
  //=============================================================================
  BattleManager.getSkillUser = function () {
    return this._subject;
  };

  //=============================================================================
  // Game_BattlerBase
  //  バルーンスプライトの表示をリクエストします。
  //=============================================================================
  Game_BattlerBase.prototype.requestBalloon =
    Game_CharacterBase.prototype.requestBalloon;
  Game_BattlerBase.prototype.balloonId = Game_CharacterBase.prototype.balloonId;
  Game_BattlerBase.prototype.startBalloon =
    Game_CharacterBase.prototype.startBalloon;
  Game_BattlerBase.prototype.isBalloonPlaying =
    Game_CharacterBase.prototype.isBalloonPlaying;
  Game_BattlerBase.prototype.endBalloon =
    Game_CharacterBase.prototype.endBalloon;

  Game_BattlerBase.prototype.requestBalloonIfNeed = function (balloonId) {
    if (balloonId > 0) {
      this.requestBalloon(balloonId);
    }
  };

  //=============================================================================
  // Game_Battler
  //  リアクションバルーンの表示をリクエストします。
  //=============================================================================
  var _Game_Battler_performSubstitute =
    Game_Battler.prototype.performSubstitute;
  Game_Battler.prototype.performSubstitute = function (target) {
    _Game_Battler_performSubstitute.apply(this, arguments);
    this.requestBalloonIfNeed(param.balloonIdSubstitute);
  };

  var _Game_Battler_performReflection =
    Game_Battler.prototype.performReflection;
  Game_Battler.prototype.performReflection = function (target) {
    _Game_Battler_performReflection.apply(this, arguments);
    this.requestBalloonIfNeed(param.balloonIdReflection);
  };

  var _Game_Battler_performCounter = Game_Battler.prototype.performCounter;
  Game_Battler.prototype.performCounter = function (target) {
    _Game_Battler_performCounter.apply(this, arguments);
    this.requestBalloonIfNeed(param.balloonIdCounter);
  };

  var _Game_Battler_performEvasion = Game_Battler.prototype.performEvasion;
  Game_Battler.prototype.performEvasion = function (target) {
    _Game_Battler_performEvasion.apply(this, arguments);
    this.requestBalloonIfNeed(param.balloonIdEvasion);
  };

  var _Game_Battler_performMagicEvasion =
    Game_Battler.prototype.performMagicEvasion;
  Game_Battler.prototype.performMagicEvasion = function () {
    _Game_Battler_performMagicEvasion.apply(this, arguments);
    this.requestBalloonIfNeed(param.balloonIdEvasion);
  };

  var _Game_Battler_performActionStart =
    Game_Battler.prototype.performActionStart;
  Game_Battler.prototype.performActionStart = function (action) {
    _Game_Battler_performActionStart.apply(this, arguments);
    this.requestBalloonIfNeed(action.getBalloonIdForUsing());
  };

  //=============================================================================
  // Game_Enemy
  //  行動決定時にバルーンを表示します。
  //=============================================================================
  var _Game_Enemy_makeActions = Game_Enemy.prototype.makeActions;
  Game_Enemy.prototype.makeActions = function () {
    _Game_Enemy_makeActions.apply(this, arguments);
    this.requestBalloonInput();
  };

  Game_Enemy.prototype.requestBalloonInput = function () {
    var number = this.numActions();
    for (var i = 0; i < number; i++) {
      this.requestBalloonIfNeed(this.action(i).getBalloonIdForInput());
    }
  };

  //=============================================================================
  // Game_Action
  //  バルーン情報のメモ欄を取得します。
  //=============================================================================
  Game_Action.prototype.getBalloonIdMetaData = function (names) {
    var metaInfo = getMetaValues(this.item(), names);
    return metaInfo ? getArgNumber(metaInfo, 1) : null;
  };

  Game_Action.prototype.getBalloonIdForInput = function () {
    return this.getBalloonIdMetaData(["BalloonInput", "決定時フキダシ"]);
  };

  Game_Action.prototype.getBalloonIdForUsing = function () {
    return this.getBalloonIdMetaData(["BalloonUsing", "使用時フキダシ"]);
  };

  //=============================================================================
  // Sprite_Battler
  //  バルーンスプライトを追加します。
  //=============================================================================
  var _Sprite_Battler_update = Sprite_Battler.prototype.update;
  Sprite_Battler.prototype.update = function () {
    _Sprite_Battler_update.apply(this, arguments);
    if (this._battler) {
      this.updateBalloon();
    }
  };

  Sprite_Battler.prototype.setupBalloon = function () {
    if (this._battler.balloonId() > 0) {
      this.startBalloon();
      this._battler.startBalloon();
    }
  };

  Sprite_Battler.prototype.startBalloon = function () {
    if (!this._balloonSprite) {
      this._balloonSprite = new Sprite_BattlerBalloon();
    }
    this._balloonSprite.setup(this._battler.balloonId());
    this.parent.addChild(this._balloonSprite);
  };

  Sprite_Battler.prototype.updateBalloon = function () {
    if (!this.isBalloonPlaying()) {
      this._battler.endBalloon();
    }
    this.setupBalloon();
    if (this._balloonSprite) {
      this._balloonSprite.x = this.x;
      this._balloonSprite.y = this.y - this.getMainHeight();
      if (!this._balloonSprite.isPlaying()) {
        this.endBalloon();
      }
    }
  };

  Sprite_Battler.prototype.endBalloon = function () {
    if (this._balloonSprite) {
      this.parent.removeChild(this._balloonSprite);
      this._balloonSprite = null;
    }
  };

  Sprite_Battler.prototype.isBalloonPlaying = function () {
    return !!this._balloonSprite;
  };

  Sprite_Battler.prototype.getMainHeight = function () {
    return this.height;
  };

  //=============================================================================
  // Sprite_Actor
  //  バルーンスプライトを追加します。
  //=============================================================================
  Sprite_Actor.prototype.getMainHeight = function () {
    return this._mainSprite.height;
  };

  //=============================================================================
  // Sprite_BattlerBalloon
  //  バトラー表示用のフキダシスプライトです。
  //=============================================================================
  function Sprite_BattlerBalloon() {
    this.initialize.apply(this, arguments);
  }

  Sprite_BattlerBalloon.prototype = Object.create(Sprite_Balloon.prototype);
  Sprite_BattlerBalloon.prototype.constructor = Sprite_BattlerBalloon;

  Sprite_BattlerBalloon.prototype.speed = function () {
    return Math.floor(
      (Sprite_Balloon.prototype.speed.call(this) * 100) /
        (param.balloonSpeedRate || 100)
    );
  };

  Sprite_BattlerBalloon.prototype.waitTime = function () {
    return param.balloonWaitTime;
  };
})();

repo_name: dazed/translations

license: unknown


code:
/*
############################################
	作者: KOBRA
	営利・非営利・18禁問わず配布可、改造も可、報告不要
	積極的に配布して皆のゲーム開発を快適にしてあげて
	http://cobrara.blogspot.jp/
	https://twitter.com/onarinin_san
############################################
*/

/*:
 * @target MZ
 * @plugindesc エロステータスを追加します
 * @author
 *
 * @param SE
 * @text SE
 * @default Cursor3
 * @desc ページを変更した時のSE音を指定、デフォルト：Cursor3
 *
 * @param SEvol
 * @text SEボリューム
 * @type number
 * @default 100
 * @desc SE音の音量を指定、デフォルト：100
 *
 * @param window
 * @text ウィンドウの表示
 * @type boolean
 * @default true
 * @desc 背景としてウィンドウの枠を表示するかどうか
 *
 * @param font
 * @text フォント
 * @default
 * @desc Project\fontsにwoffファイルを入れ、ファイル名を記入してください
 *
 * @help エロステータスプラグイン
 *
 * イベントのスクリプトでエロステータス画面を作る事が可能に
 *
 *　～開く～
 *　イベントのスクリプトで
 *　SceneManager.push(Scene_EroStatus)
 *　とやるだけ
 *
 *　～設定～
 *  スクリプトで1行目に｢CBR-エロステータス｣と記入するとエロステータスのスクリプトを使うよーって合図に
 *
 *　～初期化～
 *　｢初期化-???｣　ALLと書くと前ページ初期化、数値だと指定したページのみ初期化
 *
 *　～データ入れる～
 * ｢ページ-???｣ 数値を入れると｢今からこのページにデータ入れるよー｣という合図を行います
 *
 * ～画像～
 * ※注※　必ず画像-????.png を2行目に持ってきてください
 *
 * ｢画像-??????.png｣って書くととpicturesフォルダに保存された画像を表示、\V[2]で変数2を使ったりも可能
 * ｢x-???｣　x座標を指定
 * ｢y-???｣　y座標
 * ｢透明度-???｣　書かなくてもいい、無かったら100になる　数値は0～100
 * ｢サイズ-???｣　書かなくてもいい、無かったら100になる　数値は0～
 *
 *
 * ～テキスト～
 * ※注※　必ず テキスト-??? を2行目に持ってきてください
 *
 * ｢テキスト-??????｣　\V[2]で変数3を表示したり\{でフォントを大きくしたりできます
 * ｢x-???｣　x座標を指定
 * ｢y-???｣　y座標
 * ｢左右-?｣ 書かなくてもいい、無かったら左になる　左、中、右でx座標の始点を指定
 * ｢上下-?｣ 書かなくてもいい、無かったら上になる　上、中、下で途中でフォントサイズ大きくした時の揃え方を指定
 * ｢サイズ-??｣　書かなくてもいい、無かったら28になる
 *
 *
 */

//(function(){

var CBR = CBR || {};
CBR.eroStatus = {
  event: 0,
  se: "Cursor3",
  seVol: 100,
  addPage: 0,
  pageNow: 0,
  window: 0,
  font: false,
  data: [],
};

if (!CBR_Game_Interpreter_command355) {
  var CBR_Game_Interpreter_command355 = Game_Interpreter.prototype.command355;
  Game_Interpreter.prototype.command355 = function () {
    //CBR-xxxの場合CBR.xxxにobjを渡す
    var key = this.currentCommand().parameters[0];
    if (key.match(/^CBR\-/)) {
      var obj = [];
      //下に続いてるスクリプトの取得
      while (this.nextEventCode() === 655) {
        this._index++;
        obj[obj.length] = this.currentCommand().parameters[0];
      }
      var temp = key.split("-");
      //CBR-×××があったら
      if (CBR[temp[1]]) {
        //下に続くデータを入れる
        CBR[temp[1]](obj);
      }
      //普通にスクリプト実行
    } else {
      CBR_Game_Interpreter_command355.call(this);
    }
    return true;
  };
}

CBR["エロステータス"] = function (ary) {
  //スクリプト毎に実行されるヤツ
  //全てのデータを格納しよう
  //変数の変換は開く時かなー
  var obj = {};
  for (var A of ary) {
    //A = A.replace(/\\V\[(\d+)\]/g,function(a,b){//汚いけどこれは毎回やらないとね
    //		return $gameVariables.value(b);//律儀にNumberしなくてもいいか
    //});
    var temp = A.split(/\-(.*)/, 2);

    switch (
      temp[0] //初期化とページ変更はここで終わる
    ) {
      case "初期化":
        if (temp[1] == "ALL") {
          CBR.eroStatus.data.length = 0;
        } else {
          delete CBR.eroStatus.data[Number(temp[1]) - 1];
        }
        return; //break;
      case "ページ":
        CBR.eroStatus.addPage = Number(temp[1]) - 1;
        return; //break;
      case "画像":
      case "テキスト":
        obj.val = temp[1];
        obj.type = temp[0];
        break;
      case "x":
      case "y":
      case "サイズ":
      case "左右":
      case "上下":
      case "透明度":
        obj[temp[0]] = temp[1];
        break;
      default:
        //console.log("なにこれ？"+temp[0]);
        return;
    }
  }
  CBR.eroStatus.data[CBR.eroStatus.addPage] = CBR.eroStatus.data[
    CBR.eroStatus.addPage
  ] || { 画像: [], テキスト: [] }; //ページがなかったら作る
  CBR.eroStatus.data[CBR.eroStatus.addPage][obj.type][
    CBR.eroStatus.data[CBR.eroStatus.addPage][obj.type].length
  ] = obj; //んで入れる
};

//まずstarted const boxMargin = 4;が原因でマージンができてしまう

function Scene_EroStatus() {
  this.initialize(...arguments);
}

Scene_EroStatus.prototype = Object.create(Scene_Base.prototype);
Scene_EroStatus.prototype.constructor = Scene_EroStatus;

Scene_EroStatus.prototype.initialize = function () {
  Scene_Base.prototype.initialize.call(this);
};
Scene_EroStatus.prototype.create = function () {
  Scene_Base.prototype.create.call(this);

  //data[{},{},,,]ってなってたら空の部分を削る
  var i = CBR.eroStatus.data.length - 1;
  while (i && !CBR.eroStatus.data[i]) {
    CBR.eroStatus.data.pop();
    i--;
  }

  //開いた時表示するページ
  CBR.eroStatus.pageNow = 0;
  var i = 0;
  while (!CBR.eroStatus.data[i]) {
    i++;
  }
  CBR.eroStatus.pageNow = i;

  var param = PluginManager.parameters("CBR_EroStatus");
  CBR.eroStatus.se = param["SE"] || 100;
  CBR.eroStatus.seVol = param["SEvol"] || 100;
  if (param["window"] == "true") {
    CBR.eroStatus.window = true;
  } else {
    CBR.eroStatus.window = false;
  }
  CBR.eroStatus.font = param["font"] || false;
  if (CBR.eroStatus.font) {
    if (
      FontManager._urls["rmmz-mainfont"] !=
      "fonts/" + CBR.eroStatus.font + ".woff"
    ) {
      FontManager._states["rmmz-mainfont"] = null;
      FontManager.load("rmmz-mainfont", CBR.eroStatus.font + ".woff");
    }
  }

  this.createBackground();
  this.createWindowLayer();
  this._windowLayer.x = 0;
  this._windowLayer.y = 0;
  this.createEroStatusWindow();
};
//今まで自力でロードフラグやってたけど今回は便利な物が、シーン.isReadyのおかげ
Scene_EroStatus.prototype.start = function () {
  Scene_MenuBase.prototype.start.call(this);
  this._eroStatusWindow.refresh();
};
Scene_EroStatus.prototype.createEroStatusWindow = function () {
  const rect = this.eroStatusWindowRect();
  this._eroStatusWindow = new Window_EroStatus(rect);
  this._eroStatusWindow.setHandler("cancel", this.popScene.bind(this));
  this.addWindow(this._eroStatusWindow);
};
Scene_EroStatus.prototype.eroStatusWindowRect = function () {
  const ww = Graphics.width;
  const wh = Graphics.height;
  const wx = 0;
  const wy = 0;
  return new Rectangle(wx, wy, ww, wh);
};
Scene_EroStatus.prototype.update = function () {
  Scene_Base.prototype.update.call(this);
};
Scene_EroStatus.prototype.createBackground = function () {
  this._backgroundFilter = new PIXI.filters.BlurFilter();
  this._backgroundSprite = new Sprite();
  this._backgroundSprite.bitmap = SceneManager.backgroundBitmap();
  //なんか黒いフチが右下だけっていうのが気に入らないので四方に
  this._backgroundFilter.autoFit = false;

  this._backgroundSprite.filters = [this._backgroundFilter];
  this.addChild(this._backgroundSprite);
  this.setBackgroundOpacity(192);
};
Scene_EroStatus.prototype.setBackgroundOpacity = function (opacity) {
  this._backgroundSprite.opacity = opacity;
};
Scene_EroStatus.prototype.popScene = function () {
  FontManager._states["rmmz-mainfont"] = null;
  FontManager.load("rmmz-mainfont", $dataSystem.advanced.mainFontFilename);
  SceneManager.pop();
};

//ウィンドウ
function Window_EroStatus() {
  this.initialize(...arguments);
}

Window_EroStatus.prototype = Object.create(Window_Selectable.prototype);
Window_EroStatus.prototype.constructor = Window_EroStatus;

Window_EroStatus.prototype.initialize = function (rect) {
  Window_Selectable.prototype.initialize.call(this, rect);
  this._CBR_drawn = false;
  this.refresh();
};
Window_EroStatus.prototype.itemPadding = function () {
  return 0;
};
Window_EroStatus.prototype.updatePadding = function () {
  this.padding = 0;
};

Window_EroStatus.prototype.colSpacing = function () {
  return 0;
};
Window_EroStatus.prototype.rowSpacing = function () {
  return 0;
};

Window_EroStatus.prototype.update = function () {
  Window_Selectable.prototype.update.call(this);

  if (
    CBR.eroStatus.data.length !== 1 &&
    ImageManager.isReady() &&
    FontManager.isReady()
  ) {
    //読み込み終わってたら、結局画像読み終えてない限りリフレッシュする必要なし
    var pn = CBR.eroStatus.pageNow;
    var n;
    if (Input.isRepeated("right")) {
      for (var i = 1, len = CBR.eroStatus.data.length; i < len; i++) {
        n = i + pn;
        if (len <= i + pn) {
          n -= len;
        }
        if (CBR.eroStatus.data[n]) {
          break;
        }
      }
    } else if (Input.isRepeated("left")) {
      for (var i = 1, len = CBR.eroStatus.data.length; i < len; i++) {
        n = pn - i;
        if (n < 0) {
          n += len;
        }
        if (CBR.eroStatus.data[n]) {
          break;
        }
      }
    }
    if (n !== undefined && CBR.eroStatus.pageNow != n) {
      //ページの変更だったら
      CBR.eroStatus.pageNow = n;
      AudioManager.playSe({
        name: CBR.eroStatus.se,
        volume: CBR.eroStatus.seVol,
        pitch: 100,
        pan: 0,
      });
      this._CBR_drawn = false;
      this.refresh();
    } else if (!this._CBR_drawn) {
      //画像が読み込まれてるというのに描写されて無い時
      this.refresh();
    }
  }
};

Window_EroStatus.prototype.refresh = function () {
  const rect = this.itemLineRect(0);
  const x = rect.x;
  const y = rect.y;
  const width = rect.width;
  this.contents.clear();

  var test = CBR.eroStatus.data[CBR.eroStatus.pageNow]; //このページの画像&&テキスト
  if (!test) {
    return;
  }
  for (var obj of test["画像"]) {
    var val = obj.val.replace(/\\V\[(\d+)\]/g, function (a, b) {
      return $gameVariables.value(b);
    });
    const bitmap = ImageManager.loadPicture(val.slice(0, -4));

    const pw = bitmap.width;
    const ph = bitmap.height;
    var top = 0;
    var left = 0;
    if (obj["左右"] == "中") {
      left -= pw / 2;
    } else if (obj["左右"] == "右") {
      left -= pw;
    }
    if (obj["上下"] == "中") {
      top -= ph / 2;
    } else if (obj["上下"] == "下") {
      top -= ph;
    }
    if (obj["透明度"]) {
      this.contents.paintOpacity = (255 * Number(obj["透明度"])) / 100;
    }
    var zoom = 1;
    if (obj["サイズ"]) {
      zoom = Number(obj["サイズ"]) / 100;
    }
    this.contents.blt(
      bitmap,
      0,
      0,
      pw,
      ph,
      Number(obj.x) + left,
      Number(obj.y) + top,
      pw * zoom,
      ph * zoom
    );
    this.contents.paintOpacity = 255;
  }

  //画像読み込み全部終わってなかったら終了
  if (!ImageManager.isReady()) {
    return;
  }

  for (var obj of test["テキスト"]) {
    //まず変数や値を変換
    var text = obj.val.replace(
      /\\(\\)|\\([VNP])\[(\d+)\]|\\(<)(.+)\\>/g,
      function (a, b, c, d, e, f) {
        if (b) {
          //\\
          return "\\";
        } else if (c) {
          //[VNP]
          d = Number(d);
          switch (c) {
            case "V":
              return $gameVariables.value(d);
              break;
            case "N":
              return $gameActors._data[d]._name;
              break;
            case "P":
              return $dataActors[$gameParty._actors[d - 1]].name;
              break;
          }
        } else {
          //script
          return eval(f);
        }
      }
    );

    this.contents.context.font = this.contents._makeFontNameText();
    this.contents.fontSize =
      Number(obj["サイズ"]) || $gameSystem.mainFontSize();
    this.resetTextColor();

    const reg = RegExp(/\\([CI])\[(\d+)\]|\\\{|\\\}/, "g");
    var ary;
    var c = 0;
    var left = 0;

    var strAry = []; //分割された文字列いれる
    var wAry = []; //分割された横幅いれる
    var fAry = []; //分割ごとの操作を入れる

    var ii = 0;
    var strWidth = 0;
    var maxH = this.contents.fontSize;
    //テキストのwidthや分割集め
    while ((ary = reg.exec(text)) !== null) {
      var str = text.substring(c, ary.index); //描写したい部分を抜き出す
      strAry[ii] = str;
      wAry[ii] = this.textWidth(str);
      strWidth += wAry[ii];

      switch (ary[1]) {
        case undefined: //{や}の時
          if (ary[0].substring(1) == "{") {
            fAry[ii] = { type: "{" };
            this.contents.fontSize += 6;
            if (maxH < this.contents.fontSize) {
              maxH = this.contents.fontSize;
            }
          } else {
            fAry[ii] = { type: "}" };
            this.contents.fontSize -= 6;
          }
          break;
        default:
          fAry[ii] = { type: ary[1], val: ary[2] };
          break;
      }

      c = reg.lastIndex;
      ii++;
    }
    if (c != text.length) {
      var str = text.substring(c); //描写したい部分を抜き出す
      strAry[ii] = str;
      fAry[ii] = { type: false, val: false };
      wAry[ii] = this.textWidth(str);
      strWidth += wAry[ii];
      ii++;
    }

    this.contents.context.font = this.contents._makeFontNameText();
    this.contents.fontSize =
      Number(obj["サイズ"]) || $gameSystem.mainFontSize();

    var left = 0;
    var top = 0;
    if (obj["左右"] == "中") {
      left -= strWidth / 2;
    } else if (obj["左右"] == "右") {
      left -= strWidth;
    }
    for (var i = 0; i < ii; i++) {
      var top = 0;
      if (obj["上下"] == "中") {
        top = maxH / 2 - this.contents.fontSize / 2;
      } else if (obj["上下"] == "下") {
        top = maxH - this.contents.fontSize;
      }
      this.drawText(
        strAry[i],
        Number(obj.x) + left,
        Number(obj.y) + top,
        wAry[i],
        this.contents.fontSize,
        "right"
      );
      left += wAry[i];
      switch (fAry[i].type) {
        case "C":
          this.changeTextColor(ColorManager.textColor(fAry[i].val)); //カラチェン
          break;
        case "I":
          //return $gameActors._data[d]._name;
          break;
        case "{":
          this.contents.fontSize += 6;
          break;
        case "}":
          this.contents.fontSize -= 6;
          break;
      }
    }

    this.resetTextColor();
    this.contents.fontSize = $gameSystem.mainFontSize();
    this._CBR_drawn = true;
  }
};
//window.drawTextだとlineHeightが36に固定されちゃうので変える
Window_EroStatus.prototype.drawText = function (
  text,
  x,
  y,
  maxWidth,
  h,
  align
) {
  this.contents.drawText(text, x, y, maxWidth, h, align);
};

Window_EroStatus.prototype.open = function () {
  this.refresh();
  Window_Selectable.prototype.open.call(this);
};
//アクティブじゃなくてもキャンセルできるように
Window_EroStatus.prototype.processHandling = function () {
  if (this.isCancelEnabled() && this.isCancelTriggered()) {
    return this.processCancel();
  }
};
Window_EroStatus.prototype.loadWindowskin = function () {
  if (CBR.eroStatus.window) {
    this.windowskin = ImageManager.loadSystem("Window");
  } else {
    return;
  }
};