code:
/*
############################################
	作者: COBRA
	改造や配布好き勝手にしても大丈夫だよ
	寧ろ積極的に配布して皆のゲーム開発を快適にしてあげて
	http://cobrara.blogspot.jp/
############################################
*/

// Version 1.1.3
// 2020/4/23 \C[0]に対応してませんでした
// 2018/4/26 ロードした際ステータスの変更もロードされるよう修正
// 2017/12/13 最新のバージョン(1.5)でデプロイメントすると1回目だけ画像が表示されない問題を修正
// 2017/8/27 1.1.0 ページの表示・非表示機能を追加しました
// 2017/7/30 1.0.4 最新のコアスクリプト(ver1.2c)にも対応しました
// 2017/5/4 1.0.3 エロステータス画面を開いてる最中NPCが動いてしまう問題を修正しました
// 2017/1/31 1.0.2 changeにおいて最後の項目に｢@@,@_,@=｣が含まれている場合エスケープされない問題を修正しました
// 2017/1/30 1.0.1 ピクチャ名に変数が反映されないバグを修正しました
// 2017/1/24 1.0.0

/*:
* @plugindesc エロステータス作れちゃうプラグイン(本体)
* @author COBRA
* @help Version 1.1.3
* 自由にいじれちゃうエロステータス画面
*
* 画像はimg/picturesにpngで保存してください
*
* 0pxの画像を表示しようとするとバグります
*
*
* 詳しくはこちらで
* http://cobrara.blogspot.jp/2017/01/blog-post_24.html
*
* 横幅：816　縦幅：624

* @param eroStaName
* @desc メニューに表示される名前だよ
* Default: エロステータス
* @default エロステータス
*
*
* @param
*
*
* @param commonEvent
* @desc エロステ画面を開く直前に実行されるコモンイベント、数値
* Default:
* @default
*/

var CBR_eroStatus = [];
var CBR_eroStatusState = {};

//表示するページ変える
Game_System.prototype.CBR_eroSta_page = function (list) {
  this.availablePage = list;
  CBR_eroStatusState.num = this.availablePage;
};

//起動・ロード・ニューゲーム時
var _CBR_Game_System_initialize = Game_System.prototype.initialize;
Game_System.prototype.initialize = function () {
  _CBR_Game_System_initialize.call(this);

  //初期値
  CBR_eroStatus = [];
  CBR_eroStatusState.num = [];
  CBR_eroStatusState.numOrigin = [];
  CBR_eroStatusState.now = null;
  CBR_eroStatusState.name = null;
  CBR_eroStatusState.event = null;

  this.availablePage = [];

  //ページ数取得
  //こっちがあったら

  for (var i = 0, len = $plugins.length; i < len; i++) {
    var temp = $plugins[i].name.match(/^CBR_eroStatus_(\d+)/); //プラグインが存在して
    if (temp) {
      CBR_eroStatusState.numOrigin[CBR_eroStatusState.numOrigin.length] =
        Number(temp[1]);
      CBR_eroStatusState.num[CBR_eroStatusState.num.length] = Number(temp[1]);
    }
  }

  //変更箇所の保存
  CBR_eroStatusState.numOrigin.sort(function (a, b) {
    return a - b;
  }); //_nの小さい順に
  this._CBR_eroSta_change_list = [];

  //numOriginに[1,2,4,8]ってページが入ってる

  //numには表示すべき[2,4]だけが入ってる

  //エロステには[obj,obj,obj,obj]とOriginに対応した順番で入ってる

  this._CBR_eroSta_pageList = [];

  var param = PluginManager.parameters("CBR_eroStatus_main");
  CBR_eroStatusState.name = "" + (param["eroStaName"] || "エロステータス");
  CBR_eroStatusState.event = Number(param["commonEvent"]) || null;

  for (var i = 0, len = CBR_eroStatusState.numOrigin.length; i < len; i++) {
    //ページの数だけ
    var n = CBR_eroStatusState.numOrigin[i];
    var param = PluginManager.parameters("CBR_eroStatus_" + n);
    //nは_n.js　1,2,3
    //iはページの順番　 0,1,2
    //保存する場合は0から99
    CBR_eroStatus[i] = { p: [], t: [] };

    this._CBR_eroSta_change_list[i] = {
      p: [],
      t: [],
    };

    for (var k = 1; k < 100; k++) {
      this.CBR_eroSta_add(
        "p",
        i,
        k - 1,
        param["picName_" + k],
        param["picX_" + k],
        param["picY_" + k],
        param["picOrigin_" + k],
        param["picShow_" + k],
        param["picOpacity_" + k],
        param["picZoom_" + k]
      );
      this.CBR_eroSta_add(
        "t",
        i,
        k - 1,
        param["txtSubject_" + k],
        param["txtX_" + k],
        param["txtY_" + k],
        param["txtOrigin_" + k],
        param["txtShow_" + k],
        param["txtAlign_" + k],
        param["txtSize_" + k]
      );
    }
  }

  this._CBR_eroSta_change_list = [];
  for (var i = 0, len = CBR_eroStatusState.numOrigin.length; i < len; i++) {
    //ページ分だけチェンジリスト作る
    this._CBR_eroSta_change_list[i] = {
      p: [],
      t: [],
    };
  }
};

//セーブデータ読み込み時に実行
var _CBR_Game_System_onAfterLoad = Game_System.prototype.onAfterLoad;
Game_System.prototype.onAfterLoad = function () {
  _CBR_Game_System_onAfterLoad.call(this);

  if (this.availablePage.length) {
    CBR_eroStatusState.num = this.availablePage;
  }

  for (var i = 0, len = CBR_eroStatusState.numOrigin.length; i < len; i++) {
    //ページ数分繰り返す
    for (var j = 0; j < 2; j++) {
      var ty = !j ? "p" : "t";
      var list = this._CBR_eroSta_change_list[i][ty]; //変更したいナンバーリスト
      for (var k = 0, len2 = list.length; k < len2; k++) {
        var koumokuList = list[k].list;
        for (var m = 0, len3 = koumokuList.length; m < len3; m++) {
          //チェンジする項目数
          if (!CBR_eroStatus[i][ty][list[k].page]) {
            //その項目のデフォが存在しなかったら作成
            this.CBR_eroSta_add(ty, i);
          }
          CBR_eroStatus[i][ty][list[k].num][koumokuList[m].name] =
            koumokuList[m].val;
        }
      }
    }
  }
};

Game_System.prototype.CBR_eroSta_getPageIndex = function (num) {
  //aはaligin or opacity bはzoom
  var ary = CBR_eroStatusState.numOrigin;
  for (var i = 0, len = ary.length; i < len; i++) {
    if (ary[i] == num) {
      return i;
    }
  }
};

Game_System.prototype.CBR_eroSta_add = function (
  type,
  page,
  num,
  data,
  x,
  y,
  origin,
  show,
  a,
  b
) {
  //aはaligin or opacity bはzoom
  if (type == "p") {
    CBR_eroStatus[page].p[num] = {
      name: data,
      x: this.CBR_eroSta_changeVal("x", x),
      y: this.CBR_eroSta_changeVal("y", y),
      origin: origin || "left",
      show: show == "on",
      opacity: this.CBR_eroSta_changeVal("opacity", a),
      zoom: this.CBR_eroSta_changeVal("zoom", b),
    };
  } else if (type == "t") {
    CBR_eroStatus[page].t[num] = {
      subject: data,
      x: this.CBR_eroSta_changeVal("x", x),
      y: this.CBR_eroSta_changeVal("y", y),
      origin: origin || "left",
      show: show == "on",
      align: a || "top",
      size: this.CBR_eroSta_changeVal("size", b),
    };
  }
};

