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

/**
 * 2021/01/19 1.10.2 EventReSpawn.js でイベントを削除した場合にエラーになる不具合を修正
 * 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 () {
    const event = $gameMap.event(this._eventId);
    return event && this.isOnCurrentMap() && event.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:
/*---------------------------------------------------------------------------*
 * 2018/07/04 kido
 * https://kido0617.github.io/
 * Ver.1.1
 *---------------------------------------------------------------------------*/

/*:
 * @plugindesc デバッグウィンドウにショートカットキーを追加するプラグイン
 * @author kido
 * @help
 * 以下を参照
 * https://kido0617.github.io/rpgmaker/2018-07-04-debug-shortcut/
 *
 */

(function () {
  Input.keyMapper[83] = "S";
  Input.keyMapper[86] = "V";
  Input.keyMapper[8] = "BackSpace";
  for (var i = 0; i <= 9; i++) {
    Input.keyMapper[48 + i] = String(i);
  }
  Scene_Debug.prototype.update = function () {
    Scene_Base.prototype.update.call(this);
    if (Input.isTriggered("S")) {
      this.shortCutType = "S";
      this.strNum = "";
      this.jump();
    } else if (Input.isTriggered("V")) {
      this.shortCutType = "V";
      this.strNum = "";
      this.jump();
    } else if (Input.isTriggered("BackSpace")) {
      if (this.strNum && this.strNum.length > 0)
        this.strNum = this.strNum.substr(0, this.strNum.length - 1);
      this.jump();
    }
    for (var i = 0; i <= 9; i++) {
      if (Input.isTriggered(String(i))) {
        if (this.strNum == "" && i == 0) return;
        ("いきなり0は無し");
        this.strNum += String(i);
        this.jump();
      }
    }
  };

  Scene_Debug.prototype.jump = function () {
    if (!this.shortCutType) return;
    var rangeIndex =
      this.shortCutType == "S" ? 0 : this._rangeWindow._maxSwitches;
    if (this.strNum != "") {
      var num = parseInt(this.strNum);
      if (
        (this.shortCutType == "S" && num > $dataSystem.switches.length - 1) ||
        (this.shortCutType == "V" && num > $dataSystem.variables.length - 1)
      ) {
        SoundManager.playBuzzer();
        //最大超えたら最大値にしておく
        num =
          this.shortCutType == "S"
            ? $dataSystem.switches.length - 1
            : $dataSystem.variables.length - 1;
      }
      rangeIndex += Math.floor((num - 1) / 10);
      this._rangeWindow.select(rangeIndex);
      this._rangeWindow.deactivate();
      this._editWindow.activate();
      this._editWindow.select((num - 1) % 10);
    } else {
      this._rangeWindow.select(rangeIndex);
      this._rangeWindow.activate();
      this._editWindow.deactivate();
    }
    this.refreshHelpWindow();
  };

  var refreshHelpWindow = Scene_Debug.prototype.refreshHelpWindow;
  Scene_Debug.prototype.refreshHelpWindow = function () {
    refreshHelpWindow.call(this);
    var str = this.shortCutType + this.strNum;
    this._debugHelpWindow.drawTextEx(
      str,
      450,
      this._debugHelpWindow.lineHeight() * 4
    );
  };
})();

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// 円形クリックプラグイン
// DestinationCircleColorChange.js
// Copyright (c) 2018 村人Ａ
//=============================================================================

/*:ja
 * @plugindesc タップやクリックしたときに出る四角い白いアタリを丸にしての色を変更できます。
 * @author 村人A
 *
 * @help
 *
 *　色の指定は色の名前やカラーコードで指定できます。
 *　細かい色のコード表・色の名前はhttp://www.colordic.org/などカラーコード表が載っているページを参照してください。
 *
 * プラグインコマンド:
 *   ポインターを丸に　red    # ポインターを丸にして赤色にする
 *   ポインターを丸に　seagreen    # ポインターを丸にしてseagreen色にする
 *   ポインターを丸に　#ff0000    # ポインターを丸にして赤色にする
 */

(function () {
  // villaA_DestinationCircleChangeOn = false;
  // villaA_DestinationCircleColor = 'white';
  //
  // var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  // Game_Interpreter.prototype.pluginCommand = function(command, args) {
  // 	_Game_Interpreter_pluginCommand.call(this, command, args);
  // 	if (command === 'ポインターを丸に') {
  // 		villaA_DestinationCircleChangeOn = true;
  // 		villaA_DestinationCircleColor = args[0];
  // 	}
  // };
  var _Sprite_Destination_update = Sprite_Destination.prototype.update;
  Sprite_Destination.prototype.update = function () {
    _Sprite_Destination_update.call(this);
    // if(villaA_DestinationCircleChangeOn){
    this.bitmap.clear();
    this.bitmap.drawCircle(
      $gameMap.tileHeight() / 2,
      $gameMap.tileHeight() / 2,
      24,
      "seagreen"
    );
    // villaA_DestinationCircleChangeOn = false;
    // }
  };
})();


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

/*:
 * @plugindesc DirectivityShakePlugin
 * @author triacontane
 *
 * @help イベントコマンド「画面のシェイク」に指向性を持たせることができます。
 * 角度を指定して縦や斜めに振動させることが可能です。
 *
 * また、振動方法を通常の方法以外にsin波に設定できます。独特の抑揚がつきます。
 *
 * 「画面のシェイク」を行う直前に、必要に応じて以下のコマンドを実行してください。
 * なお、シェイクが終了すると設定は自動でリセットされます。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * DS_方向設定 90     # 角度[90度]で振動します。(角度:0...360)
 * DS_SET_ROTATION 90 # 同上
 * DS_SIN振動         # 振動をsin波に設定します。
 * DS_SIN_WAVE        # 同上
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc 指向性シェイクプラグイン
 * @author トリアコンタン
 *
 * @help イベントコマンド「画面のシェイク」に指向性を持たせることができます。
 * 角度を指定して縦や斜めに振動させることが可能です。
 *
 * また、振動方法を通常の方法以外にsin波に設定できます。独特の抑揚がつきます。
 *
 * 「画面のシェイク」を行う直前に、必要に応じて以下のコマンドを実行してください。
 * なお、シェイクが終了すると設定は自動でリセットされます。
 *
 * プラグインコマンド詳細
 *  イベントコマンド「プラグインコマンド」から実行。
 *  （パラメータの間は半角スペースで区切る）
 *
 * DS_方向設定 90     # 角度[90度]で振動します。(角度:0...360)
 * DS_SET_ROTATION 90 # 同上
 * DS_SIN振動         # 振動をsin波に設定します。
 * DS_SIN_WAVE        # 同上
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */

