code:
// DarkPlasma_TextLog
// Copyright (c) 2017 DarkPlasma
// This software is released under the MIT license.
// http://opensource.org/licenses/mit-license.php

/**
 * 2020/08/09 1.10.1 NobleMushroom.js と併用した際に、場所移動後にウィンドウが表示され続ける不具合を修正
 * 2020/08/07 1.10.0 テキストログウィンドウ拡張用インターフェースを公開
 * 2020/08/05 1.9.1 MPP_ChoiceEx.js との競合を解消
 * 2020/06/23 1.9.0 プラグインコマンドでログを追加する機能を追加
 *                  外部向けログ追加インターフェース公開
 * 2020/06/23 1.8.3 DarkPlasma_WordWrapForJapanese.js 等と併用しないとエラーになる不具合を修正
 * 2020/06/03 1.8.2 NobleMushroom.js と併用した際に、セーブ・ロード画面でログを開ける不具合を修正
 *            1.8.1 NobleMushroom.js と併用した際に、ポーズメニューでフリーズする不具合を修正
 *                  タイトルに戻ってニューゲーム/ロードした際に、直前のデータのログを引き継ぐ不具合を修正
 * 2020/05/30 1.8.0 ログから戻った際に最後のメッセージを再表示しない設定を追加
 *                  スクロールテキストをログに含める設定を追加
 *                  選択肢をログに含める設定を追加
 *                  高さ計算ロジックを整理
 * 2020/05/09 1.7.3 ログ表示/スクロール処理を軽量化
 *            1.7.2 ログ保存イベント数を超えるとログが壊れる不具合を修正
 * 2020/05/08 1.7.1 軽微なリファクタ
 *            1.7.0 名前ウィンドウの名前をログに含める設定を追加
 * 2020/03/09 1.6.4 プラグインが無効の状態で読み込まれていても有効と判定される不具合を修正
 * 2020/01/28 1.6.3 文章を表示しないイベントに自動区切り線を入れないよう修正
 * 2020/01/27 1.6.2 決定キーでログウィンドウを閉じられるよう修正
 *                  ログ開閉キーにpagedownキーを設定できるよう修正
 *            1.6.1 ログ表示時の順序が逆になる不具合を修正
 *                  DarkPlasma_WordWrapForJapanese（1.0.3以降）に対応
 *            1.6.0 ログウィンドウを開くボタンでログウィンドウを閉じられるよう修正
 *                  メッセージ同士の間隔やテキストログの行間の設定項目を追加
 *                  DarkPlasma_NameWindowに対応できていなかった不具合を修正
 *                  記録できるイベントログ数を無制限に変更
 *                  記録できるイベント数、メッセージ数の設定を追加
 *                  イベントごとにログを区切る機能を追加
 * 2020/01/23 1.5.3 選択肢が開いている最中にログウィンドウを開いて戻ろうとするとエラーで落ちる不具合を修正
 * 2020/01/18 1.5.2 DarkPlasma_NameWindowに対応
 * version 1.5.1
 * - 冗長な変数名を修正
 * - パラメータの型を明示
 * version 1.5.0
 * - マウスドラッグやスワイプでログウィンドウをスクロールする機能のおためし版を実装
 * version 1.4.0
 * - ログウィンドウがスクロール可能な場合にスクロール可能アイコンを表示する機能を実装
 * version 1.3.0
 * - ログが空の場合にメニューからログウィンドウを開こうとするとフリーズする不具合を修正
 * - 空のログウィンドウ表示可否フラグを実装
 * version 1.2.1
 * - 選択肢でログに空文字列が記録される不具合を修正
 * - ログが空でもメニューやプラグインコマンドから開けた不具合を修正
 * version 1.2.0
 * - プラグインコマンドからテキストログを開く機能を実装
 * - スイッチによるログ表示可能フラグON/OFF機能を実装
 * version 1.1.0
 * - スイッチによるログ記録のON/OFF機能を実装
 * - テキストログを開くボタンの変更機能を実装
 * - マウススクロールでもログのスクロールできる機能を実装
 * - マウス右クリックでもログを閉じることができる機能を実装
 * - マップ移動時にエラーで落ちる不具合を修正
 * - YEP_MainMenuManager.js に対応
 * version 1.0.3
 * - 並列イベント終了時にログをリセットしないよう修正
 * - ブザーフラグが正しく動作していなかった不具合を修正
 * version 1.0.2
 * - バトルイベント終了時、コモンイベント終了時にログをリセットしないよう修正
 * - 長いイベントのログが正常にスクロールできていない不具合を修正
 * version 1.0.1
 * - デフォルトには存在しないメソッドを使用していた不具合を修正
 */

/*:
 * @plugindesc イベントのテキストログを表示する
 * @author DarkPlasma
 * @license MIT
 *
 * @target MV
 * @url https://github.com/elleonard/RPGtkoolMV-Plugins
 *
 * @param Max View Count
 * @desc １画面に表示する最大のメッセージ数
 * @text 1画面のメッセージ数上限
 * @default 16
 * @type number
 *
 * @param Overflow Buzzer
 * @desc テキストログの端より先にスクロールしようとした時、ブザーを鳴らすかどうか
 * @text 限界以上スクロール時ブザー
 * @default false
 * @type boolean
 *
 * @param Disable Logging Switch
 * @desc 該当スイッチがONの間はログを残さない。0なら常にログを残す
 * @text ログ記録無効スイッチ
 * @default 0
 * @type number
 *
 * @param Open Log Key
 * @desc テキストログウィンドウを開閉するためのボタン
 * @text ログウィンドウボタン
 * @default pageup
 * @type select
 * @option pageup
 * @option pagedown
 * @option shift
 * @option control
 * @option tab
 *
 * @param Disable Show Log Switch
 * @desc 該当スイッチがONの間はログを開かない。0なら常にログを開ける
 * @text ログウィンドウ無効スイッチ
 * @defalt 0
 * @type number
 *
 * @param Show Log Window Without Text
 * @desc ログに表示すべきテキストがない場合でもログウィンドウを開く
 * @text 白紙ログでも開く
 * @default true
 * @type boolean
 *
 * @param Line Spacing
 * @desc ログ表示時の行間
 * @text ログの行間
 * @default 0
 * @type number
 *
 * @param Message Spacing
 * @desc ログ表示時のメッセージ間隔（イベントコマンド単位でひとかたまり）
 * @text メッセージの間隔
 * @default 0
 * @type number
 *
 * @param Log Event Count
 * @desc 直近何件のイベントのログを記録するか（0以下で無限）
 * @text ログ記録イベント数
 * @default 0
 * @type number
 *
 * @param Log Event Message Count
 * @desc 直近何メッセージのログを記録するか（0以下で無限）
 * @text ログ記録メッセージ数
 * @default 0
 * @type number
 *
 * @param Event Log Splitter
 * @desc イベントとイベントの間に挟むための区切り線
 * @text イベントログ区切り線
 * @default -------------------------------------------------------
 * @type string
 *
 * @param Auto Event Split
 * @desc イベントとイベントのログの間に区切り線を自動でいれるか
 * @text 自動イベント区切り線
 * @default true
 * @type boolean
 *
 * @param Include Name In Log
 * @desc 名前ウィンドウの名前をログに含めるかどうか
 * @text 名前をログに含む
 * @default true
 * @type boolean
 *
 * @param Include Scroll Text In Log
 * @desc スクロールテキストをログに含めるかどうか
 * @text スクロールテキストをログに含む
 * @default false
 * @type boolean
 *
 * @param Include Choice In Log
 * @desc 選んだ選択肢をログに含めるかどうか
 * @text 選んだ選択肢をログに含む
 * @default true
 * @type boolean
 *
 * @param Choice Format
 * @desc ログに表示する選択肢のフォーマット。{choice} は選んだ選択肢に変換される
 * @text 選択肢フォーマット
 * @default 選択肢:{choice}
 * @type string
 *
 * @param Choice Color
 * @desc ログに表示する選択肢の色。色番号で指定できる他、適切なプラグインで拡張すれば#つきカラーコードで指定可能
 * @text 選択肢カラー
 * @default 17
 *
 * @param Include Choice Cancel In Log
 * @desc 選択肢をキャンセルした際のログを含めるかどうか。選択肢をログに含むが真の場合のみ有効
 * @text キャンセルをログに含む
 * @default true
 * @type boolean
 *
 * @param Choice Cancel Text In Log
 * @desc 選択肢をキャンセルした際にログに記録する内容。キャンセルをログに含むが真の場合のみ有効
 * @text キャンセルログ
 * @default キャンセル
 * @type string
 *
 * @param Smooth Back From Log
 * @desc ログシーンから戻った際にテキストを再度表示し直さない（ヘルプに要注意事項）
 * @text テキスト再表示なし
 * @default true
 * @type boolean
 *
 * @help
 *  イベントのテキストログを表示します
 *
 *  イベント会話中またはマップ上で pageup キー（L2ボタン）でログを表示します
 *  イベント会話中はそのイベントの直前までのログを表示します
 *  ログは上下キーでスクロールすることができます
 *  キャンセルキーやログ開閉キーでログから抜け、イベントやマップに戻ります
 *
 *  注意: テキスト再表示なしを真にしている場合、
 *  Scene_Map.prototype.createMessageWindow 及び
 *  Scene_Map.prototype.createScrollTextWindow の処理を上書きします。
 *  これらの関数に処理を加えているプラグインとは競合する恐れがありますので、
 *  それらよりも下にこのプラグインを追加してください
 *  この設定が偽になっている場合、
 *  イベントに戻る際、最後のメッセージをもう一度最初から流します
 *
 *  YEP_MessageCore.jsに対応しています
 *    ツクール公式から配布されているv1.02は古いので
 *    必ず本家から最新を落として利用するようにしてください
 *
 *  YEP_MainMenuManager.jsに対応しています
 *    適切に設定すればステータスメニューからログを開くことができます
 *    設定例：
 *      Show: true
 *      Enabled: this.isTextLogEnabled()
 *      Main Bind: this.commandTextLog.bind(this)
 *
 *  プラグインコマンド showTextLog から開くことも可能です
 *
 *  プラグインコマンド insertLogSplitter を使用することで、
 *  イベントログに区切り線を追加できます
 *  自動イベント区切り線 設定をONにしておくことで、
 *  イベントごとに自動で区切り線を挿入させることもできます
 *
 *  プラグインコマンド insertTextLog XXXX を使用することで、
 *  イベントログに任意のログを追加できます
 *
 *  操作方法（デフォルト）
 *   pageupキー（L2ボタン） : ログを表示する
 *   上下キー/マウススクロール : ログをスクロールする
 *   キャンセルキー/右クリック : ログから抜ける
 *
 *  マウスドラッグやスワイプでもログをスクロールできますが、
 *  環境差異に関して未検証なのでおためし版です
 *  しばらく使われて問題が報告されなければ正式版とします
 *
 *  外部向けインターフェース
 *  $gameSystem.insertTextLog(text): ログに文字列 text を追加します
 *
 *  拡張プラグインを書くことで、テキストログウィンドウの
 *  エスケープ文字の挙動を定義できます
 *  詳細は https://github.com/elleonard/RPGtkoolMV-Plugins/blob/master/plugins/DarkPlasma_TextLogExtensionExample.js
 */