Game_System.prototype.CBR_eroSta_changeVal = function (name, val) {
  //チェンジする時 add時　ロード時のチェンジで反映させよう
  switch (name) {
    case "x":
    case "y":
      return Number(val) || 0;
      break;
    case "opacity":
    case "zoom":
      if (val) {
        return Number(val) / 100;
      } else {
        return 1;
      }
      break;
    case "show":
      return val == "on";
      break;
    case "size":
      return Number(val) || 28;
      break;
    case "name":
    case "subject":
      return val || "";
      break;
    default:
      return val;
      break;
  }
};

Game_System.prototype.CBR_eroSta_change = function (ary) {
  var txt_ary = {
    fontsize: "fontSize",
    vardigit: "varDigit",
  };

  var checkList = {
    p: ["name", "origin", "x", "y", "show", "opacity", "zoom"],
    t: ["subject", "origin", "x", "y", "show", "align", "size"],
  };

  for (var i = 0, len = ary.length; i < len; i++) {
    //変更したいpage_type_nの分だけ
    var temp = ary[i].split(/@@|@_|@=|_|=/);
    var temp2 = ary[i].match(/@@|@_|@=|_|=/g);

    var list = []; //aryを分割したものを入れる
    var temp3 = "";
    for (var k = 0, len2 = temp.length; k < len2; k++) {
      if (temp2[k]) {
        if (temp2[k].charAt(0) == "@") {
          temp3 += temp[k] + temp2[k].charAt(1);
        } else {
          list[list.length] = temp3 + temp[k];
          temp3 = "";
        }
      } else {
        list[list.length] = temp3 + temp[k];
      }
    }

    list[0] = Number(list[0]);
    var page = null;
    for (var k = 0, len2 = CBR_eroStatusState.numOrigin.length; k < len2; k++) {
      //ページ数だけ回す
      if (CBR_eroStatusState.numOrigin[k] == list[0]) {
        //nと一致したら
        page = k;
      }
    }
    var type = list[1];
    var n = Number(list[2]) - 1;

    //しつこい気もするけどエロステータス開く時の軽さを最優先で
    var obj = this._CBR_eroSta_change_list[page][type];

    var objNum = false;
    for (var k = 0, len2 = obj.length; k < len2; k++) {
      //このページのchange数
      if (n == obj[k].num) {
        //nとチェンジしたい番号が一緒だったら
        objNum = k;
        break;
      }
    }
    if (objNum === false) {
      objNum = len2;
      obj[objNum] = {
        num: n,
        list: [],
      };
    }

    //変更したいパラメータ数だけ回す
    var chaList = obj[objNum].list;
    for (var k = 3, len2 = list.length; k + 1 < len2; k += 2) {
      var listNum = false;
      for (var m = 0, len3 = chaList.length; m < len3; m++) {
        //既に存在するチェンジ数
        if (list[k] == chaList[m].name) {
          //一致する箇所があるかどうか
          listNum = m;
          break;
        }
      }
      if (listNum === false) {
        //無かったら
        listNum = len3;
        for (var m = 0, len3 = checkList[type].length; m < len3; m++) {
          //ちゃんと項目通りかチェック
          if (list[k] == checkList[type][m]) {
            break;
          } else if (m + 1 == len3) {
            //もし無かったら
            alert("ERROR:CBR_eroSta_change引数");
          }
        }
      }
      list[k + 1] = this.CBR_eroSta_changeVal(list[k], list[k + 1]);
      chaList[listNum] = {
        name: list[k],
        val: list[k + 1],
      };
      CBR_eroStatus[page][type][n][list[k]] = list[k + 1];
    }
  }
};

//########### Scene ###########
function Scene_EroStatus() {
  this.initialize.apply(this, arguments);
}
Scene_EroStatus.prototype = Object.create(Scene_MenuBase.prototype);
Scene_EroStatus.prototype.constructor = Scene_EroStatus;

Scene_EroStatus.prototype.initialize = function () {
  Scene_MenuBase.prototype.initialize.call(this);
};
Scene_EroStatus.prototype.create = function () {
  Scene_MenuBase.prototype.create.call(this);
  if (CBR_eroStatusState.event) {
    $gameTemp.reserveCommonEvent(CBR_eroStatusState.event);
  }
  this._eroStatusWindow = new Window_EroStatus();
  this._eroStatusWindow.setHandler("cancel", this.popScene.bind(this));

  this._eroStatusWindow._margin = 0; //背景ピッチリする為
  this._eroStatusWindow.margin = 0; //本当はこっちだけどね
  this._eroStatusWindow._windowFrameSprite.visible = false; //枠線を消す

  this.addWindow(this._eroStatusWindow);
};

Scene_EroStatus.prototype.update = function () {
  $gameMap.refreshIfNeeded();
  if (this.isActive()) {
    $gameMap.updateInterpreter();
  }
  $gameMap.updateVehicles();

  Scene_Base.prototype.update.call(this);
};

//########### window ###########
function Window_EroStatus() {
  this.initialize.apply(this, arguments);
}

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

Window_EroStatus.prototype.initialize = function () {
  //windowを作る
  var width = Graphics.boxWidth;
  var height = Graphics.boxHeight;
  Window_Selectable.prototype.initialize.call(this, 0, 0, width, height);
  CBR_eroStatusState.now = 0;
  this._CBR_complete = false;
};

Window_EroStatus.prototype.CBR_complete = function () {
  //描写終わったかどうか
  return this._CBR_complete;
};

