code:
//=============================================================================
// MPP_MessageEX_Op1.js
//=============================================================================
// Copyright (c) 2021 Mokusei Penguin
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @target MV MZ
 * @plugindesc Add functions related to the name window and face graphic window to the text display.
 * @author Mokusei Penguin
 * @url
 *
 * @base MPP_MessageEX
 * @orderAfter MPP_MessageEX
 *
 * @help [version 1.1.0]
 * This plugin is for RPG Maker MV and MZ.
 *
 * ▼ [Display text] control characters
 *  - The following applies if it is included in the text
 *   \NW[S]        # Display string S in name window
 *   \NC[n]        # Change the text color of the name window to n
 *   \FL           # Face graphic on the left(※1)
 *   \FR           # Face graphic on the right(※1)
 *   \FM           # Flip face graphic left and right(※1)
 *   \FW           # Display face graphic in a separate window(※1)
 *
 *  - All control characters can be in either case
 *
 * ▼ Control character details
 *  ※1: \FL, \FR, \FM, \FW (Face graphic related)
 *   - These control characters can be used in combination.
 *   - If the head is F, the order after that is appropriate and OK.
 *       Example: \FRM
 *                  => Face graphic is displayed flipped to the right
 *                \FWR
 *                  => Show face graphic window on the right
 *
 * ▼ Plugin command details
 *  - In MV, the variable N is referred to by writing v [N] in the item for
 *    inputting a numerical value.
 *  - In MZ, in the item to enter a numerical value, select the text and
 *    write v [N] to refer to the variable N.
 *
 *  〇 MV / MZ
 *
 *  〇 SetSpeakerName name  / speakerName
 *       name : Not set and hidden
 *   - Change the name displayed in the Name window.
 *   - Differences from \NW[s] apply from using this command until a different
 *     name is set for this command or \NW[s].
 *   - You can also use control commands such as \RB[S,R], display icons and
 *     item names.
 *   - Due to the specifications of the plug-in command, spaces cannot be used.
 *     (MV only)
 *   - If you want to use whitespace, use the \SET[n] command.
 *   - We do not recommend using this command with RPG Maker MZ.
 *
 * ================================
 * Mail : wood_penguin＠yahoo.co.jp (＠ is half-width)
 * Blog : http://woodpenguin.blog.fc2.com/
 * License : MIT license
 *
 * @command speakerName
 * @desc
 *
 * @arg name
 * @desc
 * @default
 *
 *
 * @param Name Window
 * @desc
 * @type struct<NameWindow>
 * @default {"Offset X":"0","Offset Y":"0","Padding":"12","Offset Line Spacing":"0","Windowskin":"Window","Default Color":"0","Font Size":"","Ruby Color":"255,255,255","Always Leave Ruby Height":"false"}
 *
 * @param Face Window
 * @desc
 * @type struct<FaceWindow>
 * @default {"Offset X":"0","Offset Y":"0","Padding":"12","Windowskin":"Window"}
 *
 */

/*~struct~NameWindow:
 * @param Offset X
 * @desc
 * @type number
 * @min -3000
 * @default 0
 *
 * @param Offset Y
 * @desc
 * @type number
 * @min -3000
 * @default -56
 *
 * @param Padding
 * @desc
 * @type number
 * @default 12
 *
 * @param Offset Line Spacing
 * @desc
 * @type number
 * @min -999
 * @default 0
 *
 * @param Windowskin
 * @desc
 * @type file
 * @require 1
 * @dir img/system
 * @default Window
 *
 * @param Default Color
 * @desc Specified by color number
 * @type number
 * @default 0
 *
 * @param Font Size
 * @desc Default value if not set
 * (Default: MV=28, MZ=26)
 * @type number
 * @min 4
 * @default
 *
 * @param Ruby Color
 * @desc Not set and always the same as the text color
 * @default 255,255,255
 *
 * @param Always Leave Ruby Height
 * @desc
 * @type boolean
 * @default false
 *
 */

/*~struct~FaceWindow:
 * @param Offset X
 * @desc
 * @type number
 * @default 0
 *
 * @param Offset Y
 * @desc
 * @type number
 * @default 0
 *
 * @param Padding
 * @desc
 * @type number
 * @default 12
 *
 * @param Windowskin
 * @desc
 * @type file
 * @require 1
 * @dir img/system
 * @default Window
 */

/*:ja
 * @target MV MZ
 * @plugindesc 文章の表示に名前ウィンドウや顔グラフィックウィンドウに関する機能を追加します。
 * @author 木星ペンギン
 * @url
 *
 * @base MPP_MessageEX
 * @orderAfter MPP_MessageEX
 *
 * @help [version 1.1.0]
 * このプラグインはRPGツクールMVおよびMZ用です。
 *
 * ▼ [文章の表示]の制御文字
 *  - 以下は文章内に含まれていた場合に適用
 *   \NW[S]        # 文字列Sを名前ウィンドウに表示
 *   \NC[n]        # 名前ウィンドウの文字色をn番に変更
 *   \FL           # 顔グラフィックを左側に表示(※1)
 *   \FR           # 顔グラフィックを右側に表示(※1)
 *   \FM           # 顔グラフィックを左右反転(※1)
 *   \FW           # 顔グラフィックを別ウィンドウで表示(※1)
 *
 *  - すべての制御文字は大文字小文字どちらでも可能
 *
 * ▼ 制御文字詳細
 *  ※1: \FL, \FR, \FM, \FW (顔グラフィック関連)
 *   - これらの制御文字は組み合わせて使用できます。
 *   - 頭がFであれば、そのあとの順番は適当でOKです。
 *       例: \FRM
 *             => 顔グラフィックを右側に左右反転に表示
 *           \FWR
 *             => 顔グラフィックウィンドウを右側に表示
 *
 * ▼ プラグインコマンド詳細
 *  - MVでは数値を入力する項目で v[N] と記述することで変数N番を参照します。
 *  - MZでは数値を入力する項目で、テキストを選択して v[N] と記述することで
 *    変数N番を参照します。
 *
 *  〇 MV / MZ
 *
 *  〇 SetSpeakerName name  / メッセージ名前表示
 *       name : 名前 (未設定で非表示)
 *   - 名前ウィンドウに表示する名前を変更します。
 *   - \NW[s] との違いは、このコマンドを使用してからこのコマンドや\NW[s]で
 *     別の名前が設定されるまで適用されます。
 *   - \RB[S,R],アイコンやアイテム名の表示といった制御コマンドも使用できます。
 *   - プラグインコマンドの仕様上、空白は使用できません。(MVのみ)
 *   - 空白を使用したい場合、\SET[n]コマンドを使用してください。
 *   - RPGツクールMZでこのコマンドを使用することはお勧めしません。
 *
 * ================================
 * Mail : wood_penguin＠yahoo.co.jp (＠は半角)
 * Blog : http://woodpenguin.blog.fc2.com/
 * License : MIT license
 *
 * @command speakerName
 * @text 名前表示
 * @desc
 *
 * @arg name
 * @desc
 * @default
 *
 *
 * @param Name Window
 * @text 名前ウィンドウ
 * @desc
 * @type struct<NameWindow>
 * @default {"Offset X":"0","Offset Y":"0","Padding":"12","Offset Line Spacing":"0","Windowskin":"Window","Default Color":"0","Font Size":"","Ruby Color":"255,255,255","Always Leave Ruby Height":"false"}
 *
 * @param Face Window
 * @text 顔グラウィンドウ
 * @desc
 * @type struct<FaceWindow>
 * @default {"Offset X":"0","Offset Y":"0","Padding":"12","Windowskin":"Window"}
 *
 */

/*~struct~NameWindow:ja
 * @param Offset X
 * @text X軸補正値
 * @desc
 * @type number
 * @min -3000
 * @default 0
 *
 * @param Offset Y
 * @text Y軸補正値
 * @desc
 * @type number
 * @min -3000
 * @default -56
 *
 * @param Padding
 * @text 余白
 * @desc
 * @type number
 * @default 12
 *
 * @param Offset Line Spacing
 * @text 行の高さ補正値
 * @desc
 * @type number
 * @min -999
 * @default 0
 *
 * @param Windowskin
 * @text ウィンドウスキン
 * @desc
 * @type file
 * @require 1
 * @dir img/system
 * @default Window
 *
 * @param Default Color
 * @text 文字色のデフォルト値
 * @desc 色番号で指定
 * @type number
 * @default 0
 *
 * @param Font Size
 * @text 文字サイズ
 * @desc 未設定の場合、デフォルト値
 * (デフォルト値: MV=28, MZ=26)
 * @type number
 * @min 4
 * @default
 *
 * @param Ruby Color
 * @text 名前のルビの色
 * @desc 未設定で常に文字色と同じ
 * @default 255,255,255
 *
 * @param Always Leave Ruby Height
 * @text 常にルビの高さを空ける
 * @desc
 * @type boolean
 * @default false
 *
 */

/*~struct~FaceWindow:ja
 * @param Offset X
 * @text X軸補正値
 * @desc
 * @type number
 * @default 0
 *
 * @param Offset Y
 * @text Y軸補正値
 * @desc
 * @type number
 * @default 0
 *
 * @param Padding
 * @text 余白
 * @desc
 * @type number
 * @default 12
 *
 * @param Windowskin
 * @text ウィンドウスキン
 * @desc
 * @type file
 * @require 1
 * @dir img/system
 * @default Window
 */