(function () {
  "use strict";
  const pluginName = "DarkPlasma_TextLog";
  const pluginParameters = PluginManager.parameters(pluginName);
  const maxViewCount = Number(pluginParameters["Max View Count"]);
  const overflowBuzzer = String(pluginParameters["Overflow Buzzer"]) === "true";
  const disableLoggingSwitch = Number(
    pluginParameters["Disable Logging Switch"]
  );
  const openLogKey = String(pluginParameters["Open Log Key"]);
  const disableShowLogSwitch = Number(
    pluginParameters["Disable Show Log Switch"]
  );
  const showLogWindowWithoutText =
    String(pluginParameters["Show Log Window Without Text"]) !== "false";

  const settings = {
    lineSpacing: Number(pluginParameters["Line Spacing"] || 8),
    messageSpacing: Number(pluginParameters["Message Spacing"] || 0),
    logEventCount: Number(pluginParameters["Log Event Count"] || 0),
    logMessageCount: Number(pluginParameters["Log Event Message Count"] || 0),
    eventLogSplitter: String(
      pluginParameters["Event Log Splitter"] ||
        "-------------------------------"
    ),
    autoEventLogSplit:
      String(pluginParameters["Auto Event Split"] || "true") === "true",
    includeName:
      String(pluginParameters["Include Name In Log"] || "true") === "true",
    includeScrollText:
      String(pluginParameters["Include Scroll Text In Log"]) === "true",
    includeChoice: String(pluginParameters["Include Choice In Log"]) === "true",
    choiceFormat: String(pluginParameters["Choice Format"]),
    choiceColor: String(pluginParameters["Choice Color"]).startsWith("#")
      ? String(pluginParameters["Choice Color"])
      : Number(pluginParameters["Choice Color"]),
    includeChoiceCancel:
      String(pluginParameters["Include Choice Cancel In Log"] || "true") ===
      "true",
    choiceCancelText: String(
      pluginParameters["Choice Cancel Text In Log"] || "キャンセル"
    ),
    smoothBackFromLog:
      String(pluginParameters["Smooth Back From Log"] || "true") === "true",
  };

  /**
   * プラグインがロードされているかどうか
   * @param {string} name プラグインの名前
   * @return {boolean}
   */
  PluginManager.isLoadedPlugin = function (name) {
    return $plugins.some((plugin) => plugin.name === name && plugin.status);
  };

  class EventTextLog {
    constructor() {
      this.initialize();
    }

    initialize() {
      this._messages = [];
    }

    /**
     * @return {LogMessage[]}
     */
    get messages() {
      return this._messages;
    }

    /**
     * @return {number}
     */
    get messageLength() {
      return this._messages.length;
    }

    /**
     * ログを追加する
     * @param {string} text テキスト
     */
    addMessageLog(text) {
      this._messages.push(new LogMessage(text));
      if (
        settings.logMessageCount > 0 &&
        this._messages.length > settings.logMessageCount
      ) {
        this._messages.splice(
          0,
          this._messages.length - settings.logMessageCount
        );
      }
    }
  }

  /**
   * ログメッセージ
   */
  class LogMessage {
    /**
     * @param {string} text テキスト
     */
    constructor(text) {
      this._text = text;
      this._height = 0;
      this._offsetY = 0;
    }

    /**
     * @return {string}
     */
    get text() {
      return this._text;
    }

    /**
     * ログウィンドウに表示する際の高さを記録する
     * （再計算の処理が重いため、一度だけ計算する）
     * @param {number} height 表示高さ
     */
    setHeight(height) {
      this._height = height;
    }

    get height() {
      return this._height;
    }

    /**
     * 表示開始Y座標を調整したいとき用
     * @param {number} offsetY Yオフセット
     */
    setOffsetY(offsetY) {
      this._offsetY = offsetY;
    }

    get offsetY() {
      return this._offsetY;
    }
  }

  /**
   * @type {EventTextLog}
   */
  let currentEventLog = new EventTextLog();
  /**
   * @type {EventTextLog[]}
   */
  let pastEventLog = [];

  // ログ表示用シーン
  class Scene_TextLog extends Scene_Base {
    constructor() {
      super();
      this.initialize.apply(this, arguments);
    }

    create() {
      super.create();
      this.createBackground();
      this.createWindowLayer();
      this.createTextLogWindow();
    }

    start() {
      super.start();
      this._textLogWindow.refresh();
    }

    createBackground() {
      this._backgroundSprite = new Sprite();
      this._backgroundSprite.bitmap = SceneManager.backgroundBitmap();
      this.addChild(this._backgroundSprite);
    }

    createTextLogWindow() {
      this._textLogWindow = new Window_TextLog();
      this._textLogWindow.setHandler("cancel", this.popScene.bind(this));
      this.addWindow(this._textLogWindow);
    }
  }

  // ログ表示用ウィンドウ
  class Window_TextLog extends Window_Base {
    constructor() {
      super();
      this.initialize.apply(this, arguments);
    }

    initialize() {
      super.initialize(0, 0, Graphics.boxWidth, Graphics.boxHeight);
      /**
       * @type {LogMessage[]}
       */
      this._viewTexts = [];
      if (pastEventLog.length > 0) {
        this._viewTexts = pastEventLog
          .map((pastLog) => pastLog.messages)
          .reverse()
          .reduce((accumlator, currentValue) =>
            currentValue.concat(accumlator)
          );
      }
      if (currentEventLog.messageLength > 0) {
        this._viewTexts = this._viewTexts.concat(currentEventLog.messages);
      }
      // 表示行数制限
      if (
        settings.logMessageCount > 0 &&
        this._viewTexts.length > settings.logMessageCount
      ) {
        this._viewTexts.splice(
          0,
          this._viewTexts.length - settings.logMessageCount
        );
      }
      this._cursor = this.calcDefaultCursor();
      this._handlers = {};
      this._maxViewCount = maxViewCount;
    }

    /**
     * @return {number}
     */
    cursor() {
      return this._cursor;
    }

    /**
     * ハンドラを登録する
     * @param {string} symbol シンボル
     * @param {Function} method メソッド
     */
    setHandler(symbol, method) {
      this._handlers[symbol] = method;
    }

    /**
     * 指定したシンボルでハンドラが登録されているか
     * @param {string} symbol シンボル
     */
    isHandled(symbol) {
      return !!this._handlers[symbol];
    }

    /**
     * 指定したシンボルのハンドラを呼び出す
     * @param {string} symbol シンボル
     */
    callHandler(symbol) {
      if (this.isHandled(symbol)) {
        this._handlers[symbol]();
      }
    }

    /**
     * @return {boolean}
     */
    isCursorMovable() {
      return true;
    }

    cursorDown() {
      if (!this.isCursorMax()) {
        this._cursor++;
      }
    }

    /**
     * これ以上下にスクロールできない状態かどうかを計算する
     * @return {boolean}
     */
    isCursorMax() {
      const size = this._viewTexts.length;
      let height = 0;
      for (let i = this.cursor(); i < size; i++) {
        const text = this._viewTexts[i].text;
        const textHeight = this._viewTexts[i].height;
        height += textHeight === 0 ? this.calcMessageHeight(text) : textHeight;
        if (height > Graphics.boxHeight - this.lineHeight()) {
          return false;
        }
      }
      return true;
    }

    cursorUp() {
      if (this.cursor() > 0) {
        this._cursor--;
      }
    }

    processCursorMove() {
      if (this.isCursorMovable()) {
        const lastCursor = this.cursor();
        let moved = false;
        if (
          Input.isRepeated("down") ||
          TouchInput.wheelY > 0 ||
          TouchInput.isDownMoved()
        ) {
          this.cursorDown();
          moved = true;
        }
        if (
          Input.isRepeated("up") ||
          TouchInput.wheelY < 0 ||
          TouchInput.isUpMoved()
        ) {
          this.cursorUp();
          moved = true;
        }
        if (overflowBuzzer && moved && lastCursor === this.cursor()) {
          SoundManager.playBuzzer();
        }
        this._needRefresh = lastCursor !== this.cursor();
      }
    }

    processCancel() {
      this.callHandler("cancel");
      SoundManager.playCancel();
    }

    processHandling() {
      if (this.isCancelEnabled() && this.isCancelTriggered()) {
        this.processCancel();
      }
    }

    /**
     * @return {boolean}
     */
    isCancelEnabled() {
      return this.isHandled("cancel");
    }

    /**
     * @return {boolean}
     */
    isCancelTriggered() {
      return (
        Input.isRepeated("cancel") ||
        Input.isTriggered("ok") ||
        Input.isTriggered(openLogKey) ||
        TouchInput.isCancelled()
      );
    }

    update() {
      super.update();
      this.updateArrows();
      this.processCursorMove();
      this.processHandling();
      /**
       * refresh処理は重いので、必要なケースのみ行う
       */
      if (this._needRefresh) {
        this.refresh();
      }
    }

    updateArrows() {
      this.upArrowVisible = this.cursor() > 0;
      this.downArrowVisible = !this.isCursorMax();
    }

    refresh() {
      this.contents.clear();
      this.drawTextLog();
    }

    drawTextLog() {
      let height = 0;
      for (let i = this.cursor(); i < this.cursor() + this._maxViewCount; i++) {
        if (i < this._viewTexts.length) {
          const text = this._viewTexts[i].text;
          const textHeight = this._viewTexts[i].height;
          const offsetY = this._viewTexts[i].offsetY;
          this.drawTextEx(text, 0, height + offsetY);
          if (textHeight === 0) {
            this._viewTexts[i].setHeight(this.calcMessageHeight(text));
          }
          height += this._viewTexts[i].height;
          if (height > Graphics.boxHeight) {
            break;
          }
        }
      }
    }

    /**
     * デフォルトのスクロール位置を計算する
     * @return {number}
     */
    calcDefaultCursor() {
      var height = 0;
      var size = this._viewTexts.length;
      for (var i = 0; i < size; i++) {
        const text = this._viewTexts[size - 1 - i].text;
        this._viewTexts[size - 1 - i].setHeight(this.calcMessageHeight(text));
        const textHeight = this._viewTexts[size - 1 - i].height;
        height += textHeight;
        if (height > Graphics.boxHeight - this.lineHeight()) {
          return i > 0 ? size - i : size - 1;
        }
      }
      return 0;
    }

    /**
     * @return {number}
     */
    lineHeight() {
      return this.contents.fontSize + settings.lineSpacing;
    }

    /**
     * メッセージの表示高さを計算する
     * @param {string} text テキスト
     * @return {number}
     */
    calcMessageHeight(text) {
      this._calcMode = true;
      let height = 0;
      const lines = text.split("\n");
      lines.forEach((line) => {
        this._lineNumber = 1;
        this.drawTextEx(line, 0, 0);
        height += (this._textHeight + settings.lineSpacing) * this._lineNumber;
      });
      this._calcMode = false;
      return height + settings.messageSpacing;
    }

    /**
     * テキストを描画し、その幅を返す
     * @param {string} text テキスト
     * @param {number} x X座標
     * @param {number} y Y座標
     * @return {number}
     */
    drawTextEx(text, x, y) {
      if (this._calcMode) {
        /**
         * 計算モード時には描画しない
         */
        let drawFunction = this.contents.drawText;
        this.contents.drawText = function () {};
        const value = super.drawTextEx(text, x, y);
        this.contents.drawText = drawFunction;
        return value;
      } else {
        return super.drawTextEx(text, x, y);
      }
    }

    /**
     * テキストの高さを計算する
     * @param {MV.textState} textState テキストの状態
     * @param {boolean} all 全文を対象とするか
     * @return {number}
     */
    calcTextHeight(textState, all) {
      /**
       * 計算モード用
       */
      this._textHeight = super.calcTextHeight(textState, all);
      return this._textHeight;
    }

    /**
     * 改行する
     * @param {MV.textState} textState テキストの状態
     */
    processNewLine(textState) {
      super.processNewLine(textState);
      if (this._calcMode) {
        this._lineNumber++;
      }
    }
  }

  window[Window_TextLog.name] = Window_TextLog;

  /**
   * テキストログを追加する
   * @param {string} text ログに追加する文字列
   */
  function addTextLog(text) {
    currentEventLog.addMessageLog(text);
  }

  /**
   * 現在のイベントのログを過去のイベントのログに移動する
   */
  function moveToPrevLog() {
    // 文章を表示しないイベントは無視する
    if (currentEventLog.messageLength === 0) {
      return;
    }
    if (settings.autoEventLogSplit) {
      addTextLog(settings.eventLogSplitter, []);
    }
    pastEventLog.push(currentEventLog);
    if (
      settings.logEventCount > 0 &&
      pastEventLog.length > settings.logEventCount
    ) {
      pastEventLog.splice(0, pastEventLog.length - settings.logEventCount);
    }
    initializeCurrentEventLog();
  }

  /**
   * 現在のイベントのログを初期化する
   */
  function initializeCurrentEventLog() {
    currentEventLog = new EventTextLog();
  }

  /**
   * 過去のイベントのログを初期化する
   */
  function initializePastEventLog() {
    pastEventLog = [];
  }

  /**テキストログを表示できるかどうか
   * A ログが１行以上ある
   * B 空のログウィンドウを表示するフラグがtrue
   * C スイッチで禁止されていない
   * (A || B) && C
   * @return {boolean}
   */
  function isTextLogEnabled() {
    return (
      (showLogWindowWithoutText ||
        currentEventLog.messageLength > 0 ||
        pastEventLog.length > 0) &&
      (disableShowLogSwitch === 0 || !$gameSwitches.value(disableShowLogSwitch))
    );
  }

  /**
   * Scene_Mapのメッセージウィンドウを退避しておくクラス
   */
  class EvacuatedMessageWindows {
    /**
     * @param {Window_Message} messageWindow メッセージウィンドウ
     * @param {Window_ScrollText} scrollTextWindow スクロールテキストウィンドウ
     * @param {Window_PauseMenu} pauseWindow ポーズメニューウィンドウ（NobleMushroom.js 用）
     */
    constructor(messageWindow, scrollTextWindow, pauseWindow) {
      this._messageWindow = messageWindow;
      this._scrollTextWindow = scrollTextWindow;
      this._pauseWindow = pauseWindow;
    }

    /**
     * @return {Window_Message}
     */
    get messageWindow() {
      return this._messageWindow;
    }

    /**
     * @return {Window_ScrollText}
     */
    get scrollTextWindow() {
      return this._scrollTextWindow;
    }

    /**
     * @return {Window_PauseMenu}
     */
    get pauseWindow() {
      return this._pauseWindow;
    }
  }

  /**
   * @type {EvacuatedMessageWindows}
   */
  let evacuatedMessageWindow = null;

  // Scene_Mapの拡張
  const _Scene_Map_start = Scene_Map.prototype.start;
  Scene_Map.prototype.start = function () {
    _Scene_Map_start.call(this);

    // 呼び出し中フラグの初期化
    this.textLogCalling = false;
  };

  const _Scene_Map_update = Scene_Map.prototype.update;
  Scene_Map.prototype.update = function () {
    // isSceneChangeOK時はイベント中も含まれるため、特殊な条件で許可する
    if (this.isActive() && !SceneManager.isSceneChanging()) {
      this.updateCallTextLog();
    }
    _Scene_Map_update.call(this);
  };

  const _Scene_Map_createMessageWindow =
    Scene_Map.prototype.createMessageWindow;
  Scene_Map.prototype.createMessageWindow = function () {
    /**
     * ログシーンからスムーズに戻るために、処理を上書きして
     * Windowインスタンスを新しく作らないようにする
     */
    if (settings.smoothBackFromLog && evacuatedMessageWindow) {
      this._messageWindow = evacuatedMessageWindow.messageWindow;
      this.addWindow(this._messageWindow);
      this._messageWindow.subWindows().forEach(function (window) {
        this.addWindow(window);
      }, this);
    } else {
      _Scene_Map_createMessageWindow.call(this);
    }
  };

  const _Scene_Map_createScrollTextWindow =
    Scene_Map.prototype.createScrollTextWindow;
  Scene_Map.prototype.createScrollTextWindow = function () {
    /**
     * ログシーンからスムーズに戻るために、処理を上書きして
     * Windowインスタンスを新しく作らないようにする
     */
    if (settings.smoothBackFromLog && evacuatedMessageWindow) {
      this._scrollTextWindow = evacuatedMessageWindow.scrollTextWindow;
      this.addWindow(this._scrollTextWindow);
    } else {
      _Scene_Map_createScrollTextWindow.call(this);
    }
  };

  if (PluginManager.isLoadedPlugin("NobleMushroom")) {
    /**
     * ハンドラを更新する
     */
    Scene_Map.prototype.refreshPauseWindowHandlers = function () {
      this._pauseWindow.setHandler(
        Scene_Map.symbolSave,
        this.callSave.bind(this)
      );
      this._pauseWindow.setHandler(
        Scene_Map.symbolLoad,
        this.callLoad.bind(this)
      );
      this._pauseWindow.setHandler("quickSave", this.callQuickSave.bind(this));
      this._pauseWindow.setHandler("quickLoad", this.callQuickLoad.bind(this));
      this._pauseWindow.setHandler("toTitle", this.callToTitle.bind(this));
      this._pauseWindow.setHandler("cancel", this.offPause.bind(this));
    };
    /**
     * NobleMushroom.js のほうが上に読み込まれている場合
     */
    if (Scene_Map.prototype.createPauseWindow) {
      const _Scene_Map_createPauseWindow =
        Scene_Map.prototype.createPauseWindow;
      Scene_Map.prototype.createPauseWindow = function () {
        /**
         * ログシーンからスムーズに戻るために、処理を上書きして
         * Windowインスタンスを新しく作らないようにする
         */
        if (settings.smoothBackFromLog && evacuatedMessageWindow) {
          this._pauseWindow = evacuatedMessageWindow.pauseWindow;
          this.refreshPauseWindowHandlers();
          this.addWindow(this._pauseWindow);
        } else {
          _Scene_Map_createPauseWindow.call(this);
        }
      };
    } else {
      const _Scene_Map_onMapLoaded = Scene_Map.prototype.onMapLoaded;
      Scene_Map.prototype.onMapLoaded = function () {
        _Scene_Map_onMapLoaded.call(this);
        if (settings.smoothBackFromLog && evacuatedMessageWindow) {
          this._windowLayer.removeChild(this._pauseWindow);
          this._pauseWindow = evacuatedMessageWindow.pauseWindow;
          this.refreshPauseWindowHandlers();
          this.addWindow(this._pauseWindow);
        }
      };
    }
  }

  Scene_Map.prototype.updateCallTextLog = function () {
    if (this.isTextLogEnabled()) {
      if (this.isTextLogCalled()) {
        this.textLogCalling = true;
      }
      if (this.textLogCalling && !$gamePlayer.isMoving()) {
        this.callTextLog();
      }
    } else {
      this.textLogCalling = false;
    }
  };

  /**
   * どういうタイミングでバックログを開いても良いか
   *  A マップを移動中（メニューを開ける間）
   *  B イベント中かつ、メッセージウィンドウが開いている
   *  C 表示すべきログが１行以上ある
   *  D ログ表示禁止スイッチがOFF
   *  E NobleMushroom.js でセーブ・ロード画面を開いていない
   *  (A || B) && C && D && E
   */
  Scene_Map.prototype.isTextLogEnabled = function () {
    return (
      ($gameSystem.isMenuEnabled() ||
        ($gameMap.isEventRunning() && !this._messageWindow.isClosed())) &&
      isTextLogEnabled() &&
      !this.isFileListWindowActive()
    );
  };

  /**
   * NobleMushroom.js でセーブ・ロード画面を開いているかどうか
   * @return {boolean}
   */
  Scene_Map.prototype.isFileListWindowActive = function () {
    return this._fileListWindow && this._fileListWindow.isOpenAndActive();
  };

  Scene_Map.prototype.isTextLogCalled = function () {
    return Input.isTriggered(openLogKey);
  };

  Scene_Map.prototype.callTextLog = function () {
    evacuatedMessageWindow = new EvacuatedMessageWindows(
      this._messageWindow,
      this._scrollTextWindow,
      this._pauseWindow
    );
    SoundManager.playCursor();
    SceneManager.push(Scene_TextLog);
    $gameTemp.clearDestination();
  };

  /**
   * Window_ScrollText
   */
  const _Window_ScrollText_terminateMessage =
    Window_ScrollText.prototype.terminateMessage;
  Window_ScrollText.prototype.terminateMessage = function () {
    if (
      settings.includeScrollText &&
      (disableLoggingSwitch === 0 ||
        !$gameSwitches.value(disableLoggingSwitch)) &&
      $gameMessage.hasText()
    ) {
      let message = {
        text: "",
      };
      message.text += this.convertEscapeCharacters($gameMessage.allText());
      addTextLog(message.text);
    }
    _Window_ScrollText_terminateMessage.call(this);
  };

  // Window_Messageの拡張
  // メッセージ表示時にログに追加する
  const _Window_Message_terminateMessage =
    Window_Message.prototype.terminateMessage;
  Window_Message.prototype.terminateMessage = function () {
    if (
      (disableLoggingSwitch === 0 ||
        !$gameSwitches.value(disableLoggingSwitch)) &&
      $gameMessage.hasText()
    ) {
      let message = {
        text: "",
      };
      // YEP_MessageCore.js or DarkPlasma_NameWindow.js のネーム表示ウィンドウに対応
      if (
        this.hasNameWindow() &&
        this._nameWindow.active &&
        settings.includeName
      ) {
        const nameColor = this.nameColorInLog(this._nameWindow._text);
        message.text += `\x1bC[${nameColor}]${this._nameWindow._text}\n\x1bC[0]`;
      }
      message.text += this.convertEscapeCharacters($gameMessage.allText());
      addTextLog(message.text);
      if ($gameMessage.isChoice()) {
        this._choiceWindow.addToLog();
      }
    }
    _Window_Message_terminateMessage.call(this);
  };

  // YEP_MessageCore.js や DarkPlasma_NameWindow のネーム表示ウィンドウを使用しているかどうか
  Window_Message.prototype.hasNameWindow = function () {
    return (
      this._nameWindow &&
      (typeof Window_NameBox !== "undefined" ||
        PluginManager.isLoadedPlugin("DarkPlasma_NameWindow"))
    );
  };

  Window_Message.prototype.nameColorInLog = function (name) {
    if (PluginManager.isLoadedPlugin("DarkPlasma_NameWindow")) {
      return this.colorByName(name);
    }
    if (Yanfly && Yanfly.Param && Yanfly.Param.MSGNameBoxColor) {
      return Yanfly.Param.MSGNameBoxColor;
    }
    return 0;
  };

  const _Window_ChoiceList_windowWidth =
    Window_ChoiceList.prototype.windowWidth;
  Window_ChoiceList.prototype.windowWidth = function () {
    // 再開時に選択肢が開いているとエラーになる不具合対策
    if (!this._windowContentsSprite) {
      return 96;
    }
    return _Window_ChoiceList_windowWidth.call(this);
  };

  /**
   * 選択した内容をログに記録する
   */
  Window_ChoiceList.prototype.addToLog = function () {
    const chosenIndex = $gameMessage.chosenIndex();
    if (
      settings.includeChoice &&
      (disableLoggingSwitch === 0 ||
        !$gameSwitches.value(disableLoggingSwitch)) &&
      $gameMessage.hasText()
    ) {
      let text = "";
      // MPP_ChoiceEx.js は choiceCancelType を-1ではなく選択肢配列のサイズにする。
      // 競合回避のため、 choiceCancelType を -1 に限定しない判定を行う。
      if (
        chosenIndex === $gameMessage.choiceCancelType() &&
        (chosenIndex < 0 || $gameMessage.choices().length <= chosenIndex)
      ) {
        if (!settings.includeChoiceCancel) {
          return;
        }
        text = settings.choiceCancelText;
      } else {
        text = $gameMessage.choices()[chosenIndex];
      }
      let message = {
        text: settings.choiceFormat.replace(
          /{choice}/gi,
          `\x1bC[${settings.choiceColor}]${text}\x1bC[0]`
        ),
      };
      addTextLog(message.text);
    }
  };

  const _Game_Message_clear = Game_Message.prototype.clear;
  Game_Message.prototype.clear = function () {
    _Game_Message_clear.call(this);
    this._chosenIndex = null;
  };

  const _Game_Message_onChoice = Game_Message.prototype.onChoice;
  Game_Message.prototype.onChoice = function (index) {
    _Game_Message_onChoice.call(this, index);
    this._chosenIndex = index;
  };

  /**
   * 選択肢で選んだ番号を返す
   * @return {number|null}
   */
  Game_Message.prototype.chosenIndex = function () {
    return this._chosenIndex;
  };

  const _Game_Player_reserveTransfer = Game_Player.prototype.reserveTransfer;
  Game_Player.prototype.reserveTransfer = function (mapId, x, y, d, fadeType) {
    _Game_Player_reserveTransfer.call(this, mapId, x, y, d, fadeType);
    /**
     * 場所移動時に退避したメッセージウィンドウを初期化する
     * そうしないと、ログウィンドウから戻ったものと判定され、場所移動後にメッセージウィンドウが表示されっぱなしになるケースがある
     */
    evacuatedMessageWindow = null;
  };

  const _Game_System_initialize = Game_System.prototype.initialize;
  Game_System.prototype.initialize = function () {
    _Game_System_initialize.call(this);
    initializeCurrentEventLog();
    initializePastEventLog();
    evacuatedMessageWindow = null;
  };

  const _Game_System_onAfterLoad = Game_System.prototype.onAfterLoad;
  Game_System.prototype.onAfterLoad = function () {
    _Game_System_onAfterLoad.call(this);
    initializeCurrentEventLog();
    initializePastEventLog();
    evacuatedMessageWindow = null;
  };

  /**
   * ログにテキストを記録する
   * @param {string} text ログに記録したいテキスト
   */
  Game_System.prototype.insertTextLog = function (text) {
    addTextLog(text);
  };

  /**
   * イベント終了時にそのイベントのログを直前のイベントのログとして保持する
   */
  const _Game_Interpreter_terminate = Game_Interpreter.prototype.terminate;
  Game_Interpreter.prototype.terminate = function () {
    // 以下の場合はリセットしない
    //  - バトルイベント終了時
    //  - コモンイベント終了時
    //  - 並列イベント終了時
    if (!this.isCommonOrBattleEvent() && !this.isParallelEvent()) {
      moveToPrevLog();
      /**
       * イベント終了時に退避しておいたメッセージウィンドウも破棄する
       */
      evacuatedMessageWindow = null;
    }
    _Game_Interpreter_terminate.call(this);
  };

  // コモンイベントは以下の条件を満たす
  //  A イベント中にcommand117で実行されるコモンイベント（depth > 0）
  //  B IDなし（eventId === 0）
  // A || B
  // ただし、バトルイベントもeventIdが0のため、厳密にその二者を区別はできない
  Game_Interpreter.prototype.isCommonOrBattleEvent = function () {
    return this._depth > 0 || this._eventId === 0;
  };

  // 並列実行イベントかどうか
  // コモンイベントは判定不能のため、isCommonOrBattleEventに任せる
  Game_Interpreter.prototype.isParallelEvent = function () {
    return (
      this._eventId !== 0 &&
      this.isOnCurrentMap() &&
      $gameMap.event(this._eventId).isTriggerIn([4])
    );
  };

  const _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    switch (command || "") {
      case "showTextLog":
        if (isTextLogEnabled()) {
          SceneManager.push(Scene_TextLog);
        }
        break;
      case "insertLogSplitter":
        addTextLog(settings.eventLogSplitter, []);
        break;
      case "insertTextLog":
        addTextLog(args[0]);
        break;
    }
  };

  // Scene_Menu拡張
  // YEP_MainMenuManager.jsでコマンド指定する際に実行する
  Scene_Menu.prototype.commandTextLog = function () {
    SceneManager.push(Scene_TextLog);
  };

  // Window_MenuCommand拡張
  Window_MenuCommand.prototype.isTextLogEnabled = function () {
    return isTextLogEnabled();
  };

  // TouchInput拡張 マウスドラッグ/スワイプ対応
  const _TouchInput_clear = TouchInput.clear;
  TouchInput.clear = function () {
    _TouchInput_clear.call(this);
    this._deltaX = 0;
    this._deltaY = 0;
  };

  const _TouchInput_update = TouchInput.update;
  TouchInput.update = function () {
    _TouchInput_update.call(this);
    if (!this.isPressed()) {
      this._deltaX = 0;
      this._deltaY = 0;
    }
  };

  const _TouchInput_onMove = TouchInput._onMove;
  TouchInput._onMove = function (x, y) {
    if (this._x !== 0) {
      this._deltaX = x - this._x;
    }
    if (this._y !== 0) {
      this._deltaY = y - this._y;
    }
    _TouchInput_onMove.call(this, x, y);
  };

  // 上下にドラッグ、スワイプしているかどうか
  // 推し続けた時間の剰余を取ってタイミングを調整しているが
  // 環境による差異については未検証
  TouchInput.isUpMoved = function () {
    return this._deltaY < 0 && this._pressedTime % 10 === 0;
  };

  TouchInput.isDownMoved = function () {
    return this._deltaY > 0 && this._pressedTime % 10 === 0;
  };
})();