(function () {
  "use strict";
  var metaTagPrefix = "DS_";

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

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

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

  //=============================================================================
  // Game_Interpreter
  //  プラグインコマンドを追加定義します。
  //=============================================================================
  var _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.apply(this, arguments);
    var commandPrefix = new RegExp("^" + metaTagPrefix);
    if (!command.match(commandPrefix)) return;
    try {
      this.pluginCommandDirectivityShake(
        command.replace(commandPrefix, ""),
        args
      );
    } catch (e) {
      if ($gameTemp.isPlaytest() && Utils.isNwjs()) {
        var window = require("nw.gui").Window.get();
        if (!window.isDevToolsOpen()) {
          var devTool = window.showDevTools();
          devTool.moveTo(0, 0);
          devTool.resizeTo(
            window.screenX + window.outerWidth,
            window.screenY + window.outerHeight
          );
          window.focus();
        }
      }
      console.log("プラグインコマンドの実行中にエラーが発生しました。");
      console.log("- コマンド名 　: " + command);
      console.log("- コマンド引数 : " + args);
      console.log("- エラー原因   : " + e.stack || e.toString());
    }
  };

  Game_Interpreter.prototype.pluginCommandDirectivityShake = function (
    command,
    args
  ) {
    switch (getCommandName(command)) {
      case "方向設定":
      case "SET_ROTATION":
        $gameScreen.setShakeRotation(getArgNumber(args[0]));
        break;
      case "SIN振動":
      case "SIN_WAVE":
        $gameScreen.setShakeSinWave();
        break;
    }
  };

  //=============================================================================
  // Game_Screen
  //  シェイクの方向を保持します。
  //=============================================================================
  Game_Screen.prototype.getShakeRotation = function () {
    return this._shakeRotation;
  };

  Game_Screen.prototype.setShakeRotation = function (value) {
    this._shakeRotation = (value * Math.PI) / 180;
  };

  Game_Screen.prototype.setShakeSinWave = function () {
    this._shakeSinWave = true;
  };

  var _Game_Screen_clearShake = Game_Screen.prototype.clearShake;
  Game_Screen.prototype.clearShake = function () {
    _Game_Screen_clearShake.apply(this, arguments);
    this.clearDirectivityShake();
  };

  Game_Screen.prototype.clearDirectivityShake = function () {
    this._shakeRotation = 0;
    this._shakeSinWave = false;
  };

  var _Game_Screen_updateShake = Game_Screen.prototype.updateShake;
  Game_Screen.prototype.updateShake = function () {
    var wasShake = this.isNeedShakeUpdate();
    if (this._shakeSinWave && wasShake) {
      this.updateSinShake();
    } else {
      _Game_Screen_updateShake.apply(this, arguments);
    }
    if (wasShake && !this.isNeedShakeUpdate()) {
      this.clearDirectivityShake();
    }
  };

  Game_Screen.prototype.updateSinShake = function () {
    this._shake =
      Math.sin((3 * this._shakeDuration * this._shakeSpeed * Math.PI) / 180) *
      this._shakePower *
      3;
    this._shakeDuration--;
  };

  Game_Screen.prototype.isNeedShakeUpdate = function () {
    return this._shakeDuration > 0 || this._shake !== 0;
  };

  //=============================================================================
  // Spriteset_Base
  //  シェイクの方向を反映します。
  //=============================================================================
  var _Spriteset_Base_updatePosition = Spriteset_Base.prototype.updatePosition;
  Spriteset_Base.prototype.updatePosition = function () {
    _Spriteset_Base_updatePosition.apply(this, arguments);
    var shakeRotation = $gameScreen.getShakeRotation();
    if (shakeRotation) {
      var shakeDistance = Math.round($gameScreen.shake());
      this.x -= shakeDistance;
      this.x += Math.cos(shakeRotation) * shakeDistance;
      this.y += Math.sin(shakeRotation) * shakeDistance;
    }
  };
})();


code:
//============================================================================
// DisplayLevelUpWithIcon.js
//============================================================================
/*:
 * @plugindesc Display learned skill name at level up with icon
 * @author Sasuke KANNAZUKI
 *
 * @help
 * This plugin does not provide plugin commands.
 *
 * [Important Note]
 * This plugin overwrites the routine of level up display method.
 * So, this plugin cannot use with another level up displaying plugin.
 * ex. DisplayOnlyAddedSkillType.js the KADOKAWA plugin.
 *
 * [License]
 * this plugin is released under MIT license.
 * http://opensource.org/licenses/mit-license.php
 */

/*:ja
 * @plugindesc レベルアップ時に覚えるスキル名の前にアイコンを追加します
 * @author 神無月サスケ
 *
 * @help
 * このプラグインには、プラグインコマンドはありません。
 *
 * ■注意
 * このプラグインは、レベルアップ時の表示メソッドを上書きするため、
 * この箇所を書き換える他のプラグインと共存できません。
 * 例えば「エミールの小さな冒険」に同梱されたKADOKAWAプラグイン
 * 「DisplayOnlyAddedSkillType.js」とは共存できません。
 *
 * ■ライセンス表記
 * このプラグインは MIT ライセンスで配布されます。
 * ご自由にお使いください。
 * http://opensource.org/licenses/mit-license.php
 */

(function () {
  // NOTE:overwritten!
  Game_Actor.prototype.displayLevelUp = function (newSkills) {
    var text = TextManager.levelUp.format(
      this._name,
      TextManager.level,
      this._level
    );
    $gameMessage.newPage();
    $gameMessage.add(text);
    newSkills.forEach(function (skill) {
      $gameMessage.add(
        TextManager.obtainSkill.format(
          "\\}\\I[" + skill.iconIndex + "]\\{" + skill.name
        )
      );
      $gameMessage.newPage();
    });
  };
})();


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

/*:
 * @plugindesc 【MMP ver.1.1】戦闘メッセージが空の場合、表示しないようにします。
 * @author 木星ペンギン
 *
 * @help ●対応しているメッセージ一覧
 * 出現
 * 先制攻撃
 * 不意打ち
 * 逃走開始
 * 逃走失敗
 * 勝利
 * 敗北
 * 経験値獲得
 * お金獲得
 * アイテム獲得
 * レベルアップ
 * スキル習得
 *
 * ================================
 * 制作 : 木星ペンギン
 * URL : http://woodpenguin.blog.fc2.com/
 */