(() => {
  "use strict";

  const pluginName = "MPP_MessageEX_Op1";

  // Plugin Parameters
  const parameters = PluginManager.parameters(pluginName);
  const paramReplace = (key, value) => {
    try {
      return JSON.parse(value);
    } catch (e) {
      return value;
    }
  };
  const param_NameWindow = JSON.parse(
    parameters["Name Window"] || "{}",
    paramReplace
  );
  const param_FaceWindow = JSON.parse(
    parameters["Face Window"] || "{}",
    paramReplace
  );

  // MPP_MessageEX.js
  const baseParameters = PluginManager.parameters("MPP_MessageEX");
  const param_RubyOy = Number(baseParameters["Ruby Oy"] || 0);
  const param_DefaultRubySize = Number(
    baseParameters["Default Ruby Size"] || 14
  );

  // Dealing with other plugins
  const __base = (obj, prop) => {
    if (obj.hasOwnProperty(prop)) {
      return obj[prop];
    } else {
      const proto = Object.getPrototypeOf(obj);
      return function () {
        return proto[prop].apply(this, arguments);
      };
    }
  };

  // RPG Maker Param
  const _textColor = function (index) {
    return Utils.RPGMAKER_NAME === "MV"
      ? this.textColor(index)
      : ColorManager.textColor(index);
  };
  const _fontSize = function () {
    return Utils.RPGMAKER_NAME === "MV"
      ? this.standardFontSize()
      : $gameSystem.mainFontSize();
  };

  //-------------------------------------------------------------------------
  // PluginManager

  PluginManager.registerCommand(pluginName, "speakerName", (args) => {
    $gameMessage.setBasicSpeakerName(args.name || "");
  });

  //-------------------------------------------------------------------------
  // Game_Message

  const _Game_Message_initialize = Game_Message.prototype.initialize;
  Game_Message.prototype.initialize = function () {
    _Game_Message_initialize.apply(this, arguments);
    this._basicSpeakerName = "";
  };

  const _Game_Message_clear = Game_Message.prototype.clear;
  Game_Message.prototype.clear = function () {
    _Game_Message_clear.apply(this, arguments);
    this._nameColorIndex = 0;
  };

  Game_Message.prototype.clearBasicSpeakerName = function () {
    this._basicSpeakerName = "";
  };

  Game_Message.prototype.basicSpeakerName = function () {
    return this._basicSpeakerName;
  };

  Game_Message.prototype.nameColorIndex = function () {
    return this._nameColorIndex;
  };

  Game_Message.prototype.setBasicSpeakerName = function (name) {
    this._basicSpeakerName = name || "";
  };

  Game_Message.prototype.setNameColorIndex = function (colorIndex) {
    this._nameColorIndex = colorIndex;
  };

  if (!Game_Message.prototype.isRTL) {
    Game_Message.prototype.isRTL = function () {
      return false;
    };
  }

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

  const _mzCommands = {
    SetSpeakerName: { name: "speakerName", keys: ["name"] },
  };
  Object.assign(_mzCommands, {
    メッセージ名前表示: _mzCommands.SetSpeakerName,
  });

  const _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.apply(this, arguments);
    const params = _mzCommands[command];
    if (params) {
      const args2 = Object.assign(
        ...params.keys.map((k, i) => ({ [k]: args[i] }))
      );
      PluginManager.callCommand(this, pluginName, params.name, args2);
    }
  };

  //-----------------------------------------------------------------------------
  // Window_Message

  Window_Message.prototype.setFaceBoxWindow = function (faceBoxWindow) {
    this._faceBoxWindow = faceBoxWindow;
  };

  Window_Message.prototype.setNameBoxWindow = function (nameBoxWindow) {
    this._nameBoxWindow = nameBoxWindow;
  };

  const _Window_Message_clearFlagsMessageEx =
    Window_Message.prototype.clearFlagsMessageEx;
  Window_Message.prototype.clearFlagsMessageEx = function () {
    _Window_Message_clearFlagsMessageEx.call(this);
    this._faceParams = { mirror: $gameMessage.isRTL() };
    this._speakerName = "";
    this._nameColorIndex = param_NameWindow["Default Color"] || 0;
  };

  const _Window_Message_convertEscapeCharacters =
    Window_Message.prototype.convertEscapeCharacters;
  Window_Message.prototype.convertEscapeCharacters = function (text) {
    text = _Window_Message_convertEscapeCharacters.apply(this, arguments);
    text = text.replace(/\x1bF([LRMW]+)/gi, (_, p1) => {
      const code = p1.toUpperCase();
      if (code.includes("L")) this._faceParams.right = false;
      if (code.includes("R")) this._faceParams.right = true;
      if (code.includes("M")) this._faceParams.mirror = true;
      if (code.includes("W")) this._faceParams.onBox = true;
      return "";
    });
    text = text.replace(/\x1bNW\[([^\]]+)\]/gi, (_, p1) => {
      this._speakerName = p1;
      return "";
    });
    text = text.replace(/\x1bNC\[(\d+)\]/gi, (_, p1) => {
      this._nameColorIndex = Number(p1);
      return "";
    });
    return text;
  };

  const _Window_Message_update = Window_Message.prototype.update;
  Window_Message.prototype.update = function () {
    _Window_Message_update.apply(this, arguments);
    this.synchronizeNameBoxMV();
  };

  Window_Message.prototype.synchronizeNameBoxMV = function () {
    if (Utils.RPGMAKER_NAME === "MV") {
      this._nameBoxWindow.openness = this.openness;
    }
  };

  const _Window_Message_startMessage = Window_Message.prototype.startMessage;
  Window_Message.prototype.startMessage = function () {
    this._faceBoxWindow.clear();
    _Window_Message_startMessage.apply(this, arguments);
    this._faceBoxWindow.start();
    this._nameBoxWindow.start();
  };

  const _Window_Message_terminateMessageEx =
    Window_Message.prototype.terminateMessageEx;
  Window_Message.prototype.terminateMessageEx = function () {
    _Window_Message_terminateMessageEx.call(this);
    this._faceBoxWindow.needClose();
  };

  const _Window_Message_newPage = Window_Message.prototype.newPage;
  Window_Message.prototype.newPage = function (textState) {
    _Window_Message_newPage.apply(this, arguments);
    if (Utils.RPGMAKER_NAME === "MV") this.updateSpeakerNameMv();
    this.updateSpeakerFace();
  };

  const _Window_Message_updateSpeakerName =
    Window_Message.prototype.updateSpeakerName;
  Window_Message.prototype.updateSpeakerName = function () {
    $gameMessage.setNameColorIndex(this._nameColorIndex);
    _Window_Message_updateSpeakerName.apply(this, arguments);
  };

  Window_Message.prototype.updateSpeakerNameMv = function () {
    $gameMessage.setNameColorIndex(this._nameColorIndex);
    if (this._speakerName !== "") {
      $gameMessage.clearBasicSpeakerName();
    }
    const name = this._speakerName || $gameMessage.basicSpeakerName();
    this._nameBoxWindow.setName(name);
  };

  Window_Message.prototype.updateSpeakerFace = function () {
    const faceName = $gameMessage.faceName();
    const faceIndex = $gameMessage.faceIndex();
    this._faceBoxWindow.setParam(faceName, faceIndex, this._faceParams);
  };

  Window_Message.prototype.drawMessageFace = function () {
    this._faceBoxWindow.refresh();
  };

  const _Window_Message_newLineX = Window_Message.prototype.newLineX;
  Window_Message.prototype.newLineX = function () {
    const { right, onBox = false } = this._faceParams;
    return onBox || right ? 0 : _Window_Message_newLineX.apply(this, arguments);
  };

  //-------------------------------------------------------------------------
  // Window_FaceBox

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

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

  Window_FaceBox.prototype.initialize = function () {
    if (Utils.RPGMAKER_NAME === "MV") {
      Window_Base.prototype.initialize.call(this, 0, 0, 0, 0);
    } else {
      Window_Base.prototype.initialize.call(this, new Rectangle());
    }
    this.openness = 0;
    this._targetX = 0;
    this._moveDuration = 0;
    this._needClose = false;
    this.clear();
  };

  Window_FaceBox.prototype.setMessageWindow = function (messageWindow) {
    this._messageWindow = messageWindow;
  };

  Window_FaceBox.prototype.clear = function () {
    this._faceName = "";
    this._faceIndex = 0;
    this._onBox = false;
    this._mirror = false;
    this._right = false;
  };

  Window_FaceBox.prototype.loadWindowskin = function () {
    const name = param_FaceWindow["Windowskin"] || "Window";
    this.windowskin = ImageManager.loadSystem(name);
  };

  Window_FaceBox.prototype.needClose = function () {
    this._needClose = true;
  };

  Window_FaceBox.prototype.setParam = function (faceName, faceIndex, params) {
    this._faceName = faceName;
    this._faceIndex = faceIndex;
    this._onBox = !!params.onBox;
    this._right = params.right;
    this._mirror = !!params.mirror;
  };

  Window_FaceBox.prototype.update = function () {
    Window_Base.prototype.update.call(this);
    if (this._needClose) {
      this.close();
      this._needClose = false;
    }
    this.updateMove();
  };

  Window_FaceBox.prototype.updateMove = function () {
    if (this._moveDuration > 0) {
      const d = this._moveDuration;
      this.x = (this.x * (d - 1) + this._targetX) / d;
      this._moveDuration--;
    }
  };

  Window_FaceBox.prototype.start = function () {
    this.updatePlacement();
    this.updateBackground();
    this.updateMirror();
    this.appear();
    this.createContents();
  };

  Window_FaceBox.prototype.appear = function () {
    this._targetX = this.windowX();
    const targetY = this.windowY();
    if (!this._onBox) {
      this.x = this._targetX;
      this._moveDuration = 0;
    } else if (
      this.isClosed() ||
      this.x !== this._targetX ||
      this.y !== targetY
    ) {
      const boxMarginX = (Graphics.width - Graphics.boxWidth) / 2;
      this.x = (this._right ? Graphics.width : -this.width) - boxMarginX;
      this._moveDuration = 8;
    }
    this.y = targetY;
    this.openness = 255;
    this._closing = false;
    this._needClose = false;
  };

  Window_FaceBox.prototype.updatePlacement = function () {
    this.padding = this._onBox
      ? param_FaceWindow["Padding"] || 12
      : this._messageWindow.padding;
    this.width = this.windowWidth();
    this.height = this.windowHeight();
  };

  Window_FaceBox.prototype.windowX = function () {
    const messageWindow = this._messageWindow;
    const targetX =
      messageWindow.x + (this._right ? messageWindow.width - this.width : 0);
    if (this._onBox) {
      const offsetX = param_FaceWindow["Offset X"] || 0;
      return targetX + offsetX;
    } else {
      return targetX;
    }
  };

  Window_FaceBox.prototype.windowY = function () {
    const messageWindow = this._messageWindow;
    if (this._onBox) {
      const offsetY = param_FaceWindow["Offset Y"] || 0;
      if (messageWindow.y >= this.height) {
        return messageWindow.y - this.height + offsetY;
      } else {
        return messageWindow.y + messageWindow.height + offsetY;
      }
    } else {
      return messageWindow.y;
    }
  };

  Window_FaceBox.prototype.updateBackground = function () {
    const background = this._onBox ? $gameMessage.background() : 2;
    this.setBackgroundType(background);
    this._isWindow = this._onBox;
  };

  Window_FaceBox.prototype.updateMirror = function () {
    const contentsSprite = this._windowContentsSprite || this._contentsSprite;
    contentsSprite.anchor.x = this._mirror ? 1 : 0;
    contentsSprite.scale.x = this._mirror ? -1 : 1;
  };

  Window_FaceBox.prototype.windowWidth = function () {
    const faceWidth = Window_Base._faceWidth || ImageManager.faceWidth;
    const padding = this.padding + (this._onBox ? 0 : 4);
    return faceWidth + padding * 2;
  };

  Window_FaceBox.prototype.windowHeight = function () {
    if (this._onBox) {
      const faceHeight = Window_Base._faceHeight || ImageManager.faceHeight;
      return faceHeight + this.padding * 2;
    } else {
      return this._messageWindow.height;
    }
  };

  Window_FaceBox.prototype.refresh = function () {
    this.contents.clear();
    const height = this.height - this.padding * 2;
    const faceHeight = Window_Base._faceHeight || ImageManager.faceHeight;
    const dx = this._onBox ? 0 : 4;
    const dy = Math.floor((height - faceHeight) / 2);
    Window_Base.prototype.drawFace.call(
      this,
      this._faceName,
      this._faceIndex,
      dx,
      dy
    );
  };

  //-------------------------------------------------------------------------
  // Window_NameBox

  if (Utils.RPGMAKER_NAME === "MZ") {
    Window_NameBox.prototype.loadWindowskin = function () {
      const name = param_NameWindow["Windowskin"] || "Window";
      this.windowskin = ImageManager.loadSystem(name);
    };

    Window_NameBox.prototype.lineHeight = function () {
      const spacing = param_NameWindow["Offset Line Spacing"] || 0;
      return this.contents.fontSize + 10 + spacing;
    };

    Window_NameBox.prototype.updatePadding = function () {
      this.padding = param_NameWindow["Padding"] || $gameSystem.windowPadding();
    };

    const _Window_NameBox_resetFontSettings =
      Window_NameBox.prototype.resetFontSettings;
    Window_NameBox.prototype.resetFontSettings = function () {
      _Window_NameBox_resetFontSettings.apply(this, arguments);
      this.contents.fontSize =
        param_NameWindow["Font Size"] || _fontSize.call(this);
      this.resetTextColor();
    };

    const _Window_NameBox_resetTextColor = __base(
      Window_NameBox.prototype,
      "resetTextColor"
    );
    Window_NameBox.prototype.resetTextColor = function () {
      _Window_NameBox_resetTextColor.apply(this, arguments);
      const color = _textColor.call(this, $gameMessage.nameColorIndex());
      this.changeTextColor(color);
    };

    // overwrite
    Window_NameBox.prototype.windowHeight = function () {
      return this.itemHeight() + this.padding * 2 + this._rubyHeight;
    };

    Window_NameBox.prototype.createTextState = function (text, x, y, width) {
      const textState = Window_Base.prototype.createTextState.apply(
        this,
        arguments
      );
      textState.y += this._rubyHeight;
      return textState;
    };

    const _Window_NameBox_start = Window_NameBox.prototype.start;
    Window_NameBox.prototype.start = function () {
      this.updateRubyHeight();
      _Window_NameBox_start.apply(this, arguments);
    };

    Window_NameBox.prototype.updateRubyHeight = function () {
      Window_NameBoxMV.prototype.updateRubyHeight.call(this);
    };

    const _Window_NameBox_processEscapeCharacter = __base(
      Window_NameBox.prototype,
      "processEscapeCharacter"
    );
    Window_NameBox.prototype.processEscapeCharacter = function (
      code,
      textState
    ) {
      if (code === "RB") {
        this.processRubyCharacter(textState, this.obtainEscapeTexts(textState));
      } else {
        _Window_NameBox_processEscapeCharacter.apply(this, arguments);
      }
    };

    Window_NameBox.prototype.obtainEscapeTexts = function (textState) {
      return Window_Message.prototype.obtainEscapeTexts.call(this, textState);
    };

    Window_NameBox.prototype.processRubyCharacter = function (
      textState,
      texts
    ) {
      const c = texts[0];
      const cw = this.textWidth(c);
      const fontSize = this.contents.fontSize;
      const textColor = this.contents.textColor;
      this.contents.fontSize = param_DefaultRubySize;
      const r = texts[1];
      const rw = this.textWidth(r);
      const maxWidth = Math.max(cw, rw);
      if (textState.drawing) {
        if (param_NameWindow["Ruby Color"]) {
          this.changeTextColor(
            "rgb(%1)".format(param_NameWindow["Ruby Color"])
          );
        }
        const rx = textState.x + (maxWidth - rw) / 2;
        const ry = textState.y - this._rubyHeight + param_RubyOy;
        this.contents.drawText(r, rx, ry, rw * 2, param_DefaultRubySize + 4);

        const cx = textState.x + (maxWidth - cw) / 2;
        this.changeTextColor(textColor);
        this.contents.fontSize = fontSize;
        this.contents.drawText(c, cx, textState.y, cw * 2, textState.height);
      } else {
        this.contents.fontSize = fontSize;
      }
      textState.x += maxWidth;
    };

    const _Window_NameBox_updatePlacement =
      Window_NameBox.prototype.updatePlacement;
    Window_NameBox.prototype.updatePlacement = function () {
      _Window_NameBox_updatePlacement.apply(this, arguments);
      const offsetX = param_NameWindow["Offset X"] || 0;
      const offsetY = param_NameWindow["Offset Y"] || 0;
      this.x += $gameMessage.isRTL() ? -offsetX : offsetX;
      this.y += this._messageWindow.y > 0 ? offsetY : -offsetY;
    };
  }

  //-------------------------------------------------------------------------
  // Window_NameBoxMV

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

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

  Window_NameBoxMV.prototype.initialize = function () {
    Window_Base.prototype.initialize.call(this, 0, 0, 0, 0);
    this.openness = 0;
    this._name = "";
  };

  Window_NameBoxMV.prototype.lineHeight = function () {
    const spacing = param_NameWindow["Offset Line Spacing"] || 0;
    return this.contents.fontSize + 8 + spacing;
  };

  Window_NameBoxMV.prototype.standardPadding = function () {
    return (
      param_NameWindow["Padding"] ||
      Window_Base.prototype.standardPadding.call(this)
    );
  };

  Window_NameBoxMV.prototype.setMessageWindow = function (messageWindow) {
    this._messageWindow = messageWindow;
  };

  Window_NameBoxMV.prototype.loadWindowskin = function () {
    const name = param_NameWindow["Windowskin"] || "Window";
    this.windowskin = ImageManager.loadSystem(name);
  };

  Window_NameBoxMV.prototype.setName = function (name) {
    if (this._name !== name) {
      this._name = name;
      this.refresh();
    }
  };

  Window_NameBoxMV.prototype.clear = function () {
    this.setName("");
  };

  Window_NameBoxMV.prototype.start = function () {
    this.updateRubyHeight();
    this.updatePlacement();
    this.updateBackground();
    this.createContents();
    this.refresh();
  };

  Window_NameBoxMV.prototype.updateRubyHeight = function () {
    this._rubyHeight = 0;
    const text = this.convertEscapeCharacters(this._name);
    const regExp = /\x1bRB\[.+?\]/i;
    if (param_NameWindow["Always Leave Ruby Height"] || regExp.test(text)) {
      this._rubyHeight = Math.max(param_DefaultRubySize - param_RubyOy, 4);
    }
  };

  Window_NameBoxMV.prototype.updatePlacement = function () {
    this.width = this.windowWidth();
    this.height = this.windowHeight();
    const messageWindow = this._messageWindow;
    const offsetX = param_NameWindow["Offset X"] || 0;
    const offsetY = param_NameWindow["Offset Y"] || 0;
    this.x = messageWindow.x + offsetX;
    if (messageWindow.y > 0) {
      this.y = messageWindow.y - this.height + offsetY;
    } else {
      this.y = messageWindow.y + messageWindow.height - offsetY;
    }
  };

  Window_NameBoxMV.prototype.updateBackground = function () {
    this.setBackgroundType($gameMessage.background());
  };

  Window_NameBoxMV.prototype.windowWidth = function () {
    if (this._name) {
      const textWidth = this.textWidthEx(this._name);
      const padding = this.padding + this.textPadding();
      const width = Math.ceil(textWidth) + padding * 2;
      return Math.min(width, Graphics.boxWidth);
    } else {
      return 0;
    }
  };

  Window_NameBoxMV.prototype.windowHeight = function () {
    return this.fittingHeight(1) + this._rubyHeight;
  };

  Window_NameBoxMV.prototype.refresh = function () {
    this.contents.clear();
    const pad = this.textPadding();
    const width = this.contents.width - pad * 2;
    this.drawTextEx(this._name, pad, this._rubyHeight, width);
  };

  Window_NameBoxMV.prototype.textWidthEx = function (text) {
    return this.drawTextEx(text, 0, this.contents.height + this._rubyHeight);
  };

  Window_NameBoxMV.prototype.resetFontSettings = function () {
    Window_Base.prototype.resetFontSettings.call(this);
    this.contents.fontSize =
      param_NameWindow["Font Size"] || _fontSize.call(this);
    this.resetTextColor();
  };

  Window_NameBoxMV.prototype.resetTextColor = function () {
    Window_Base.prototype.resetTextColor.call(this);
    const color = _textColor.call(this, $gameMessage.nameColorIndex());
    this.changeTextColor(color);
  };

  Window_NameBoxMV.prototype.processEscapeCharacter = function (
    code,
    textState
  ) {
    if (code === "RB") {
      this.processRubyCharacter(textState, this.obtainEscapeTexts(textState));
    } else {
      Window_Base.prototype.processEscapeCharacter.call(this, code, textState);
    }
  };

  Window_NameBoxMV.prototype.obtainEscapeTexts = function (textState) {
    return Window_Message.prototype.obtainEscapeTexts.call(this, textState);
  };

  Window_NameBoxMV.prototype.processRubyCharacter = function (
    textState,
    texts
  ) {
    const c = texts[0];
    const cw = this.textWidth(c);
    const fontSize = this.contents.fontSize;
    const textColor = this.contents.textColor;
    this.contents.fontSize = param_DefaultRubySize;
    const r = texts[1];
    const rw = this.textWidth(r);
    const maxWidth = Math.max(cw, rw);

    if (param_NameWindow["Ruby Color"]) {
      this.changeTextColor("rgb(%1)".format(param_NameWindow["Ruby Color"]));
    }
    const rx = textState.x + (maxWidth - rw) / 2;
    const ry = textState.y - this._rubyHeight + param_RubyOy;
    this.contents.drawText(r, rx, ry, rw + 8, param_DefaultRubySize + 4);

    const cx = textState.x + (maxWidth - cw) / 2;
    this.changeTextColor(textColor);
    this.contents.fontSize = fontSize;
    this.contents.drawText(c, cx, textState.y, cw + 8, textState.height);
    textState.x += maxWidth;
  };

  Window_NameBoxMV.prototype.calcTextHeight = function (textState, all) {
    const textHeight = Window_Base.prototype.calcTextHeight.call(
      this,
      textState,
      all
    );
    const spacing = param_NameWindow["Offset Line Spacing"] || 0;
    return textHeight + spacing;
  };

  //-----------------------------------------------------------------------------
  // Scene_Message

  if (Utils.RPGMAKER_NAME === "MZ") {
    const _Scene_Message_createAllWindows =
      Scene_Message.prototype.createAllWindows;
    Scene_Message.prototype.createAllWindows = function () {
      _Scene_Message_createAllWindows.apply(this, arguments);
      this.createFaceBoxWindow();
      this._messageWindow.setFaceBoxWindow(this._faceBoxWindow);
      this._faceBoxWindow.setMessageWindow(this._messageWindow);
    };

    Scene_Message.prototype.createFaceBoxWindow = function () {
      this._faceBoxWindow = new Window_FaceBox();
      const index = this._windowLayer.children.indexOf(this._nameBoxWindow);
      this._windowLayer.addChildAt(this._faceBoxWindow, index);
    };
  }

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

  if (Utils.RPGMAKER_NAME === "MV") {
    const _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
    Scene_Map.prototype.createAllWindows = function () {
      _Scene_Map_createAllWindows.apply(this, arguments);
      this.createFaceBoxWindowMV();
      this.createNameBoxWindowMV();
      this.associateWindowsMessageEx();
    };

    Scene_Map.prototype.createFaceBoxWindowMV = function () {
      this._faceBoxWindow = new Window_FaceBox();
      this.addWindow(this._faceBoxWindow);
    };

    Scene_Map.prototype.createNameBoxWindowMV = function () {
      this._nameBoxWindow = new Window_NameBoxMV();
      this.addWindow(this._nameBoxWindow);
    };

    Scene_Map.prototype.associateWindowsMessageEx = function () {
      const messageWindow = this._messageWindow;
      messageWindow.setNameBoxWindow(this._nameBoxWindow);
      messageWindow.setFaceBoxWindow(this._faceBoxWindow);
      this._nameBoxWindow.setMessageWindow(messageWindow);
      this._faceBoxWindow.setMessageWindow(messageWindow);
    };
  }

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

  if (Utils.RPGMAKER_NAME === "MV") {
    const _Scene_Battle_createAllWindows =
      Scene_Battle.prototype.createAllWindows;
    Scene_Battle.prototype.createAllWindows = function () {
      _Scene_Battle_createAllWindows.apply(this, arguments);
      this.createFaceBoxWindowMV();
      this.createNameBoxWindowMV();
      this.associateWindowsMessageEx();
    };

    Scene_Battle.prototype.createFaceBoxWindowMV = function () {
      this._faceBoxWindow = new Window_FaceBox();
      this.addWindow(this._faceBoxWindow);
    };

    Scene_Battle.prototype.createNameBoxWindowMV = function () {
      this._nameBoxWindow = new Window_NameBoxMV();
      this.addWindow(this._nameBoxWindow);
    };

    Scene_Battle.prototype.associateWindowsMessageEx = function () {
      const messageWindow = this._messageWindow;
      messageWindow.setNameBoxWindow(this._nameBoxWindow);
      messageWindow.setFaceBoxWindow(this._faceBoxWindow);
      this._nameBoxWindow.setMessageWindow(messageWindow);
      this._faceBoxWindow.setMessageWindow(messageWindow);
    };
  }
})();