code:
//=============================================================================
// EnemyBook.js
//=============================================================================

/*:
 * @plugindesc Displays detailed statuses of enemies.
 * @author Yoji Ojima
 *
 * @param Unknown Data
 * @desc The index name for an unknown enemy.
 * @default ??????
 *
 * @help
 *
 * Plugin Command:
 *   EnemyBook open         # Open the enemy book screen
 *   EnemyBook add 3        # Add enemy #3 to the enemy book
 *   EnemyBook remove 4     # Remove enemy #4 from the enemy book
 *   EnemyBook complete     # Complete the enemy book
 *   EnemyBook clear        # Clear the enemy book
 *
 * Enemy Note:
 *   <desc1:foobar>         # Description text in the enemy book, line 1
 *   <desc2:blahblah>       # Description text in the enemy book, line 2
 *   <book:no>              # This enemy does not appear in the enemy book
 */

/*:ja
 * @plugindesc モンスター図鑑です。敵キャラの詳細なステータスを表示します。
 * @author Yoji Ojima
 *
 * @param Unknown Data
 * @desc 未確認の敵キャラの索引名です。
 * @default ？？？？？？
 *
 * @help
 *
 * プラグインコマンド:
 *   EnemyBook open         # 図鑑画面を開く
 *   EnemyBook add 3        # 敵キャラ３番を図鑑に追加
 *   EnemyBook remove 4     # 敵キャラ４番を図鑑から削除
 *   EnemyBook complete     # 図鑑を完成させる
 *   EnemyBook clear        # 図鑑をクリアする
 *
 * 敵キャラのメモ:
 *   <desc1:なんとか>       # 説明１行目
 *   <desc2:かんとか>       # 説明２行目
 *   <book:no>              # 図鑑に載せない場合
 */