(function () {
  //-------------------------------------------------------------------------
  // BattleManager

  BattleManager.displayStartMessages = function () {
    if (TextManager.emerge.length > 0) {
      $gameTroop.enemyNames().forEach(function (name) {
        $gameMessage.add(TextManager.emerge.format(name));
      });
    }
    if (this._preemptive && TextManager.preemptive.length > 0) {
      $gameMessage.add(TextManager.preemptive.format($gameParty.name()));
    } else if (this._surprise && TextManager.surprise.length > 0) {
      $gameMessage.add(TextManager.surprise.format($gameParty.name()));
    }
  };

  BattleManager.displayVictoryMessage = function () {
    if (TextManager.victory.length > 0) {
      $gameMessage.add(TextManager.victory.format($gameParty.name()));
    }
  };

  BattleManager.displayDefeatMessage = function () {
    if (TextManager.defeat.length > 0) {
      $gameMessage.add(TextManager.defeat.format($gameParty.name()));
    }
  };

  BattleManager.displayEscapeSuccessMessage = function () {
    if (TextManager.escapeStart.length > 0) {
      $gameMessage.add(TextManager.escapeStart.format($gameParty.name()));
    }
  };

  BattleManager.displayEscapeFailureMessage = function () {
    if (TextManager.escapeStart.length > 0) {
      $gameMessage.add(TextManager.escapeStart.format($gameParty.name()));
    }
    if (TextManager.escapeFailure.length > 0) {
      $gameMessage.add("\\." + TextManager.escapeFailure);
    }
  };

  var _BattleManager_displayExp = BattleManager.displayExp;
  BattleManager.displayExp = function () {
    if (TextManager.escapeStart.length > 0) {
      _BattleManager_displayExp.call(this);
    }
  };

  var _BattleManager_displayGold = BattleManager.displayGold;
  BattleManager.displayGold = function () {
    if (TextManager.obtainGold.length > 0) {
      _BattleManager_displayGold.call(this);
    }
  };

  var _BattleManager_displayDropItems = BattleManager.displayDropItems;
  BattleManager.displayDropItems = function () {
    if (TextManager.obtainItem.length > 0) {
      _BattleManager_displayDropItems.call(this);
    }
  };

  //-------------------------------------------------------------------------
  // BattleManager

  Game_Actor.prototype.displayLevelUp = function (newSkills) {
    if (TextManager.levelUp.length > 0) {
      var text = TextManager.levelUp.format(
        this._name,
        TextManager.level,
        this._level
      );
      $gameMessage.newPage();
      $gameMessage.add(text);
    }
    if (TextManager.obtainSkill.length > 0) {
      newSkills.forEach(function (skill) {
        $gameMessage.add(TextManager.obtainSkill.format(skill.name));
      });
    }
  };
})();


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


code:
//=============================================================================
// ExcludeMaterialGuard.js
// ----------------------------------------------------------------------------
// (C) 2017 Triacontane
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php
// ----------------------------------------------------------------------------
// Version
// 1.0.1 2020/08/18 ヘルプの注釈と英語版のヘルプと追加
// 1.0.0 2017/08/24 初版
// ----------------------------------------------------------------------------
// [Blog]   : https://triacontane.blogspot.jp/
// [Twitter]: https://twitter.com/triacontane/
// [GitHub] : https://github.com/triacontane/
//=============================================================================

/*:
 * @plugindesc MaterialSelectorPlugin
 * @author triacontane
 *
 * @param ImageFiles
 * @desc This is a list of image materials to exclude from the delete unused files feature.
 * @default
 * @require 1
 * @dir img/
 * @type file[]
 *
 * @param AudioFiles
 * @desc This is a list of audio material to exclude from the delete unused files feature.
 * @default
 * @require 1
 * @dir audio/
 * @type file[]
 *
 * @help By selecting a material, you can delete unused material.
 * You can exclude them from the list.
 *
 * By supporting the type designation function implemented in the main body
 * version 1.5.0 of Maker MV, you can remove the target.
 * You can select multiple files from the file dialog.
 *
 * It is not possible to keep all the files in a folder,
 * but you must select all the files one by one.
 *
 * This plugin is released under the MIT License.
 */
/*:ja
 * @plugindesc 未使用素材削除ガードプラグイン
 * @author トリアコンタン
 *
 * @param 画像素材
 * @desc 未使用ファイル削除機能の対象外にする画像素材のリストです。
 * @default
 * @require 1
 * @dir img/
 * @type file[]
 *
 * @param 音声素材
 * @desc 未使用ファイル削除機能の対象外にする音声素材のリストです。
 * @default
 * @require 1
 * @dir audio/
 * @type file[]
 *
 * @help 素材を選択しておくことで未使用素材削除機能の
 * 対象から外すことができます。
 *
 * ツクールMVの本体バージョン1.5.0で実装された型指定機能に対応することで
 * ファイルダイアログから複数のファイルを選択することができます。
 *
 * 指定したフォルダ以下の全てのファイルを残す、といったことはできません。
 * その場合は全ファイルをひとつずつ選択する必要があります。
 *
 * ※ RPGツクールMV本体のヘルプに未使用素材削除機能の詳細が記載されています。
 * RPGツクールMV > 資料集 > 未使用ファイル削除ツール プラグインへの対応
 *
 * このプラグインにはプラグインコマンドはありません。
 *
 * 利用規約：
 *  作者に無断で改変、再配布が可能で、利用形態（商用、18禁利用等）
 *  についても制限はありません。
 *  このプラグインはもうあなたのものです。
 */


code:
//=============================================================================
// 戦闘時のウィンドウ配置を変更するプラグイン
// FTKR_BattleWindowLayout.js
// プラグインNo : 76
// 作成者     : フトコロ
// 作成日     : 2018/04/08
// 最終更新日 : 2020/04/26
// バージョン : v1.3.0
//=============================================================================

var Imported = Imported || {};
Imported.FTKR_BWL = true;

var FTKR = FTKR || {};
FTKR.BWL = FTKR.BWL || {};