code:
//=============================================================================
// MPP_MovePos.js
//=============================================================================
// Copyright (c) 2015 Mokusei Penguin
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @plugindesc 【ver.1.0】指定座標まで自動で移動させるスクリプトの追加。
 * @author 木星ペンギン
 *
 * @help [移動ルートの設定]内のスクリプト:
 *   this.movePos(x, y)           # 座標(x, y)に向かって移動します。
 *   this.movePos(x, y, skip)
 *
 *   skip で true を設定した場合、移動できなかった時点で移動を中断します。
 *
 * ●注意
 *  ・[移動ルートの設定]のオプションにある[移動できない場合は飛ばす]には
 *    チェックを入れないでください。
 *
 *  ・プラグインパラメータで指定できる移動できる[Search Limit(移動できる距離)]が
 *    一度に移動できる最大距離です。
 *    現在位置からこの数値以上に遠い座標を指定することはできません。
 *    一度で移動するのではなく複数回に分けて移動させてください。
 *
 *  ・[Search Limit(移動できる距離)]を増やすことで一度に移動できる距離を
 *    増やせますが、処理が重くなります。
 *
 * ================================
 * 制作 : 木星ペンギン
 * URL : http://woodpenguin.blog.fc2.com/
 *
 * @param Search Limit
 * @desc 移動できる距離
 * @default 12
 *
 */