(function () {
  var parameters = PluginManager.parameters("EnemyBook");
  var unknownData = String(parameters["Unknown Data"] || "??????");

  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.call(this, command, args);
    if (command === "EnemyBook") {
      switch (args[0]) {
        case "open":
          SceneManager.push(Scene_EnemyBook);
          break;
        case "add":
          $gameSystem.addToEnemyBook(Number(args[1]));
          break;
        case "remove":
          $gameSystem.removeFromEnemyBook(Number(args[1]));
          break;
        case "complete":
          $gameSystem.completeEnemyBook();
          break;
        case "clear":
          $gameSystem.clearEnemyBook();
          break;
      }
    }
  };

  Game_System.prototype.addToEnemyBook = function (enemyId) {
    if (!this._enemyBookFlags) {
      this.clearEnemyBook();
    }
    this._enemyBookFlags[enemyId] = true;
  };

  Game_System.prototype.removeFromEnemyBook = function (enemyId) {
    if (this._enemyBookFlags) {
      this._enemyBookFlags[enemyId] = false;
    }
  };

  Game_System.prototype.completeEnemyBook = function () {
    this.clearEnemyBook();
    for (var i = 1; i < $dataEnemies.length; i++) {
      this._enemyBookFlags[i] = true;
    }
  };

  Game_System.prototype.clearEnemyBook = function () {
    this._enemyBookFlags = [];
  };

  Game_System.prototype.isInEnemyBook = function (enemy) {
    if (this._enemyBookFlags && enemy) {
      return !!this._enemyBookFlags[enemy.id];
    } else {
      return false;
    }
  };

  var _Game_Troop_setup = Game_Troop.prototype.setup;
  Game_Troop.prototype.setup = function (troopId) {
    _Game_Troop_setup.call(this, troopId);
    this.members().forEach(function (enemy) {
      if (enemy.isAppeared()) {
        $gameSystem.addToEnemyBook(enemy.enemyId());
      }
    }, this);
  };

  var _Game_Enemy_appear = Game_Enemy.prototype.appear;
  Game_Enemy.prototype.appear = function () {
    _Game_Enemy_appear.call(this);
    $gameSystem.addToEnemyBook(this._enemyId);
  };

  var _Game_Enemy_transform = Game_Enemy.prototype.transform;
  Game_Enemy.prototype.transform = function (enemyId) {
    _Game_Enemy_transform.call(this, enemyId);
    $gameSystem.addToEnemyBook(enemyId);
  };

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

  Scene_EnemyBook.prototype = Object.create(Scene_MenuBase.prototype);
  Scene_EnemyBook.prototype.constructor = Scene_EnemyBook;

  Scene_EnemyBook.prototype.initialize = function () {
    Scene_MenuBase.prototype.initialize.call(this);
  };

  Scene_EnemyBook.prototype.create = function () {
    Scene_MenuBase.prototype.create.call(this);
    this._indexWindow = new Window_EnemyBookIndex(0, 0);
    this._indexWindow.setHandler("cancel", this.popScene.bind(this));
    var wy = this._indexWindow.height;
    var ww = Graphics.boxWidth;
    var wh = Graphics.boxHeight - wy;
    this._statusWindow = new Window_EnemyBookStatus(0, wy, ww, wh);
    this.addWindow(this._indexWindow);
    this.addWindow(this._statusWindow);
    this._indexWindow.setStatusWindow(this._statusWindow);
  };

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

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

  Window_EnemyBookIndex.lastTopRow = 0;
  Window_EnemyBookIndex.lastIndex = 0;

  Window_EnemyBookIndex.prototype.initialize = function (x, y) {
    var width = Graphics.boxWidth;
    var height = this.fittingHeight(6);
    Window_Selectable.prototype.initialize.call(this, x, y, width, height);
    this.refresh();
    this.setTopRow(Window_EnemyBookIndex.lastTopRow);
    this.select(Window_EnemyBookIndex.lastIndex);
    this.activate();
  };

  Window_EnemyBookIndex.prototype.maxCols = function () {
    return 3;
  };

  Window_EnemyBookIndex.prototype.maxItems = function () {
    return this._list ? this._list.length : 0;
  };

  Window_EnemyBookIndex.prototype.setStatusWindow = function (statusWindow) {
    this._statusWindow = statusWindow;
    this.updateStatus();
  };

  Window_EnemyBookIndex.prototype.update = function () {
    Window_Selectable.prototype.update.call(this);
    this.updateStatus();
  };

  Window_EnemyBookIndex.prototype.updateStatus = function () {
    if (this._statusWindow) {
      var enemy = this._list[this.index()];
      this._statusWindow.setEnemy(enemy);
    }
  };

  Window_EnemyBookIndex.prototype.refresh = function () {
    this._list = [];
    for (var i = 1; i < $dataEnemies.length; i++) {
      var enemy = $dataEnemies[i];
      if (enemy.name && enemy.meta.book !== "no") {
        this._list.push(enemy);
      }
    }
    this.createContents();
    this.drawAllItems();
  };

  Window_EnemyBookIndex.prototype.drawItem = function (index) {
    var enemy = this._list[index];
    var rect = this.itemRectForText(index);
    var name;
    if ($gameSystem.isInEnemyBook(enemy)) {
      name = enemy.name;
    } else {
      name = unknownData;
    }
    this.drawText(name, rect.x, rect.y, rect.width);
  };

  Window_EnemyBookIndex.prototype.processCancel = function () {
    Window_Selectable.prototype.processCancel.call(this);
    Window_EnemyBookIndex.lastTopRow = this.topRow();
    Window_EnemyBookIndex.lastIndex = this.index();
  };

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

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

  Window_EnemyBookStatus.prototype.initialize = function (x, y, width, height) {
    Window_Base.prototype.initialize.call(this, x, y, width, height);
    this._enemy = null;
    this._enemySprite = new Sprite();
    this._enemySprite.anchor.x = 0.5;
    this._enemySprite.anchor.y = 0.5;
    this._enemySprite.x = width / 2 - 20;
    this._enemySprite.y = height / 2;
    this.addChildToBack(this._enemySprite);
    this.refresh();
  };

  Window_EnemyBookStatus.prototype.setEnemy = function (enemy) {
    if (this._enemy !== enemy) {
      this._enemy = enemy;
      this.refresh();
    }
  };

  Window_EnemyBookStatus.prototype.update = function () {
    Window_Base.prototype.update.call(this);
    if (this._enemySprite.bitmap) {
      var bitmapHeight = this._enemySprite.bitmap.height;
      var contentsHeight = this.contents.height;
      var scale = 1;
      if (bitmapHeight > contentsHeight) {
        scale = contentsHeight / bitmapHeight;
      }
      this._enemySprite.scale.x = scale;
      this._enemySprite.scale.y = scale;
    }
  };

  Window_EnemyBookStatus.prototype.refresh = function () {
    var enemy = this._enemy;
    var x = 0;
    var y = 0;
    var lineHeight = this.lineHeight();

    this.contents.clear();

    if (!enemy || !$gameSystem.isInEnemyBook(enemy)) {
      this._enemySprite.bitmap = null;
      return;
    }

    var name = enemy.battlerName;
    var hue = enemy.battlerHue;
    var bitmap;
    if ($gameSystem.isSideView()) {
      bitmap = ImageManager.loadSvEnemy(name, hue);
    } else {
      bitmap = ImageManager.loadEnemy(name, hue);
    }
    this._enemySprite.bitmap = bitmap;

    this.resetTextColor();
    this.drawText(enemy.name, x, y);

    x = this.textPadding();
    y = lineHeight + this.textPadding();

    for (var i = 0; i < 8; i++) {
      this.changeTextColor(this.systemColor());
      this.drawText(TextManager.param(i), x, y, 160);
      this.resetTextColor();
      this.drawText(enemy.params[i], x + 160, y, 60, "right");
      y += lineHeight;
    }

    var rewardsWidth = 280;
    x = this.contents.width - rewardsWidth;
    y = lineHeight + this.textPadding();

    this.resetTextColor();
    this.drawText(enemy.exp, x, y);
    x += this.textWidth(enemy.exp) + 6;
    this.changeTextColor(this.systemColor());
    this.drawText(TextManager.expA, x, y);
    x += this.textWidth(TextManager.expA + "  ");

    this.resetTextColor();
    this.drawText(enemy.gold, x, y);
    x += this.textWidth(enemy.gold) + 6;
    this.changeTextColor(this.systemColor());
    this.drawText(TextManager.currencyUnit, x, y);

    x = this.contents.width - rewardsWidth;
    y += lineHeight;

    for (var j = 0; j < enemy.dropItems.length; j++) {
      var di = enemy.dropItems[j];
      if (di.kind > 0) {
        var item = Game_Enemy.prototype.itemObject(di.kind, di.dataId);
        this.drawItemName(item, x, y, rewardsWidth);
        y += lineHeight;
      }
    }

    var descWidth = 480;
    x = this.contents.width - descWidth;
    y = this.textPadding() + lineHeight * 7;
    this.drawTextEx(enemy.meta.desc1, x, y + lineHeight * 0, descWidth);
    this.drawTextEx(enemy.meta.desc2, x, y + lineHeight * 1, descWidth);
  };
})();