//=============================================================================
/*:
 * @plugindesc v1.3.0 戦闘時のウィンドウ配置を変更する
 * @author フトコロ
 *
 * @param Show Actor Face
 * @desc アクターの顔画像を表示する
 * @type boolean
 * @on 有効
 * @off 無効
 * @default true
 *
 * @param Party
 * @text パーティーコマンドの設定
 *
 * @param Party Command PositionY
 * @desc パーティーコマンドウィンドウを表示する縦の位置を指定します。
 * @type select
 * @option ステータスウィンドウの上に横に表示
 * @value 0
 * @option 画面中央
 * @value 1
 * @default 0
 * @parent Party
 *
 * @param Party Command PositionX
 * @desc パーティーコマンドウィンドウを表示する横の位置を指定します。
 * @type select
 * @option 左寄せ
 * @value 0
 * @option 中央
 * @value 1
 * @option 右寄せ
 * @value 2
 * @default 0
 * @parent Party
 *
 * @param Party Command Window
 * @desc パーティーコマンドウィンドウの表示設定
 * @type struct<window>
 * @default {"width":"","height":"","background":"0"}
 * @parent Party
 *
 * @param Actor
 * @text アクターコマンドの設定
 *
 * @param Actor Command Position
 * @desc アクターコマンドウィンドウを表示する場所を指定します。
 * @type select
 * @option ステータスウィンドウのアクターに重ねる
 * @value 0
 * @option ステータスウィンドウの上に横に表示
 * @value 1
 * @option ステータスウィンドウのアクターの上に縦に表示
 * @value 2
 * @default 0
 * @parent Actor
 *
 * @param Actor Command PositionY
 * @desc アクターコマンドウィンドウを表示する縦の位置を指定します。
 * ステータスウィンドウの上表示の場合は無効です。
 * @type select
 * @option 上寄せ
 * @value 0
 * @option 中央
 * @value 1
 * @option 下寄せ
 * @value 2
 * @default 0
 * @parent Actor
 *
 * @param Actor Command PositionX
 * @desc アクターコマンドウィンドウを表示する横の位置を指定します。
 * @type select
 * @option 右寄せ
 * @value 0
 * @option 中央
 * @value 1
 * @option 左寄せ
 * @value 2
 * @default 0
 * @parent Actor
 *
 * @param Actor Command Window
 * @desc アクターコマンドウィンドウの表示設定
 * Actor Command Position の設定により一部の設定が無効になる
 * @type struct<window>
 * @default {"width":"","height":"","background":"0"}
 * @parent Actor
 *
 * @param Status
 * @text ステータスウィンドウの設定
 *
 * @param Hide When Selecting Actor
 * @parent Status
 * @desc アクター選択時にステータスウィンドウを非表示にする
 * @type boolean
 * @on 有効
 * @off 無効
 * @default true
 *
 * @param Hide When Selecting Enemy
 * @parent Status
 * @desc エネミー選択時にステータスウィンドウを非表示にする
 * @type boolean
 * @on 有効
 * @off 無効
 * @default true
 *
 *
 * @help
 *-----------------------------------------------------------------------------
 * 概要
 *-----------------------------------------------------------------------------
 * 戦闘時のウィンドウ配置やサイズを変更します。
 *
 * １．ステータスウィンドウの幅を画面サイズと同じにします。
 * ２．ステータスウィンドウのアクターを横並びに変更します。(*1)
 * ３．アクターコマンドウィンドウの表示位置を、ステータスウィンドウの
 * 　　選択中のアクターに重ねます。(*2)
 * ４．パーティーコマンドウィンドウをステータスウィンドウの上に表示し
 * 　　コマンドを横並びにします。
 *
 *
 * (*1) ステータスウィンドウの表示内容は、顔画像、名前、ステート、HP、MP、TPです。
 *      顔画像は、プラグインパラメータで表示のON/OFFを変えられます。
 *      TPは、「バトル画面でTPを表示」にチェックが入っている場合に表示します。
 *
 * (*2) プラグインパラメータで、パーティーコマンドウィンドウと同じ表示位置に
 *      変更できます。
 *
 *
 *-----------------------------------------------------------------------------
 * 設定方法
 *-----------------------------------------------------------------------------
 * 1.「プラグインマネージャー(プラグイン管理)」に、本プラグインを追加して
 *    ください。
 *
 * 2. FTKR_AlternatingTurnBattle.jsと組み合わせる場合は、このプラグインが
 *    下になるように配置してください。
 *
 *
 *-----------------------------------------------------------------------------
 * 本プラグインのライセンスについて(License)
 *-----------------------------------------------------------------------------
 * 本プラグインはMITライセンスのもとで公開しています。
 * This plugin is released under the MIT License.
 *
 * Copyright (c) 2018 Futokoro
 * http://opensource.org/licenses/mit-license.php
 *
 *
 * プラグイン公開元
 * https://github.com/futokoro/RPGMaker/blob/master/README.md
 *
 *
 *-----------------------------------------------------------------------------
 * 変更来歴
 *-----------------------------------------------------------------------------
 *
 * v1.3.0 - 2020/04/26 : 機能追加
 *    1. アクター選択時とエネミー選択時にステータスウィンドウを非表示にする機能を
 *       プラグインパラメータでON/OFFできるように変更。
 *
 * v1.2.0 - 2018/08/19 : 機能追加
 *    1. パーティーコマンドとアクターコマンドの設定機能を追加。
 *
 * v1.1.1 - 2018/08/17 : 不具合修正
 *    1. FTKR_FVActorAnimationと処理が重複していた部分を修正。
 *
 * v1.1.0 - 2018/04/09 : 機能追加、不具合修正
 *    1. ステータスウィンドウでアクター同士の表示が重なる場合がある不具合を修正。
 *    2. アクターコマンドウィンドウの表示位置を変更する機能を追加。
 *    3. FTKR_AlternatingTurnBattle.jsの v1.1.0 に対応。
 *
 * v1.0.0 - 2018/04/08 : 初版作成
 *
 *-----------------------------------------------------------------------------
 */
//=============================================================================
/*~struct~window:
 * @param width
 * @desc ウィンドウの幅をpixel単位で設定します。
 * 空欄：デフォルト設定、-1：画面幅
 * @type number
 * @min -1
 * @default
 *
 * @param height
 * @desc ウィンドウの高さを行数(lineNumber)で設定します。
 * 空欄：デフォルト設定
 * @type number
 * @default
 *
 * @param background
 * @desc ウィンドウの背景を設定します。
 * @type select
 * @option ウィンドウ
 * @value 0
 * @option 暗くする
 * @value 1
 * @option 透明
 * @value 2
 * @default 0
 *
 */