Window_EroStatus.prototype.update = function () {
  //毎回image描写してもいいけどそれだと負荷が多くなるのでこの方法で
  Window_Selectable.prototype.update.call(this);

  if (1 < CBR_eroStatusState.num.length && this.isOpenAndActive()) {
    //操作があった時
    if (Input.isRepeated("right") || Input.isRepeated("left")) {
      SoundManager.playCursor(2); //音楽鳴らす
      CBR_eroStatusState.now =
        CBR_eroStatusState.now + 1 < CBR_eroStatusState.num.length
          ? CBR_eroStatusState.now + 1
          : 0;
      this._CBR_complete = false; //初期化
      //this._statusWindow.refresh();//切り替えしたんでリフレッシュ
    }
  }

  var page = $gameSystem.CBR_eroSta_getPageIndex(
    CBR_eroStatusState.num[CBR_eroStatusState.now]
  );

  if (!this.CBR_complete()) {
    //まだ画像の描写してないのなら
    var flag = false;
    var ary = CBR_eroStatus[page].p;
    var p_data = [];
    //ピクチャの数だけ
    for (var i = 0, len = ary.length; i < len; i++) {
      var name = ary[i].name;
      if (!name || !ary[i].show) {
        continue;
      }
      name = name.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);
          }
        }
      );

      if (ary[i].var) {
        //変数があったら入れる
        var v = "" + $gameVariables.value(ary[i].var);
        if (ary[i].varDigit) {
          //2ケタの時は2まで
          if (v.length >= ary[i].varDigit) {
            name += v.substr(-1 * ary[i].varDigit, 1);
          } else {
            name = false;
          }
        } else {
          name += v;
        }
      }
      if (name) {
        var temp = ImageManager.loadPicture(name); //初回読み込み
        if (temp) {
          //if(temp._isLoading || temp._loadingState == 'requesting'){//前者は古いver用 ロード中ならアウト
          if (!temp.width) {
            //前者は古いver用 ロード中ならアウト
            flag = true;
            break;
          }
        } else {
          //その名前の画像が無かったら
          flag = true;
          this._CBR_complete = true;
          break;
        }
        p_data[i] = {
          w: temp.width,
          h: temp.height,
        };
      }
    }

    if (!flag) {
      //全ロードが終わってたら
      this.contents.clear();

      //ピクチャの表示
      var ary = CBR_eroStatus[page].p;
      for (var i = 0, len = ary.length; i < len; i++) {
        var name = ary[i].name;
        if (!name || !ary[i].show) {
          continue;
        }

        //変数とか文字化
        name = name.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);
            }
          }
        );

        if (name) {
          this.changePaintOpacity(ary[i].opacity);

          var x = ary[i].x;
          var y = ary[i].y;
          if (ary[i].origin == "center") {
            x -= (p_data[i].w * ary[i].zoom) / 2;
            y -= (p_data[i].h * ary[i].zoom) / 2;
          }
          this.drawPicture("pictures", name, 0, 0, x, y, 0, 0, ary[i].zoom, 0);
        }
      }

      //テキストの表示
      this.resetTextColor();
      var ary = CBR_eroStatus[page].t;
      for (var i = 0, len = ary.length; i < len; i++) {
        var size = ary[i].size; // ary[i].fontSize;
        var temp = ary[i].subject;
        if (!temp || !ary[i].show) {
          continue;
        }

        var opAry = temp.match(/(\\\{|\\\}|\\[CI]\[\d+\])+/g);

        //先頭にある場合は"","tesa"になる
        var strAry = temp.split(/(?:\\\{|\\\}|\\[CI]\[\d+\])+/);

        var str = "";
        var allW = 0;
        var maxSize = null;
        var dataFAry = [];
        var dataWAry = [];
        var drawI = [];
        var drawC = [];
        //分割した配列の数
        for (var k = 0, len2 = strAry.length; k < len2; k++) {
          //前方にある\{のフォントサイズを入れる
          dataFAry[k] = k ? dataFAry[k - 1] : 0;
          drawI[k] = [];

          //変数とか文字化
          strAry[k] = strAry[k].replace(
            /\\(\\)|\\([VNP])\[(\d+)\]|\\(G)|\\(<)(.+)\\>/g,
            function (a, b, c, d, e, f, g) {
              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 if (e) {
                //G
                return $dataSystem.currencyUnit;
              } else {
                //script
                return eval(g);
              }
            }
          );

          //自身の前に区切りマッチがあったら
          if (0 < k) {
            var temp = opAry[k - 1].split("\\"); //\\{\\}を分割する
            for (var m = 1, len3 = temp.length; m < len3; m++) {
              switch (temp[m].charAt(0)) {
                case "{":
                  dataFAry[k] += 6;
                  break;
                case "}":
                  dataFAry[k] -= 6;
                  break;
                case "C":
                  drawC[k] = Number(temp[m].match(/\[(\d+)\]/)[1]); //Cは複数あっても最後のが適応されれば良いわけで
                  break;
                case "I":
                  drawI[k][drawI[k].length] = Number(
                    temp[m].match(/\[(\d+)\]/)[1]
                  );
                  break;
              }
            }
          }
          this.contents.fontSize = size + dataFAry[k];
          this.contents.context.font = this.contents._makeFontNameText();
          dataWAry[k] = this.contents.context.measureText(strAry[k]).width; //何の為に+4するのか忘れた
          allW += dataWAry[k];

          if (strAry[k]) {
            //先頭に\{や変数がある時の問題　アイコン乃場合もここを通さないと
            if (maxSize === null) {
              //まだ記録されてなかったら入れよう
              maxSize = dataFAry[k];
            } else {
              maxSize = maxSize < dataFAry[k] ? dataFAry[k] : maxSize;
            }
          }
        }

        var x = ary[i].x;
        if (ary[i].origin == "center") {
          x -= allW / 2;
        } else if (ary[i].origin == "right") {
          x -= allW;
        }
        for (var k = 0, len2 = strAry.length; k < len2; k++) {
          this.contents.fontSize = size + dataFAry[k];
          this.contents.context.font = this.contents._makeFontNameText();
          //bottom→下揃え原点の上　top→上揃え原点の下　center→原点
          var line = ary[i].y;
          var iconLine = ary[i].y;
          if (ary[i].align == "top") {
            line += (size + dataFAry[k]) / 2;
          } else if (ary[i].align == "bottom") {
            line -= (size + dataFAry[k]) / 2;
            iconLine -= Window_Base._iconWidth;
          } else {
            iconLine -= Window_Base._iconWidth / 2;
          }
          if (drawI[k].length) {
            for (var m = 0, len3 = drawI[k].length; m < len3; m++) {
              this.drawIcon(drawI[k][m], x, iconLine);
              x += Window_Base._iconWidth;
            }
          }
          if (drawC[k] || drawC[k] === 0) {
            this.changeTextColor(this.textColor(drawC[k]));
          }
          this.contents.drawText(strAry[k], x, line, dataWAry[k], 0, "left");
          x += dataWAry[k];
        }
        this.contents.fontSize = this.standardFontSize();
      }
      this.resetTextColor();
      this.changePaintOpacity(true);

      this.activate();
      this._CBR_complete = true;
    }
  }
};

Window_EroStatus.prototype.drawPicture = function (
  dir,
  filename,
  sx,
  sy,
  x,
  y,
  w,
  h,
  zoom,
  hue
) {
  var bitmap = ImageManager.loadBitmap("img/" + dir + "/", filename, hue, true);
  this.contents.blt(
    bitmap,
    sx,
    sy,
    bitmap.width,
    bitmap.height,
    x,
    y,
    bitmap.width * zoom,
    bitmap.height * zoom
  );
};
Window_EroStatus.prototype.standardPadding = function () {
  return 0;
};
Window_Status.prototype.lineColor = function () {
  return this.normalColor();
};
Window_Status.prototype.maxEquipmentLines = function () {
  return 6;
};

//#########　コマンドの追加　##########
Scene_Menu.prototype.commandEroSta = function () {
  SceneManager.push(Scene_EroStatus);
};
setTimeout(function () {
  var _Scene_Menu_createCommandWindow =
    Scene_Menu.prototype.createCommandWindow;
  Scene_Menu.prototype.createCommandWindow = function () {
    _Scene_Menu_createCommandWindow.call(this);
    this._commandWindow.setHandler("eroStatus", this.commandEroSta.bind(this));
  };
}, 0);
_Window_MenuCommand_addOriginalCommands =
  Window_MenuCommand.prototype.addOriginalCommands;