repo_name: Idkwtcm/violated

license: unknown


code:
//=============================================================================
// イベント接触判定カスタマイズ　Ver1.00
/*:
@plugindesc イベント接触判定カスタマイズプラグイン
@author 摘草 http:re-wind.org/
@help 通常、イベント起動条件が「プレイヤーから接触」「イベントから接触」となっている
イベントは決定キーで隣のマスからも起動できてしまいますが、
それを無効化するプラグインです。
ゲーム中から変数t_ev_trigを操作することで設定の随時変更も恐らく可能（未確認）。
ファイル名を変更すると正常に動作しません。ファイル名を変える場合は
「EVtrig_Custum」部分を任意のファイル名に書き換えてください。

パラメータの値を変更することで下記のように動作します。

↓パラメータの値
0：プレイヤーから接触＆イベントから接触の両方無効
1：イベントから接触のみ無効
2：プレイヤーから接触のみ無効
3：無効化しない
@param t_ev_trig
@desc 0:プレイヤーから接触＆イベントから接触　1:イベントから接触のみ　2:プレイヤーから接触のみ　3:無効化しない（デフォルト）
@default 0

*/
//=============================================================================

(function () {
  var parameters = PluginManager.parameters("EVtrig_Custum");
  var t_ev_trig = String(parameters["t_ev_trig"]);
  var t_ev_trig_type = String(parameters["t_ev_trig_type"]);

  //分岐

  if (t_ev_trig == 0) {
    t_ev_trig_type = "[0]";
  } else if (t_ev_trig == 1) {
    t_ev_trig_type = "[0,1]";
  } else if (t_ev_trig == 2) {
    t_ev_trig_type = "[0,2]";
  } else if (t_ev_trig == 3) {
    t_ev_trig_type = "[0,1,2]";
  }

  //分岐ここまで

  Game_Player.prototype.triggerButtonAction = function () {
    if (Input.isTriggered("ok")) {
      if (this.getOnOffVehicle()) {
        return true;
      }
      this.checkEventTriggerHere([0]);
      if ($gameMap.setupStartingEvent()) {
        return true;
      }
      this.checkEventTriggerThere(t_ev_trig_type);
      if ($gameMap.setupStartingEvent()) {
        return true;
      }
    }
    return false;
  };
})();


code:
/*=============================================================================
 ExtraGauge.js
----------------------------------------------------------------------------
 (C)2020 Triacontane
 This software is released under the MIT License.
 http://opensource.org/licenses/mit-license.php
----------------------------------------------------------------------------
 Version
 1.0.3 2020/09/16 ゲージ表示後に一度シーンを切り替えてからマップ移動するとゲージピクチャが消えてしまう問題を修正
 1.0.2 2020/09/12 ヘルプのスクリプトの誤記を修正
 1.0,1 2020/08/30 非表示のときは画像を更新しないよう修正
 1.0.0 2020/08/29 初版
----------------------------------------------------------------------------
 [Blog]   : https://triacontane.blogspot.jp/
 [Twitter]: https://twitter.com/triacontane/
 [GitHub] : https://github.com/triacontane/
=============================================================================*/

/*:
 * @plugindesc 汎用ゲージ追加プラグイン
 * @target MZ
 * @url https://github.com/triacontane/RPGMakerMV/tree/mz_master/ExtraGauge.js
 * @base PluginCommonBase
 * @author トリアコンタン
 *
 * @param GaugeList
 * @text ゲージリスト
 * @desc 各画面に追加するゲージのリストです。
 * @default []
 * @type struct<Gauge>[]
 *
 * @help ExtraGauge.js
 *
 * 各画面に追加で任意のゲージを好きなだけ表示できます。
 * 現在値や最大値を変数、スクリプトから指定すれば、あとは値の変動に応じて
 * 自動的にゲージが増減します。
 *
 * ゲージは、マップ画面と戦闘画面ではピクチャの上かつウィンドウの下に、
 * それ以外の画面ではウィンドウの上に表示されます。
 *
 * このプラグインの利用にはベースプラグイン『PluginCommonBase.js』が必要です。
 * 『PluginCommonBase.js』は、RPGツクールMZのインストールフォルダ配下の
 * 以下のフォルダに格納されています。
 * dlc/BasicResources/plugins/official
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

/*~struct~Gauge:
 *
 * @param SceneName
 * @text 対象シーン
 * @desc 追加対象のシーンです。オリジナルのシーンを対象にする場合はシーンクラス名を直接記入します。
 * @type select
 * @default Scene_Title
 * @option タイトル
 * @value Scene_Title
 * @option マップ
 * @value Scene_Map
 * @option ゲームオーバー
 * @value Scene_Gameover
 * @option バトル
 * @value Scene_Battle
 * @option メインメニュー
 * @value Scene_Menu
 * @option アイテム
 * @value Scene_Item
 * @option スキル
 * @value Scene_Skill
 * @option 装備
 * @value Scene_Equip
 * @option ステータス
 * @value Scene_Status
 * @option オプション
 * @value Scene_Options
 * @option セーブ
 * @value Scene_Save
 * @option ロード
 * @value Scene_Load
 * @option ゲーム終了
 * @value Scene_End
 * @option ショップ
 * @value Scene_Shop
 * @option 名前入力
 * @value Scene_Name
 * @option デバッグ
 * @value Scene_Debug
 *
 * @param Id
 * @text 識別子
 * @desc ゲージの識別子です。特に使用されませんが、分かりやすい名称を設定すると管理がしやすくなります。
 * @default gauge01
 *
 * @param SwitchId
 * @text 表示スイッチID
 * @desc 指定したスイッチがONの場合のみ画面に表示されます。0を指定すると常に表示されます。
 * @default 0
 * @type switch
 *
 * @param OpacityVariable
 * @text 不透明度変数ID
 * @desc 不透明度を取得する変数番号です。0を指定すると常に不透明度255で表示されます。
 * @default 0
 * @type variable
 *
 * @param Layout
 * @text レイアウト
 * @desc ゲージの表示座標と幅、高さです。スクリプトを使用する場合、変数witch, heightでUIエリアの幅と高さを取得できます。
 * @type struct<Layout>
 * @default {"x":"width / 2","y":"30","width":"width * 0.8","height":"36","GaugeX":"0","GaugeHeight":"0","Vertical":"false"}
 *
 * @param CurrentMethod
 * @text 現在値取得方法
 * @desc ゲージの現在値を取得する方法です。変数、スクリプトのいずれかを設定します。
 * @default {"VariableId":"1","Script":"","FixedValue":""}
 * @type struct<Method>
 *
 * @param MaxMethod
 * @text 最大値取得方法
 * @desc ゲージの最大値を取得する方法です。変数、スクリプト、固定値のいずれかを設定します。
 * @default {"VariableId":"0","Script":"","FixedValue":"100"}
 * @type struct<Method>
 *
 * @param Detail
 * @text 詳細設定
 * @desc ゲージの配置や色などの細かい設定です。
 * @type struct<Detail>
 * @default
 *
 * @param LowerPicture
 * @text 下ピクチャ
 * @desc ゲージの下に表示されるピクチャです。ゲージの中心と画像の中心が合わせて表示されます。
 * @default
 * @type struct<Picture>
 *
 * @param UpperPicture
 * @text 上ピクチャ
 * @desc ゲージの上に表示されるピクチャです。ゲージの中心と画像の中心が合わせて表示されます。
 * @default
 * @type struct<Picture>
 *
 * @param Battler
 * @text バトラー情報
 * @desc ゲージの主体となるバトラー情報の参照方法を指定します。現在値、最大値をスクリプトで決める場合のみ使用します。
 * @default
 * @type struct<Battler>
 */