(function () {
  var paramParse = function (obj) {
    return JSON.parse(JSON.stringify(obj, paramReplace));
  };

  var paramReplace = function (key, value) {
    try {
      return JSON.parse(value || null);
    } catch (e) {
      return value;
    }
  };

  //=============================================================================
  // プラグイン パラメータ
  //=============================================================================
  var parameters = PluginManager.parameters("FTKR_BattleWindowLayout");

  FTKR.BWL = {
    showFace: paramParse(parameters["Show Actor Face"]) || false,
    partyCmdPosY: +(paramParse(parameters["Party Command PositionY"]) || 0),
    partyCmdPosX: +(paramParse(parameters["Party Command PositionX"]) || 0),
    partyCmdWindow: paramParse(parameters["Party Command Window"]),
    actorCmdPos: +(paramParse(parameters["Actor Command Position"]) || 0),
    actorCmdPosY: +(paramParse(parameters["Actor Command PositionY"]) || 0),
    actorCmdPosX: +(paramParse(parameters["Actor Command PositionY"]) || 0),
    actorCmdWindow: paramParse(parameters["Actor Command Window"]),
  };

  var enabledStatusWhenSelectActor = paramParse(
    parameters["Hide When Selecting Actor"]
  );
  var enabledStatusWhenSelectEnemy = paramParse(
    parameters["Hide When Selecting Enemy"]
  );

  //=============================================================================
  // Scene_Battle
  //=============================================================================

  Scene_Battle.prototype.updateWindowPositions = function () {};

  var _BWL_Scene_Battle_startActorCommandSelection =
    Scene_Battle.prototype.startActorCommandSelection;
  Scene_Battle.prototype.startActorCommandSelection = function () {
    _BWL_Scene_Battle_startActorCommandSelection.call(this);
    this._actorCommandWindow.refreshPosition();
  };

  if (enabledStatusWhenSelectActor) {
    var _BWL_Scene_Battle_selectActorSelection =
      Scene_Battle.prototype.selectActorSelection;
    Scene_Battle.prototype.selectActorSelection = function () {
      _BWL_Scene_Battle_selectActorSelection.call(this);
      this._statusWindow.hide();
    };

    var _BWL_Scene_Battle_onActorOk = Scene_Battle.prototype.onActorOk;
    Scene_Battle.prototype.onActorOk = function () {
      _BWL_Scene_Battle_onActorOk.call(this);
      this._statusWindow.show();
    };

    var _BWL_Scene_Battle_onActorCancel = Scene_Battle.prototype.onActorCancel;
    Scene_Battle.prototype.onActorCancel = function () {
      _BWL_Scene_Battle_onActorCancel.call(this);
      this._statusWindow.show();
    };
  } //enabledStatusWhenSelectActor

  if (enabledStatusWhenSelectEnemy) {
    var _BWL_Scene_Battle_selectEnemySelection =
      Scene_Battle.prototype.selectEnemySelection;
    Scene_Battle.prototype.selectEnemySelection = function () {
      _BWL_Scene_Battle_selectEnemySelection.call(this);
      this._statusWindow.hide();
    };

    var _BWL_Scene_Battle_onEnemyOk = Scene_Battle.prototype.onEnemyOk;
    Scene_Battle.prototype.onEnemyOk = function () {
      _BWL_Scene_Battle_onEnemyOk.call(this);
      this._statusWindow.show();
    };

    var _BWL_Scene_Battle_onEnemyCancel = Scene_Battle.prototype.onEnemyCancel;
    Scene_Battle.prototype.onEnemyCancel = function () {
      _BWL_Scene_Battle_onEnemyCancel.call(this);
      this._statusWindow.show();
    };
  } //enabledStatusWhenSelectEnemy

  //=============================================================================
  // Window_BattleStatus
  //=============================================================================

  var _BWL_Window_BattleStatus_changeActorOnMouse =
    Window_BattleStatus.prototype.changeActorOnMouse;
  Window_BattleStatus.prototype.changeActorOnMouse = function (index) {
    _BWL_Window_BattleStatus_changeActorOnMouse.call(this, index);
    BattleManager._actorCommandWindow.refreshPosition();
  };

  Window_BattleStatus.prototype.maxCols = function () {
    return $gameParty.battleMembers().length;
  };

  Window_BattleStatus.prototype.windowWidth = function () {
    return Graphics.boxWidth;
  };

  Window_BattleStatus.prototype.spacing = function () {
    return this.padding * 2;
  };

  Window_BattleStatus.prototype.numVisibleRows = function () {
    return 4;
  };

  Window_BattleStatus.prototype.itemHeight = function () {
    return this.lineHeight() * this.numVisibleRows();
  };

  Window_BattleStatus.prototype.drawItem = function (index) {
    var lineHeight = this.lineHeight();
    var actor = $gameParty.battleMembers()[index];
    var rect = this.itemRect(index);
    var x = rect.x;
    var y = rect.y;
    var width = rect.width;
    if (FTKR.BWL.showFace) {
      var x2 = x + Math.max((width - 144) / 2, 0);
      this.drawActorFace(actor, x2, y, width);
    }
    this.drawActorName(actor, x, y, width);
    this.drawActorIcons(actor, x, y + lineHeight * 1, width);
    this.drawActorHp(actor, x, y + lineHeight * 2, width);
    if ($dataSystem.optDisplayTp) {
      var width2 = (width - 4) / 2;
      this.drawActorMp(actor, x, y + lineHeight * 3, width2);
      this.drawActorTp(actor, x + width2 + 4, y + lineHeight * 3, width2);
    } else {
      this.drawActorMp(actor, x, y + lineHeight * 3, width);
    }
  };

  //=============================================================================
  // Window_BattleEnemy
  //=============================================================================

  Window_BattleEnemy.prototype.windowWidth = function () {
    return Graphics.boxWidth;
  };

  //=============================================================================
  // Window_PartyCommand
  //=============================================================================

  Window_PartyCommand.prototype.initialize = function () {
    var x =
      (+FTKR.BWL.partyCmdPosX * (Graphics.boxWidth - this.windowWidth())) / 2;
    Window_Command.prototype.initialize.call(this, x, 0);
    switch (+FTKR.BWL.partyCmdPosY) {
      case 1:
        var y = (Graphics.boxHeight - this.windowHeight()) / 2;
        break;
      default:
        var y =
          Graphics.boxHeight -
          this.statusWindow().windowHeight() -
          this.windowHeight();
        break;
    }
    this.y = y;
    this.setBackgroundType(+FTKR.BWL.partyCmdWindow.background);
    this.openness = 0;
    this.deactivate();
  };

  Window_PartyCommand.prototype.statusWindow = function () {
    return SceneManager._scene._statusWindow;
  };

  Window_PartyCommand.prototype.windowWidth = function () {
    return this.windowBwlWidth();
  };

  Window_PartyCommand.prototype.windowBwlWidth = function () {
    var width = FTKR.BWL.partyCmdWindow.width;
    switch (width) {
      case -1:
        return Graphics.boxWidth;
      default:
        return !width ? Graphics.boxWidth : +width;
    }
  };

  Window_PartyCommand.prototype.numVisibleRows = function () {
    return +FTKR.BWL.partyCmdWindow.height || 1;
  };

  Window_PartyCommand.prototype.maxCols = function () {
    return Math.ceil(this.maxItems() / this.numVisibleRows());
  };

  Window_PartyCommand.prototype.itemTextAlign = function () {
    return "center";
  };

  //=============================================================================
  // Window_ActorCommand
  //=============================================================================

  Window_ActorCommand.prototype.initialize = function () {
    switch (FTKR.BWL.actorCmdPos) {
      case 1: //上横
      case 2: //上縦
        var y =
          Graphics.boxHeight -
          this.statusWindow().windowHeight() -
          this.windowHeight();
        break;
      default: //重ね
        var y =
          Graphics.boxHeight -
          this.statusWindow().windowHeight() +
          (FTKR.BWL.actorCmdPosY *
            (this.statusWindow().windowHeight() - this.windowHeight())) /
            2;
        break;
    }
    var x = this.offsetX();
    Window_Command.prototype.initialize.call(this, x, y);
    console.log(this.x, this.y, this.width, this.height);
    this.setBackgroundType(+FTKR.BWL.actorCmdWindow.background);
    this.openness = 0;
    this.deactivate();
    this._actor = null;
  };

  Window_ActorCommand.prototype.offsetX = function () {
    return (
      (+FTKR.BWL.actorCmdPosX *
        ((FTKR.BWL.actorCmdPos == 1 ? Graphics.boxWidth : this.actorWidth()) -
          this.windowWidth())) /
      2
    );
  };

  Window_ActorCommand.prototype.actorWidth = function () {
    return (
      SceneManager._scene._statusWindow.width /
      SceneManager._scene._statusWindow.maxCols()
    );
  };

  Window_ActorCommand.prototype.statusWindow = function () {
    return SceneManager._scene._statusWindow;
  };

  Window_ActorCommand.prototype.windowWidth = function () {
    return (
      this.windowBwlWidth() ||
      (FTKR.BWL.actorCmdPos == 1 ? Graphics.boxWidth : this.actorWidth())
    );
  };

  Window_ActorCommand.prototype.windowBwlWidth = function () {
    var width = +FTKR.BWL.actorCmdWindow.width;
    switch (width) {
      case -1:
        return Graphics.boxWidth;
      default:
        return width;
    }
  };

  Window_ActorCommand.prototype.refreshPosition = function () {
    if (FTKR.BWL.actorCmdPos != 1)
      this.x =
        this.actorWidth() * BattleManager.actor().index() + this.offsetX();
  };

  Window_ActorCommand.prototype.numVisibleRows = function () {
    return (
      +FTKR.BWL.actorCmdWindow.height || (FTKR.BWL.actorCmdPos == 1 ? 1 : 4)
    );
  };

  Window_ActorCommand.prototype.maxCols = function () {
    return FTKR.BWL.actorCmdPos == 1 ? 4 : 1;
  };

  Window_ActorCommand.prototype.itemTextAlign = function () {
    return FTKR.BWL.actorCmdPos == 1 ? "center" : "left";
  };

  var _BWL_Window_ActorCommand_changeInputWindow =
    Window_ActorCommand.prototype.changeInputWindow;
  Window_ActorCommand.prototype.changeInputWindow = function () {
    _BWL_Window_ActorCommand_changeInputWindow.call(this);
    this.refreshPosition();
  };
})(); //EOF