(function () {
  var parameters = PluginManager.parameters("MPP_MovePos");

  var searchLimit = Number(parameters["Search Limit"]);

  Game_Character.prototype.movePos = function (x, y, skippable) {
    skippable = skippable || false;
    var direction = this.findDirectionTo(x, y);
    if (direction > 0) {
      this.moveStraight(direction);
      this.setMovementSuccess(false);
    } else if (Math.abs(this._x - x) + Math.abs(this._y - y) < searchLimit) {
      this.setMovementSuccess(skippable || this.pos(x, y));
    }
  };

  //558
  Game_Character.prototype.searchLimit = function () {
    return searchLimit;
  };
})();

repo_name: Idkwtcm/violated

license: unknown


code:
//=============================================================================
// MPP_SelfVariable.js
//=============================================================================
// Copyright (c) 2017-2020 Mokusei Penguin
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================

/*:
 * @plugindesc 【v1.3】各イベントにセルフ変数を追加します。
 * @author 木星ペンギン
 *
 * @help プラグインコマンド:
 *   DeleteSelfVariable mapIds var   # 指定したマップIDのセルフ変数を0にする
 *   SetSelfVariable mapIds evIds var n    # セルフ変数の値を変更する
 *
 * ================================================================
 * ▼ 概要
 * --------------------------------
 *  〇 セルフ変数について
 *   ・プラグインパラメータにて設定した番号の変数が、
 * 　  イベントごとのセルフ変数を参照するようになります。
 *
 *   ・イベントコマンドの[変数の操作]から設定した番号の変数の操作を行うと、
 *     実行中のイベントのセルフ変数が変更されます。
 *
 *   ・イベントの[出現条件]ではセルフ変数が参照されます。
 *
 *   ・コモンイベントでセルフ変数を操作した場合、以下のようになります。
 *     >マップのイベントから[コモンイベントの呼び出し]を行った場合
 *      各イベントのセルフ変数が参照されます。
 *
 *     >コモンイベントを自動実行or並列実行した場合
 *      コモンイベントごとのセルフ変数が参照されます。
 *
 *   ・トループのバトルイベントにはセルフ変数が適用されません。
 *     通常の変数と同じ扱いとなります。
 *
 *   ・通常のイベントでも、並列処理の場合は以下のコマンドでは使用できません。
 * 　  （並列処理でなければ使用できます）
 *     >文章の表示（制御文字）
 *     >選択肢の表示（制御文字）
 *     >数値入力の処理
 *     >アイテム選択の処理
 *     >文章のスクロール表示（制御文字）
 *
 *
 * ================================================================
 * ▼ パラメータ全般
 * --------------------------------
 *  〇 範囲指定について
 *   一部のプラグインコマンドとプラグインパラメータでは範囲指定が使用できます。
 *
 *   n-m と表記することで、nからmまでの数値を指定できます。
 *   (例 : 1-4,8,10-12 => 1,2,3,4,8,10,11,12)
 *
 *
 * ================================================================
 * ▼ プラグインコマンド詳細
 * --------------------------------
 *  〇 DeleteSelfVariable mapIds var
 *      mapIds : マップID (範囲指定可)
 *      var    : 0にするセルフ変数の番号 (範囲指定可)
 *
 *   指定したマップIDの指定したセルフ変数を全て0にします。
 *   v[n] と指定することで変数 n 番の値を参照します。
 *   範囲指定する場合は間にスペースを入れないでください。
 *
 *   例： DeleteSelfVariable 1 3
 *         => マップID 1 番のセルフ変数 3 番を0にします。
 *
 *       DeleteSelfVariable v[13] 1-5
 *         => 変数 n 番のマップIDのセルフ変数 1～5 番を0にします。
 *
 *       DeleteSelfVariable 1-5,8 1,2
 *         => マップID 1～5と8 のセルフ変数 1と2 番を0にします。
 *
 * --------------------------------
 *  〇 SetSelfVariable mapIds evIds var n
 *      mapIds : マップID (範囲指定可)
 *      evIds  : イベントID (範囲指定可)
 *      var    : セルフ変数の番号 (範囲指定可)
 *      n      : 設定する値
 *
 *   マップID、イベントID、セルフ変数番号を指定して、値 n を設定します。
 *   v[n] と指定することで変数 n 番の値を参照します。
 *   範囲指定する場合は間にスペースを入れないでください。
 *
 *   例： SetSelfVariable 1 2 3 5
 *         => マップID 1 番のイベントID 3 番のセルフ変数 3 番を5にします。
 *
 *       DeleteSelfVariable 1-3 1,3,5 2-5, v[5]
 *         => マップID 1～3 番のイベントID 1と3と5 番のセルフ変数 2～5 番を
 *            変数 5 番の値にします。
 *
 *
 * ================================================================
 * ▼ プラグインパラメータ 詳細
 * --------------------------------
 *  〇 Plugin Commands
 *   プラグインコマンド名はプラグインパラメータから変更できます。
 *   コマンドを短くしたり日本語にしたりなどして、自分が使いやすいようにしてください。
 *   変更後もデフォルトのコマンドでも動作します。
 *
 *
 * ================================
 * 制作 : 木星ペンギン
 * URL : http://woodpenguin.blog.fc2.com/
 *
 * @param === Basic ===
 * @default 【基本的な設定】
 *
 * @param Variables
 * @desc セルフ変数にする変数の番号
 * (範囲指定可)
 * @default
 * @parent === Basic ===
 *
 * @param === Command ===
 * @default 【コマンド関連】
 *
 * @param Plugin Commands
 * @type struct<Plugin>
 * @desc プラグインコマンド名
 * @default {"DeleteSelfVariable":"DeleteSelfVariable","SetSelfVariable":"SetSelfVariable"}
 * @parent === Command ===
 *
 */