Window_MenuCommand.prototype.addOriginalCommands = function () {
  _Window_MenuCommand_addOriginalCommands.call(this);
  this.addCommand(CBR_eroStatusState.name, "eroStatus", true);
};

repo_name: Idkwtcm/violated

license: unknown


code:
/*
##################################################
	作者: COBRA
	改造や配布しても大丈夫だよ
	寧ろ積極的に配布して皆のゲーム快適にしてあげて
	もし音信普通になったら誰でもいいから引き継いで
	http://cobrara.blogspot.jp/
	https://twitter.com/onarinin_san
##################################################
*/

/*:
 * @plugindesc 画像合成
 * @author COBRA
 * @help Version 1.0.0　2020/2/8
 * rpg_core.js v1.6.1に対応
 *
 *
 * 画像の名前に\V[n]で変数名も使えます
 * ピクチャを消去、セーブ→ロードしても効果は持続します
 *
 * イベントのスクリプトで実行してね
 * 合成する画像全て読み終えてから全て同時に描写されます
 *
 * ～合成したい時～
 *
 * CBR-画像合成　(これを1行目に書いてね)
 * <合成したい画像名.png>　(2行目に書いてね)
 * 追加したい画像名.png　(1行につき1つまでだよ)
 *
 *
 * ～解除したい時～
 *
 * CBR-画像合成
 * <解除したい画像名.png>　(これを1行目に書いてね)
 *
 *
 * おわり
 */

var CBR = CBR || {};
CBR.imgFusion = {};

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;
  };
}

//他の人がややこしくなるだろうからGame_Systemには追加したくない
CBR.imgFusion.key = function (name) {
  //後に何があるかわからないから.pngは残す
  var key = null;
  var ary = $gameSystem._CBR_imgFusion._fusionList;
  for (var i = 0, len = ary.length; i < len; i++) {
    if (ary[i].base == name) {
      key = i;
    }
  }
  return key;
};

//基画像、要素のロード完了後実行するヤツ
CBR.imgFusion.onLoad = function (e) {
  //ロード終わっても合成解除されてCBR_imgFusionが消されてたら
  if (!this.CBR_imgFusion) {
    this.clear();
    this._context.drawImage(this._image, 0, 0);
    return;
  }
  if (!CBR.imgFusion.check(this.CBR_imgFusion._name)) {
    //今後何があるかわらないから
    return;
  }
  this.clear();
  this._context.drawImage(this._image, 0, 0);
  //終わってた！画像描写するぞー！
  var key = CBR.imgFusion.key(this.CBR_imgFusion._name);
  var ary = $gameSystem._CBR_imgFusion._fusionList;
  for (var i = 0, len = ary[key].add_ary.length; i < len; i++) {
    var bitmap2 = ImageManager.loadBitmap(
      "img/pictures/",
      ary[key].add_ary[i].slice(0, -4),
      undefined,
      true
    );
    this.context.drawImage(bitmap2._image, 0, 0);
  }
  //オンロードしたらbitmapがキャッシュされるんで追加描写は前もって
  //キャッシュのbitmapはちゃんと変更されてる、だから消してまた読み込んだ時反映されてる
  //Game_Pictureにはアップデートがある picture.update();
  //もしロード終了後の流れだったら
  if (!this._loadingState) {
    this._loadingState = this._CBR_loadingState;
    this._renewCanvas = Bitmap.prototype._renewCanvas; //元に戻す
  }

  //ロード終了→オンロード→_renewCanvas内での実行だったらこれが終わった後オンロード実行される
  if (e) {
    this._renewCanvas();
  } else {
    Bitmap.prototype._onLoad.call(this);
    //もしピクチャが表示されてたらこの場でピクチャをリフレッシュ
    var temp = this.CBR_imgFusion._name.slice(0, -4);
    if (SceneManager._scene._spriteset) {
      for (var i = 1; i < 101; i++) {
        var temp2 = $gameScreen._pictures[i];
        //Game_Pictureがあったら
        if (temp2 && temp == temp2._name) {
          //ピクチャスプライトをリフレッシュする
          SceneManager._scene._spriteset._pictureContainer.children[
            i - 1
          ]._refresh();
          this._baseTexture.update(); //リフレッシュしたらbitmapのベーステクスチャもアップデートする事。リフレッシュの挙動的に
          break;
        }
      }
    }
  }
};

//その名前の要素が全部読み込めてるかどうか できてたらtrue
CBR.imgFusion.check = function (name) {
  var key = CBR.imgFusion.key(name);
  var temp = true;
  var ary = $gameSystem._CBR_imgFusion._fusionList;
  if (key !== null) {
    for (var i = 0, len = ary[key].add_ary.length; i < len; i++) {
      //素材読みこむよー
      var bitmap = ImageManager.loadBitmap(
        "img/pictures/",
        ary[key].add_ary[i].slice(0, -4),
        undefined,
        true
      );
      //終わってなかったよ
      if (bitmap._loadingState != "loaded") {
        //素材のロード終わったら実行する奴
        bitmap._CBR_imgFusion_parent = name;
        var test = function () {
          //普通にロード終わったよ
          Bitmap.prototype._onLoad.call(this);
          //ベース画像を読みこむ
          var bitmap = ImageManager.loadBitmap(
            "img/pictures/",
            this._CBR_imgFusion_parent.slice(0, -4),
            undefined,
            true
          );
          //そしてオンロード オンロードはloadでバインドしたものとは別物だからダメ
          bitmap.CBR_imgFusion_load();
        };
        bitmap._image.removeEventListener("load", bitmap._loadListener);
        bitmap._image.addEventListener(
          "load",
          (bitmap._loadListener = test.bind(bitmap))
        );
        //ダメだったよ
        temp = false;
        break;
      }
    }
  }
  return temp;
};

var _CBRimgFusion_Game_System_initialize = Game_System.prototype.initialize;
Game_System.prototype.initialize = function () {
  _CBRimgFusion_Game_System_initialize.call(this);

  this._CBR_imgFusion = {};
  this._CBR_imgFusion._fusionList = [];
};

var _CBRimgFusion_ImageManager_loadPicture = ImageManager.loadPicture;
ImageManager.loadPicture = function (filename, hue) {
  //フュージョンに同じものあるかな？
  var temp = false;
  for (
    var i = 0, len = $gameSystem._CBR_imgFusion._fusionList.length;
    i < len;
    i++
  ) {
    if ($gameSystem._CBR_imgFusion._fusionList[i].base == filename + ".png") {
      temp = true;
      break;
    }
  }

  //あったー
  if (temp) {
    //bitmap初期設定
    var bitmap = this.loadBitmap("img/pictures/", filename, hue, true);
    //ロード時、systemには残ってるけどbitmapは初期化されてしまってるとき
    if (!bitmap.CBR_imgFusion) {
      bitmap.CBR_imgFusion = {};
      bitmap.CBR_imgFusion._name = filename + ".png";
      bitmap.CBR_imgFusion_load = CBR.imgFusion.onLoad;

      //基画像がロード中だったらロード終わった後に実行させないとね
      //ロード済みだったら合成しちゃお
      if (
        bitmap._loadingState == "requesting" ||
        bitmap._loadingState == "decrypting"
      ) {
        //ロード終わったらload()実行させないとね！
        bitmap._renewCanvas = function () {
          this._CBR_loadingState = this._loadingState;
          this._loadingState = null;
          this.CBR_imgFusion_load(true);
          return;
        };
      }
    }

    if (bitmap._loadingState == "loaded") {
      bitmap.CBR_imgFusion_load(); //とりあえず更新
    }
    return bitmap;
  } else {
    return _CBRimgFusion_ImageManager_loadPicture.call(this, filename, hue);
  }
};

