code:
//=============================================================================
// MessageWindowHidden.js
// ----------------------------------------------------------------------------
// (C)2015-2018 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 2.0.0 2018/03/31 消去するトリガーを複数指定できる機能を追加。パラメータの指定方法を見直し。
// 1.4.0 2018/03/10 指定したスイッチがONの間はウィンドウ消去を無効化できる機能を追加
// 1.3.2 2017/08/02 ponidog_BackLog_utf8.jsとの競合を解消
// 1.3.1 2017/07/03 古いYEP_MessageCore.jsのネーム表示ウィンドウが再表示できない不具合の修正(by DarkPlasmaさま)
// 1.3.0 2017/03/16 連動して非表示にできるピクチャを複数指定できる機能を追加
// 1.2.1 2017/02/07 端末依存の記述を削除
// 1.2.0 2016/01/02 メッセージウィンドウと連動して指定したピクチャの表示/非表示が自動で切り替わる機能を追加
// 1.1.0 2016/08/25 選択肢の表示中はウィンドウを非表示にできないよう仕様変更
// 1.0.4 2016/07/22 YEP_MessageCore.jsのネーム表示ウィンドウと連携する機能を追加
// 1.0.3 2016/01/24 メッセージウィンドウが表示されていないときも非表示にできてしまう現象の修正
// 1.0.2 2016/01/02 競合対策
// 1.0.1 2015/12/31 コメント追加＋英語対応（仕様に変化なし）
// 1.0.0 2015/12/30 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc Erase message window
 * @author triacontane
 *
 * @param triggerButton
 * @desc Trigger buttons
 * (light_click or shift or control)
 * @default ["light_click"]
 * @type combo[]
 * @option light_click
 * @option shift
 * @option control
 * @option tab
 * @option pageup
 * @option pagedown
 * @option debug
 *
 * @param linkPictureNumbers
 * @desc Picture number of window show/hide
 * @default
 * @type number[]
 *
 * @param disableSwitchId
 * @desc 指定した番号のスイッチがONのとき、プラグインの機能が無効になります。
 * @default 0
 * @type switch
 *
 * @help Erase message window (and restore) when triggered
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc メッセージウィンドウ一時消去プラグイン
 * @author トリアコンタン
 *
 * @param triggerButton
 * @text ボタン名称
 * @desc ウィンドウを消去するボタンです。(複数登録可能) プラグイン等で入力可能なボタンを追加した場合は直接入力
 * @default ["右クリック"]
 * @type combo[]
 * @option 右クリック
 * @option shift
 * @option control
 * @option tab
 * @option pageup
 * @option pagedown
 * @option debug
 *
 * @param linkPictureNumbers
 * @text 連動ピクチャ番号
 * @desc ウィンドウ消去時に連動して不透明度を[0]にするピクチャの番号です。
 * @default
 * @type number[]
 *
 * @param disableSwitchId
 * @text 無効スイッチ番号
 * @desc 指定した番号のスイッチがONのとき、プラグインの機能が無効になります。
 * @default 0
 * @type switch
 *
 * @help メッセージウィンドウを表示中に指定したボタンを押下することで
 * メッセージウィンドウを消去します。もう一度押すと戻ります。
 *
 * ウィンドウ消去時に連動して不透明度を[0]にするピクチャを指定することができます。
 * 背景に特定のピクチャを使用している場合などに指定してください。
 * 再表示すると不透明度は[255]になります。
 *
 * ver2.0.0よりパラメータの指定方法が一部変更になりました。
 * 以前のバージョンを使っていた方は再設定をお願いします。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */
(function () {
  "use strict";

  /**
   * Create plugin parameter. param[paramName] ex. param.commandPrefix
   * @param pluginName plugin name(EncounterSwitchConditions)
   * @returns {Object} Created parameter
   */
  var createPluginParameter = function (pluginName) {
    var paramReplacer = function (key, value) {
      if (value === "null") {
        return value;
      }
      if (value[0] === '"' && value[value.length - 1] === '"') {
        return value;
      }
      try {
        return JSON.parse(value);
      } catch (e) {
        return value;
      }
    };
    var parameter = JSON.parse(
      JSON.stringify(PluginManager.parameters(pluginName), paramReplacer)
    );
    PluginManager.setParameters(pluginName, parameter);
    return parameter;
  };
  var param = createPluginParameter("MessageWindowHidden");

  //=============================================================================
  // Game_Picture
  //  メッセージウィンドウの表示可否と連動します。
  //=============================================================================
  Game_Picture.prototype.linkWithMessageWindow = function (opacity) {
    this._opacity = opacity;
    this._targetOpacity = opacity;
  };

  //=============================================================================
  // Window_Message
  //  指定されたボタン押下時にウィンドウとサブウィンドウを非表示にします。
  //=============================================================================
  var _Window_Message_updateWait = Window_Message.prototype.updateWait;
  Window_Message.prototype.updateWait = function () {
    if (
      !this.isClosed() &&
      this.isTriggeredHidden() &&
      !$gameMessage.isChoice()
    ) {
      if (!this.isHidden()) {
        this.hideAllWindow();
      } else {
        this.showAllWindow();
      }
    }
    var wait = _Window_Message_updateWait.apply(this, arguments);
    if (this.isHidden() && this.visible) {
      this.hideAllWindow();
    }
    return wait;
  };

  Window_Message.prototype.hideAllWindow = function () {
    this.hide();
    this.subWindows().forEach(
      function (subWindow) {
        this.hideSubWindow(subWindow);
      }.bind(this)
    );
    if (this.hasNameWindow() && !this.nameWindowIsSubWindow())
      this.hideSubWindow(this._nameWindow);
    this.linkPictures(0);
    this._hideByMessageWindowHidden = true;
  };

  Window_Message.prototype.showAllWindow = function () {
    this.show();
    this.subWindows().forEach(
      function (subWindow) {
        this.showSubWindow(subWindow);
      }.bind(this)
    );
    if (this.hasNameWindow() && !this.nameWindowIsSubWindow())
      this.showSubWindow(this._nameWindow);
    this.linkPictures(255);
    this._hideByMessageWindowHidden = false;
  };

  Window_Message.prototype.isHidden = function () {
    return this._hideByMessageWindowHidden;
  };

  Window_Message.prototype.linkPictures = function (opacity) {
    if (!param.linkPictureNumbers) {
      return;
    }
    param.linkPictureNumbers.forEach(function (pictureId) {
      this.linkPicture(opacity, pictureId);
    }, this);
  };

  Window_Message.prototype.linkPicture = function (opacity, pictureId) {
    var picture = $gameScreen.picture(pictureId);
    if (picture) {
      picture.linkWithMessageWindow(opacity);
    }
  };

  Window_Message.prototype.hideSubWindow = function (subWindow) {
    subWindow.prevVisible = subWindow.visible;
    subWindow.hide();
  };

  Window_Message.prototype.showSubWindow = function (subWindow) {
    if (subWindow.prevVisible) subWindow.show();
    subWindow.prevVisible = undefined;
  };

  Window_Message.prototype.hasNameWindow = function () {
    return this._nameWindow && typeof Window_NameBox !== "undefined";
  };

  // 古いYEP_MessageCore.jsでは、ネーム表示ウィンドウはsubWindowsに含まれる
  Window_Message.prototype.nameWindowIsSubWindow = function () {
    return (
      this.subWindows().filter(function (subWindow) {
        return subWindow === this._nameWindow;
      }, this).length > 0
    );
  };

  Window_Message.prototype.isTriggeredHidden = function () {
    if (
      param.disableSwitchId > 0 &&
      $gameSwitches.value(param.disableSwitchId)
    ) {
      return false;
    }
    return param.triggerButton.some(function (button) {
      switch (button) {
        case "":
        case "右クリック":
        case "light_click":
          return TouchInput.isCancelled();
        case "ok":
          return false;
        default:
          return Input.isTriggered(button);
      }
    });
  };

  var _Window_Message_updateInput = Window_Message.prototype.updateInput;
  Window_Message.prototype.updateInput = function () {
    if (this.isHidden()) return true;
    return _Window_Message_updateInput.apply(this, arguments);
  };

  //=============================================================================
  // Window_ChoiceList、Window_NumberInput、Window_EventItem
  //  非表示の間は更新を停止します。
  //=============================================================================
  var _Window_ChoiceList_update = Window_ChoiceList.prototype.update;
  Window_ChoiceList.prototype.update = function () {
    if (!this.visible) return;
    _Window_ChoiceList_update.apply(this, arguments);
  };

  var _Window_NumberInput_update = Window_NumberInput.prototype.update;
  Window_NumberInput.prototype.update = function () {
    if (!this.visible) return;
    _Window_NumberInput_update.apply(this, arguments);
  };

  var _Window_EventItem_update = Window_EventItem.prototype.update;
  Window_EventItem.prototype.update = function () {
    if (!this.visible) return;
    _Window_EventItem_update.apply(this, arguments);
  };
})();


code:
//=============================================================================
// MultipleWindowSkinSystem.js
// ----------------------------------------------------------------------------
// Copyright (c) 2017-2018 Tsumio
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.0.3 2018/01/21 ウィンドウの画像を正常に読み込めるよう修正。
// 1.0.2 2018/01/12 ライセンス表記を修正。
// 1.0.1 2018/01/12 注釈が不正な場合、通常のウィンドウを表示するよう変更。
// 1.0.0 2018/01/12 公開。
// ----------------------------------------------------------------------------
// [GitHub] : https://github.com/Tsumio/rmmv-plugins
// [Blog]   : http://ntgame.wpblog.jp/
// [Twitter]: https://twitter.com/TsumioNtGame
//=============================================================================