/*~struct~Layout:
 *
 * @param x
 * @text X座標
 * @desc X座標です。原点は中央です。数値以外を指定した場合はスクリプトとして評価します。
 * @default width / 2
 *
 * @param y
 * @text Y座標
 * @desc Y座標です。原点は中央です。数値以外を指定した場合はスクリプトとして評価します。
 * @default 30
 *
 * @param width
 * @text 横幅
 * @desc 横幅です。数値以外を指定した場合はスクリプトとして評価します。
 * @default width * 0.8
 *
 * @param height
 * @text 高さ
 * @desc 高さです。数値以外を指定した場合はスクリプトとして評価します。
 * @default 36
 *
 * @param GaugeX
 * @text ゲージX座標
 * @desc ゲージのX座標です。ラベルが長い文字の場合は変更してください。
 * @default 0
 *
 * @param GaugeHeight
 * @text ゲージ高さ
 * @desc ゲージの高さです。0を指定すると全体の高さに合わせられます。
 * @default 0
 *
 * @param Vertical
 * @text 縦ゲージ
 * @desc 有効にすると縦方向ゲージになります。ラベルなども縦方向になるので注意してください。
 * @default false
 * @type boolean
 */

/*~struct~Picture:
 *
 * @param FileName
 * @text ファイル名
 * @desc ピクチャのファイル名です。
 * @default
 * @type file
 * @dir img/pictures
 *
 * @param OffsetX
 * @text X座標補正値
 * @desc X座標の補正値です。
 * @default 0
 * @type number
 * @min -9999
 *
 * @param OffsetY
 * @text Y座標補正値
 * @desc Y座標の補正値です。
 * @default 0
 * @type number
 * @min -9999
 */

/*~struct~Method:
 *
 * @param VariableId
 * @text 取得変数ID
 * @desc ゲージの値を取得する変数番号です。スクリプトより優先して参照されます。
 * @default 0
 * @type variable
 *
 * @param Script
 * @text 取得スクリプト
 * @desc ゲージの値を取得するスクリプトです。固定値より優先して参照されます。
 * @default
 * @type combo
 * @option battler.hp; // HP
 * @option battler.mhp; // 最大HP
 * @option battler.mp; // MP
 * @option battler.mmp; // 最大MP
 * @option battler.tp; // TP
 * @option battler.maxTp(); // 最大MP
 * @option meta.value; // メモ欄[value]の値
 *
 * @param FixedValue
 * @text 固定値
 * @desc ゲージの値を固定値で設定します。現在値に固定値を指定することは推奨しません。
 * @default
 * @type number
 * @min 1
 */

/*~struct~Detail:
 *
 * @param RisingSmoothness
 * @text 上昇中のなめらかさ
 * @desc 大きい数を指定するとゲージがゆっくりと上昇します。
 * @default 1
 * @type number
 * @min 1
 *
 * @param FallingSmoothness
 * @text 下降中のなめらかさ
 * @desc 大きい数を指定するとゲージがゆっくりと下降します。
 * @default 1
 * @type number
 * @min 1
 *
 * @param GaugeColorPreset
 * @text ゲージ色のプリセット
 * @desc ゲージ色をプリセットから簡易指定します。詳細指定があればそちらが優先されます。
 * @default hp
 * @type select
 * @option
 * @option hp
 * @option mp
 * @option tp
 * @option time
 *
 * @param GaugeColorLeft
 * @text ゲージ色(左)
 * @desc 左側のゲージ色です。テキストカラー番号かCSS色指定(rgba(0, 0, 0, 0))を指定します。
 * @default 0
 *
 * @param GaugeColorRight
 * @text ゲージ色(右)
 * @desc 右側のゲージ色です。テキストカラー番号かCSS色指定(rgba(0, 0, 0, 0))を指定します。
 * @default 0
 *
 * @param BackColor
 * @text ゲージ背景色
 * @desc ゲージ背景色です。テキストカラー番号かCSS色指定(rgba(0, 0, 0, 0))を指定します。
 * @default 0
 *
 * @param Label
 * @text ラベル
 * @desc ゲージの左に表示されるラベル文字列です。
 * @default
 *
 * @param LabelFont
 * @text ラベルフォント
 * @desc ラベルを表示するときのフォント情報です。未指定の場合はゲージのデフォルト値が使用されます。
 * @default
 * @type struct
 *
 * @param DrawValue
 * @text 現在値を描画する
 * @desc ゲージの右側に現在値を描画します。
 * @default true
 * @type boolean
 *
 * @param ValueFont
 * @text 現在値フォント
 * @desc 現在値を表示するときのフォント情報です。未指定の場合はゲージのデフォルト値が使用されます。
 * @default
 * @type struct
 *
 * @param FlashIfFull
 * @text 満タン時にフラッシュ
 * @desc ゲージの現在値が最大値以上になるとゲージをフラッシュさせます。
 * @default false
 * @type boolean
 */

/*~struct~Font:
 *
 * @param Face
 * @text フォント名
 * @desc フォント名です。woffファイルを指定してください。
 * @default
 * @type file
 * @dir fonts
 *
 * @param Size
 * @text フォントサイズ
 * @desc フォントサイズです。
 * @default 0
 * @type number
 *
 * @param Color
 * @text テキストカラー
 * @desc テキストカラーです。テキストカラー番号かCSS色指定(rgba(0, 0, 0, 0))を指定します。
 * @default 0
 * @type number
 *
 * @param OutlineColor
 * @text アウトラインカラー
 * @desc アウトラインカラーです。テキストカラー番号かCSS色指定(rgba(0, 0, 0, 0))を指定します。
 * @default 0
 * @type number
 *
 * @param OutlineWidth
 * @text アウトライン横幅
 * @desc アウトラインの横幅です。
 * @default 0
 * @type number
 */

/*~struct~Battler:
 *
 * @param Type
 * @text バトラー種別
 * @desc ゲージの主体となるバトラーの取得方法です。
 * @default
 * @type select
 * @option アクターID
 * @value ActorId
 * @option パーティの並び順
 * @value PartyIndex
 * @option 敵キャラID
 * @value EnemyId
 * @option 敵グループの並び順(戦闘画面で有効)
 * @value TroopIndex
 * @option メニュー画面で選択したアクター(メニュー詳細画面で有効)
 * @value MenuActor
 *
 * @param ActorId
 * @text アクターID
 * @desc 種別選択で『アクターID』を選択したときのアクターIDです。
 * @default 0
 * @type actor
 *
 * @param EnemyId
 * @text 敵キャラID
 * @desc 種別選択で『敵キャラID』を選択したときの敵キャラIDです。
 * @default 0
 * @type enemy
 *
 * @param Index
 * @text 並び順
 * @desc 種別選択で『パーティの並び順』『敵グループの並び順』を選択したときの並び順です。先頭は[0]です。
 * @default 0
 * @type number
 */