//合成するぞー
CBR["画像合成"] = function (ary) {
  //ベースと要素の変数を実行
  for (var i = 0, len = ary.length; i < len; i++) {
    ary[i] = ary[i].replace(/\\V\[(\d+)\]/g, function (a, b) {
      //汚いけどこれは毎回やらないとね
      return $gameVariables.value(b); //律儀にNumberしなくてもいいか
    });
  }

  var base = ary.shift().slice(1, -1);
  var key = CBR.imgFusion.key(base);

  //同じベース画像だったら上書きする
  if (key === null) {
    key = $gameSystem._CBR_imgFusion._fusionList.length;
  }
  $gameSystem._CBR_imgFusion._fusionList[key] = {
    base: base,
    add_ary: ary,
  };

  var bitmap = ImageManager.loadBitmap(
    "img/pictures/",
    base.slice(0, -4),
    undefined,
    true
  );

  //初期設定
  bitmap.CBR_imgFusion = {};
  bitmap.CBR_imgFusion._name = base;
  //コレや素材の読み込みが終わったら実行するヤツ
  bitmap.CBR_imgFusion_load = CBR.imgFusion.onLoad;

  //ロード済みだったら合成しちゃお
  if (bitmap._loadingState == "loaded") {
    //ベースがピクチャとして表示されてなかったら隠す
    var temp = base.slice(0, -4);
    if (SceneManager._scene._spriteset) {
      for (var i = 1; i < 101; i++) {
        var temp2 = $gameScreen._pictures[i];
        //Game_Pictureがあったら
        if (temp2 && temp == temp2._name) {
          break;
        }
      }
      if (i == 101) {
        bitmap.clear();
      }
    }
    bitmap.CBR_imgFusion_load();
    //ロード・解読中だったら
  } else if (
    bitmap._loadingState == "requesting" ||
    bitmap._loadingState == "decrypting"
  ) {
    //ロード終わったらload()実行させないとね！
    bitmap._renewCanvas = function () {
      this._CBR_loadingState = this._loadingState;
      this._loadingState = null;
      this.CBR_imgFusion_load(true);
      return;
    };
  }
};