//=============================================================================
// jQuery.easing(include EASING EQUATIONS) is:
// Copyright (c) 2008 George McGinley Smith
// EASING EQUATIONS is:
// Copyright (c) 2001 Robert Penner
//
// Neither the name of the the names of contributors may be used to endorse or
// promote products derived from this software without specific prior written permission.
//=============================================================================

/*:
 * @plugindesc Dynamically change the image and display method of the message window.
 * @author Tsumio
 *
 * @param ----Basic Settings----
 * @desc
 * @default
 *
 * @param WindowsSettings
 * @type struct<WindowSettings>[]
 * @desc Settings of windows.
 *
 * @param PictureId
 * @type number
 * @max 999
 * @desc Picture ID to use for standing picture.
 * @default 100
 *
 * @help Dynamically change the image and display method of the message window.
 *
 * ----feature----
 * -> Dynamically change the image and display method of the message window.
 * -> Easing available.
 *
 * ----how to use----
 * After introducing this plugin, please set the window settings from the plugin parameter.
 * You can set any number of windows.
 *
 * Parameters meaning:
 * ・uniqueID -> Unique value used to distinguish message windows
 * ・skin: -> Skin image to apply to message window
 * ・actorName -> Name of the name window
 * ・picture -> Picture settings to be linked with the window
 * ・opacity -> Opacity
 * ・tone -> Tone
 * ・movement -> Where to display windows from
 * ・duration -> Time until easing stops
 * ・easingType -> Easing type
 *
 * After setting the parameters, create a "show text" event in the same way as usual of the event editor.
 * At this time, please create an "comment" event in front of the corresponding sentence.
 * Write a character string set with uniqueID in "comment".
 * It is also possible to give uniqueID "Black" to sentence A and give uniqueID "White" to sentence B in one event.
 *
 * Please do the above for each "show text" event.
 * When you run the game and start the event, a message window with uniqueID set in the "comment" event will be displayed.
 *
 * If the "comment" event is not set, a normal message window will be displayed.
 *
 * ---picture----
 * The picture uses the number specified by the "pictureId" of the plugin parameter.
 * If you leave the fileName parameter of the picture blank, the picture will not be displayed.
 *
 * ----name window----
 * It is displayed only when actorName is set.
 *
 * ---easing----
 * What is easing ?
 * See http://easings.net/
 *
 * EASING EQUATIONS of this program is created by Robert Penner.
 * See http://robertpenner.com/easing/
 *
 * In addition, I created the easing function by referring to the code published by George McGinley Smith.
 * See https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
 *
 * I may be paying attention to licenses, but if there is any violation please contact me.
 *
 * ----plugin command----
 * There is no plugin command.
 *
 * ----change log---
 * 1.0.3 2018/01/21 Fix a bug that can't load windows images.
 * 1.0.2 2018/01/12 Fix license notation.
 * 1.0.1 2018/01/12 If comment is invalid, to display normal window.
 * 1.0.0 2018/01/12 Release.
 *
 * ----remarks----
 * I shall not be responsible for any loss, damages and troubles from using this plugin.
 *
 * ----Terms of Use----
 * This plugin is free for both commercial and non-commercial use.
 * You may edit the source code to suit your needs,
 * so long as you don't claim the source code belongs to you.
 *
 */
/*:ja
 * @plugindesc メッセージウィンドウの画像や表示方法を動的に変更できるようにします。
 * @author ツミオ
 *
 * @param ----基本的な設定----
 * @desc
 * @default
 *
 * @param ウィンドウの設定
 * @type struct<WindowSettings>[]
 * @desc ウィンドウの設定。
 *
 * @param ピクチャ番号
 * @type number
 * @max 999
 * @desc 立ち絵の表示に使用するピクチャ番号。
 * @default 100
 *
 * @help メッセージウィンドウの画像や表示方法を動的に変更できるようにします。
 *
 * 【特徴】
 * ・メッセージウィンドウの画像や表示方法を動的に変更できるようにします。
 * ・イージングが利用できます。
 *
 * 【使用方法】
 * プラグインの導入後、プラグインパラメーターからウィンドウの設定をおこなってください。
 * ウィンドウはいくつでも設定できます。
 *
 * 各パラメーターは次のような意味です。
 * ・uniqueID： メッセージウィンドウを区別するために使用する一意の値
 * ・skin: メッセージウィンドウに適用するスキン画像
 * ・actorName:名前ウィンドウに表示する名前
 * ・picture：ウィンドウの表示に連動させるピクチャの設定
 * ・opacity: 透明度
 * ・tone: 色調
 * ・movement: どこからウィンドウを表示させるか
 * ・duration: イージングが停止するまでの時間
 * ・easingType: イージングの種類
 *
 * パラメーター設定後、イベントエディタの「文章の表示」で通常と同じように文章の表示イベントを作成します。
 * このとき、該当の文章の一つ手前に「注釈」イベントを作成してください。
 * 「注釈」にはuniqueIDで設定した文字列を書き込みます。
 * 一つのイベント内でAという文章にはuniqueID「Black」を与え、Bという文章にはuniqueID「White」を与えるといったことも可能です。
 *
 * 以上を各文章に対しておこなってください。
 * ゲームを実行し、イベントを起動すると「注釈」イベントで設定したuniqueIDのメッセージウィンドウが表示されます。
 *
 * なお、「注釈」イベントが設定されていない場合、通常のメッセージウィンドウが表示されます。
 *
 * 【ピクチャ】
 * ピクチャはプラグインパラメータの「ピクチャ番号」で指定した番号を利用します。
 * また、ピクチャのfileNameパラメータを空白にしておくと、ピクチャは表示されません。
 *
 * 【名前ウィンドウ】
 * actorNameを設定した場合にのみ表示されます。
 *
 * 【イージング】
 * イージングがどのような動作をするのかは、イージング早見表が参考になるかもしれません。
 * http://easings.net/ja
 *
 * なお、当プログラムで使用しているイージングの計算式はRobert Penner氏によって作成されました。
 * http://robertpenner.com/easing/
 *
 * また、George McGinley Smith氏が公開しているコードを参考にイージングの機能を作成しました。
 * https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
 *
 * ライセンスには注意しているつもりですが、もし何か違反があればご連絡ください。
 *
 * 【プラグインコマンド】
 * プラグインコマンドはありません。
 *
 * 【更新履歴】
 * 1.0.3 2018/01/21 ウィンドウの画像を正常に読み込めるよう修正。
 * 1.0.2 2018/01/12 ライセンス表記を修正。
 * 1.0.1 2018/01/12 注釈が不正な場合、通常のウィンドウを表示するよう変更。
 * 1.0.0 2018/01/12 公開。
 *
 * 【備考】
 * 当プラグインを利用したことによるいかなる損害に対しても、制作者は一切の責任を負わないこととします。
 *
 * 【利用規約】
 * ソースコードの著作権者が自分であると主張しない限り、
 * 作者に無断で改変、再配布が可能です。
 * 利用形態（商用、18禁利用等）についても制限はありません。
 * 自由に使用してください。
 *
 */
/*~struct~WindowSettings:
 *
 * @param uniqueID
 * @type string
 * @desc ユニークID(Unique ID).
 *
 * @param skin
 * @type file
 * @desc スキン(Skin).
 * @dir img/system
 *
 * @param actorName
 * @type string
 * @desc アクター名(Actor name).
 *
 * @param picture
 * @type struct<Picture>
 * @desc ピクチャの設定(Picture settings).
 *
 * @param opacity
 * @type number
 * @max 255
 * @desc 透明度(Opacity).
 * @default 192
 *
 * @param tone
 * @type struct<Tone>
 * @desc 色調(Tone).
 * @default {"red":"0","green":"0","blue":"0"}
 *
 * @param movement
 * @type select
 * @option None
 * @option fromTop
 * @option fromBottom
 * @option fromRight
 * @option fromLeft
 * @desc 動作(Movement).
 * @default None
 *
 * @param duration
 * @type number
 * @decimals 1
 * @desc 期間(Duration)。秒(Sec)。
 * @default 0.3
 *
 * @param easingType
 * @type select
 * @option linear
 * @option easeInQuad
 * @option easeOutQuad
 * @option easeInOutQuad
 * @option easeInCubic
 * @option easeOutCubic
 * @option easeInOutCubic
 * @option easeInQuart
 * @option easeOutQuart
 * @option easeInOutQuart
 * @option easeInQuint
 * @option easeOutQuint
 * @option easeInOutQuint
 * @option easeInSine
 * @option easeOutSine
 * @option easeInOutSine
 * @option easeInExpo
 * @option easeOutExpo
 * @option easeInOutExpo
 * @option easeInCirc
 * @option easeOutCirc
 * @option easeInOutCirc
 * @option easeInElastic
 * @option easeOutElastic
 * @option easeInOutElastic
 * @option easeOutBounce
 * @desc イージングの種類(Easing type).
 * @default linear
 *
 */