/*~struct~Plugin:
 * @param DeleteSelfVariable
 * @desc 指定したマップIDのセルフスイッチをOFFにする
 * @default DeleteSelfVariable
 *
 * @param SetSelfVariable
 * @desc セルフ変数の値を変更する
 * @default SetSelfVariable
 *
 */

var MPP = MPP || {};

(function (exports) {
  "use strict";

  MPP.paramRange =
    MPP.paramRange ||
    function (param) {
      var result = [];
      param.split(",").forEach((id) => {
        if (/(\d+)-(\d+)/.test(id)) {
          for (var n = Number(RegExp.$1); n <= Number(RegExp.$2); n++) {
            result.push(n);
          }
        } else {
          result.push(Number(id));
        }
      });
      return result;
    };

  const Params = {};

  {
    let parameters = PluginManager.parameters("MPP_SelfVariable");

    Params.Variables = MPP.paramRange(parameters["Variables"]);

    //=== Command ===
    Params.PluginCommands = JSON.parse(parameters["Plugin Commands"]);
  }

  const Alias = {};

  //-----------------------------------------------------------------------------
  // Game_Variables

  //15
  Alias.GaVa_clear = Game_Variables.prototype.clear;
  Game_Variables.prototype.clear = function () {
    Alias.GaVa_clear.apply(this, arguments);
    this._selfVariables = {};
    this._mapId = 0;
    this._eventId = 0;
  };

  //19
  Alias.GaVa_value = Game_Variables.prototype.value;
  Game_Variables.prototype.value = function (variableId) {
    if (this._eventId > 0 && Params.Variables.contains(variableId)) {
      var key = [this._mapId, this._eventId, variableId];
      return this._selfVariables[key] || 0;
    } else {
      return Alias.GaVa_value.apply(this, arguments);
    }
  };

  //23
  Alias.GaVa_setValue = Game_Variables.prototype.setValue;
  Game_Variables.prototype.setValue = function (variableId, value) {
    if (this._eventId > 0 && Params.Variables.contains(variableId)) {
      if (typeof value === "number") {
        value = Math.floor(value);
      }
      var key = [this._mapId, this._eventId, variableId];
      this._selfVariables[key] = value;
      this.onChange();
    } else {
      Alias.GaVa_setValue.apply(this, arguments);
    }
  };

  Game_Variables.prototype.setSelfVariable = function (
    mapId,
    eventId,
    variableId,
    value
  ) {
    if (eventId > 0 && eventId > 0 && Params.Variables.contains(variableId)) {
      if (typeof value === "number") {
        value = Math.floor(value);
      }
      var key = [mapId, eventId, variableId];
      this._selfVariables[key] = value;
      this.onChange();
    }
  };

  Game_Variables.prototype.deleteSelfVariables = function (
    mapId,
    evIds,
    vaIds
  ) {
    var re = new RegExp(mapId + ",(\\d+),(\\d+)");
    for (var key in this._selfVariables) {
      if (re.test(key)) {
        if (
          (evIds.length === 0 || evIds.includes(parseInt(RegExp.$1))) &&
          (vaIds.length === 0 || vaIds.includes(parseInt(RegExp.$2)))
        ) {
          delete this._selfVariables[key];
        }
      }
    }
    this.onChange();
  };

  Game_Variables.prototype.reserveEvent = function (mapId, eventId) {
    this._mapId = mapId;
    this._eventId = eventId;
  };

  //-----------------------------------------------------------------------------
  // Game_Event

  //188
  Alias.GaEv_findProperPageIndex = Game_Event.prototype.findProperPageIndex;
  Game_Event.prototype.findProperPageIndex = function () {
    $gameVariables.reserveEvent(this._mapId, this._eventId);
    return Alias.GaEv_findProperPageIndex.apply(this, arguments);
  };

  //-----------------------------------------------------------------------------
  // Game_CommonEvent

  //24
  Alias.GaCoEv_refresh = Game_CommonEvent.prototype.refresh;
  Game_CommonEvent.prototype.refresh = function () {
    Alias.GaCoEv_refresh.apply(this, arguments);
    if (this._interpreter) {
      this._interpreter._commonEventId = this._commonEventId;
    }
  };

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

  //55
  Alias.GaIn_setupReservedCommonEvent =
    Game_Interpreter.prototype.setupReservedCommonEvent;
  Game_Interpreter.prototype.setupReservedCommonEvent = function () {
    this._commonEventId = $gameTemp._commonEventId;
    return Alias.GaIn_setupReservedCommonEvent.apply(this, arguments);
  };

  //68
  Alias.GaIn_update = Game_Interpreter.prototype.update;
  Game_Interpreter.prototype.update = function () {
    this.reserveSelfVar();
    Alias.GaIn_update.apply(this, arguments);
  };

  //608
  Alias.GaIn_setupChild = Game_Interpreter.prototype.setupChild;
  Game_Interpreter.prototype.setupChild = function (list, eventId) {
    Alias.GaIn_setupChild.apply(this, arguments);
    this._childInterpreter._commonEventId = this._commonEventId;
  };

  Game_Interpreter.prototype.reserveSelfVar = function () {
    if (this._commonEventId) {
      $gameVariables.reserveEvent(-1, this._commonEventId);
    } else {
      $gameVariables.reserveEvent(this._mapId, this._eventId);
    }
  };

  //1722
  Alias.GaIn_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    Alias.GaIn_pluginCommand.apply(this, arguments);
    var args2 = this.mppPluginCommandArgs2(args);
    switch (command) {
      case Params.PluginCommands.DeleteSelfVariable:
      case "DeleteSelfVariable":
        var varIds = MPP.paramRange(args2[1]);
        MPP.paramRange(args2[0]).forEach(function (mapId) {
          $gameVariables.deleteSelfVariables(mapId, [], varIds);
        });
        break;
      case Params.PluginCommands.SetSelfVariable:
      case "SetSelfVariable":
        var mapIds = MPP.paramRange(args2[0]);
        var evIds = MPP.paramRange(args2[1]);
        var varIds = MPP.paramRange(args2[2]);
        mapIds.forEach((n1) =>
          evIds.forEach((n2) =>
            varIds.forEach((n3) =>
              $gameVariables.setSelfVariable(n1, n2, n3, args2[3])
            )
          )
        );
        break;
    }
  };

  Game_Interpreter.prototype.mppPluginCommandArgs2 = function (args) {
    var convertVar = function () {
      return $gameVariables.value(parseInt(arguments[1]));
    };
    return args.map((arg) => arg.replace(/v\[(\d+)\]/gi, convertVar));
  };
})(this);


code:
/*:
 * NOTE: Images are stored in the img/system folder.
 *
 * @plugindesc Show a Splash Screen "Made with MV" and/or a Custom Splash Screen before going to main screen.
 * @author Dan "Liquidize" Deptula
 *
 * @help This plugin does not provide plugin commands.
 *
 * @param Show Made With MV
 * @desc Enabled/Disables showing the "Made with MV" splash screen.
 * OFF - false     ON - true
 * Default: ON
 * @default true
 *
 * @param Made with MV Image
 * @desc The image to use when showing "Made with MV"
 * Default: MadeWithMv
 * @default MadeWithMv
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param Show Custom Splash
 * @desc Enabled/Disables showing the "Made with MV" splash screen.
 * OFF - false     ON - true
 * Default: OFF
 * @default false
 *
 * @param Custom Image
 * @desc The image to use when showing "Made with MV"
 * Default:
 * @default
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param Fade Out Time
 * @desc The time it takes to fade out, in frames.
 * Default: 120
 * @default 120
 *
 * @param Fade In Time
 * @desc The time it takes to fade in, in frames.
 * Default: 120
 * @default 120
 *
 * @param Wait Time
 * @desc The time between fading in and out, in frames.
 * Default: 160
 * @default 160
 *
 */
/*:ja
 * メモ: イメージはimg／systemフォルダ内に保存されます。
 *
 * @plugindesc メイン画面へ進む前に、"Made with MV"のスプラッシュ画面もしくはカスタマイズされたスプラッシュ画面を表示します。
 * @author Dan "Liquidize" Deptula
 *
 * @help  このプラグインにはプラグインコマンドはありません。
 *
 * @param Show Made With MV
 * @desc "Made with MV"のスプラッシュ画面を表示できる/できないようにします。
 * OFF - false     ON - true
 * デフォルト: ON
 * @default true
 *
 * @param Made with MV Image
 * @desc "Made with MV"を表示する際に使用する画像
 * デフォルト: MadeWithMv
 * @default MadeWithMv
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param Show Custom Splash
 * @desc "Made with MV"のスプラッシュ画面を表示できる/できないようにします。
 * OFF - false     ON - true
 * デフォルト: OFF
 * @default false
 *
 * @param Custom Image
 * @desc "Made with MV"を表示する際に使用する画像
 * デフォルト:
 * @default
 * @require 1
 * @dir img/system/
 * @type file
 *
 * @param Fade Out Time
 * @desc フェードアウトに要する時間（フレーム数）
 * デフォルト: 120
 * @default 120
 *
 * @param Fade In Time
 * @desc フェードインに要する時間（フレーム数）
 * デフォルト: 120
 * @default 120
 *
 * @param Wait Time
 * @desc フェードインからフェードアウトまでに要する時間（フレーム数）
 * デフォルト: 160
 * @default 160
 *
 */
var Liquidize = Liquidize || {};
Liquidize.MadeWithMV = {};
Liquidize.MadeWithMV.Parameters = PluginManager.parameters("MadeWithMv");