code:
//=============================================================================
// バトル画面のステータス表示を変更するプラグイン
// FTKR_CSS_BattleStatus.js
// プラグインNo : 16
// 作成者     : フトコロ
// 作成日     : 2017/04/11
// 最終更新日 : 2018/12/29
// バージョン : v2.2.0
//=============================================================================

var Imported = Imported || {};
Imported.FTKR_CSS_BS = true;

var FTKR = FTKR || {};
FTKR.CSS = FTKR.CSS || {};
FTKR.CSS.BS = FTKR.CSS.BS || {};

//=============================================================================
/*:
 * @plugindesc v2.2.0 バトル画面のステータス表示を変更するプラグイン
 * @author フトコロ
 *
 * @param Enabled Save WindowLayout
 * @desc ウィンドウ設定データをセーブできるようにする。
 * @default false
 * @type boolean
 * @on 有効
 * @off 無効
 *
 * @param --バトルパーティー設定--
 * @desc
 *
 * @param Max Battle Members
 * @desc バトルに参加する最大人数を設定します。
 * 0 - この機能を無効にします
 * @default 0
 *
 * @param --レイアウト設定--
 * @desc
 *
 * @param statusList
 * @desc 表示するステータスとその位置を設定します。
 * @type struct<status>[]
 * @default ["{\"text\":\"name\",\"x\":\"0\",\"y\":\"0\",\"width\":\"150\"}","{\"text\":\"state\",\"x\":\"156\",\"y\":\"0\",\"width\":\"150\"}","{\"text\":\"[hp/mp]\",\"value\":\"\",\"x\":\"312\",\"y\":\"0\",\"width\":\"width - 312\"}"]
 *
 * @param Actor Status Space In Text
 * @desc Text内で複数表示する場合の間隔を指定します。
 * @default 5
 *
 * @param --ウィンドウ設定--
 * @desc
 *
 * @param Enabled Custom Window
 * @desc ウィンドウのレイアウト変更機能を使うか。
 * 0 - 無効, 1 - 有効
 * @default 0
 *
 * @param Number Visible Rows
 * @desc ステータスウィンドウの縦の行数：デフォルト 4
 * @default 4
 *
 * @param Number Max Cols
 * @desc アクターを横に並べる数：デフォルト 1
 * @default 1
 *
 * @param Cursol Line Number
 * @desc カーソル高さの行数：デフォルト 1
 * @default 1
 *
 * @param Cursol Height Space
 * @desc 縦のカーソル間隔：デフォルト 0
 * @default 0
 *
 * @param Font Size
 * @desc フォントサイズ：デフォルト 28
 * @default 28
 *
 * @param Window Padding
 * @desc ウィンドウの周囲の余白：デフォルト 18
 * @default 18
 *
 * @param Window Line Height
 * @desc ウィンドウ内の1行の高さ：デフォルト 36
 * @default 36
 *
 * @param Window Opacity
 * @desc ウィンドウ内の背景の透明度：デフォルト 192
 * @default 192
 *
 * @param Hide Window Frame
 * @desc ウィンドウ枠を非表示にするか
 * 1 - 非表示にする、0 - 表示する
 * @default 0
 *
 * @param --アクターの位置設定--
 * @desc
 *
 * @param Enable Custom Position
 * @desc アクターの位置変更機能を使うか。
 * 0 - 無効, 1 - 有効
 * @default 0
 *
 * @param Max Number of Vertical
 * @desc アクターを縦に並べる最大数
 * @default 4
 *
 * @param Center Position X
 * @desc 前列の中心のX座標
 * @default 600
 *
 * @param Center Position Y
 * @desc 前列の中心のY座標
 * @default 312
 *
 * @param Diff Position X
 * @desc 横方向のアクターの間隔
 * @default 32
 *
 * @param Diff Position Y
 * @desc 縦方向のアクターの間隔
 * @default 48
 *
 * @param Diff Column
 * @desc 横方向の列の間隔
 * @default 96
 *
 * @help
 *-----------------------------------------------------------------------------
 * 概要
 *-----------------------------------------------------------------------------
 * 本プラグインを実装することで、バトル画面で表示するアクターの
 * ステータス表示のレイアウトを変更できます。
 *
 * このプラグインには、FTKR_CustomSimpleActorStatus.js (v3.0.0以降)が必要です。
 *
 * プラグインの使い方は、下のオンラインマニュアルページを見てください。
 * https://github.com/futokoro/RPGMaker/blob/master/FTKR_CSS_BattleStatus.ja.md
 *
 *
 *-----------------------------------------------------------------------------
 * 設定方法
 *-----------------------------------------------------------------------------
 * 1.「プラグインマネージャー(プラグイン管理)」に、本プラグインを追加して
 *    ください。
 *
 * 2. 以下のプラグインと組み合わせる場合は、プラグイン管理の順番に注意してください。
 *
 *    FTKR_CustomSimpleActorStatus.js (ステータス表示を変更)
 *    ↑このプラグインよりも上に登録↑
 *    FTKR_CSS_BattleStatus.js
 *
 *
 *-----------------------------------------------------------------------------
 * アクターのバトルステータス表示の設定
 *-----------------------------------------------------------------------------
 * プラグインパラメータの設定により、バトル画面で表示する
 * ステータスの表示レイアウトを変更することができます。
 *
 * 各パラメータの意味と、設定方法は、
 * FTKR_CustomSimpleActorStatus.jsのヘルプを参照してください。
 *
 * なお、歩行キャラ、SV戦闘キャラ、カスタムパラメータ、カスタムゲージの
 * 設定は、FTKR_CustomSimpleActorStatus.jsの設定に従います。
 *
 *
 *-----------------------------------------------------------------------------
 * バトルステータスウィンドウの設定
 *-----------------------------------------------------------------------------
 * 以下のプラグインパラメータで設定できます。
 *
 * <Enabled Custom Window>
 *    :バトル画面のウィンドウ変更機能を使うか指定します。
 *    :0 - 無効, 1 - 有効
 *
 * <Number Visible Rows>
 *    :ステータスウィンドウの縦の行数を変更します。
 *    :デフォルトは4行です。
 *    :この値を変えても、コマンドウィンドウのサイズは変わりません。
 *
 * <Number Max Cols>
 *    :ウィンドウ内でアクターを横に並べる数を変更します。
 *    :デフォルトは 1 です。
 *
 * <Cursol Line Number>
 *    :カーソルの高さを何行分にするか設定します。
 *    :デフォルトは 1 です。
 *
 * <Cursol Height Space>
 *    :縦のカーソル間隔を設定します。
 *    :デフォルトは 0 です。(単位はpixel)
 *
 * <Font Size>
 *    :ウィンドウ内のフォントサイズを変更します。
 *    :デフォルトは 28 です。(単位はpixel)
 *
 * <Window Padding>
 *    :ウィンドウの周囲の余白を変更します。
 *    :デフォルトは 18 です。(単位はpixel)
 *
 * <Window Line Height>
 *    :ウィンドウ内の1行の高さを変更します。
 *    :デフォルトは 36 です。(単位はpixel)
 *
 * <Window Opacity>
 *    :ウィンドウ内の背景の透明度を変更します。
 *    :デフォルトは 192 です。
 *    :0 - 透明、255 - 不透明
 *
 * <Hide Window Frame>
 *    :ウィンドウ枠を非表示にするか指定します。
 *    :1 - 非表示にする、0 - 表示する
 *    :デフォルトは表示します。
 *
 *
 * ＜ウィンドウの高さ＞
 * ウィンドウの高さは、以下の計算式で算出します。
 *    [ウィンドウ高さ] ＝ [縦の行数] × [1行の高さ] + [余白のサイズ] × 2
 *
 *
 * ＜フォントサイズと行の高さ＞
 * 基本的に、下の大小関係になるように設定しましょう。
 *    フォントサイズ ＜ 1行の高さ
 *
 *
 * ＜ウィンドウを消す方法＞
 * 以下の設定にすると、ウィンドウ枠とウィンドウの背景が消えて
 * アクターのステータスだけを表示します。
 *
 * <Window Opacity>     : 0
 * <Hide Window Frame>  : 1
 *
 *
 *-----------------------------------------------------------------------------
 * バトルフィールド上のアクターの位置設定
 *-----------------------------------------------------------------------------
 * 以下のプラグインパラメータで設定できます。
 *
 * <Enable Custom Position>
 *    :アクターの位置変更機能を使うか指定します。
 *    :0 - 無効, 1 - 有効
 *
 * <Max Number of Vertical>
 *    :アクターを縦に何人まで並べるか設定します。
 *    :バトルメンバーがこの数以上になった場合、後列に配置します。
 *
 * <Center Position *>
 *    :前列の中心の座標を設定します。
 *
 * <Diff Position *>
 *    :2番目以降のアクターの位置を先頭のアクターから
 *    :どの程度ずらすか設定します。
 *
 * <Diff Column>
 *    :横方向の列の間隔を設定します。
 *
 *
 *-----------------------------------------------------------------------------
 * 本プラグインのライセンスについて(License)
 *-----------------------------------------------------------------------------
 * 本プラグインはMITライセンスのもとで公開しています。
 * This plugin is released under the MIT License.
 *
 * Copyright (c) 2017,2018 Futokoro
 * http://opensource.org/licenses/mit-license.php
 *
 *
 * プラグイン公開元
 * https://github.com/futokoro/RPGMaker/blob/master/README.md
 *
 *-----------------------------------------------------------------------------
 * 変更来歴
 *-----------------------------------------------------------------------------
 *
 * v2.2.0 - 2018/12/29 : 機能追加
 *    1. ウィンドウ設定をセーブできる機能を追加。
 *
 * v2.1.3 - 2018/12/13 : プラグインパラメータstatusListの初期値変更
 *
 * v2.1.2 - 2018/09/29 : 機能追加
 *    1. プラグインパラメータのリストで選択できる項目を追加。
 *
 * v2.1.1 - 2018/09/12 : 不具合修正
 *    1. プラグインパラメータ Number Visible Rows が反映されない不具合を修正。
 *
 * v2.1.0 - 2018/08/30 : 機能追加
 *    1. プラグインパラメータで表示するステータスをリストで選択できる機能を追加。
 *
 * v2.0.0 - 2018/08/19 : FTKR_CustomSimpleActorStatus v3.0.0 対応版に変更
 *
 * v1.3.0 - 2017/11/18 : 仕様変更
 *    1. FTKR_CustomSimpleActorStatus.js の v2.6.0に対応。
 *
 * v1.2.1 - 2017/06/11 : 機能追加
 *    1. バトルに参加する最大人数を設定する機能を追加。
 *
 * v1.2.0 - 2017/05/31 : 機能追加
 *    1. バトルフィールド上のSVキャラの初期位置変更機能を拡張。
 *
 * v1.1.2 - 2017/05/11 : 機能追加
 *    1. バトルフィールド上のSVキャラの初期位置変更機能追加。
 *
 * v1.1.1 - 2017/05/06 : 機能追加
 *    1. 縦のカーソル間隔を設定する機能を追加。
 *
 * v1.1.0 - 2017/04/21 : 機能変更
 *    1. FTKR_CustomSimpleActorStatus.jsのv1.4.0に対応
 *    2. ウィンドウのレイアウト変更のON/OFF機能を追加。
 *
 * v1.0.1 - 2017/04/12 : 機能追加
 *    1. ウィンドウの余白と1行の高さ、透明度、枠の有無を変更する機能を追加。
 *    2. カーソル高さを変更する機能を追加。
 *
 * v1.0.0 - 2017/04/11 : 初版作成
 *
 *-----------------------------------------------------------------------------
 */