/*~struct~Tone:
 *
 * @param red
 * @type number
 * @max 255
 * @desc 赤(Red).
 * @default 0
 *
 * @param green
 * @type number
 * @max 255
 * @desc 緑(Green).
 * @default 0
 *
 * @param blue
 * @type number
 * @max 255
 * @desc 青(Blue).
 * @default 0
 *
 */
/*~struct~Picture:
 *
 * @param fileName
 * @type file
 * @desc ピクチャのファイル名前(File name of the picture).
 * @dir img/pictures
 *
 * @param origin
 * @type select
 * @option 左上(LeftTop)
 * @value 0
 * @option 中央(Center)
 * @value 1
 * @desc 原点(Origin).
 * @default 0
 *
 * @param x
 * @type number
 * @max 10000
 * @min -10000
 * @desc X座標(X coordinate).
 * @default 0
 *
 * @param y
 * @type number
 * @max 10000
 * @min -10000
 * @desc Y座標(Y coordinate).
 * @default 0
 *
 * @param scaleX
 * @type number
 * @max 10000
 * @min -10000
 * @desc 幅の拡大率。パーセンテージ。(Scale X.Percentage)
 * @default 100
 *
 * @param scaleY
 * @type number
 * @max 10000
 * @min -10000
 * @desc 高さの拡大率。パーセンテージ。(Scale Y.Percentage)
 * @default 100
 *
 * @param opacity
 * @type number
 * @max 255
 * @desc 透明度(Opacity)
 * @default 255
 *
 * @param blendMode
 * @type select
 * @option 通常(Normal)
 * @value 0
 * @option 加算(Addition)
 * @value 1
 * @option 乗算(Multiply)
 * @value 2
 * @option スクリーン(Screen)
 * @value 3
 * @desc 合成方法(BlendMode)
 * @default 0
 *
 */