code:
//=============================================================================
// CharacterPopupDamage.js
// ----------------------------------------------------------------------------
// (C) 2016 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.6.1 2019/04/20 ダメージが0だった場合の表記を「MISS」から「0」に変更
// 1.6.0 2018/11/11 プラグインの型指定機能に対応
//                  ポップアップ効果音を消音できるスイッチを追加
// 1.5.1 2017/11/10 コピペミスによる誤記を修正
// 1.5.0 2017/04/23 ポップアップ時にキャラクターをフラッシュさせる機能を追加
// 1.4.0 2017/03/03 ピクチャより前面にポップアップできる設定を追加
//                  回転がない場合でも拡大率を自由に変更できるよう修正
// 1.3.0 2017/01/23 スリップダメージのポップアップに対応
//                  対応するフォロワーのポップアップを表示する機能を追加
// 1.2.0 2016/12/31 ポップアップの色調設定機能を追加
//                  ポップアップの表示方法を詳細指定できる機能を追加
// 1.1.1 2016/09/15 最新の修正で自動ポップアップの設定が手動に影響していた問題を修正
// 1.1.0 2016/09/14 MPダメージ用に専用効果音を指定できる機能を追加
//                  HP、MP、TP、増加、減少の条件で個別に出力可否を設定できる機能を追加
// 1.0.3 2016/09/10 VE_BasicModule.jsとの競合を解消
// 1.0.2 2016/04/17 ポップアップ無効化のプラグインコマンドが機能していなかった問題を修正
// 1.0.1 2016/04/10 HPの増減との連動で増やすと減らすが逆に解釈されていたのを修正
// 1.0.0 2016/04/09 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc キャラクターのダメージポッププラグイン
 * @author トリアコンタン
 *
 * @param 効果音演奏
 * @desc 状況に応じたシステム効果音を自動演奏します。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param 消音スイッチID
 * @desc 指定したIDのスイッチがONになっているとき、システム効果音が自動演奏されなくなります。
 * @default 0
 * @type switch
 *
 * @param X座標補正
 * @desc ポップアップ位置のX座標を補正します。
 * @default 0
 *
 * @param Y座標補正
 * @desc ポップアップ位置のY座標を補正します。
 * @default 0
 *
 * @param HP自動ポップアップ
 * @desc HPの増減を自動ポップアップの対象にします。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param MP自動ポップアップ
 * @desc MPの増減を自動ポップアップの対象にします。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param TP自動ポップアップ
 * @desc TPの増減を自動ポップアップの対象にします。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param 増加自動ポップアップ
 * @desc パラメータの増加を自動ポップアップの対象にします。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param 減少自動ポップアップ
 * @desc パラメータの減少を自動ポップアップの対象にします。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param MPダメージ音
 * @desc MPダメージ時の効果音ファイル名を別途指定(audio/se)します。何も指定しないとHPと同じになります。
 * @default
 *
 * @param 回転
 * @desc 数字の回転運動を有効にします。
 * @default true
 * @type boolean
 *
 * @param X方向半径
 * @desc 数字を回転させる場合のX方向の半径です。
 * @default 40
 *
 * @param Y方向半径
 * @desc 数字を回転させる場合のY方向の半径です。
 * @default 40
 *
 * @param 回転速度
 * @desc 数字を回転させる場合の速度です。
 * @default 60
 *
 * @param 拡大率
 * @desc 初期状態の拡大率です。
 * @default 100
 *
 * @param 拡大率変化値
 * @desc 1フレームごとの拡大率の変化値です。
 * @default -10
 *
 * @param 最前面表示
 * @desc ポップアップをピクチャより前面に表示します。
 * @default false
 * @type boolean
 *
 * @help マップ画面でイベントやプレイヤーに数字をポップアップさせる機能を提供します。
 * マップ上でのダメージや回復の演出に利用できます。演出は戦闘時のものと同一です。
 * 指定する値をマイナスにすると回復扱いとなり色が変わります。
 * また、クリティカルにすると数字の色が一瞬、赤くなります。
 *
 * また「HPの増減」等のイベント実行時に自動で変化量をポップアップする機能や、
 * ダメージ床を通過した際に自動でポップアップする機能も用意されています。
 * パラメータにより、HPのみや増加のみといった条件指定もできます。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * ・CPD_DAMAGE or ポップアップダメージ [キャラクターID] [ダメージ値] [反転]
 * キャラクターを指定してダメージをポップアップします。
 * キャラクターの指定は以下の通りです。
 * -1   : プレイヤー
 *  0   : 実行中のイベント
 *  1.. : 指定したIDのイベント
 *
 * 反転を有効にすると、ポップアップの回転方向が逆になります。
 * （パラメータの「回転」を有効にしている場合）
 *
 * CPD_DAMAGE 5 -300 ON
 * ポップアップダメージ 0 \v[1] OFF
 *
 * ・CPD_CRITICAL or ポップアップクリティカル
 * キャラクターを指定してダメージをクリティカル扱いでポップアップします。
 *
 * CPD_CRITICAL -1 100 ON
 * ポップアップクリティカル 3 \v[1] OFF
 *
 * ・CPD_MP_DAMAGE or ポップアップMPダメージ
 * キャラクターを指定してMPダメージをポップアップします。
 *
 * CPD_MP_DAMAGE 5 -300 ON
 * ポップアップMPダメージ 0 \v[1] OFF
 *
 * ・CPD_MP_CRITICAL or ポップアップMPクリティカル
 * キャラクターを指定してMPダメージをクリティカル扱いでポップアップします。
 *
 * CPD_MP_CRITICAL -1 100 ON
 * ポップアップMPクリティカル 3 \v[1] OFF
 *
 * ・CPD_MISS or ポップアップミス
 * キャラクターを指定してmissをポップアップします。
 *
 * CPD_MISS -1 ON
 * ポップアップミス 3 OFF
 *
 * ・CPD_INVALID or ポップアップ無効化
 * 自動ポップアップを無効にします。
 * 有効になっているとイベントコマンド「HPの増減」「MPの増減」「TPの増減」
 * およびダメージ床によるダメージが自動でポップアップします。
 * 初期状態では有効です。
 *
 * ・CPD_VALID or ポップアップ有効化
 * 自動ポップアップを再度有効にします。
 *
 * ・CPD_SETTING_TONE or ポップアップ設定_色調 [赤] [緑] [青] [グレー]
 * ポップアップ画像の色調を変更できます。色調の設定値を順番に指定してください。
 *
 * CPD_SETTING_TONE 255 0 0 255
 * ポップアップ設定_色調 -255 -255 -255 0
 *
 * ・CPD_SETTING_FLASH or ポップアップ設定_フラッシュ [赤] [緑] [青] [強さ]
 * ポップアップ時にキャラクターをフラッシュします。
 * フラッシュするのはダメージを受けた場合のみです。
 *
 * CPD_SETTING_FLASH 255 0 0 255
 * ポップアップ設定_フラッシュ 255 0 0 255
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  var pluginName = "CharacterPopupDamage";
  var settings = {
    /* MPダメージ専用効果音(ファイル名はパラメータで指定) */
    mpDamageSe: {
      volume: 90,
      pitch: 100,
      pan: 0,
    },
  };

  var getCommandName = function (command) {
    return (command || "").toUpperCase();
  };

  var getParamBoolean = function (paramNames) {
    var value = getParamOther(paramNames);
    return (
      (value || "").toUpperCase() === "ON" ||
      (value || "").toUpperCase() === "TRUE"
    );
  };

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

  var getParamString = function (paramNames) {
    var value = getParamOther(paramNames);
    return value === null ? "" : value;
  };

  var getParamOther = 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 null;
  };

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

  var getArgBoolean = function (arg) {
    return (arg || "").toUpperCase() === "ON";
  };

  var convertEscapeCharactersAndEval = function (text, evalFlg) {
    if (text === null || text === undefined) text = "";
    var window = SceneManager._scene._windowLayer.children[0];
    if (window) {
      var result = window.convertEscapeCharacters(text);
      return evalFlg ? eval(result) : result;
    } else {
      return text;
    }
  };

  //=============================================================================
  // パラメータの取得と整形
  //=============================================================================
  var paramPlaySe = getParamBoolean(["PlaySe", "効果音演奏"]);
  var paramSuppressSwitchId = getParamNumber(
    ["SuppressSwitchId", "消音スイッチID"],
    0
  );
  var paramOffsetX = getParamNumber(["OffsetX", "X座標補正"]);
  var paramOffsetY = getParamNumber(["OffsetY", "Y座標補正"]);
  var paramTpAutoPop = getParamBoolean(["TPAutoPop", "TP自動ポップアップ"]);
  var paramMpAutoPop = getParamBoolean(["MPAutoPop", "MP自動ポップアップ"]);
  var paramHpAutoPop = getParamBoolean(["HPAutoPop", "HP自動ポップアップ"]);
  var paramIncreaseAutoPop = getParamBoolean([
    "IncreaseAutoPop",
    "増加自動ポップアップ",
  ]);
  var paramDecreaseAutoPop = getParamBoolean([
    "DecreaseAutoPop",
    "減少自動ポップアップ",
  ]);
  var paramMpDamageSe = getParamString(["MPDamageSe", "MPダメージ音"]);
  var paramRotation = getParamBoolean(["Rotation", "回転"]);
  var paramRadiusX = getParamNumber(["RadiusX", "X方向半径"]);
  var paramRadiusY = getParamNumber(["RadiusY", "Y方向半径"]);
  var paramRotateSpeed = getParamNumber(["RotateSpeed", "回転速度"]);
  var paramScale = getParamNumber(["Scale", "拡大率"]);
  var paramScaleDelta = getParamNumber(["ScaleDelta", "拡大率変化値"]);
  var paramOnTop = getParamBoolean(["OnTop", "最前面表示"]);

  //=============================================================================
  // Game_Interpreter
  //  プラグインコマンドを追加定義します。
  //=============================================================================
  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.apply(this, arguments);
    this.pluginCommandCharacterPopupDamage(command, args);
  };

  Game_Interpreter.prototype.pluginCommandCharacterPopupDamage = function (
    command,
    args
  ) {
    var popupArgs = [];
    switch (getCommandName(command)) {
      case "CPD_DAMAGE":
      case "ポップアップダメージ":
        popupArgs = [getArgNumber(args[1]), false, getArgBoolean(args[2])];
        this.callCharacterPopup(args, "popupDamage", popupArgs);
        break;
      case "CPD_CRITICAL":
      case "ポップアップクリティカル":
        popupArgs = [getArgNumber(args[1]), true, getArgBoolean(args[2])];
        this.callCharacterPopup(args, "popupDamage", popupArgs);
        break;
      case "CPD_MP_DAMAGE":
      case "ポップアップMPダメージ":
        popupArgs = [getArgNumber(args[1]), false, getArgBoolean(args[2])];
        this.callCharacterPopup(args, "popupMpDamage", popupArgs);
        break;
      case "CPD_MP_CRITICAL":
      case "ポップアップMPクリティカル":
        popupArgs = [getArgNumber(args[1]), true, getArgBoolean(args[2])];
        this.callCharacterPopup(args, "popupMpDamage", popupArgs);
        break;
      case "CPD_MISS":
      case "ポップアップミス":
        popupArgs = [getArgBoolean(args[1])];
        this.callCharacterPopup(args, "popupMiss", popupArgs);
        break;
      case "CPD_VALID":
      case "ポップアップ有効化":
        $gameSystem.setSuppressAutoPopup(false);
        break;
      case "CPD_INVALID":
      case "ポップアップ無効化":
        $gameSystem.setSuppressAutoPopup(true);
        break;
      case "CPD_SETTING_TONE":
      case "ポップアップ設定_色調":
        var red = getArgNumber(args[0]);
        var green = getArgNumber(args[1]);
        var blue = getArgNumber(args[2]);
        var gray = getArgNumber(args[3]);
        $gameSystem.setPopupDamageTone([red, green, blue, gray]);
        break;
      case "CPD_SETTING_FLASH":
      case "ポップアップ設定_フラッシュ":
        var flashRed = getArgNumber(args[0], 0);
        var flashGreen = getArgNumber(args[1], 0);
        var flashBlue = getArgNumber(args[2], 0);
        var alpha = getArgNumber(args[3], 0) || 255;
        $gameSystem.setPopupDamageFlash([
          flashRed,
          flashGreen,
          flashBlue,
          alpha,
        ]);
        break;
    }
  };

  var _Game_Interpreter_command311 = Game_Interpreter.prototype.command311;
  Game_Interpreter.prototype.command311 = function () {
    var value = -this.operateValue(
      this._params[2],
      this._params[3],
      this._params[4]
    );
    this.iterateActorEx(
      this._params[0],
      this._params[1],
      function (actor) {
        actor.popupDamage(value);
      }.bind(this)
    );
    return _Game_Interpreter_command311.apply(this, arguments);
  };

  var _Game_Interpreter_command312 = Game_Interpreter.prototype.command312;
  Game_Interpreter.prototype.command312 = function () {
    var value = -this.operateValue(
      this._params[2],
      this._params[3],
      this._params[4]
    );
    this.iterateActorEx(
      this._params[0],
      this._params[1],
      function (actor) {
        actor.popupMpDamage(value);
      }.bind(this)
    );
    return _Game_Interpreter_command312.apply(this, arguments);
  };

  var _Game_Interpreter_command326 = Game_Interpreter.prototype.command326;
  Game_Interpreter.prototype.command326 = function () {
    var value = -this.operateValue(
      this._params[2],
      this._params[3],
      this._params[4]
    );
    this.iterateActorEx(
      this._params[0],
      this._params[1],
      function (actor) {
        actor.popupTpDamage(value);
      }.bind(this)
    );
    return _Game_Interpreter_command326.apply(this, arguments);
  };

  Game_Interpreter.prototype.callCharacterPopup = function (
    args,
    methodName,
    extend
  ) {
    var character = this.character(getArgNumber(args[0], -1));
    if (character) character[methodName].apply(character, extend);
  };

  //=============================================================================
  // Game_Actor
  //  ダメージ床によるポップアップを処理します。
  //=============================================================================
  var _Game_Actor_executeFloorDamage = Game_Actor.prototype.executeFloorDamage;
  Game_Actor.prototype.executeFloorDamage = function () {
    this.popupMapDamage(_Game_Actor_executeFloorDamage);
  };

  var _Game_Actor_turnEndOnMap = Game_Actor.prototype.turnEndOnMap;
  Game_Actor.prototype.turnEndOnMap = function () {
    this.popupMapDamage(_Game_Actor_turnEndOnMap);
  };

  Game_Actor.prototype.popupMapDamage = function (callBackFunc) {
    var prevHp = this.hp;
    var prevMp = this.mp;
    var prevTp = this.tp;
    callBackFunc.apply(this);
    var character = this.getCharacterObject();
    if (!character) return;
    var hpDamage = prevHp - this.hp;
    if (hpDamage !== 0 && $gameSystem.isNeedAutoHpPopup(hpDamage))
      character.popupDamage(hpDamage, false);
    var mpDamage = prevMp - this.mp;
    if (mpDamage !== 0 && $gameSystem.isNeedAutoMpPopup(mpDamage))
      character.popupMpDamage(mpDamage, false);
    var tpDamage = prevTp - this.tp;
    if (tpDamage !== 0 && $gameSystem.isNeedAutoTpPopup(tpDamage))
      character.popupDamage(tpDamage, false);
  };

  Game_Actor.prototype.popupDamage = function (value) {
    var character = this.getCharacterObject();
    if (!character) return;
    if (value !== 0 && $gameSystem.isNeedAutoHpPopup(value)) {
      character.popupDamage(value, false);
    }
  };

  Game_Actor.prototype.popupMpDamage = function (value) {
    var character = this.getCharacterObject();
    if (!character) return;
    if (value !== 0 && $gameSystem.isNeedAutoMpPopup(value)) {
      character.popupMpDamage(value, false);
    }
  };

  Game_Actor.prototype.popupTpDamage = function (value) {
    var character = this.getCharacterObject();
    if (!character) return;
    if (value !== 0 && $gameSystem.isNeedAutoTpPopup(value)) {
      character.popupDamage(value, false);
    }
  };

  Game_Actor.prototype.getCharacterObject = function () {
    var index = $gameParty.battleMembers().indexOf(this);
    var result;
    switch (index) {
      case -1:
        result = null;
        break;
      case 0:
        result = $gamePlayer;
        break;
      default:
        var followers = $gamePlayer.followers();
        result = followers.isVisible() ? followers.follower(index - 1) : null;
    }
    return result;
  };

  //=============================================================================
  // Game_System
  //  オートポップアップの有効フラグを追加定義します。
  //=============================================================================
  var _Game_System_initialize = Game_System.prototype.initialize;
  Game_System.prototype.initialize = function () {
    _Game_System_initialize.apply(this, arguments);
    this._suppressAutoPopup = false;
    this._popupDamageTone = null;
    this._popupDamageFlash = null;
  };

  Game_System.prototype.setSuppressAutoPopup = function (value) {
    this._suppressAutoPopup = !!value;
  };

  Game_System.prototype.isSuppressAutoPopup = function () {
    return this._suppressAutoPopup;
  };

  Game_System.prototype.isNeedAutoHpPopup = function (value) {
    return paramHpAutoPop && this.isNeedAutoPopup(value);
  };

  Game_System.prototype.isNeedAutoMpPopup = function (value) {
    return paramMpAutoPop && this.isNeedAutoPopup(value);
  };

  Game_System.prototype.isNeedAutoTpPopup = function (value) {
    return paramTpAutoPop && this.isNeedAutoPopup(value);
  };

  Game_System.prototype.isNeedAutoPopup = function (value) {
    return (
      !$gameSystem.isSuppressAutoPopup() &&
      ((paramIncreaseAutoPop && value < 0) ||
        (paramDecreaseAutoPop && value > 0))
    );
  };

  Game_System.prototype.getPopupDamageTone = function () {
    return this._popupDamageTone;
  };

  Game_System.prototype.setPopupDamageTone = function (value) {
    this._popupDamageTone = value;
  };

  Game_System.prototype.getPopupDamageFlash = function () {
    return this._popupDamageFlash;
  };

  Game_System.prototype.setPopupDamageFlash = function (value) {
    this._popupDamageFlash = value;
  };

  //=============================================================================
  // Game_CharacterBase
  //  ダメージ情報を保持します。
  //=============================================================================
  Game_CharacterBase.prototype.popupDamage = function (
    value,
    critical,
    mirror
  ) {
    this.startDamagePopup(value, critical, false, mirror);
  };

  Game_CharacterBase.prototype.popupMpDamage = function (
    value,
    critical,
    mirror
  ) {
    this.startDamagePopup(value, critical, true, mirror);
  };

  Game_CharacterBase.prototype.popupMiss = function (mirror) {
    this.startDamagePopup(null, false, mirror);
  };

  Game_CharacterBase.prototype.isDamagePopupRequested = function () {
    return this._damagePopup;
  };

  Game_CharacterBase.prototype.clearDamagePopup = function () {
    if (!this._damageInfo || this._damageInfo.length === 0) {
      this._damagePopup = false;
    }
  };

  Game_CharacterBase.prototype.startDamagePopup = function (
    value,
    critical,
    mpFlg,
    mirror
  ) {
    this._damagePopup = true;
    if (!this._damageInfo) this._damageInfo = [];
    var damageInfo = {
      value: value,
      critical: critical,
      mpFlg: mpFlg,
      mirror: mirror,
    };
    if (this.isPlayPopupSe()) {
      this.playPopupSe(damageInfo);
    }
    this._damageInfo.push(damageInfo);
  };

  Game_CharacterBase.prototype.playPopupSe = function (damageInfo) {
    if (damageInfo.value === null) {
      SoundManager.playMiss();
    } else if (damageInfo.value < 0) {
      SoundManager.playRecovery();
    } else if (damageInfo.mpFlg && paramMpDamageSe) {
      settings.mpDamageSe.name = paramMpDamageSe;
      AudioManager.playStaticSe(settings.mpDamageSe);
    } else if (this === $gamePlayer) {
      SoundManager.playActorDamage();
    } else {
      SoundManager.playEnemyDamage();
    }
  };

  Game_CharacterBase.prototype.shiftDamageInfo = function () {
    return this._damageInfo ? this._damageInfo.shift() : null;
  };

  Game_CharacterBase.prototype.isPlayPopupSe = function () {
    return paramPlaySe && !$gameSwitches.value(paramSuppressSwitchId);
  };

  //=============================================================================
  // Sprite_Character
  //  ダメージをポップアップします。
  //=============================================================================
  var _Sprite_Character_update = Sprite_Character.prototype.update;
  Sprite_Character.prototype.update = function () {
    _Sprite_Character_update.apply(this, arguments);
    this.updateDamagePopup();
  };

  Sprite_Character.prototype.updateDamagePopup = function () {
    this.setupDamagePopup();
    if (this._damages && this._damages.length > 0) {
      for (var i = 0; i < this._damages.length; i++) {
        this._damages[i].update();
      }
      if (!this._damages[0].isPlaying()) {
        this.getPopupParent().removeChild(this._damages[0]);
        this._damages.shift();
      }
    }
    if (this._popupFlash) {
      this.updateDamagePopupFlash();
    }
  };

  Sprite_Character.prototype.updateDamagePopupFlash = function () {
    this.setBlendColor(this._popupFlash);
    this._popupFlash[3] -= this._popupFlashSpeed;
    if (this._popupFlash[3] <= 0) {
      this._popupFlash = null;
      this._popupFlashSpeed = 0;
    }
  };

  Sprite_Character.prototype.setupDamagePopup = function () {
    if (!this._character.isDamagePopupRequested()) return;
    var sprite = new Sprite_CharacterDamage();
    sprite.x = this.x + this.damageOffsetX();
    sprite.y = this.y + this.damageOffsetY();
    if (!sprite.z) sprite.z = 9;
    sprite.setupCharacter(this._character);
    if (!this._damages) this._damages = [];
    this._damages.push(sprite);
    this.getPopupParent().addChild(sprite);
    this._character.clearDamagePopup();
    if (!sprite.isMiss() && !sprite.isRecover()) {
      this.setupDamagePopupFlash();
    }
  };

  Sprite_Character.prototype.setupDamagePopupFlash = function () {
    var flashColor = $gameSystem.getPopupDamageFlash();
    if (!flashColor) return;
    this._popupFlash = flashColor.clone();
    this._popupFlashSpeed = Math.floor(this._popupFlash[3] / 30);
    this.updateDamagePopupFlash();
  };

  Sprite_Character.prototype.damageOffsetX = function () {
    return paramOffsetX;
  };

  Sprite_Character.prototype.damageOffsetY = function () {
    return paramOffsetY;
  };

  Sprite_Character.prototype.getPopupParent = function () {
    return paramOnTop ? this.parent.parent.parent : this.parent;
  };

  //=============================================================================
  // Sprite_CharacterDamage
  //  ダメージ情報を受け取ってセットアップします。
  //=============================================================================
  function Sprite_CharacterDamage() {
    this.initialize.apply(this, arguments);
  }

  Sprite_CharacterDamage.prototype = Object.create(Sprite_Damage.prototype);
  Sprite_CharacterDamage.prototype.constructor = Sprite_CharacterDamage;

  Sprite_CharacterDamage.prototype.setupCharacter = function (character) {
    var damageInfo = character.shiftDamageInfo();
    this._toneColor = $gameSystem.getPopupDamageTone();
    this._mirror = damageInfo.mirror;
    this._damageInfo = damageInfo;
    this._digit = 0;
    if (this.isMiss()) {
      this.createMissForCharacter();
    } else {
      this.createDigits(damageInfo.mpFlg ? 2 : 0, damageInfo.value);
    }
    if (damageInfo.critical) {
      this.setupCriticalEffect();
    }
  };

  Sprite_CharacterDamage.prototype.isMiss = function () {
    return this._damageInfo.value === null;
  };

  Sprite_CharacterDamage.prototype.isRecover = function () {
    return this._damageInfo.value < 0;
  };

  Sprite_CharacterDamage.prototype.createMissForCharacter = function () {
    var w = this.digitWidth();
    var h = this.digitHeight();
    var sprite = this.createChildSprite();
    sprite.setFrame(0, 4 * h, 4 * w, h);
    sprite.dy = 0;
    sprite.x = w / 2;
    sprite.digit++;
    this._digit++;
  };

  Sprite_CharacterDamage.prototype.createChildSprite = function () {
    var sprite = Sprite_Damage.prototype.createChildSprite.apply(
      this,
      arguments
    );
    sprite.frame = 0;
    sprite.digit = this._digit++;
    if (this._toneColor) sprite.setColorTone(this._toneColor);
    return sprite;
  };

  Sprite_CharacterDamage.prototype.updateChild = function (sprite) {
    if (paramRotation) {
      this.updateChildRotation(sprite);
      sprite.setBlendColor(this._flashColor);
    } else {
      Sprite_Damage.prototype.updateChild.apply(this, arguments);
      sprite.x = 0;
    }
    if (paramScale) {
      this.updateChildScale(sprite);
    }
    sprite.frame++;
  };

  Sprite_CharacterDamage.prototype.updateChildRotation = function (sprite) {
    var frame = sprite.frame;
    var speed = (frame / 3600) * paramRotateSpeed;
    sprite.rx = paramRadiusX * (Math.cos(speed) - 1);
    sprite.ry = -paramRadiusY * Math.sin(speed);
    if (this._mirror) {
      sprite.rx *= -1;
    }
    sprite.x = Math.round(sprite.rx);
    sprite.y = Math.round(sprite.ry);
  };

  Sprite_CharacterDamage.prototype.updateChildScale = function (sprite) {
    var frame = sprite.frame;
    var scale = (paramScale + (frame * paramScaleDelta) / 10) / 100;
    sprite.scale.x = scale;
    sprite.scale.y = scale;
    sprite.x +=
      (sprite.digit - (this._digit - 1) / 2) * (this.digitWidth() * scale);
  };
})();