//=============================================================================
/*~struct~status:
 * @param text
 * @desc 表示するステータスを選択
 * リストにない場合は、直接テキストで記述
 * @default
 * @type select
 * @option 名前
 * @value name
 * @option 二つ名
 * @value nickname
 * @option 職業
 * @value class
 * @option レベル
 * @value level
 * @option HP
 * @value hp
 * @option MP
 * @value mp
 * @option TP
 * @value tp
 * @option 顔画像
 * @value face
 * @option 顔画像(サイズ指定)
 * @value face(%1)
 * @option 歩行キャラ画像
 * @value chara
 * @option SV戦闘キャラ画像
 * @value sv
 * @option ステート(横)
 * @value state
 * @option ステート(縦)
 * @value state2(%1)
 * @option プロフィール
 * @value profile
 * @option 通常能力値
 * @value param(%1)
 * @option 通常能力値(素)
 * @value pbase(%1)
 * @option 通常能力値(増加分)
 * @value pdiff(%1)
 * @option 装備
 * @value equip(%1)
 * @option 装備パラメータ
 * @value eparam(%1)
 * @option カスタムパラメータ
 * @value custom(%1)
 * @option カスタムゲージ
 * @value gauge(%1)
 * @option アクター別カスタムゲージ
 * @value agauge(%1)
 * @option クラス別カスタムゲージ
 * @value cgauge(%1)
 * @option カスタム画像
 * @value image
 * @option カスタム画像(登録ID)
 * @value image(%1)
 * @option メッセージ
 * @value message
 * @option テキスト
 * @value text(%1)
 * @option JS計算式(数値表示)
 * @value eval(%1)
 * @option JS計算式(文字列表示)
 * @value streval(%1)
 * @option 横線
 * @value line
 * @option AOP能力値
 * @value aop(%1)
 * @option AOP能力値(素)
 * @value aopbase(%1)
 * @option AOP能力値(増加分)
 * @value aopdiff(%1)
 * @option AOP装備パラメータ
 * @value eaop(%1)
 * @option アイテム名
 * @value iname
 * @option アイテムアイコン
 * @value iicon
 * @option アイテム説明
 * @value idesc
 * @option アイテムタイプ
 * @value itype
 * @option アイテム装備タイプ
 * @value ietype
 * @option アイテム範囲
 * @value iscope
 * @option アイテム属性
 * @value ielement
 * @option アイテム設定詳細
 * @value iparam(%1)
 * @option アイテムカスタム画像
 * @value iimage(%1)
 * @option マップ名
 * @value mapname
 *
 * @param value
 * @desc code(%1)の形式で設定するステータスの%1の内容を入力
 * @default
 *
 * @param x
 * @desc 表示するX座標
 * @default 0
 *
 * @param y
 * @desc 表示するY座標
 * @default 0
 *
 * @param width
 * @desc 表示する幅
 * @default 0
 *
 */