(() => {
  "use strict";
  const script = document.currentScript;
  const param = PluginManagerEx.createParameter(script);
  if (!param.GaugeList) {
    param.GaugeList = [];
  }

  const _Scene_Base_create = Scene_Base.prototype.create;
  Scene_Base.prototype.create = function () {
    _Scene_Base_create.apply(this, arguments);
    if (!(this instanceof Scene_Map)) {
      this.createExtraGauges();
    }
  };

  const _Scene_Map_create = Scene_Map.prototype.create;
  Scene_Map.prototype.create = function () {
    _Scene_Map_create.apply(this, arguments);
    this.createExtraGauges();
  };

  Scene_Base.prototype.createExtraGauges = function () {
    this._extraGauges = this.findExtraGaugeList().map((data) => {
      return new Sprite_ExtraGaugeContainer(
        data,
        data.Detail || {},
        data.Layout || {}
      );
    });
  };

  const _Scene_Base_createWindowLayer = Scene_Base.prototype.createWindowLayer;
  Scene_Base.prototype.createWindowLayer = function () {
    if (this instanceof Scene_Message) {
      this.addExtraGauge();
    }
    _Scene_Base_createWindowLayer.apply(this, arguments);
  };

  const _Scene_Base_start = Scene_Base.prototype.start;
  Scene_Base.prototype.start = function () {
    _Scene_Base_start.apply(this, arguments);
    this.addExtraGauge();
  };

  Scene_Base.prototype.addExtraGauge = function () {
    if (this._extraGaugesAdd) {
      return;
    }
    this._extraGauges.forEach((extraGauge) => {
      this.addChild(extraGauge);
    });
    this._extraGaugesAdd = true;
  };

  Scene_Base.prototype.findExtraGaugeList = function () {
    const currentSceneName = PluginManagerEx.findClassName(this);
    return (param.GaugeList || []).filter(function (data) {
      return data.SceneName === currentSceneName;
    }, this);
  };

  const _Sprite_Gauge_initialize = Sprite_Gauge.prototype.initialize;
  Sprite_Gauge.prototype.initialize = function (data, detail, layout) {
    if (data) {
      this._data = data;
      this._detail = detail;
      this._layout = layout;
    }
    _Sprite_Gauge_initialize.apply(this, arguments);
  };

  /**
   * Sprite_ExtraGaugeContainer
   * 追加ゲージとピクチャを含むコンテナです。
   */
  class Sprite_ExtraGaugeContainer extends Sprite {
    constructor(data, detail, layout) {
      super();
      this._data = data;
      this._detail = detail;
      this._layout = layout;
      this.create();
    }

    create() {
      this._gauge = new Sprite_ExtraGauge(
        this._data,
        this._detail,
        this._layout
      );
      this._lower = this.createPicture(this._data.LowerPicture);
      this.addChild(this._gauge);
      this._upper = this.createPicture(this._data.UpperPicture);
      this.setupPosition();
      this.update();
    }

    setupPosition() {
      this.x = this._gauge.findLayoutValue(this._layout.x);
      this.y = this._gauge.findLayoutValue(this._layout.y);
    }

    update() {
      super.update();
      this.updateVisibly();
      this.updateOpacity();
    }

    updateVisibly() {
      this.visible = this.isVisible();
    }

    updateOpacity() {
      if (this._detail.OpacityVariable) {
        this.opacity = $gameVariables.value(this._detail.OpacityVariable);
      }
    }

    isVisible() {
      return !this._data.SwitchId || $gameSwitches.value(this._data.SwitchId);
    }

    createPicture(pictureData) {
      if (!pictureData || !pictureData.FileName) {
        return null;
      }
      const sprite = new Sprite();
      sprite.anchor.x = 0.5;
      sprite.anchor.y = 0.5;
      sprite.bitmap = ImageManager.loadPicture(pictureData.FileName);
      sprite.x = pictureData.OffsetX || 0;
      sprite.y = pictureData.OffsetY || 0;
      this.addChild(sprite);
      return sprite;
    }
  }

  /**
   * Sprite_ExtraGauge
   * 追加ゲージを扱うクラスです。
   */
  class Sprite_ExtraGauge extends Sprite_Gauge {
    constructor(data, detail, layout) {
      super(data, detail, layout);
      this.setup(this.findBattler(), this._detail.GaugeColorPreset);
      this.setupPosition();
    }

    findBattler() {
      const battlerData = this._data.Battler;
      if (!battlerData) {
        return $gameParty.menuActor();
      }
      const methodName = `findBattler${battlerData.Type}`;
      if (this[methodName]) {
        return this[methodName](battlerData);
      } else {
        return $gameParty.menuActor();
      }
    }

    findBattlerActorId(battlerData) {
      return $gameActors.actor(battlerData.ActorId);
    }

    findBattlerPartyIndex(battlerData) {
      return $gameParty.members()[battlerData.Index];
    }

    findBattlerEnemyId(battlerData) {
      return new Game_Enemy(battlerData.EnemyId, 0, 0);
    }

    findBattlerTroopIndex(battlerData) {
      return $gameTroop.members()[battlerData.Index];
    }

    updateBitmap() {
      const visible = this.parent ? this.parent.visible : false;
      if (visible) {
        if (!this._prevVisible) {
          this._value = this._targetValue;
          this._maxValue = this._targetMaxValue;
        }
        super.updateBitmap();
      }
      this._prevVisible = visible;
    }

    updateFlashing() {
      if (!this._detail.FlashIfFull) {
        return;
      }
      if (this.isFull()) {
        this._flashingCount++;
        if (this._flashingCount % 20 < 10) {
          this.setBlendColor(this.flashingColor1());
        } else {
          this.setBlendColor(this.flashingColor2());
        }
      } else {
        this.setBlendColor([0, 0, 0, 0]);
      }
    }

    flashingColor1() {
      return [255, 255, 255, 96];
    }

    flashingColor2() {
      return [255, 255, 255, 64];
    }

    isFull() {
      return this._value >= this._maxValue;
    }

    setupPosition() {
      this.anchor.x = 0.5;
      this.anchor.y = 0.5;
      if (this._layout.Vertical) {
        this.rotation = (270 * Math.PI) / 180;
      }
    }

    bitmapWidth() {
      return this.findLayoutValue(this._layout.width) || super.bitmapWidth();
    }

    bitmapHeight() {
      return this.findLayoutValue(this._layout.height) || super.bitmapHeight();
    }

    gaugeHeight() {
      return (
        this.findLayoutValue(this._layout.GaugeHeight) || this.bitmapHeight()
      );
    }

    gaugeX() {
      return this.findLayoutValue(this._layout.GaugeX) || 0;
    }

    findLayoutValue(value) {
      if (isNaN(value)) {
        try {
          const width = $dataSystem.advanced.uiAreaWidth;
          const height = $dataSystem.advanced.uiAreaHeight;
          return eval(value);
        } catch (e) {
          console.error(e);
          return 0;
        }
      } else {
        return value;
      }
    }

    currentValue() {
      return this.findValue(this._data.CurrentMethod);
    }

    currentMaxValue() {
      return Math.max(this.findValue(this._data.MaxMethod), 1);
    }

    findValue(method) {
      if (!method) {
        return 0;
      } else if (method.VariableId) {
        return $gameVariables.value(method.VariableId);
      } else if (method.Script) {
        const battler = this._battler;
        const meta = battler.isActor()
          ? battler.actor().meta
          : battler.enemy().meta;
        try {
          return eval(method.Script);
        } catch (e) {
          console.error(e);
          return 0;
        }
      } else {
        return method.FixedValue;
      }
    }

    label() {
      return this._detail.Label || "";
    }

    labelColor() {
      return this.findColor(this.findLabelFont().Color, super.labelColor());
    }

    labelOutlineColor() {
      return this.findColor(
        this.findLabelFont().OutlineColor,
        super.labelOutlineColor()
      );
    }

    labelOutlineWidth() {
      return this.findLabelFont().OutlineWidth || super.labelOutlineWidth();
    }

    labelFontFace() {
      return this.findLabelFont().Face || super.labelFontFace();
    }

    labelFontSize() {
      return this.findLabelFont().Size || super.labelFontSize();
    }

    findLabelFont() {
      return this._detail.LabelFont || {};
    }

    valueColor() {
      return this.findColor(this.findValueFont().Color, super.valueColor());
    }

    valueOutlineColor() {
      return this.findColor(
        this.findValueFont().OutlineColor,
        super.valueOutlineColor()
      );
    }

    valueOutlineWidth() {
      return this.findValueFont().OutlineWidth || super.valueOutlineWidth();
    }

    valueFontFace() {
      return this.findValueFont().Face || super.valueFontFace();
    }

    valueFontSize() {
      return this.findValueFont().Size || super.valueFontSize();
    }

    findValueFont() {
      return this._detail.ValueFont || {};
    }

    gaugeBackColor() {
      return this.findColor(this._detail.BackColor, super.gaugeBackColor());
    }

    gaugeColor1() {
      return this.findColor(this._detail.GaugeColorLeft, super.gaugeColor1());
    }

    gaugeColor2() {
      return this.findColor(this._detail.GaugeColorRight, super.gaugeColor2());
    }

    isValid() {
      return true;
    }

    smoothness() {
      if (this._value <= this._targetValue) {
        return this._detail.RisingSmoothness || 1;
      } else {
        return this._detail.FallingSmoothness || 1;
      }
    }

    drawValue() {
      if (this._detail.DrawValue) {
        super.drawValue();
      }
    }

    findColor(code, defaultColor = null) {
      if (!code) {
        return defaultColor ? defaultColor : ColorManager.normalColor();
      } else if (isNaN(code)) {
        return code;
      } else {
        return ColorManager.textColor(code);
      }
    }
  }
})();


code:
//=============================================================================
// FixImageLoading.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015-2017 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 2.0.1 2019/04/06 MoviePicture.jsとの競合を修正
// 2.0.0 2017/06/09 本体ver1.5.0に合わせて再作成
// 1.1.1 2016/11/20 ロード完了時にframeが更新されない不具合を修正
//                  ロード中にframeが変更された場合に、ロード完了まで反映を遅らせる仕様を追加
// 1.1.0 2016/11/16 liply_GC.jsとの競合を解消 by 奏 ねこま様
// 1.0.0 2016/05/02 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:ja
 * @plugindesc 画像ロード時のチラつき防止プラグイン
 * @target MZ @url https://github.com/triacontane/RPGMakerMV/tree/mz_master @author トリアコンタン
 *
 * @help キャッシュしていない画像を表示したときに
 * 一瞬発生するチラつきを防止します。
 * 画像のロードが完了するまで以前に表示していた画像を残します。
 *
 * 逆に画像を消したいときは明示的にピクチャの消去等を行ってから
 * 表示してください。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";

  var _Sprite__renderCanvas = Sprite.prototype._renderCanvas;
  Sprite.prototype._renderCanvas = function (renderer) {
    _Sprite__renderCanvas.apply(this, arguments);
    if (this.isExistLoadingBitmap()) {
      this._renderCanvas_PIXI(renderer);
    }
  };

  var _Sprite__renderWebGL = Sprite.prototype._renderWebGL;
  Sprite.prototype._renderWebGL = function (renderer) {
    _Sprite__renderWebGL.apply(this, arguments);
    if (this.isExistLoadingBitmap()) {
      if (this._isPicture) {
        this._speedUpCustomBlendModes(renderer);
        renderer.setObjectRenderer(renderer.plugins.picture);
        if (!this.isVideoPicture || !this.isVideoPicture()) {
          renderer.plugins.picture.render(this);
        }
      } else {
        renderer.setObjectRenderer(renderer.plugins.sprite);
        renderer.plugins.sprite.render(this);
      }
    }
  };

  Sprite.prototype.isExistLoadingBitmap = function () {
    return this.bitmap && !this.bitmap.isReady();
  };
})();


code:
/*:ja
 * @plugindesc (v.1.0) アクター/職業/レベル/スクリプトで特徴を追加指定できます。
 *
 * @author Galv - galvs-scripts.com
 *
 * @param Display Trait On Level
 * @text レベルアップ表示
 * @type boolean
 * @on 表示
 * @off 非表示
 * @desc デフォルトのレベルアップメッセージに特徴取得を表示
 * 表示:true / 非表示:false
 * @default true
 *
 * @param Trait Gained Text
 * @text 獲得特徴テキスト
 * @desc レベルアップで特徴を獲得する前に表示されるテキスト
 * @default 獲得特徴:
 *
 *
 * @help
 * 翻訳:ムノクラ
 * https://fungamemake.com/
 * https://twitter.com/munokura/
 *
 * 元プラグイン:
 * https://galvs-scripts.com/2017/01/05/mv-dynamic-traits/
 *
 *   Galv's Dynamic Traits
 * ---------------------------------------------------------------------------
 * このプラグインを使用すると、
 * ゲーム中にアクターに新しい特徴を手動で追加したり、
 * アクターと職業を設定して、アクターがレベルアップした時、
 * 新しい特徴を付与したりできます。
 * アクターと職業には、特定のレベルに到達した時、
 * 取得する特徴を制御するメモタグがあり、
 * 必要に応じて、レベルアップメッセージに取得した特徴の通知を追加できます。
 *
 * 特徴レベルアップテキストをより詳細にカスタマイズすることは可能ですが、
 * プラグインファイルを編集して行う必要があり、
 * それがどのように機能するかを理解するにはJavaScriptの理解が必要です。
 * Galvにこれを教えるように頼まないでください。
 *
 * ---------------------------------------------------------------------------
 *   アクター、職業のメモタグ
 * ---------------------------------------------------------------------------
 * レベルで獲得した特徴
 * ----------------------
 * アクターと職業には、
 * 指定された各レベルアップで獲得される特徴のリストを指定するために、
 * 次のメモタグでタグ付けできます。
 * それぞれが|で区切られたlvl、code、id、val特徴を
 * いくつでも入れられます。
 *
 *       <traits:lvl,code,id,val|lvl,code,id,val|lvl,code,id,val>
 *
 * lvlは、コードで取得される特徴のレベルです。
 * idおよびvalの設定は、以下の表で確認できます。
 *
 * 特徴              CODE  ID                 VAL
 * ----------------  ----  -----------        -------------
 * 属性有効度        11    属性ID             %数
 * 弱体有効度        12    通常能力値ID*      %数
 * ステート有効度    13    ステートID         %数
 * ステート無効化    14    ステートID         なし
 *
 * 通常能力値        21    通常能力値ID*      %数
 * 追加能力値        22    追加能力値ID*      %数
 * 特殊能力値        23    特殊能力値ID*      %数
 *
 * 攻撃時属性        31    属性ID             なし
 * 攻撃時ステート    32    属性ID             %数
 * 攻撃速度補正      33    整数               なし
 * 攻撃追加回数      34    0                  整数
 *
 * スキルタイプ追加  41    スキルタイプID     なし
 * スキルタイプ封印  42    スキルタイプID     なし
 * スキル追加        43    スキルID           なし
 * スキル封印        44    スキルID           なし
 *
 * 武器タイプ装備    51    武器タイプID       なし
 * 防具タイプ装備    52    防具タイプID       なし
 * 装備固定          53    装備ID             なし
 * 装備封印          54    装備ID             なし
 * スロットタイプ    55    0:通常 / 1:二刀流  なし
 *
 * 行動回数追加      61    0                  %数
 * 特殊フラグ        62    フラグID*          なし
 * 消滅エフェクト    63    消滅ID*            なし
 * パーティ能力      64    パーティ能力ID*    なし
 * ---------------------------------------------------------------------------
 * 注意点
 *   通常、データベースで確認できる値のIDは1から始まります。
 *   上記の*がある場合、リストの最初のIDは1ではなく0です。
 *
 *   VALがなしの場合、メモタグ/スクリプトのvalに0を入力してください。
 *
 *   アクターに複数のレベルに同じ特徴コードを設定している場合、
 *   最高レベルの特徴を使用します。
 *   職業に複数のレベルに同じ特徴コードを設定している場合、
 *   最高レベルの特徴を使用します。
 *
 *   アクターと職業が同じ特徴コードを設定している場合、
 *   アクターは両方の特徴を実行しますが、
 *   それぞれの特徴の中で最高のもののみを使用します。
 * ---------------------------------------------------------------------------
 *
 * ---------------------------------------------------------------------------
 *  スクリプトコール
 * ---------------------------------------------------------------------------
 * アクターは、スクリプトコールと使って手動で特徴を追加できます。
 * スクリプトコールを使用して、
 * これらの追加された特徴をアクターから再び削除することもできます。
 * ただし、レベル/データベースからアクター/アイテム/ステート等から
 * 追加された特徴を削除することはできません。
 *
 * この手法を使用して特徴を追加すると、
 * 過去に同じコードの手法によって追加された特徴が置き換えられます。
 * したがって、これらの手動で追加された特徴のアクターには、
 * 各特徴の1つのみが残ります。
 *
 *    Galv.DTRAITS.addTrait(actorId,code,id,value);
 *
 *    Galv.DTRAITS.removeTrait(actorId,code);
 *
 * ---------------------------------------------------------------------------
 */