Liquidize.MadeWithMV.ShowMV = JSON.parse(
  Liquidize.MadeWithMV.Parameters["Show Made With MV"]
);
Liquidize.MadeWithMV.MVImage = String(
  Liquidize.MadeWithMV.Parameters["Made with MV Image"]
);
Liquidize.MadeWithMV.ShowCustom = JSON.parse(
  Liquidize.MadeWithMV.Parameters["Show Custom Splash"]
);
Liquidize.MadeWithMV.CustomImage = String(
  Liquidize.MadeWithMV.Parameters["Custom Image"]
);
Liquidize.MadeWithMV.FadeOutTime =
  Number(Liquidize.MadeWithMV.Parameters["Fade Out Time"]) || 120;
Liquidize.MadeWithMV.FadeInTime =
  Number(Liquidize.MadeWithMV.Parameters["Fade In Time"]) || 120;
Liquidize.MadeWithMV.WaitTime =
  Number(Liquidize.MadeWithMV.Parameters["Wait Time"]) || 160;

//-----------------------------------------------------------------------------
// Scene_Splash
//
// This is a constructor, implementation is done in the inner scope.

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

(function () {
  //-----------------------------------------------------------------------------
  // Scene_Boot
  //
  // The scene class for dealing with the game boot.

  var _Scene_Boot_loadSystemImages = Scene_Boot.prototype.loadSystemImages;
  Scene_Boot.prototype.loadSystemImages = function () {
    _Scene_Boot_loadSystemImages.call(this);
    if (Liquidize.MadeWithMV.ShowMV) {
      ImageManager.loadSystem(Liquidize.MadeWithMV.MVImage);
    }
    if (Liquidize.MadeWithMV.ShowCustom) {
      ImageManager.loadSystem(Liquidize.MadeWithMV.CustomImage);
    }
  };

  var _Scene_Boot_start = Scene_Boot.prototype.start;
  Scene_Boot.prototype.start = function () {
    if (
      (Liquidize.MadeWithMV.ShowMV || Liquidize.MadeWithMV.ShowCustom) &&
      !DataManager.isBattleTest() &&
      !DataManager.isEventTest()
    ) {
      SceneManager.goto(Scene_Splash);
    } else {
      _Scene_Boot_start.call(this);
    }
  };

  //-----------------------------------------------------------------------------
  // Scene_Splash
  //
  // The scene class for dealing with the splash screens.

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

  Scene_Splash.prototype.initialize = function () {
    Scene_Base.prototype.initialize.call(this);
    this._mvSplash = null;
    this._customSplash = null;
    this._mvWaitTime = Liquidize.MadeWithMV.WaitTime;
    this._customWaitTime = Liquidize.MadeWithMV.WaitTime;
    this._mvFadeOut = false;
    this._mvFadeIn = false;
    this._customFadeOut = false;
    this._customFadeIn = false;
  };

  Scene_Splash.prototype.create = function () {
    Scene_Base.prototype.create.call(this);
    this.createSplashes();
  };

  Scene_Splash.prototype.start = function () {
    Scene_Base.prototype.start.call(this);
    SceneManager.clearStack();
    if (this._mvSplash != null) {
      this.centerSprite(this._mvSplash);
    }
    if (this._customSplash != null) {
      this.centerSprite(this._customSplash);
    }
  };

  Scene_Splash.prototype.update = function () {
    if (Liquidize.MadeWithMV.ShowMV) {
      if (!this._mvFadeIn) {
        this.startFadeIn(Liquidize.MadeWithMV.FadeInTime, false);
        this._mvFadeIn = true;
      } else {
        if (this._mvWaitTime > 0 && this._mvFadeOut == false) {
          this._mvWaitTime--;
        } else {
          if (this._mvFadeOut == false) {
            this._mvFadeOut = true;
            this.startFadeOut(Liquidize.MadeWithMV.FadeOutTime, false);
          }
        }
      }
    }

    if (Liquidize.MadeWithMV.ShowCustom) {
      if (Liquidize.MadeWithMV.ShowMV && this._mvFadeOut == true) {
        if (!this._customFadeIn && this._fadeDuration == 0) {
          this._customSplash.opacity = 255;
          this._customWaitTime = Liquidize.MadeWithMV.WaitTime;
          this.startFadeIn(Liquidize.MadeWithMV.FadeInTime, false);
          this._customFadeIn = true;
        } else {
          if (this._customWaitTime > 0 && this._customFadeOut == false) {
            this._customWaitTime--;
          } else {
            if (this._customFadeOut == false) {
              this._customFadeOut = true;
              this.startFadeOut(Liquidize.MadeWithMV.FadeOutTime, false);
            }
          }
        }
      } else if (!Liquidize.MadeWithMV.ShowMV) {
        if (!this._customFadeIn) {
          this._customSplash.opacity = 255;
          this.startFadeIn(Liquidize.MadeWithMV.FadeInTime, false);
          this._customFadeIn = true;
        } else {
          if (this._customWaitTime > 0 && this._customFadeOut == false) {
            this._customWaitTime--;
          } else {
            if (this._customFadeOut == false) {
              this._customFadeOut = true;
              this.startFadeOut(Liquidize.MadeWithMV.FadeOutTime, false);
            }
          }
        }
      }
    }

    if (Liquidize.MadeWithMV.ShowCustom) {
      if (
        Liquidize.MadeWithMV.ShowMV &&
        this._mvFadeOut == true &&
        this._customFadeOut == true
      ) {
        this.gotoTitleOrTest();
      } else if (!Liquidize.MadeWithMV.ShowMV && this._customFadeOut == true) {
        this.gotoTitleOrTest();
      }
    } else {
      if (this._mvFadeOut == true) {
        this.gotoTitleOrTest();
      }
    }

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

  Scene_Splash.prototype.createSplashes = function () {
    if (Liquidize.MadeWithMV.ShowMV) {
      this._mvSplash = new Sprite(
        ImageManager.loadSystem(Liquidize.MadeWithMV.MVImage)
      );
      this.addChild(this._mvSplash);
    }
    if (Liquidize.MadeWithMV.ShowCustom) {
      this._customSplash = new Sprite(
        ImageManager.loadSystem(Liquidize.MadeWithMV.CustomImage)
      );
      this._customSplash.opacity = 0;
      this.addChild(this._customSplash);
    }
  };

  Scene_Splash.prototype.centerSprite = function (sprite) {
    sprite.x = Graphics.width / 2;
    sprite.y = Graphics.height / 2;
    sprite.anchor.x = 0.5;
    sprite.anchor.y = 0.5;
  };

  Scene_Splash.prototype.gotoTitleOrTest = function () {
    Scene_Base.prototype.start.call(this);
    SoundManager.preloadImportantSounds();
    if (DataManager.isBattleTest()) {
      DataManager.setupBattleTest();
      SceneManager.goto(Scene_Battle);
    } else if (DataManager.isEventTest()) {
      DataManager.setupEventTest();
      SceneManager.goto(Scene_Map);
    } else {
      this.checkPlayerLocation();
      DataManager.setupNewGame();
      SceneManager.goto(Scene_Title);
      Window_TitleCommand.initCommandPosition();
    }
    this.updateDocumentTitle();
  };

  Scene_Splash.prototype.updateDocumentTitle = function () {
    document.title = $dataSystem.gameTitle;
  };

  Scene_Splash.prototype.checkPlayerLocation = function () {
    if ($dataSystem.startMapId === 0) {
      throw new Error("Player's starting position is not set");
    }
  };
})();


code:
//=============================================================================
// MakeScreenCapture.js
// ----------------------------------------------------------------------------
// (C)2015-2018 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.7.3 2018/06/28 出力パスの算出方法を変更
// 1.7.2 2018/03/06 各種ファンクションキーにCtrlおよびAltの同時押し要否の設定を追加しました。
// 1.7.1 2017/11/11 総合開発支援プラグインとの連携による修正
// 1.7.0 2017/08/13 パラメータの型指定機能に対応
// 1.6.0 2016/12/25 jpg保存時の拡張子を「jpeg」→「jpg」に変更
//                  jpeg品質をパラメータから指定できる機能を追加
// 1.5.0 2016/10/20 本体バージョン1.3.2でエラーが発生していたのを修正
// 1.4.0 2016/10/06 パラメータに環境変数を使えるように修正
// 1.3.0 2016/06/24 WEBP形式のショートカットキーを追加
// 1.2.3 2016/06/23 著名に画像とテキストを両方使えるよう修正
// 1.2.2 2016/05/13 プラグインコマンドから出力したときに拡張子の表示がおかしくなる問題を修正
// 1.2.1 2016/05/11 定期実行キャプチャを行ったときに拡張子の表示がおかしくなる問題を修正
// 1.2.0 2016/04/23 署名に任意の画像ファイルを利用できるようになりました。
//                  細部のリファクタリング
// 1.1.5 2016/04/10 画像の出力先を管理画面のパラメータとして設定できるよう修正
// 1.1.4 2016/03/31 画像の出力先を絶対パスで指定できるよう修正
// 1.1.3 2016/03/15 文章のスクロール表示が正しくキャプチャできない問題を修正
// 1.1.2 2016/03/01 pngとjpegの形式ごとのファンクションキーを割り当てるよう修正
// 1.1.1 2016/02/26 PrintScreenでもキャプチャできるように修正
// 1.1.0 2016/02/25 複数のウィンドウを含む画面で正しくキャプチャできない不具合を修正
//                  高度な設定項目の追加
// 1.0.0 2016/02/24 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc Screen Capture Plugin
 * @author triacontane
 *
 * @param FuncKeyPngCapture
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずpng形式で出力します。
 * @default F6
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param FuncKeyJpegCapture
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずjpeg形式で出力します。
 * @default F7
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param FuncKeyWebpCapture
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずwebp形式で出力します。
 * @default
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param SimultaneousCtrl
 * @desc 各機能を利用する際にCtrlキーの同時押しが必要かどうかです。他のプラグインと対象キーが競合する場合に利用します。
 * @default false
 * @type boolean
 *
 * @param SimultaneousAlt
 * @desc 各機能を利用する際にAltキーの同時押しが必要かどうかです。他のプラグインと対象キーが競合する場合に利用します。
 * @default false
 * @type boolean
 *
 * @param FileName
 * @desc 画像のファイル名です。
 * プラグインコマンドから実行した場合は参照されません。
 * @default image
 *
 * @param Location
 * @desc ファイルの出力パスです。相対パス、絶対パスが利用できます。
 * 区切り文字は「/」もしくは「\」で指定してください。
 * @default captures
 *
 * @param FileFormat
 * @desc 画像のデフォルト保存形式です。(png/jpeg/webp)
 * @default png
 * @type select
 * @option png
 * @option jpeg
 * @option webp
 *
 * @param NumberDigit
 * @desc キャプチャファイルの連番桁数です。
 * @default 2
 * @type number
 *
 * @param TimeStamp
 * @desc ONにすると連番の代わりにタイムスタンプを付与します。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param Signature
 * @desc 保存時に画像の右下に書き込まれる署名です。
 * @default
 *
 * @param SignatureSize
 * @desc 署名のフォントサイズです。
 * @default 22
 * @type number
 *
 * @param SignatureImage
 * @desc 保存時に画像の右下に書き込まれる著名画像ファイル名です。「img/pictures」に配置。拡張子不要。
 * @default
 * @require 1
 * @dir img/pictures/
 * @type file
 *
 * @param Interval
 * @desc キャプチャを定期実行する間隔（秒単位）です。
 * 0にすると、定期キャプチャを行いません。
 * @default 0
 * @type number
 *
 * @param SeName
 * @desc キャプチャ実行時に演奏する効果音のファイル名です。
 * @default
 * @require 1
 * @dir audio/se/
 * @type file
 *
 * @param JpegQuality
 * @desc JPEG出力したときの品質です。値を小さくすると容量も小さくなります。(1...10)
 * @default 9
 * @type number
 * @min 1
 * @max 10
 *
 * @help プレー中のゲーム画面をキャプチャして
 * ファイルに保存したり、ピクチャとして表示したりできます。
 * キャプチャは以下のタイミングで実行されます。
 *
 * ・ファンクションキー or PrintScreen押下
 * ・一定時間ごと
 * ・プラグインコマンド実行時
 *
 * プラグインコマンド以外は、テストプレー時のみ有効になります。
 *
 * キャプチャしたファイルの保存場所は絶対パス、相対パスいずれも指定できるほか、
 * OSの環境変数（%USERPROFILE%など）にも対応しています。
 *
 * また、キャプチャの際に著名を自動で埋め込むことができます。
 * 著名は文字列で指定できるほか、任意の画像も指定可能です。
 * （両方指定すると画像が優先されます）
 *
 * 注意！
 * キャプチャピクチャの表示状態はセーブできません。
 * セーブされる前に「ピクチャの消去」で消去してください。
 *
 * 注意！
 * キャプチャを出力する機能はローカル環境でのみ有効です。
 * ブラウザやスマホ上では動作しません。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * MSC_MAKE
 *  実行時点でのキャプチャを作成して保持します。
 *  ex：MSC_MAKE
 *
 * MSC_PICTURE
 *  保持していた画面キャプチャをピクチャに表示します。
 *  このコマンドの直後に「ピクチャの表示」を実行するとキャプチャピクチャが
 *  表示されます。
 *  ex：MSC_PICTURE
 *
 * MSC_SAVE [ファイル名]
 *  保持していた画面キャプチャをファイルに保存します。
 *  ファイル名は自由に指定できます。
 *  拡張子は自動で設定されるので設定不要です。
 *  ex：MSC_SAVE image
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc 画面キャプチャ管理プラグイン
 * @author トリアコンタン
 *
 * @param PNGキャプチャキー
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずpng形式で出力します。
 * @default F6
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param JPEGキャプチャキー
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずjpeg形式で出力します。
 * @default F7
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param WEBPキャプチャキー
 * @desc キャプチャとファイル保存を行うファンクションキーです。
 * 保存形式の設定にかかわらずwebp形式で出力します。
 * @default F9
 * @type select
 * @option none
 * @option F1
 * @option F2
 * @option F3
 * @option F4
 * @option F5
 * @option F6
 * @option F7
 * @option F8
 * @option F9
 * @option F10
 * @option F11
 * @option F12
 *
 * @param Ctrl同時押し
 * @desc 各機能を利用する際にCtrlキーの同時押しが必要かどうかです。他のプラグインと対象キーが競合する場合に利用します。
 * @default false
 * @type boolean
 *
 * @param Alt同時押し
 * @desc 各機能を利用する際にAltキーの同時押しが必要かどうかです。他のプラグインと対象キーが競合する場合に利用します。
 * @default false
 * @type boolean
 *
 * @param ファイル名
 * @desc 画像のファイル名です。
 * プラグインコマンドから実行した場合は参照されません。
 * @default image
 *
 * @param 出力場所
 * @desc ファイルの出力パスです。相対パス、絶対パスが利用できます。
 * 区切り文字は「/」もしくは「\」で指定してください。
 * @default captures
 *
 * @param 保存形式
 * @desc 画像のデフォルト保存形式です。(png/jpeg/webp)
 * @default png
 * @type select
 * @option png
 * @option jpeg
 * @option webp
 *
 * @param 連番桁数
 * @desc キャプチャファイルの連番桁数です。数値はゲーム実行の度に初期化されるのでご注意ください。
 * @default 2
 * @type number
 *
 * @param タイムスタンプ
 * @desc ONにすると連番の代わりにタイムスタンプを付与します。(ON/OFF)
 * @default true
 * @type boolean
 *
 * @param 署名
 * @desc 保存時に画像の右下に書き込まれる署名です。
 * @default
 *
 * @param 署名サイズ
 * @desc 署名のフォントサイズです。
 * @default 22
 * @type number
 *
 * @param 署名画像
 * @desc 保存時に画像の右下に書き込まれる著名画像ファイル名です。「img/pictures」に配置。拡張子不要。
 * @default
 * @require 1
 * @dir img/pictures/
 * @type file
 *
 * @param 実行間隔
 * @desc キャプチャを定期実行する間隔（秒単位）です。
 * 0にすると、定期キャプチャを行いません。
 * @default 0
 * @type number
 *
 * @param 効果音
 * @desc キャプチャ実行時に演奏する効果音のファイル名です。
 * @default
 * @require 1
 * @dir audio/se/
 * @type file
 *
 * @param JPEG品質
 * @desc JPEG出力したときの品質です。値を小さくすると容量も小さくなります。(1...10)
 * @default 9
 * @type number
 * @min 1
 * @max 10
 *
 * @help プレー中のゲーム画面をキャプチャして
 * ファイルに保存したり、ピクチャとして表示したりできます。
 * キャプチャは以下のタイミングで実行されます。
 *
 * ・ファンクションキー or PrintScreen押下
 * ・一定時間ごと
 * ・プラグインコマンド実行時
 *
 * プラグインコマンド以外は、テストプレー時のみ有効になります。
 *
 * キャプチャしたファイルの保存場所は絶対パス、相対パスいずれも指定できるほか、
 * OSの環境変数（%USERPROFILE%など）にも対応しています。
 *
 * また、キャプチャの際に著名を自動で埋め込むことができます。
 * 著名は文字列で指定できるほか、任意の画像も指定可能です。
 * （両方指定すると画像が優先されます）
 *
 * 注意！
 * キャプチャピクチャの表示状態はセーブできません。
 * セーブされる前に「ピクチャの消去」で消去してください。
 *
 * 注意！
 * キャプチャを出力する機能はローカル環境でのみ有効です。
 * ブラウザやスマホ上では動作しません。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * MSC_MAKE or 画面キャプチャ作成
 *  実行時点でのキャプチャを作成して保持します。
 *  例：画面キャプチャ作成
 *
 * MSC_PICTURE or 画面キャプチャピクチャ
 *  保持していた画面キャプチャをピクチャに表示します。
 *  このコマンドの直後に「ピクチャの表示」を実行するとキャプチャピクチャが
 *  表示されます。
 *  例：画面キャプチャピクチャ
 *
 * MSC_SAVE [ファイル名] or 画面キャプチャ保存 [ファイル名]
 *  保持していた画面キャプチャをファイルに保存します。
 *  ファイル名は自由に指定できます。
 *  拡張子は自動で設定されるので設定不要です。
 *  例：画面キャプチャ保存 image
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  //=============================================================================
  // ユーザ書き換え領域 - 開始 -
  //  高度な設定を記述しています。必要な場合は書き換えてください。
  //=============================================================================
  var settings = {
    /* 署名のフォント情報です。faceはあらかじめフォントをロードしておかなければ使えません */
    signature: {
      face: "GameFont",
      color: "rgba(255,255,255,1.0)",
      align: "right",
    },
    /* 効果音情報です。ファイル名はプラグイン管理画面から取得します */
    se: { volume: 90, pitch: 100, pan: 0 },
    /* テストプレー以外での動作を無効にするフラグです */
    testOnly: true,
  };
  //=============================================================================
  // ユーザ書き換え領域 - 終了 -
  //=============================================================================
  var pluginName = "MakeScreenCapture";

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

  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 getParamBoolean = function (paramNames) {
    var value = getParamOther(paramNames);
    return (
      (value || "").toUpperCase() === "ON" ||
      (value || "").toUpperCase() === "TRUE"
    );
  };

  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 Utils.isNwjs() ? convertEnvironmentVariable(name) : name;
    }
    return null;
  };

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

  var getArgString = function (arg, upperFlg) {
    arg = convertEscapeCharacters(arg);
    return upperFlg ? arg.toUpperCase() : arg;
  };

  var convertEnvironmentVariable = function (text) {
    if (text == null) text = "";
    text = text.replace(
      /%(\w+)%/gi,
      function () {
        return process.env[arguments[1]] || "";
      }.bind(this)
    );
    return text;
  };

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

  //=============================================================================
  // パラメータの取得と整形
  //=============================================================================
  var paramFuncKeyPngCapture = getParamString([
    "FuncKeyPngCapture",
    "PNGキャプチャキー",
  ]);
  var paramFuncKeyJpegCapture = getParamString([
    "FuncKeyJpegCapture",
    "JPEGキャプチャキー",
  ]);
  var paramFuncKeyWebpCapture = getParamString([
    "FuncKeyWebpCapture",
    "WEBPキャプチャキー",
  ]);
  var paramFileName = getParamString(["FileName", "ファイル名"]);
  var paramLocation = getParamString(["Location", "出力場所"]);
  var paramFileFormat = getParamString([
    "FileFormat",
    "保存形式",
  ]).toLowerCase();
  var paramSignature = getParamString(["Signature", "署名"]);
  var paramSignatureImage = getParamString(["SignatureImage", "署名画像"]);
  var paramSignatureSize = getParamNumber(["SignatureSize", "署名サイズ"]);
  var paramNumberDigit = getParamNumber(["NumberDigit", "連番桁数"]);
  var paramInterval = getParamNumber(["Interval", "実行間隔"]);
  var paramSeName = getParamString(["SeName", "効果音"]);
  var paramTimeStamp = getParamBoolean(["TimeStamp", "タイムスタンプ"]);
  var paramJpegQuality = getParamNumber(["JpegQuality", "JPEG品質"]);
  var paramSimultaneousCtrl = getParamBoolean([
    "SimultaneousCtrl",
    "Ctrl同時押し",
  ]);
  var paramSimultaneousAlt = getParamBoolean([
    "SimultaneousAlt",
    "Alt同時押し",
  ]);

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

  Game_Interpreter.prototype.pluginCommandMakeScreenCapture = function (
    command,
    args
  ) {
    switch (getCommandName(command)) {
      case "MSC_MAKE":
      case "画面キャプチャ作成":
        SceneManager.makeCapture();
        break;
      case "MSC_PICTURE":
      case "画面キャプチャピクチャ":
        $gameScreen.captureFlg = true;
        break;
      case "MSC_SAVE":
      case "画面キャプチャ保存":
        SceneManager.saveCapture(
          getArgString(args[0]) || paramFileName,
          paramFileFormat
        );
        break;
    }
  };

  //=============================================================================
  // Game_Screen
  //  キャプチャピクチャ用のプロパティを追加定義します。
  //=============================================================================
  var _Game_Screen_clear = Game_Screen.prototype.clear;
  Game_Screen.prototype.clear = function () {
    _Game_Screen_clear.apply(this, arguments);
    this.clearCapturePicture();
  };

  Game_Screen.prototype.clearCapturePicture = function () {
    this.captureFlg = false;
  };

  //=============================================================================
  // Game_Picture
  //  キャプチャピクチャ用のプロパティを追加定義します。
  //=============================================================================
  var _Game_Picture_show = Game_Picture.prototype.show;
  Game_Picture.prototype.show = function (
    name,
    origin,
    x,
    y,
    scaleX,
    scaleY,
    opacity,
    blendMode
  ) {
    if ($gameScreen.captureFlg) {
      arguments[0] = Date.now().toString();
      this.captureFlg = true;
    } else {
      this.captureFlg = null;
    }
    $gameScreen.clearCapturePicture();
    _Game_Picture_show.apply(this, arguments);
  };

  //=============================================================================
  // Scene_Base
  //  定期実行キャプチャを定義します。
  //=============================================================================
  var _Scene_Base_update = Scene_Base.prototype.update;
  Scene_Base.prototype.update = function () {
    _Scene_Base_update.apply(this, arguments);
    var count = Graphics.frameCount;
    if (
      paramInterval !== 0 &&
      Utils.isTestCapture() &&
      (count + 1) % (paramInterval * 60) === 0
    ) {
      SceneManager.takeCapture();
    }
  };

  //=============================================================================
  // Sprite_Picture
  //  画像の動的生成を追加定義します。
  //=============================================================================
  var _Sprite_Picture_loadBitmap = Sprite_Picture.prototype.loadBitmap;
  Sprite_Picture.prototype.loadBitmap = function () {
    if (this.picture().captureFlg) {
      this.bitmap = SceneManager.getCapture();
    } else {
      _Sprite_Picture_loadBitmap.apply(this, arguments);
    }
  };

  //=============================================================================
  // Utils
  //  テスト用のキャプチャを許可するかどうかを返します。
  //=============================================================================
  Utils.isTestCapture = function () {
    return !settings.testOnly || Utils.isOptionValid("test");
  };

  //=============================================================================
  // Bitmap
  //  対象のビットマップを保存します。現状、ローカル環境下でのみ動作します。
  //=============================================================================
  Bitmap.prototype.save = function (fileName, format, extend) {
    var data = this._canvas.toDataURL("image/" + format, extend);
    data = data.replace(/^.*,/, "");
    if (format === "jpeg") format = "jpg";
    if (data) StorageManager.saveImg(fileName, format, data);
  };

  Bitmap.prototype.sign = function (text, fontInfo) {
    this.fontFace = fontInfo.face;
    this.fontSize = fontInfo.size;
    this.textColor = fontInfo.color;
    this.drawText(
      text,
      8,
      this.height - this.fontSize - 8,
      this.width - 8 * 2,
      this.fontSize,
      fontInfo.align
    );
  };

  Bitmap.prototype.signAndSave = function (
    signature,
    fileName,
    format,
    signatureImage
  ) {
    var fileFullPath = StorageManager.getLocalImgFileName(fileName);
    if (signatureImage) {
      this.signImage(signatureImage, signature);
    }
    this.sign(paramSignature, signature);
    this.save(
      fileFullPath,
      format,
      format === "jpeg" ? paramJpegQuality / 10 : undefined
    );
  };

  Bitmap.prototype.signImage = function (signBitmap, fontInfo) {
    var dx = 0,
      dy = this.height - signBitmap.height;
    switch (fontInfo.align) {
      case "center":
        dx = this.width / 2 - signBitmap.width / 2;
        break;
      case "right":
        dx = this.width - signBitmap.width;
        break;
    }
    this.blt(signBitmap, 0, 0, signBitmap.width, signBitmap.height, dx, dy);
  };

  //=============================================================================
  // Input
  //  ファンクションキーのマップを定義します。
  //=============================================================================
  Input.functionReverseMapper = {
    F1: 112,
    F2: 113,
    F3: 114,
    F4: 115,
    F5: 116,
    F6: 117,
    F7: 118,
    F8: 119,
    F9: 120,
    F10: 121,
    F11: 122,
    F12: 123,
  };

  //=============================================================================
  // SceneManager
  //  ファンクションキーが押下されたときにキャプチャを実行します。
  //=============================================================================
  SceneManager.captureNumber = 0;
  SceneManager.makeCapture = function () {
    if (paramSeName) {
      var se = settings.se;
      se.name = paramSeName;
      AudioManager.playSe(se);
    }
    this._captureBitmap = this.snap();
  };

  SceneManager.getCapture = function () {
    return this._captureBitmap || ImageManager.loadEmptyBitmap();
  };

  SceneManager.saveCapture = function (fileName, format) {
    if (!this._captureBitmap) return;
    var signature = this.getSignature();
    if (paramSignatureImage) {
      var image = ImageManager.loadPicture(paramSignatureImage, 0);
      image.addLoadListener(
        function () {
          this._captureBitmap.signAndSave(signature, fileName, format, image);
        }.bind(this)
      );
    } else {
      this._captureBitmap.signAndSave(signature, fileName, format, null);
    }
  };

  SceneManager.getSignature = function () {
    var signature = settings.signature;
    signature.size = paramSignatureSize;
    return signature;
  };

  SceneManager.takeCapture = function (format) {
    if (!format) {
      format = paramFileFormat;
    }
    this.makeCapture();
    this.saveCapture(paramFileName, format);
  };

  var _SceneManager_setupErrorHandlers = SceneManager.setupErrorHandlers;
  SceneManager.setupErrorHandlers = function () {
    _SceneManager_setupErrorHandlers.apply(this, arguments);
    if (Utils.isTestCapture()) {
      document.addEventListener("keyup", this.onKeyUpForCapture.bind(this));
    }
  };

  var _SceneManager_onKeyDown = SceneManager.onKeyDown;
  SceneManager.onKeyDown = function (event) {
    _SceneManager_onKeyDown.apply(this, arguments);
    if (
      paramSimultaneousCtrl === event.ctrlKey &&
      paramSimultaneousAlt === event.altKey &&
      Utils.isTestCapture()
    ) {
      this.onKeyDownForCapture(event);
    }
  };

  SceneManager.onKeyDownForCapture = function (event) {
    switch (event.keyCode) {
      case Input.functionReverseMapper[paramFuncKeyPngCapture]:
        SceneManager.takeCapture("png");
        break;
      case Input.functionReverseMapper[paramFuncKeyJpegCapture]:
        SceneManager.takeCapture("jpeg");
        break;
      case Input.functionReverseMapper[paramFuncKeyWebpCapture]:
        SceneManager.takeCapture("webp");
        break;
    }
  };

  SceneManager.onKeyUpForCapture = function (event) {
    // PrintScreen
    if (event.keyCode === 44) SceneManager.takeCapture();
  };

  //=============================================================================
  // StorageManager
  //  イメージファイルを保存します。
  //=============================================================================
  StorageManager.saveImg = function (fileName, format, data) {
    if (this.isLocalMode()) {
      this.saveImgToLocalFile(fileName + "." + format, data);
    } else {
      this.saveImgToWebStorage(fileName, data);
    }
  };

  StorageManager.saveImgToWebStorage = function (fileName, data) {
    localStorage.setItem(fileName, data);
  };

  StorageManager.saveImgToLocalFile = function (fileName, data) {
    var fs = require("fs");
    var dirPath = this.localImgFileDirectoryPath();
    var filePath = dirPath + fileName;
    if (!fs.existsSync(dirPath)) {
      fs.mkdirSync(dirPath);
    }
    fs.writeFileSync(filePath, new Buffer(data, "base64"));
  };

  StorageManager.localImgFileDirectoryPath = function () {
    var filePath = paramLocation;
    if (!filePath.match(/^[A-Z]:/)) {
      var path = require("path");
      filePath = path.join(path.dirname(process.mainModule.filename), filePath);
    }
    return decodeURIComponent(
      filePath.match(/\/$/) ? filePath : filePath + "/"
    );
  };

  StorageManager.getLocalImgFileName = function (fileName) {
    if (paramTimeStamp) {
      var date = new Date();
      return (
        fileName +
        "_" +
        date.getFullYear() +
        (date.getMonth() + 1).padZero(2) +
        date.getDate().padZero(2) +
        "_" +
        date.getHours().padZero(2) +
        date.getMinutes().padZero(2) +
        date.getSeconds().padZero(2)
      );
    } else {
      var number = SceneManager.captureNumber;
      if (number >= Math.pow(10, paramNumberDigit)) number = 0;
      SceneManager.captureNumber = number + 1;
      return fileName + (number > 0 ? number.padZero(paramNumberDigit) : "");
    }
  };
})();