(function () {
  var paramParse = function (obj) {
    return JSON.parse(JSON.stringify(obj, paramReplace));
  };

  var paramReplace = function (key, value) {
    try {
      return JSON.parse(value || null);
    } catch (e) {
      return value;
    }
  };

  //=============================================================================
  // プラグイン パラメータ
  //=============================================================================
  var parameters = PluginManager.parameters("FTKR_CSS_BattleStatus");

  var saveCssWindow =
    paramParse(parameters["Enabled Save WindowLayout"]) || false;

  FTKR.CSS.BS.party = {
    maxMembers: Number(parameters["Max Battle Members"] || 0),
  };

  //ウィンドウ設定オブジェクト
  FTKR.CSS.BS.window = {
    enabled: Number(parameters["Enabled Custom Window"] || 0),
    numVisibleRows: Number(parameters["Number Visible Rows"] || 0),
    fontSize: Number(parameters["Font Size"] || 0),
    padding: Number(parameters["Window Padding"] || 0),
    lineHeight: Number(parameters["Window Line Height"] || 0),
    opacity: Number(parameters["Window Opacity"] || 0),
    hideFrame: Number(parameters["Hide Window Frame"] || 0),
    maxCols: Number(parameters["Number Max Cols"] || 0),
    cursorHeight: Number(parameters["Cursol Line Number"] || 0),
    hspace: Number(parameters["Cursol Height Space"] || 0),
  };

  //簡易ステータスオブジェクト
  FTKR.CSS.BS.simpleStatus = {
    statusList: paramParse(parameters["statusList"]),
    spaceIn: Number(parameters["Actor Status Space In Text"] || 0),
  };

  FTKR.CSS.BS.position = {
    enabled: Number(parameters["Enable Custom Position"] || 0),
    diffX: Number(parameters["Diff Position X"] || 0),
    diffY: Number(parameters["Diff Position Y"] || 0),
    diffCol: Number(parameters["Diff Column"] || 0),
    centerX: Number(parameters["Center Position X"] || 0),
    centerY: Number(parameters["Center Position Y"] || 0),
    maxVer: Number(parameters["Max Number of Vertical"] || 0),
  };

  //=============================================================================
  // Game_System
  //=============================================================================
  var _Game_System_initialize = Game_System.prototype.initialize;
  Game_System.prototype.initialize = function () {
    _Game_System_initialize.call(this);
    if (saveCssWindow) {
      this.resetCssBattleWindow();
    }
  };

  Game_System.prototype.resetCssBattleWindow = function () {
    this._cssBattleWindow = JsonEx.makeDeepCopy(FTKR.CSS.BS.window);
  };

  Game_System.prototype.cssBattleWindow = function () {
    return saveCssWindow ? this._cssBattleWindow : FTKR.CSS.BS.window;
  };

  //=============================================================================
  // Game_Party
  //=============================================================================
  if (FTKR.CSS.BS.party.maxMembers) {
    Game_Party.prototype.maxBattleMembers = function () {
      return FTKR.CSS.BS.party.maxMembers;
    };
  }

  //=============================================================================
  // Window_BattleStatus
  // バトル画面のステータスウィンドウの表示クラス
  //=============================================================================
  if (Imported.FTKR_CSS) {
    Window_BattleStatus.prototype.standardCssLayout = function () {
      return $gameSystem.cssBattleWindow();
    };

    Window_BattleStatus.prototype.standardCssStatus = function () {
      return FTKR.CSS.BS.simpleStatus;
    };

    Window_BattleStatus.prototype.itemHeight = function () {
      return this.cursorHeight()
        ? this.lineHeight() * this.cursorHeight()
        : Window_Selectable.prototype.itemHeight.call(this);
    };

    //ウィンドウの行数
    var _DS_Window_BattleStatus_numVisibleRows =
      Window_BattleStatus.prototype.numVisibleRows;
    Window_BattleStatus.prototype.numVisibleRows = function () {
      return $gameSystem.cssBattleWindow().enabled
        ? $gameSystem.cssBattleWindow().numVisibleRows
        : _DS_Window_BattleStatus_numVisibleRows.call(this);
    };

    //書き換え
    //アクター1人分のステータス表示
    Window_BattleStatus.prototype.drawItem = function (index) {
      var lss = this._lssStatus;
      var actor = $gameParty.battleMembers()[index];
      var rect = this.itemRectForText(index);
      this.drawCssActorStatus(
        index,
        actor,
        rect.x,
        rect.y,
        rect.width,
        rect.height,
        lss
      );
    };
  } //FTKR_CustomSimpleActorStatus.jsが必要

  //=============================================================================
  // Sprite_Actor
  // バトルフィールド上のSVキャラの位置変更
  //=============================================================================
  var _BS_Sprite_Actor_setActorHome = Sprite_Actor.prototype.setActorHome;
  Sprite_Actor.prototype.setActorHome = function (index) {
    _BS_Sprite_Actor_setActorHome.call(this, index);
    if (FTKR.CSS.BS.position.enabled) {
      this.setHome(this.partyPositionX(index), this.partyPositionY(index));
    }
  };

  Sprite_Actor.prototype.partyPositionX = function (index) {
    var party = Math.min(
      $gameParty.battleMembers().length,
      FTKR.CSS.BS.position.maxVer
    );
    var col = Math.floor(index / party);
    var centerX =
      FTKR.CSS.BS.position.centerX -
      this.centerDiffX(party) +
      col * FTKR.CSS.BS.position.diffCol;
    var positionX = centerX + (index % party) * FTKR.CSS.BS.position.diffX;
    return positionX;
  };

  Sprite_Actor.prototype.partyPositionY = function (index) {
    var party = Math.min(
      $gameParty.battleMembers().length,
      FTKR.CSS.BS.position.maxVer
    );
    var centerY = FTKR.CSS.BS.position.centerY - this.centerDiffY(party);
    var positionY = centerY + (index % party) * FTKR.CSS.BS.position.diffY;
    return positionY;
  };

  Sprite_Actor.prototype.centerDiffY = function (party) {
    var value1 = Math.floor((party + 1) / 2) * FTKR.CSS.BS.position.diffY;
    var value2 =
      ((Math.floor(party / 2 - 1) * 2 + 1) * FTKR.CSS.BS.position.diffY) / 2;
    return party % 2 ? value1 : value2;
  };

  Sprite_Actor.prototype.centerDiffX = function (party) {
    var value1 = Math.floor((party + 1) / 2) * FTKR.CSS.BS.position.diffX;
    var value2 =
      ((Math.floor(party / 2 - 1) * 2 + 1) * FTKR.CSS.BS.position.diffX) / 2;
    return party % 2 ? value1 : value2;
  };
})(); //EOF