(function () {
  "use strict";
  var pluginName = "MultipleWindowSkinSystem";

  ////=============================================================================
  //// Local function
  ////  These functions checks & formats pluguin's command parameters.
  ////  I borrowed these functions from Triacontane.Thanks!
  ////=============================================================================
  var getParamString = function (paramNames) {
    if (!Array.isArray(paramNames)) paramNames = [paramNames];
    for (var i = 0; i < paramNames.length; i++) {
      var name = PluginManager.parameters(pluginName)[paramNames[i]];
      if (name) return name;
    }
    return "";
  };

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

  //This function is not written by Triacontane.Tsumio wrote this function !
  var convertParam = function (param) {
    if (param !== undefined) {
      try {
        return JSON.parse(param);
      } catch (e) {
        console.group();
        console.error(
          "%cParameter is invalid ! You should check the following parameter !",
          "background-color: #5174FF"
        );
        console.error("Parameter:" + eval(param));
        console.error("Error message :" + e);
        console.groupEnd();
      }
    }
  };

  //This function is not written by Triacontane.Tsumio wrote this function !
  var convertArrayParam = function (param) {
    if (param !== undefined) {
      try {
        const array = JSON.parse(param);
        for (let i = 0; i < array.length; i++) {
          array[i] = JSON.parse(array[i]);
        }
        return array;
      } catch (e) {
        console.group();
        console.error(
          "%cParameter is invalid ! You should check the following parameter !",
          "background-color: #5174FF"
        );
        console.error("Parameter:" + eval(param));
        console.error("Error message :" + e);
        console.groupEnd();
      }
    }
  };

  /**
   * Convert to number.Receive converted JSON object.
   * @param {Object} obj
   *
   */
  //This function is not written by Triacontane.Tsumio wrote this function !
  var convertToNumber = function (obj) {
    for (var prop in obj) {
      obj[prop] = Number(obj[prop]);
    }
    return obj;
  };

  ////=============================================================================
  //// Get and set pluguin parameters.
  ////=============================================================================
  var param = {};
  //Basic Stteings
  param.windowsSettings = getParamString([
    "WindowsSettings",
    "ウィンドウの設定",
  ]);
  param.pictureId = getParamNumber(["PictureId", "ピクチャ番号"]);

  ////==============================
  //// Convert parameters.
  ////==============================
  param.windowsSettings = convertArrayParam(param.windowsSettings);

  ////==============================
  //// Convert to Number.
  ////==============================
  //None

  ////=============================================================================
  //// Scene_Boot
  ///   Override this class for loading images.
  ////=============================================================================
  const _Scene_Boot_loadSystemWindowImage =
    Scene_Boot.prototype.loadSystemWindowImage;
  Scene_Boot.prototype.loadSystemWindowImage = function () {
    _Scene_Boot_loadSystemWindowImage.call(this);

    //Addtional window images.
    for (let setting of param.windowsSettings) {
      ImageManager.reserveSystem(setting.skin);
    }
  };

  ////=============================================================================
  //// Scene_Map
  ////  Add MultipleWindow.
  ////=============================================================================
  const _Scene_Map_createMessageWindow =
    Scene_Map.prototype.createMessageWindow;
  Scene_Map.prototype.createMessageWindow = function () {
    _Scene_Map_createMessageWindow.call(this);
    this.createMultipleMessageWindows();
  };

  Scene_Map.prototype.createMultipleMessageWindows = function () {
    const factory = new WindowFactory();
    this._multipleMessageWindow = new Map();
    for (let setting of param.windowsSettings) {
      this._multipleMessageWindow.set(
        setting.uniqueID,
        factory.getInstance(setting.uniqueID)
      );
      this.addWindow(this._multipleMessageWindow.get(setting.uniqueID));
      this._multipleMessageWindow
        .get(setting.uniqueID)
        .subWindows()
        .forEach(function (window) {
          this.addWindow(window);
        }, this);
    }
  };

  ////=============================================================================
  //// MultipleWindow_Base
  ////  Inherit from Window_Message.
  ////=============================================================================
  const _Window_Message_canStart = Window_Message.prototype.canStart;
  Window_Message.prototype.canStart = function () {
    const result = _Window_Message_canStart.call(this);
    return result && this.isEnabled();
  };

  const _Window_Message_updateWait = Window_Message.prototype.updateWait;
  Window_Message.prototype.updateWait = function () {
    const result = _Window_Message_updateWait.call(this);
    this.modifyWindow();
    return result;
  };

  const _Window_Message_startInput = Window_Message.prototype.startInput;
  Window_Message.prototype.startInput = function () {
    if (!this.isEnabled()) {
      return false;
    }
    const result = _Window_Message_startInput.call(this);
    return result;
  };

  Window_Message.prototype.modifyWindow = function () {
    if (this.isEnabled()) {
      this.show();
    } else {
      //HACK : These code may cause problems.
      this.close();
      this.hide();
    }
  };

  Window_Message.prototype.isEnabled = function () {
    return (
      $gameMessage.currentWindow === null || !this.anyMultipleWindowValid()
    );
  };

  Window_Message.prototype.anyMultipleWindowValid = function () {
    for (let setting of param.windowsSettings) {
      if (setting.uniqueID === $gameMessage.currentWindow) {
        return true;
      }
    }
    return false;
  };

  ////=============================================================================
  //// Game_Interpreter
  ////  Decide the appropriate window from the comments.
  ////=============================================================================
  const _Game_Interpreter_command108 = Game_Interpreter.prototype.command108;
  Game_Interpreter.prototype.command108 = function () {
    //Comment
    $gameMessage.currentWindow = this._params[0];

    const result = _Game_Interpreter_command108.call(this);
    return result;
  };

  const _Game_Interpreter_terminate = Game_Interpreter.prototype.terminate;
  Game_Interpreter.prototype.terminate = function () {
    _Game_Interpreter_terminate.call(this);

    //After the event ends, forcibly erase the picture.
    PictureAction.erase();
  };

  ////=============================================================================
  //// Game_Message
  ////  Add ccurent window information.
  ////=============================================================================
  const _Game_Message_clear = Game_Message.prototype.clear;
  Game_Message.prototype.clear = function () {
    _Game_Message_clear.call(this);
    this.currentWindow = null;
  };

  ////=============================================================================
  //// PictureAction
  ////  Create a picture.
  ////=============================================================================
  class PictureAction {
    /**
     * @param {PictureSettings} settings
     */
    static tryShow(settings) {
      if (!this.canShow(settings.FILE_NAME)) {
        return false;
      }
      $gameScreen.showPicture(
        param.pictureId,
        settings.FILE_NAME,
        settings.FILE_NAME,
        settings.X,
        settings.Y,
        settings.SCALE_X,
        settings.SCALE_Y,
        settings.OPACITY,
        settings.BLEND_MODE
      );
      return true;
    }

    static erase() {
      $gameScreen.erasePicture(param.pictureId);
    }

    static canShow(fileName) {
      return fileName.length > 0;
    }
  }

  ////=============================================================================
  //// PictureSettings
  ////  Settings.
  ////=============================================================================
  class PictureSettings {
    constructor(settings) {
      this.initialize.apply(this, arguments);
    }

    initialize(settings) {
      this._fileName = settings.fileName;
      this._origin = Number(settings.origin);
      this._x = Number(settings.x);
      this._y = Number(settings.y);
      this._scaleX = Number(settings.scaleX);
      this._scaleY = Number(settings.scaleY);
      this._opacity = Number(settings.opacity);
      this._blendMode = Number(settings.blendMode);
    }

    get FILE_NAME() {
      return this._fileName;
    }

    get ORIGIN() {
      return this._origin;
    }

    get X() {
      return this._x;
    }

    get Y() {
      return this._y;
    }

    get SCALE_X() {
      return this._scaleX;
    }

    get SCALE_Y() {
      return this._scaleY;
    }

    get OPACITY() {
      return this._opacity;
    }

    get BLEND_MODE() {
      return this._blendMode;
    }
  }

  ////=============================================================================
  //// EasingFactory
  ////  Create easing data.
  ////  t: current time, b: begInnIng value, c: change In value, d: duration
  ////
  ////  EASING EQUATIONS are created by Robert Penner.
  ////  See http://robertpenner.com/easing/
  ////
  ////  And I referred to jQuery Easing written by George McGinley Smith.
  ////  See https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
  ////=============================================================================
  //=============================================================================
  // jQuery.easing(include EASING EQUATIONS) is:
  // Copyright (c) 2008 George McGinley Smith
  // EASING EQUATIONS is:
  // Copyright (c) 2001 Robert Penner
  //
  // Neither the name of the the names of contributors may be used to endorse or
  // promote products derived from this software without specific prior written permission.
  //=============================================================================
  class EasingFactory {
    /**
     * Get initialize location.
     */
    static create(type, windowWidth, windowHeight, easingType) {
      const initialPosition = this.getInitialPosition(
        type,
        windowWidth,
        windowHeight
      );
      const data = { initPos: initialPosition, easingFunc: this[easingType] };
      return data;
    }

    static getInitialPosition(type, windowWidth, windowHeight) {
      const posList = this.getPositionList(type, windowWidth, windowHeight);

      for (let elm of posList) {
        if (elm.type === type) {
          return elm;
        }
      }
      return posList[0]; //None
    }

    static getPositionList(type, windowWidth, windowHeight) {
      const defaultX = (Graphics.boxWidth - windowWidth) / 2;
      const defaultY =
        ($gameMessage.positionType() * (Graphics.boxHeight - windowHeight)) / 2;
      const posList = [];

      //Push.
      posList.push({ x: defaultX, y: defaultY, type: "None" });
      posList.push({ x: defaultX, y: -windowHeight, type: "fromTop" });
      posList.push({
        x: defaultX,
        y: Graphics.boxHeight + windowHeight,
        type: "fromBottom",
      });
      posList.push({
        x: defaultX + windowWidth,
        y: defaultY,
        type: "fromRight",
      });
      posList.push({ x: -windowWidth, y: defaultY, type: "fromLeft" });

      return posList;
    }

    // t: current time, b: begInnIng value, c: change In value, d: duration
    static linear(t, b, c, d) {
      return (c * t) / d + b;
    }

    static easeInQuad(t, b, c, d) {
      return c * (t /= d) * t + b;
    }

    static easeOutQuad(t, b, c, d) {
      return -c * (t /= d) * (t - 2) + b;
    }

    static easeInOutQuad(t, b, c, d) {
      if ((t /= d / 2) < 1) return (c / 2) * t * t + b;
      return (-c / 2) * (--t * (t - 2) - 1) + b;
    }

    static easeInCubic(t, b, c, d) {
      return c * (t /= d) * t * t + b;
    }

    static easeOutCubic(t, b, c, d) {
      return c * ((t = t / d - 1) * t * t + 1) + b;
    }

    static easeInOutCubic(t, b, c, d) {
      if ((t /= d / 2) < 1) return (c / 2) * t * t * t + b;
      return (c / 2) * ((t -= 2) * t * t + 2) + b;
    }

    static easeInQuart(t, b, c, d) {
      return c * (t /= d) * t * t * t + b;
    }

    static easeOutQuart(t, b, c, d) {
      return -c * ((t = t / d - 1) * t * t * t - 1) + b;
    }

    static easeInOutQuart(t, b, c, d) {
      if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t + b;
      return (-c / 2) * ((t -= 2) * t * t * t - 2) + b;
    }

    static easeInQuint(t, b, c, d) {
      return c * (t /= d) * t * t * t * t + b;
    }

    static easeOutQuint(t, b, c, d) {
      return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
    }

    static easeInOutQuint(t, b, c, d) {
      if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t * t + b;
      return (c / 2) * ((t -= 2) * t * t * t * t + 2) + b;
    }

    static easeInSine(t, b, c, d) {
      return -c * Math.cos((t / d) * (Math.PI / 2)) + c + b;
    }

    static easeOutSine(t, b, c, d) {
      return c * Math.sin((t / d) * (Math.PI / 2)) + b;
    }

    static easeInOutSine(t, b, c, d) {
      return (-c / 2) * (Math.cos((Math.PI * t) / d) - 1) + b;
    }

    static easeInExpo(t, b, c, d) {
      return t == 0 ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
    }

    static easeOutExpo(t, b, c, d) {
      return t == d ? b + c : c * (-Math.pow(2, (-10 * t) / d) + 1) + b;
    }

    static easeInOutExpo(t, b, c, d) {
      if (t == 0) return b;
      if (t == d) return b + c;
      if ((t /= d / 2) < 1) return (c / 2) * Math.pow(2, 10 * (t - 1)) + b;
      return (c / 2) * (-Math.pow(2, -10 * --t) + 2) + b;
    }

    static easeInCirc(t, b, c, d) {
      return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
    }

    static easeOutCirc(t, b, c, d) {
      return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
    }

    static easeInOutCirc(t, b, c, d) {
      if ((t /= d / 2) < 1) return (-c / 2) * (Math.sqrt(1 - t * t) - 1) + b;
      return (c / 2) * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
    }

    static easeInElastic(t, b, c, d) {
      var s = 1.70158;
      var p = 0;
      var a = c;
      if (t == 0) return b;
      if ((t /= d) == 1) return b + c;
      if (!p) p = d * 0.3;
      if (a < Math.abs(c)) {
        a = c;
        var s = p / 4;
      } else var s = (p / (2 * Math.PI)) * Math.asin(c / a);
      return (
        -(
          a *
          Math.pow(2, 10 * (t -= 1)) *
          Math.sin(((t * d - s) * (2 * Math.PI)) / p)
        ) + b
      );
    }

    static easeOutElastic(t, b, c, d) {
      var s = 1.70158;
      var p = 0;
      var a = c;
      if (t == 0) return b;
      if ((t /= d) == 1) return b + c;
      if (!p) p = d * 0.3;
      if (a < Math.abs(c)) {
        a = c;
        var s = p / 4;
      } else var s = (p / (2 * Math.PI)) * Math.asin(c / a);
      return (
        a * Math.pow(2, -10 * t) * Math.sin(((t * d - s) * (2 * Math.PI)) / p) +
        c +
        b
      );
    }

    static easeInOutElastic(t, b, c, d) {
      var s = 1.70158;
      var p = 0;
      var a = c;
      if (t == 0) return b;
      if ((t /= d / 2) == 2) return b + c;
      if (!p) p = d * (0.3 * 1.5);
      if (a < Math.abs(c)) {
        a = c;
        var s = p / 4;
      } else var s = (p / (2 * Math.PI)) * Math.asin(c / a);
      if (t < 1)
        return (
          -0.5 *
            (a *
              Math.pow(2, 10 * (t -= 1)) *
              Math.sin(((t * d - s) * (2 * Math.PI)) / p)) +
          b
        );
      return (
        a *
          Math.pow(2, -10 * (t -= 1)) *
          Math.sin(((t * d - s) * (2 * Math.PI)) / p) *
          0.5 +
        c +
        b
      );
    }

    static easeOutBounce(t, b, c, d) {
      if ((t /= d) < 1 / 2.75) {
        return c * (7.5625 * t * t) + b;
      } else if (t < 2 / 2.75) {
        return c * (7.5625 * (t -= 1.5 / 2.75) * t + 0.75) + b;
      } else if (t < 2.5 / 2.75) {
        return c * (7.5625 * (t -= 2.25 / 2.75) * t + 0.9375) + b;
      } else {
        return c * (7.5625 * (t -= 2.625 / 2.75) * t + 0.984375) + b;
      }
    }
  }

  ////=============================================================================
  //// MultipleWindow_Base
  ////  Inherit from Window_Message.
  ////=============================================================================
  class MultipleWindow_Base extends Window_Message {
    /**
     * @param {MultipleWindow_Settings} settings
     */
    initialize(settings) {
      this._settings = settings;
      this._easing = null;
      this._easingTime = 0;
      super.initialize();
    }

    /**
     * @return {MultipleWindow_Settings}
     */
    get SETTINGS() {
      return this._settings;
    }

    loadWindowskin() {
      this.windowskin = ImageManager.loadSystem(this.SETTINGS.SKIN_NAME);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }

    hide() {
      super.hide();
      this._actorNameWindow.hide();
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    canStart() {
      //NOTE : Don't use "super.canStart()".It cause some troubles.
      return (
        $gameMessage.hasText() && !$gameMessage.scrollMode() && this.isEnabled()
      );
    }

    createSubWindows() {
      super.createSubWindows();
      this._goldWindow = new MultipleWindow_Gold(0, 0, this.SETTINGS);
      this._goldWindow.x = Graphics.boxWidth - this._goldWindow.width;
      this._goldWindow.openness = 0;
      this._choiceWindow = new MultipleWindow_ChoiceList(this, this.SETTINGS);
      this._numberWindow = new MultipleWindow_NumberInput(this, this.SETTINGS);
      this._itemWindow = new MultipleWindow_EventItem(this, this.SETTINGS);
      this._actorNameWindow = new MultipleWindow_ActorName(this, this.SETTINGS);
    }

    //Override
    subWindows() {
      return [
        this._goldWindow,
        this._choiceWindow,
        this._numberWindow,
        this._itemWindow,
        this._actorNameWindow,
      ];
    }

    update() {
      super.update();

      this.updateEasing();
    }

    updateEasing() {
      if (!this._easing) {
        return;
      }
      //Initialize.
      const startValueX = this._easing.initPos.x;
      const startValueY = this._easing.initPos.y;
      const changeValueX = this.destX - startValueX;
      const changeValueY = this.destY - startValueY;
      const duration = this.SETTINGS.DURATION;

      //Update position.
      if (this.easingTime <= duration) {
        this.x = this._easing.easingFunc(
          this.easingTime,
          startValueX,
          changeValueX,
          duration
        );
        this.y = this._easing.easingFunc(
          this.easingTime,
          startValueY,
          changeValueY,
          duration
        );
      }

      //Update time.
      this.updateEasingTime();
    }

    startEasing() {
      //Initialize destination.
      this.destX = this.x;
      this.destY = this.y;

      //Set initial location.
      this._easing = EasingFactory.create(
        this.SETTINGS.MOVEMENT,
        this.windowWidth(),
        this.windowHeight(),
        this.SETTINGS.EASING_TYPE
      );
      this.x = this._easing.initPos.x;
      this.y = this._easing.initPos.y;

      //Initialize time.
      this.resetEasingTime();
    }

    startMessage() {
      super.startMessage();
      this.startEasing();
      this._actorNameWindow.start();
      this.tryShowPicture();
    }

    updatePlacement() {
      super.updatePlacement();
      this.x = (Graphics.boxWidth - this.windowWidth()) / 2; //Initial position.
    }

    /**
     * Can enable this window ?
     */
    isEnabled() {
      //Override.
      return $gameMessage.currentWindow === this.SETTINGS.UNIQUE_ID;
    }

    get easingTime() {
      return this._easingTime / 60;
    }

    updateEasingTime() {
      this._easingTime++;
    }

    resetEasingTime() {
      this._easingTime = 0;
    }

    tryShowPicture() {
      const isValid = PictureAction.tryShow(this.SETTINGS.PICTURE);
      if (!isValid) {
        PictureAction.erase();
      }
    }
  }

  ////=============================================================================
  //// SettingsFactory
  ////  MultipleWindow_Settings of factory.
  ////=============================================================================
  class WindowFactory {
    constructor() {
      this.initialize.apply(this, arguments);
    }

    initialize() {
      const settings = new SettingsFactory();
      this._instances = new Map();

      //Set all settings from parameter.
      for (let entry of settings.instances.entries()) {
        this._instances.set(entry[0], new MultipleWindow_Base(entry[1])); //key, value
      }
    }

    get instances() {
      return this._instances;
    }

    getInstance(windowName) {
      return this.instances.get(windowName);
    }

    existInstances() {
      return !!this._instances;
    }
  }

  ////=============================================================================
  //// SettingsFactory
  ////  MultipleWindow_Settings of factory.
  ////=============================================================================
  class SettingsFactory {
    constructor() {
      this.initialize.apply(this, arguments);
    }

    initialize() {
      this._instances = new Map();
      //Set all settings from parameter.
      for (let setting of param.windowsSettings) {
        this._instances.set(
          setting.uniqueID,
          new MultipleWindow_Settings(
            setting.uniqueID,
            setting.skin,
            setting.opacity,
            setting.tone,
            setting.movement,
            setting.duration,
            setting.easingType,
            setting.actorName,
            setting.picture
          )
        );
      }
    }

    get instances() {
      return this._instances;
    }

    getInstance(windowName) {
      return this.instances.get(windowName);
    }

    existInstances() {
      return !!this._instances;
    }
  }

  ////=============================================================================
  //// MultipleWindow_Settings
  ////  Multiple window settings.
  ////=============================================================================
  class MultipleWindow_Settings {
    constructor(
      uniqueID,
      skinName,
      opacity,
      tone,
      movement,
      duration,
      easingType,
      actorName,
      picture
    ) {
      this.initialize.apply(this, arguments);
    }

    initialize(
      uniqueID,
      skinName,
      opacity,
      tone,
      movement,
      duration,
      easingType,
      actorName,
      picture
    ) {
      this._uniqueID = uniqueID;
      this._skinName = skinName;
      this._opacity = Number(opacity);
      this._tone = convertToNumber(convertParam(tone));
      this._movement = movement;
      this._duration = duration;
      this._easingType = easingType;
      this._actorName = actorName;
      this._picture = new PictureSettings(convertParam(picture));
    }

    /**
     * @return {String}
     */
    get SKIN_NAME() {
      return this._skinName;
    }

    /**
     * @return {String}
     */
    get UNIQUE_ID() {
      return this._uniqueID;
    }

    /**
     * @return {Number}
     */
    get OPACITY() {
      return this._opacity;
    }

    /**
     * @return {Object}
     */
    get TONE() {
      return this._tone;
    }

    /**
     * @return {String}
     */
    get MOVEMENT() {
      return this._movement;
    }

    /**
     * @return {Number}
     */
    get DURATION() {
      return this._duration;
    }

    /**
     * @return {String}
     */
    get EASING_TYPE() {
      return this._easingType;
    }

    /**
     * @return {String}
     */
    get ACTOR_NAME() {
      return this._actorName;
    }

    /**
     * @return {String}
     */
    get PICTURE() {
      return this._picture;
    }
  }

  ////=============================================================================
  //// MultipleWindow_Gold
  ////
  ////=============================================================================
  class MultipleWindow_Gold extends Window_Gold {
    /**
     * @param {MultipleWindow_Settings} settings
     */
    initialize(x, y, settings) {
      this.SETTINGS = settings;
      super.initialize(x, y);

      this.windowskin = ImageManager.loadSystem(settings.SKIN_NAME);
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }
  }

  ////=============================================================================
  //// MultipleWindow_ChoiceList
  ////
  ////=============================================================================
  class MultipleWindow_ChoiceList extends Window_ChoiceList {
    /**
     * @param {MultipleWindow_Settings} skin
     */
    initialize(messageWindow, settings) {
      this.SETTINGS = settings;
      super.initialize(messageWindow);

      this.windowskin = ImageManager.loadSystem(settings.SKIN_NAME);
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }

    //Override.
    updatePlacement() {
      var positionType = $gameMessage.choicePositionType();
      var messageY = this._messageWindow.destY; //Changed.
      this.width = this.windowWidth();
      this.height = this.windowHeight();
      switch (positionType) {
        case 0:
          this.x = 0;
          break;
        case 1:
          this.x = (Graphics.boxWidth - this.width) / 2;
          break;
        case 2:
          this.x = Graphics.boxWidth - this.width;
          break;
      }
      if (messageY >= Graphics.boxHeight / 2) {
        this.y = messageY - this.height;
      } else {
        this.y = messageY + this._messageWindow.height;
      }
    }
  }

  ////=============================================================================
  //// MultipleWindow_NumberInput
  ////
  ////=============================================================================
  class MultipleWindow_NumberInput extends Window_NumberInput {
    /**
     * @param {MultipleWindow_Settings} settings
     */
    initialize(messageWindow, settings) {
      this.SETTINGS = settings;
      super.initialize(messageWindow);

      this.windowskin = ImageManager.loadSystem(settings.SKIN_NAME);
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }

    //Override.
    updatePlacement() {
      var messageY = this._messageWindow.destY;
      var spacing = 8;
      this.width = this.windowWidth();
      this.height = this.windowHeight();
      this.x = (Graphics.boxWidth - this.width) / 2;
      if (messageY >= Graphics.boxHeight / 2) {
        this.y = messageY - this.height - spacing;
      } else {
        this.y = messageY + this._messageWindow.height + spacing;
      }
    }
  }

  ////=============================================================================
  //// MultipleWindow_EventItem
  ////
  ////=============================================================================
  class MultipleWindow_EventItem extends Window_EventItem {
    /**
     * @param {MultipleWindow_Settings} settings
     */
    initialize(messageWindow, settings) {
      this.SETTINGS = settings;
      super.initialize(messageWindow);

      this.windowskin = ImageManager.loadSystem(settings.SKIN_NAME);
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }

    updatePlacement() {
      if (this._messageWindow.destY >= Graphics.boxHeight / 2) {
        this.y = 0;
      } else {
        this.y = Graphics.boxHeight - this.height;
      }
    }
  }

  ////=============================================================================
  //// MultipleWindow_ActorName
  ////  Sub window for actor name.
  ////=============================================================================
  class MultipleWindow_ActorName extends Window_Base {
    /**
     * @param {MultipleWindow_Settings} settings
     */
    constructor(messageWindow, settings) {
      this.initialize.apply(this, arguments);
    }

    /**
     * @param {MultipleWindow_Settings} settings
     */
    initialize(messageWindow, settings) {
      //Class Settings.
      this.SETTINGS = settings;
      this._easing = null;
      this._easingTime = 0;

      //Local settings.
      const actorName = settings.ACTOR_NAME;
      const tempBitmap = new Bitmap();
      const width =
        tempBitmap.measureTextWidth(actorName || "") +
        this.standardPadding() * 2;
      const height = this.fittingHeight(1);

      //Initialize
      super.initialize(0, 0, width, height);
      this._messageWindow = messageWindow;
      this.windowskin = ImageManager.loadSystem(settings.SKIN_NAME);
      this._isEnabled = !!actorName;

      //Move
      this.move(0, 0, width, height);
      this.hide();

      //Draw actor name
      this.drawTextEx(actorName, 0, 0);
    }

    start() {
      if (!this.isEnabled()) {
        return;
      }
      this.updatePlacement();
      this.show();
      this.startEasing();
    }

    updateTone() {
      const tone = this.SETTINGS.TONE;
      this.setTone(tone.red, tone.blue, tone.green);
    }

    standardBackOpacity() {
      return this.SETTINGS.OPACITY;
    }

    updatePlacement() {
      const messageY = this._messageWindow.destY; //Changed.
      this.x = 0;
      if (messageY >= Graphics.boxHeight / 2) {
        this.y = messageY - this.height;
      } else {
        this.y = messageY + this._messageWindow.height;
      }
    }

    isEnabled() {
      return this._isEnabled;
    }

    update() {
      super.update();

      this.updateEasing();
    }

    updateEasing() {
      if (!this._easing) {
        return;
      }
      //Initialize.
      const startValueX = this._easing.initPos.x;
      const startValueY = this._easing.initPos.y;
      const changeValueX = this.destX - startValueX;
      const changeValueY = this.destY - startValueY;
      const duration = this.SETTINGS.DURATION;

      //Update position.
      if (this.easingTime <= duration) {
        this.x = this._easing.easingFunc(
          this.easingTime,
          startValueX,
          changeValueX,
          duration
        );
        this.y = this._easing.easingFunc(
          this.easingTime,
          startValueY,
          changeValueY,
          duration
        );
      }

      //Update time.
      this.updateEasingTime();
    }

    startEasing() {
      //Initialize destination.
      this.destX = this.x;
      this.destY = this.y;

      //Set initial location.
      this._easing = EasingFactory.create(
        this.SETTINGS.MOVEMENT,
        this.width,
        this.height,
        this.SETTINGS.EASING_TYPE
      );
      this.x = this._easing.initPos.x;
      this.y = this._easing.initPos.y;

      //Initialize time.
      this.resetEasingTime();
    }

    get easingTime() {
      return this._easingTime / 60;
    }

    updateEasingTime() {
      this._easingTime++;
    }

    resetEasingTime() {
      this._easingTime = 0;
    }
  }

  ////=============================================================================
  //// Debug
  ////  This static class is for simple debugging.I/O.
  ////=============================================================================
  class Debug {
    /**
     * Instead of constructor.
     * At debugging, this method should be executed on loaded.
     */
    static on() {
      this._debugMode = true;
      this._stack = [];
      console.warn(`${this.FILENAME} : Debug mode turned ON.`);
    }

    /**
     * Instead of constructor.
     * At release, this method should be executed on loaded.
     */
    static off() {
      this._debugMode = false;
      this._stack = [];
      console.warn(`${this.FILENAME} : Debug mode turned OFF.`);
    }

    static get FILENAME() {
      return "MultipleWindowSkinSystem";
    }

    static get isDebugMode() {
      return this._debugMode;
    }

    static outputStack() {
      if (!this.isDebugMode) {
        return;
      }

      if (this._stack.length > 0) {
        this._stack.forEach(function (element) {
          console.log(element);
        }, this);
        return `Stack length is ${this._stack.length}.`;
      }
      return "Stack length is 0.";
    }

    static clearStack() {
      if (!this.isDebugMode) {
        return;
      }

      this._stack = [];
    }

    static push(arg) {
      if (!this.isDebugMode) {
        return;
      }

      this._stack.push(arg);
    }

    /**
     * Private method.
     * @param {Function} func
     * @param {Array} args
     */
    static _output(func, args) {
      if (!this.isDebugMode) {
        return;
      }

      args = Array.prototype.slice.call(args); //ES6: Array.from(args);
      for (var arg of args) {
        console[func](arg);
        this.push(args);
      }
    }

    static log(args) {
      this._output("log", arguments);
    }

    static dir(args) {
      this._output("dir", arguments);
    }

    static info(args) {
      this._output("info", arguments);
    }

    static warn(args) {
      this._output("warn", arguments);
    }

    static error(args) {
      this._output("error", arguments);
    }

    static assert(test, message, optionalParam) {
      if (!this.isDebugMode) {
        return;
      }

      console.assert(test, message, optionalParam);
    }

    static modify() {
      this._debugMode = !this._debugMode;
      var status = this._debugMode ? "ON" : "OFF";
      console.warn(`Debug mode turned ${status}.`);
    }
  }

  //Debug.on();
  Debug.off();
})();

/* ============================================================
 * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
 *
 * Open source under the BSD License.
 *
 * Copyright © 2008 George McGinley Smith
 * All rights reserved.
 * https://raw.github.com/danro/jquery-easing/master/LICENSE
 * ======================================================== */

/*
 *
 * TERMS OF USE - EASING EQUATIONS
 *
 * Open source under the BSD License.
 *
 * Copyright © 2001 Robert Penner
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of
 * conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 *
 * Neither the name of the author nor the names of contributors may be used to endorse
 * or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 *  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// NRP_MessageSpeed.js
//=============================================================================
/*:
 * @target MV MZ
 * @plugindesc v1.03 Changes the message speed.
 * @author Takeshi Sunagawa (http://newrpg.seesaa.net/)
 * @url http://newrpg.seesaa.net/article/485101364.html
 *
 * @help Changes the message speed.
 * You can also add an item
 * for changing the message speed in the options.
 *
 * -------------------------------------------------------------------
 * [Usage]
 * -------------------------------------------------------------------
 * Set the "DefaultSpeed" to your preference.
 * 100 is the normal message speed.
 * For example, 150 is 1.5 times the normal speed.
 * If you set a large number such as 99999,
 * instantaneous display is also possible.
 *
 * If you want to add an item to the option screen,
 * please set a numerical value to "OptionPosition".
 * ※In the initial state (blank), the item will be hidden.
 *
 * Also, the value set in "MessageSpeedList" will be displayed
 * as a candidate for the option.
 *
 * -------------------------------------------------------------------
 * [Terms]
 * -------------------------------------------------------------------
 * There are no restrictions.
 * Modification, redistribution freedom, commercial availability,
 * and rights indication are also optional.
 * The author is not responsible,
 * but will deal with defects to the extent possible.
 *
 * @param DefaultSpeed
 * @type number
 * @default 100
 * @desc Set the message speed with 100 as the standard.
 * For example, 150 is 1.5 times the normal speed.
 *
 * @param SpeedVariable
 * @type variable
 * @desc This variable controls the message speed.
 * It takes precedence over "DefaultSpeed" and optional settings.
 *
 * @param DisableShowFastSwitch
 * @type switch
 * @desc Disables instantaneous message display while the switch is on.
 * Always disabled if 0 (none) is specified. Disabled if blank (DEL).
 *
 * @param <Option>
 * @desc Option-related items.
 *
 * @param OptionPosition
 * @parent <Option>
 * @type number
 * @desc The position where the item is inserted into the option screen.
 * 0 for top, blank (DEL) for hidden.
 *
 * @param OptionName
 * @parent <Option>
 * @type string
 * @default Message Speed
 * @desc Set the display name in the option screen.
 *
 * @param MessageSpeedList
 * @parent <Option>
 * @type struct<MessageSpeed>[]
 * @default ["{\"Name\":\"50%\",\"MessageSpeed\":\"50\"}","{\"Name\":\"75%\",\"MessageSpeed\":\"75\"}","{\"Name\":\"100%\",\"MessageSpeed\":\"100\"}","{\"Name\":\"150%\",\"MessageSpeed\":\"150\"}","{\"Name\":\"200%\",\"MessageSpeed\":\"200\"}","{\"Name\":\"Instant\",\"MessageSpeed\":\"99999\"}"]
 * @desc Candidate message speeds that can be selected as options.
 */

/*~struct~MessageSpeed:
 * @param Name
 * @type text
 * @desc The display name of the message speed.
 *
 * @param MessageSpeed
 * @type number
 * @default 100
 * @desc Set the message speed with 100 as the standard.
 * For example, 150 is 1.5 times the normal speed.
 */

/*:ja
 * @target MV MZ
 * @plugindesc v1.03 メッセージ速度を変更します。
 * @author 砂川赳（http://newrpg.seesaa.net/）
 * @url http://newrpg.seesaa.net/article/485101364.html
 *
 * @help メッセージ速度を変更します。
 * さらに、オプションにメッセージ速度変更用の項目を追加できます。
 *
 * -------------------------------------------------------------------
 * ■使用方法
 * -------------------------------------------------------------------
 * 『標準メッセージ速度』をお好みで設定してください。
 * 100が通常のメッセージ速度です。
 * 例えば、150なら通常の1.5倍速になります。
 * 99999など大きな数字を設定すれば、瞬間表示も可能です。
 *
 * オプション画面へ項目を追加する場合は、
 * 『オプション挿入位置』に数値を設定してください。
 * ※初期状態（空白）では非表示となります。
 *
 * また、『メッセージ速度の候補』に設定した値が、
 * オプションの候補として表示されます。
 *
 * -------------------------------------------------------------------
 * ■利用規約
 * -------------------------------------------------------------------
 * 特に制約はありません。
 * 改変、再配布自由、商用可、権利表示も任意です。
 * 作者は責任を負いませんが、不具合については可能な範囲で対応します。
 *
 * @param DefaultSpeed
 * @text 標準メッセージ速度
 * @type number
 * @default 100
 * @desc 100を標準としてメッセージ速度を設定してください。
 * 例えば、150なら通常の1.5倍速となります。
 *
 * @param SpeedVariable
 * @text メッセージ速度変数
 * @type variable
 * @desc メッセージ速度を制御する変数です。
 * 『標準メッセージ速度』やオプション設定より優先されます。
 *
 * @param DisableShowFastSwitch
 * @text 瞬間表示禁止スイッチ
 * @type switch
 * @desc スイッチがオンの間、キー押下時の瞬間表示を禁止します。
 * 0（なし）を指定すると常に禁止。空白（DEL）なら無効。
 *
 * @param <Option>
 * @text ＜オプション関連＞
 * @desc オプション関連の項目です。
 *
 * @param OptionPosition
 * @text オプション挿入位置
 * @parent <Option>
 * @type number
 * @desc オプション画面に挿入する位置です。
 * 0が先頭、空白（DEL）なら非表示。
 *
 * @param OptionName
 * @text オプション表示名
 * @parent <Option>
 * @type string
 * @default メッセージ速度
 * @desc オプション画面での表示名を設定します。
 *
 * @param MessageSpeedList
 * @text メッセージ速度の候補
 * @parent <Option>
 * @type struct<MessageSpeed>[]
 * @default ["{\"Name\":\"50%\",\"MessageSpeed\":\"50\"}","{\"Name\":\"75%\",\"MessageSpeed\":\"75\"}","{\"Name\":\"100%\",\"MessageSpeed\":\"100\"}","{\"Name\":\"150%\",\"MessageSpeed\":\"150\"}","{\"Name\":\"200%\",\"MessageSpeed\":\"200\"}","{\"Name\":\"瞬間\",\"MessageSpeed\":\"99999\"}"]
 * @desc オプションとして選択できるメッセージ速度の候補です。
 */

/*~struct~MessageSpeed:ja
 * @param Name
 * @text 表示名
 * @type text
 * @desc メッセージ速度の表示名です。
 *
 * @param MessageSpeed
 * @text メッセージ速度
 * @type number
 * @default 100
 * @desc 100を標準としてメッセージ速度を設定してください。
 * 例えば、150なら通常の1.5倍速となります。
 */

(function () {
  "use strict";

  /**
   * ●構造体（二重配列）をJSで扱えるように変換
   */
  function parseStruct2(arg) {
    const ret = [];
    if (arg) {
      for (const str of JSON.parse(arg)) {
        ret.push(JSON.parse(str));
      }
    }
    return ret;
  }
  function toBoolean(str, def) {
    if (str === true || str === "true") {
      return true;
    } else if (str === false || str === "false") {
      return false;
    }
    return def;
  }
  function toNumber(str, def) {
    if (str == undefined || str == "") {
      return def;
    }
    return isNaN(str) ? def : +(str || def);
  }

  const PLUGIN_NAME = "NRP_MessageSpeed";
  const parameters = PluginManager.parameters(PLUGIN_NAME);
  const pDefaultSpeed = toNumber(parameters["DefaultSpeed"], 100);
  const pSpeedVariable = toNumber(parameters["SpeedVariable"]);
  const pDisableShowFastSwitch = toNumber(parameters["DisableShowFastSwitch"]);
  const pOptionPosition = toNumber(parameters["OptionPosition"]);
  const pOptionName = parameters["OptionName"];
  const pMessageSpeedList = parseStruct2(parameters["MessageSpeedList"]);

  // 識別子
  const MESSAGE_SPEED_SYMBOL = "messageSpeed";

  let mMessageCount = 0;
  let mDisableShowFast = false;

  /**
   * ●メッセージ開始
   */
  const _Window_Message_startMessage = Window_Message.prototype.startMessage;
  Window_Message.prototype.startMessage = function () {
    // カウント初期化
    mMessageCount = 0;

    _Window_Message_startMessage.apply(this, arguments);
  };

  /**
   * ●メッセージの更新
   */
  const _Window_Message_updateMessage = Window_Message.prototype.updateMessage;
  Window_Message.prototype.updateMessage = function () {
    // メッセージがない場合は終了
    if (!this._textState) {
      return false;
    }

    // 瞬間表示するかどうか？
    mDisableShowFast = isDisabledShowFast();
    // 出力する文字数を蓄積
    mMessageCount += getMessageSpeed() / 100;

    let ret = true;

    // 出力するメッセージがある場合は本来の処理を呼び出し
    if (mMessageCount >= 1) {
      ret = _Window_Message_updateMessage.apply(this, arguments);
    }

    mDisableShowFast = false;
    return ret;
  };

  /**
   * ●文字出力の停止判定
   * ※本来は瞬間表示時（false）に文字表示を一気に行うための判定。
   * 　当プラグインでは、これを利用して２文字以上の同時表示を行う。
   */
  const _Window_Message_shouldBreakHere =
    Window_Message.prototype.shouldBreakHere;
  Window_Message.prototype.shouldBreakHere = function (textState) {
    // １文字出力したので減算
    mMessageCount--;
    // 追加の出力文字が存在する場合
    if (mMessageCount >= 1 && this.canBreakHere(textState)) {
      // ウェイト命令がある場合は停止
      if (this.isWaiting()) {
        // 出力文字数をクリア
        mMessageCount = 0;
        return true;
      }
      // それ以外は文字表示続行
      return false;
    }

    return _Window_Message_shouldBreakHere.apply(this, arguments);
  };

  /**
   * ●決定キーによるメッセージの瞬間表示制御
   */
  const _Window_Message_updateShowFast =
    Window_Message.prototype.updateShowFast;
  Window_Message.prototype.updateShowFast = function () {
    if (mDisableShowFast && isTriggered()) {
      return;
    }
    _Window_Message_updateShowFast.apply(this, arguments);
  };

  // ----------------------------------------------------------------------------
  // 共通関数
  // ----------------------------------------------------------------------------

  /**
   * ●メッセージ速度を取得
   */
  function getMessageSpeed() {
    // 変数指定がある場合はそちらを優先
    if (pSpeedVariable && $gameVariables.value(pSpeedVariable)) {
      return $gameVariables.value(pSpeedVariable);

      // オプション指定がある場合
    } else if (ConfigManager.messageSpeed) {
      return ConfigManager.messageSpeed;
    }
    // それ以外はデフォルト値を使用
    return pDefaultSpeed;
  }

  /**
   * ●瞬間表示を禁止するかどうか？
   */
  function isDisabledShowFast() {
    // 0なら常に禁止
    if (pDisableShowFastSwitch === 0) {
      return true;
    }
    // それ以外はスイッチがオンの場合のみ禁止
    return $gameSwitches.value(pDisableShowFastSwitch);
  }

  /**
   * ●Window_Message.prototype.isTriggeredの本来の処理。
   * ※MessageSkip.jsとの併用に対応するため別途定義
   */
  function isTriggered() {
    return (
      Input.isRepeated("ok") ||
      Input.isRepeated("cancel") ||
      TouchInput.isRepeated()
    );
  }

  // ----------------------------------------------------------------------------
  // オプション関連
  // ----------------------------------------------------------------------------

  /**
   * オプションを使用しない場合はここで処理終了
   */
  if (pOptionPosition == undefined) {
    return;
  }

  /**
   * ●オプション候補の最小値
   */
  function messageSpeedMin() {
    return toNumber(pMessageSpeedList[0].MessageSpeed);
  }

  /**
   * ●オプション候補の最大値
   */
  function messageSpeedMax() {
    return toNumber(
      pMessageSpeedList[pMessageSpeedList.length - 1].MessageSpeed
    );
  }

  // メッセージ速度の初期値
  ConfigManager.messageSpeed = pDefaultSpeed;

  /**
   * ●オプション画面の項目生成
   */
  const _ConfigManager_makeData = ConfigManager.makeData;
  ConfigManager.makeData = function () {
    const config = _ConfigManager_makeData.apply(this, arguments);

    config.messageSpeed = this.messageSpeed;
    return config;
  };

  /**
   * ●オプション画面の項目生成
   */
  const _ConfigManager_applyData = ConfigManager.applyData;
  ConfigManager.applyData = function (config) {
    _ConfigManager_applyData.apply(this, arguments);

    this.messageSpeed = this.readMessageSpeed(config, MESSAGE_SPEED_SYMBOL);
  };

  /**
   * 【独自】メッセージ速度をコンフィグから読込
   */
  ConfigManager.readMessageSpeed = function (config, name) {
    const value = config[name];
    if (value !== undefined) {
      return Number(value).clamp(messageSpeedMin(), messageSpeedMax());
    } else {
      return pDefaultSpeed;
    }
  };

  /**
   * ●表示状態取得
   */
  const _Window_Options_statusText = Window_Options.prototype.statusText;
  Window_Options.prototype.statusText = function (index) {
    const symbol = this.commandSymbol(index);
    const value = this.getConfigValue(symbol);

    if (isMessageSpeedSymbol(symbol)) {
      return messageSpeedStatusText(value);
    }

    return _Window_Options_statusText.apply(this, arguments);
  };

  /**
   * ●メッセージ速度の表示名
   */
  function messageSpeedStatusText(value) {
    const messageSpeed = pMessageSpeedList.find(
      (messageSpeed) => messageSpeed.MessageSpeed == value
    );
    if (messageSpeed) {
      return messageSpeed.Name;
    }
    return "";
  }

  /**
   * ●決定キー
   */
  const _Window_Options_processOk = Window_Options.prototype.processOk;
  Window_Options.prototype.processOk = function () {
    const index = this.index();
    const symbol = this.commandSymbol(index);
    const value = this.getConfigValue(symbol);

    if (isMessageSpeedSymbol(symbol)) {
      this.changeMessageSpeedValue(symbol, nextMessageSpeed(value), true);
      return;
    }

    _Window_Options_processOk.apply(this, arguments);
  };

  /**
   * ●カーソル右
   */
  const _Window_Options_cursorRight = Window_Options.prototype.cursorRight;
  Window_Options.prototype.cursorRight = function (wrap) {
    const index = this.index();
    const symbol = this.commandSymbol(index);
    const value = this.getConfigValue(symbol);

    if (isMessageSpeedSymbol(symbol)) {
      this.changeMessageSpeedValue(symbol, nextMessageSpeed(value), false);
      return;
    }

    _Window_Options_cursorRight.apply(this, arguments);
  };

  /**
   * ●カーソル左
   */
  const _Window_Options_cursorLeft = Window_Options.prototype.cursorLeft;
  Window_Options.prototype.cursorLeft = function (wrap) {
    const index = this.index();
    const symbol = this.commandSymbol(index);
    const value = this.getConfigValue(symbol);

    if (isMessageSpeedSymbol(symbol)) {
      this.changeMessageSpeedValue(symbol, preMessageSpeed(value), false);
      return;
    }

    _Window_Options_cursorLeft.apply(this, arguments);
  };

  /**
   * 【独自】メッセージ速度の値を変更
   */
  Window_Options.prototype.changeMessageSpeedValue = function (
    symbol,
    value,
    wrap
  ) {
    // 現在値が最大の状態で決定を押した場合
    if (wrap && this.getConfigValue(symbol) == messageSpeedMax()) {
      this.changeValue(symbol, messageSpeedMin());
      return;
    }

    value = value.clamp(messageSpeedMin(), messageSpeedMax());
    this.changeValue(symbol, value);
  };

  /**
   * ●次のメッセージ速度を取得
   */
  function nextMessageSpeed(value) {
    let messageSpeed = pMessageSpeedList.find(
      (messageSpeed) => messageSpeed.MessageSpeed == value
    );
    const index = pMessageSpeedList.indexOf(messageSpeed);
    // 次の値を取得できれば返す
    if (pMessageSpeedList[index + 1]) {
      messageSpeed = toNumber(pMessageSpeedList[index + 1].MessageSpeed);
      return messageSpeed;
    }
    // それ以外は最大値
    return messageSpeedMax();
  }

  /**
   * ●前のメッセージ速度を取得
   */
  function preMessageSpeed(value) {
    let messageSpeed = pMessageSpeedList.find(
      (messageSpeed) => messageSpeed.MessageSpeed == value
    );
    const index = pMessageSpeedList.indexOf(messageSpeed);
    // 前の値を取得できれば返す
    if (pMessageSpeedList[index - 1]) {
      messageSpeed = toNumber(pMessageSpeedList[index - 1].MessageSpeed);
      return messageSpeed;
    }
    // それ以外は最小値
    return messageSpeedMin();
  }

  /**
   * ●メッセージ速度の項目追加
   */
  const _Window_Options_makeCommandList =
    Window_Options.prototype.makeCommandList;
  Window_Options.prototype.makeCommandList = function () {
    _Window_Options_makeCommandList.apply(this, arguments);

    this._list.splice(pOptionPosition, 0, {
      name: pOptionName,
      symbol: MESSAGE_SPEED_SYMBOL,
      enabled: true,
      ext: null,
    });

    // Mano_InputConfig.jsとの競合対処
    if (this._gamepadOptionIndex >= pOptionPosition) {
      this._gamepadOptionIndex++;
    }
    if (this._keyboardConfigIndex >= pOptionPosition) {
      this._keyboardConfigIndex++;
    }
  };

  /**
   * ●設定値を反映
   */
  const _Window_Options_setConfigValue =
    Window_Options.prototype.setConfigValue;
  Window_Options.prototype.setConfigValue = function (symbol, volume) {
    _Window_Options_setConfigValue.apply(this, arguments);

    if (isMessageSpeedSymbol(symbol)) {
      // メッセージ速度を反映
      ConfigManager.messageSpeed = volume;
    }
  };

  /**
   * ●メッセージ速度のオプションか？
   */
  function isMessageSpeedSymbol(symbol) {
    if (symbol == MESSAGE_SPEED_SYMBOL) {
      return true;
    }
    return false;
  }

  /**
   * ●コマンド数を加算
   */
  const _Scene_Options_maxCommands = Scene_Options.prototype.maxCommands;
  Scene_Options.prototype.maxCommands = function () {
    return _Scene_Options_maxCommands.apply(this, arguments) + 1;
  };
})();


code:
//=============================================================================
// OverpassTile.js
//=============================================================================

/*:
 * @plugindesc Settings for bridges which characters can pass through.
 * @author Yoji Ojima
 *
 * @param Overpass Region ID
 * @desc The region ID for "overpass" such as bridges.
 * @default 255
 *
 * @param Gateway Region ID
 * @desc The region ID for "gateway" such as bridge ends.
 * @default 254
 *
 * @help
 *
 * This plugin uses region ID to determine a floor level.
 * In default, set 255 to bridge tiles and 254 to ends of them.
 *
 * Note: This plugin does not support the collision judgment modification
 *       between characters who are in different floors.
 */

/*:ja
 * @plugindesc キャラクターが下をくぐり抜けられる橋の設定です。
 * @author Yoji Ojima
 *
 * @param Overpass Region ID
 * @desc 橋などの立体交差部分に設定するリージョンIDです。
 * @default 255
 *
 * @param Gateway Region ID
 * @desc 橋の両端など、立体交差の入り口部分に設定するリージョンIDです。
 * @default 254
 *
 * @help
 *
 * このプラグインは、床の高さを決定するのにリージョンIDを使用します。
 * デフォルトでは橋の部分に255、その両端に254を設定してください。
 *
 * 注意：このプラグインは、異なる階層にいるキャラクター間の衝突判定修正は
 *       サポートしていません。
 */

(function () {
  var parameters = PluginManager.parameters("OverpassTile");
  var overpassRegionId = Number(parameters["Overpass Region ID"] || 255);
  var gatewayRegionId = Number(parameters["Gateway Region ID"] || 254);

  var _Tilemap_isOverpassPosition = Tilemap.prototype._isOverpassPosition;
  Tilemap.prototype._isOverpassPosition = function (mx, my) {
    var regionId = this._readMapData(mx, my, 5);
    if (regionId === overpassRegionId) {
      return true;
    } else {
      return _Tilemap_isOverpassPosition.call(this, mx, my);
    }
  };

  var _Game_CharacterBase_screenZ = Game_CharacterBase.prototype.screenZ;
  Game_CharacterBase.prototype.screenZ = function () {
    if (this._higherLevel) {
      return 5;
    } else {
      return _Game_CharacterBase_screenZ.call(this);
    }
  };

  var _Game_CharacterBase_isMapPassable =
    Game_CharacterBase.prototype.isMapPassable;
  Game_CharacterBase.prototype.isMapPassable = function (x, y, d) {
    if (_Game_CharacterBase_isMapPassable.call(this, x, y, d)) {
      var x2 = $gameMap.roundXWithDirection(x, d);
      var y2 = $gameMap.roundYWithDirection(y, d);
      var d2 = this.reverseDir(d);
      var regionId1 = $gameMap.regionId(x, y);
      var regionId2 = $gameMap.regionId(x2, y2);
      if (this._higherLevel && regionId1 !== gatewayRegionId) {
        return regionId2 === gatewayRegionId || regionId2 === overpassRegionId;
      }
      if (!this._higherLevel && regionId1 === overpassRegionId) {
        if (regionId2 === overpassRegionId) {
          var bit1 = (1 << (d / 2 - 1)) & 0x0f;
          var bit2 = (1 << (d2 / 2 - 1)) & 0x0f;
          var flags = $gameMap.tilesetFlags();
          var tileId1 = $gameMap.tileId(x, y, 0);
          var tileId2 = $gameMap.tileId(x, y, 1);
          var tileId3 = $gameMap.tileId(x2, y2, 0);
          var tileId4 = $gameMap.tileId(x2, y2, 1);
          if ((flags[tileId1] | flags[tileId2]) & bit1) {
            return false;
          }
          if ((flags[tileId3] | flags[tileId4]) & bit2) {
            return false;
          }
        }
        return regionId2 !== gatewayRegionId;
      }
      return true;
    } else {
      return false;
    }
  };

  var _Game_CharacterBase_refreshBushDepth =
    Game_CharacterBase.prototype.refreshBushDepth;
  Game_CharacterBase.prototype.refreshBushDepth = function () {
    _Game_CharacterBase_refreshBushDepth.call(this);
    var regionId = this.regionId();
    if (regionId === gatewayRegionId) {
      this._higherLevel = true;
    } else if (regionId !== overpassRegionId) {
      this._higherLevel = false;
    }
  };
})();