code:
//=============================================================================
// GeneralTrigger.js
// ----------------------------------------------------------------------------
// Copyright (c) 2015 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.1.0 2016/07/06 レベルアップ時、レベルダウン時のトリガーを追加
// 1.0.2 2016/06/22 最強装備を選択した場合にエラーが発生する問題を修正
// 1.0.1 2016/06/17 ロードが失敗するバグを修正
// 1.0.0 2016/06/14 初版
// ----------------------------------------------------------------------------
// [Blog]   : http://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc トリガープラグイン
 * @author トリアコンタン
 *
 * @param ニューゲーム
 * @desc ニューゲーム時にONになるスイッチ番号
 * @default 0
 *
 * @param コンティニュー
 * @desc コンティニュー時にONになるスイッチ番号
 * @default 0
 *
 * @param オプション画面
 * @desc オプション画面を出た時にONになるスイッチ番号。ただしタイトル画面の場合は無効です。
 * @default 0
 *
 * @param メニュー画面
 * @desc メニュー画面を出た時にONになるスイッチ番号
 * @default 0
 *
 * @param セーブ画面
 * @desc セーブ画面を出た時にONになるスイッチ番号
 * @default 0
 *
 * @param 戦闘画面
 * @desc 戦闘画面を出た時にONになるスイッチ番号
 * @default 0
 *
 * @param ショップ画面
 * @desc ショップ画面を出た時にONになるスイッチ番号
 * @default 0
 *
 * @param 別マップ移動
 * @desc 別マップ移動時にONになるスイッチ番号
 * @default 0
 *
 * @param アイテム増減
 * @desc アイテム増減時にONになるスイッチ番号
 * @default 0
 *
 * @param 武器増減
 * @desc 武器増減時にONになるスイッチ番号
 * @default 0
 *
 * @param 防具増減
 * @desc 防具増減時にONになるスイッチ番号
 * @default 0
 *
 * @param アイテムID
 * @desc アイテム、武器、防具入手時に格納されるアイテムIDを格納する変数番号
 * @default 0
 *
 * @param アイテム個数
 * @desc アイテム、武器、防具入手時に格納されるアイテム増減数を格納する変数番号
 * @default 0
 *
 * @param メンバー加入
 * @desc メンバー加入時にONになるスイッチ番号
 * @default 0
 *
 * @param メンバー離脱
 * @desc メンバー離脱時にONになるスイッチ番号
 * @default 0
 *
 * @param レベルアップ
 * @desc レベルアップ時にONになるスイッチ番号
 * @default 0
 *
 * @param レベルダウン
 * @desc レベルダウン時にONになるスイッチ番号
 * @default 0
 *
 * @param アクターID
 * @desc 加入・離脱、レベルアップ、レベルダウンしたアクターIDを格納する変数番号
 * @default 0
 *
 * @param マップ画面でのみ有効
 * @desc アイテムの増減やレベルアップについて、マップ画面でのみスイッチをONにします。(ON/OFF)
 * @default OFF
 *
 * @help ゲーム中、様々な局面でスイッチをONにします。
 * 主に並列処理、自動実行のコモンイベントと組み合わせて使用します。
 * 以下のタイミングでスイッチをONにできます。
 *
 * ・ニューゲーム
 * ・コンティニュー
 * ・メニュー画面を閉じたとき
 * ・オプション画面を閉じたとき
 * ・セーブ画面を閉じたとき
 * ・ショップ画面を閉じたとき
 * ・別マップに移動したとき
 * ・アイテムを入手したとき
 * ・メンバーが加入、離脱したとき
 * ・レベルが増減したとき
 *
 * また、トリガーの種類によっては、スイッチがONになると同時に変数に
 * 所定の値が代入されます。
 *
 * 例えば、アイテム入手のトリガーがONになったときに指定された変数に
 * アイテムIDが格納されます。
 * 専用の入手インフォメーション等が作成できます。
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

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

  var getParamOther = function (paramNames) {
    if (!Array.isArray(paramNames)) paramNames = [paramNames];
    for (var i = 0; i < paramNames.length; i++) {
      var name = PluginManager.parameters(pluginName)[paramNames[i]];
      if (name) return name;
    }
    return null;
  };

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

  //=============================================================================
  // パラメータの取得と整形
  //=============================================================================
  var paramNewGame = getParamNumber(["NewGame", "ニューゲーム"]);
  var paramContinue = getParamNumber(["Continue", "コンティニュー"]);
  var paramOptions = getParamNumber(["Options", "オプション画面"]);
  var paramSave = getParamNumber(["Save", "セーブ画面"]);
  var paramMenu = getParamNumber(["Menu", "メニュー画面"]);
  var paramBattle = getParamNumber(["Battle", "戦闘画面"]);
  var paramShop = getParamNumber(["Shop", "ショップ画面"]);
  var paramMoveMap = getParamNumber(["MoveMap", "別マップ移動"]);
  var paramGainItem = getParamNumber(["GainItem", "アイテム増減"]);
  var paramGainWeapon = getParamNumber(["GainWeapon", "武器増減"]);
  var paramGainArmor = getParamNumber(["GainArmor", "防具増減"]);
  var paramItemId = getParamNumber(["ItemId", "アイテムID"]);
  var paramItemAmount = getParamNumber(["ItemAmount", "アイテム個数"]);
  var paramAddMember = getParamNumber(["AddMember", "メンバー加入"]);
  var paramRemoveMember = getParamNumber(["RemoveMember", "メンバー離脱"]);
  var paramLevelUp = getParamNumber(["LevelUp", "レベルアップ"]);
  var paramLevelDown = getParamNumber(["LevelDown", "レベルダウン"]);
  var paramActorId = getParamNumber(["ActorId", "アクターID"]);
  var paramValidOnlyMap = getParamBoolean([
    "ValidOnlyMap",
    "マップ画面でのみ有効",
  ]);

  //=============================================================================
  // SceneManager
  //  トリガースイッチを設定処理を追加定義します。
  //=============================================================================
  var _SceneManager_pop = SceneManager.pop;
  SceneManager.pop = function () {
    if (this._stack.length > 0) {
      this._scene.setPopTrigger();
    }
    _SceneManager_pop.apply(this, arguments);
  };

  SceneManager.setTriggerSwitch = function (switchNumber) {
    if ($gameSwitches && switchNumber > 0) {
      $gameSwitches.setValue(switchNumber, true);
    }
  };

  SceneManager.setTriggerVariable = function (variableNumber, value) {
    if ($gameVariables && variableNumber > 0) {
      $gameVariables.setValue(variableNumber, value);
    }
  };

  SceneManager.isTriggerValid = function () {
    return !paramValidOnlyMap || this._scene instanceof Scene_Map;
  };

  //=============================================================================
  // DataManager
  //  ニューゲーム、コンティニューのトリガースイッチを設定します。
  //=============================================================================
  var _DataManager_setupNewGame = DataManager.setupNewGame;
  DataManager.setupNewGame = function () {
    _DataManager_setupNewGame.apply(this, arguments);
    SceneManager.setTriggerSwitch(paramNewGame);
  };

  var _DataManager_loadGame = DataManager.loadGame;
  DataManager.loadGame = function (saveFileId) {
    var result = _DataManager_loadGame.apply(this, arguments);
    SceneManager.setTriggerSwitch(paramContinue);
    return result;
  };

  //=============================================================================
  // Game_Player
  //  場所移動時にトリガースイッチを設定します。
  //=============================================================================
  var _Game_Player_reserveTransfer = Game_Player.prototype.reserveTransfer;
  Game_Player.prototype.reserveTransfer = function (mapId, x, y, d, fadeType) {
    _Game_Player_reserveTransfer.apply(this, arguments);
    SceneManager.setTriggerSwitch(paramMoveMap);
  };

  var _Game_Party_addActor = Game_Party.prototype.addActor;
  Game_Party.prototype.addActor = function (actorId) {
    var length = this._actors.length;
    _Game_Party_addActor.apply(this, arguments);
    if (length !== this._actors.length && SceneManager.isTriggerValid()) {
      SceneManager.setTriggerSwitch(paramAddMember);
      SceneManager.setTriggerVariable(paramActorId, actorId);
    }
  };

  var _Game_Party_removeActor = Game_Party.prototype.removeActor;
  Game_Party.prototype.removeActor = function (actorId) {
    var length = this._actors.length;
    _Game_Party_removeActor.apply(this, arguments);
    if (length !== this._actors.length && SceneManager.isTriggerValid()) {
      SceneManager.setTriggerSwitch(paramRemoveMember);
      SceneManager.setTriggerVariable(paramActorId, actorId);
    }
  };

  var _Game_Party_gainItem = Game_Party.prototype.gainItem;
  Game_Party.prototype.gainItem = function (item, amount, includeEquip) {
    _Game_Party_gainItem.apply(this, arguments);
    if (!item || !SceneManager.isTriggerValid()) return;
    switch (this.itemContainer(item)) {
      case this._items:
        SceneManager.setTriggerSwitch(paramGainItem);
        break;
      case this._weapons:
        SceneManager.setTriggerSwitch(paramGainWeapon);
        break;
      case this._armors:
        SceneManager.setTriggerSwitch(paramGainArmor);
        break;
    }
    SceneManager.setTriggerVariable(paramItemId, item.id);
    SceneManager.setTriggerVariable(paramItemAmount, amount);
  };

  var _Game_Actor_levelUp = Game_Actor.prototype.levelUp;
  Game_Actor.prototype.levelUp = function () {
    _Game_Actor_levelUp.apply(this, arguments);
    if (SceneManager.isTriggerValid()) {
      SceneManager.setTriggerSwitch(paramLevelUp);
      SceneManager.setTriggerVariable(paramActorId, this.actorId());
    }
  };

  var _Game_Actor_levelDown = Game_Actor.prototype.levelDown;
  Game_Actor.prototype.levelDown = function () {
    _Game_Actor_levelDown.apply(this, arguments);
    if (SceneManager.isTriggerValid()) {
      SceneManager.setTriggerSwitch(paramLevelDown);
      SceneManager.setTriggerVariable(paramActorId, this.actorId());
    }
  };

  //=============================================================================
  // Scene_Base
  //  各クラス用のトリガースイッチを設定します。
  //=============================================================================
  Scene_Base.prototype.setPopTrigger = function () {};

  Scene_Options.prototype.setPopTrigger = function () {
    SceneManager.setTriggerSwitch(paramOptions);
  };

  Scene_Menu.prototype.setPopTrigger = function () {
    SceneManager.setTriggerSwitch(paramMenu);
  };

  Scene_Save.prototype.setPopTrigger = function () {
    SceneManager.setTriggerSwitch(paramSave);
  };

  Scene_Shop.prototype.setPopTrigger = function () {
    SceneManager.setTriggerSwitch(paramShop);
  };

  Scene_Battle.prototype.setPopTrigger = function () {
    SceneManager.setTriggerSwitch(paramBattle);
  };
})();