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

/**
 * 2023/10/08 2.0.0 保持ログメッセージに関するプログラム上のインターフェース変更 (Breaking Change)
 *                  保持ログメッセージ件数設定を追加
 * 2023/10/06 1.3.0 ウィンドウ退避のインターフェースを公開
 * 2023/09/21 1.2.1 リファクタ
 * 2023/07/22 1.2.0 タッチUIが有効な場合にキャンセルボタンを表示
 *            1.1.2 名前の制御文字をログ記録時点で展開するように修正
 * 2023/01/30 1.1.1 決定キーでログウィンドウが閉じない不具合を修正
 * 2022/11/03 1.1.0 開閉キーのpageup/pagedownを非推奨化
 *                  開閉キーでログウィンドウを閉じられない不具合を修正
 *                  決定キーでもログウィンドウを閉じられるように変更
 * 2022/11/02 1.0.0 公開
 */

/*:
 * @plugindesc イベントテキストのログを保持・表示する
 * @author DarkPlasma
 * @license MIT
 *
 * @target MZ
 * @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release
 *
 * @param disableLoggingSwitch
 * @desc 設定したスイッチがONの間はログを残しません。0の場合、常にログを残します。
 * @text ログ記録無効スイッチ
 * @type switch
 * @default 0
 *
 * @param openLogKeys
 * @desc テキストログウィンドウを開閉するためのボタンを設定します。
 * @text ログ開閉ボタン
 * @type select[]
 * @option shift
 * @option control
 * @option tab
 * @option pageup (非推奨)
 * @value pageup
 * @option pagedown (非推奨)
 * @value pagedown
 * @default ["tab"]
 *
 * @param disableLogWindowSwitch
 * @desc 設定したスイッチがONの間はログウィンドウを開けません。0の場合、常に開けます。
 * @text ログウィンドウ無効スイッチ
 * @type switch
 * @default 0
 *
 * @param lineSpacing
 * @desc ログの行間を設定します。
 * @text ログの行間
 * @type number
 * @default 0
 *
 * @param messageSpacing
 * @desc ログのメッセージの間隔を設定します。メッセージはイベントコマンド単位でひとかたまりです。
 * @text メッセージ間隔
 * @type number
 * @default 0
 *
 * @param logSplitter
 * @desc イベントの切れ目などに挟むための区切り線を設定します。
 * @text ログ区切り線
 * @type string
 * @default -------------------------------------------------------
 *
 * @param autoSplit
 * @desc ONの場合、バトル、コモン、並列イベントを除くイベント終了時に区切り線を自動で入れます。
 * @text 自動区切り線
 * @type boolean
 * @default true
 *
 * @param choiceFormat
 * @desc ログに表示する選択肢のフォーマットを設定します。{choice}は選んだ選択肢に変換されます。
 * @text 選択肢フォーマット
 * @type string
 * @default 選択肢:{choice}
 *
 * @param choiceColor
 * @desc ログに表示する選択肢の色を設定します。
 * @text 選択肢色
 * @type number
 * @default 17
 *
 * @param choiceCancelText
 * @desc 選択肢をキャンセルした際に記録する内容を設定します。
 * @text キャンセルログ
 * @type string
 * @default キャンセル
 *
 * @param smoothBackFromLog
 * @desc ONの場合、ログシーンから戻った際にテキストを再度表示し直しません。
 * @text テキスト再表示なし
 * @type boolean
 * @default true
 *
 * @param backgroundImage
 * @desc ログシーンに表示する背景画像を設定します。
 * @text 背景画像
 * @type file
 * @dir img
 *
 * @param showLogWindowFrame
 * @desc ONの場合、ログウィンドウ枠を表示します。
 * @text ウィンドウ枠表示
 * @type boolean
 * @default true
 *
 * @param escapeCharacterCodes
 * @desc \XXX[YYY]の形式でYYYをログから消したい場合、ここにXXXを追加します。
 * @text パラメータを除外したい制御文字
 * @type string[]
 * @default []
 *
 * @param scrollSpeed
 * @desc 上下キーによるスクロールの速さを設定します。大きいほど速くなります。
 * @text スクロール速さ
 * @type number
 * @default 1
 * @min 1
 *
 * @param scrollSpeedHigh
 * @desc PageUp/PageDownキーによるスクロールの速さを設定します。
 * @text 高速スクロール速さ
 * @type number
 * @default 10
 * @min 1
 *
 * @param maxLogMessages
 * @desc ログメッセージを保持する件数を設定します。増やしすぎるとゲームの挙動に影響し得ることに注意してください。
 * @text ログメッセージ保持数
 * @type number
 * @default 200
 *
 * @command showTextLog
 * @text ログウィンドウを開く
 *
 * @command insertLogSplitter
 * @text ログに区切り線を追加する
 *
 * @command insertTextLog
 * @text ログに指定したテキストを追加する
 * @arg text
 * @text テキスト
 * @type string
 *
 * @help
 * version: 2.0.0
 * イベントで表示されたテキストをログとして保持、表示します。
 * ログはセーブデータには保持されません。
 *
 * マップ上、イベント中にログ開閉キーを押すことでログウィンドウを開きます。
 * ログ開閉キー、決定キー、キャンセルキーのいずれかでログウィンドウを閉じます。
 */

(() => {
	"use strict";

	const pluginName = document.currentScript.src.replace(/^.*\/(.*).js$/, function () {
		return arguments[1];
	});

	function parseArgs_insertTextLog(args) {
		return {
			text: String(args.text || ``)
		};
	}

	const command_showTextLog = "showTextLog";

	const command_insertLogSplitter = "insertLogSplitter";

	const command_insertTextLog = "insertTextLog";

	const pluginParametersOf = (pluginName) => PluginManager.parameters(pluginName);

	const pluginParameters = pluginParametersOf(pluginName);

	const settings = {
		disableLoggingSwitch: Number(pluginParameters.disableLoggingSwitch || 0),
		openLogKeys: JSON.parse(pluginParameters.openLogKeys || '["tab"]').map((e) => {
			return String(e || ``);
		}),
		disableLogWindowSwitch: Number(pluginParameters.disableLogWindowSwitch || 0),
		lineSpacing: Number(pluginParameters.lineSpacing || 0),
		messageSpacing: Number(pluginParameters.messageSpacing || 0),
		logSplitter: String(pluginParameters.logSplitter || `-------------------------------------------------------`),
		autoSplit: String(pluginParameters.autoSplit || true) === "true",
		choiceFormat: String(pluginParameters.choiceFormat || `選択肢:{choice}`),
		choiceColor: Number(pluginParameters.choiceColor || 17),
		choiceCancelText: String(pluginParameters.choiceCancelText || `キャンセル`),
		smoothBackFromLog: String(pluginParameters.smoothBackFromLog || true) === "true",
		backgroundImage: String(pluginParameters.backgroundImage || ``),
		showLogWindowFrame: String(pluginParameters.showLogWindowFrame || true) === "true",
		escapeCharacterCodes: JSON.parse(pluginParameters.escapeCharacterCodes || "[]").map((e) => {
			return String(e || ``);
		}),
		scrollSpeed: Number(pluginParameters.scrollSpeed || 1),
		scrollSpeedHigh: Number(pluginParameters.scrollSpeedHigh || 10),
		maxLogMessages: Number(pluginParameters.maxLogMessages || 200)
	};

	function Window_ObtainEscapeParamTextMixIn(windowClass) {
		/**
		 * [YYY]のYYYを取り出し、カンマ区切りで配列化して返す
		 */
		windowClass.obtainEscapeParamText = function (textState) {
			const arr = /^\[(.+?)\]/.exec(textState.text.slice(textState.index));
			if (arr) {
				textState.index += arr[0].length;
				return arr[1].split(",");
			} else {
				return [];
			}
		};
	}

	PluginManager.registerCommand(pluginName, command_showTextLog, function (args) {
		SceneManager.push(Scene_TextLog);
	});
	PluginManager.registerCommand(pluginName, command_insertTextLog, function (args) {
		const parsedArgs = parseArgs_insertTextLog(args);
		$gameTemp.eventTextLog().pushLog("", parsedArgs.text);
	});
	PluginManager.registerCommand(pluginName, command_insertLogSplitter, function (args) {
		$gameTemp.eventTextLog().pushSplitter();
	});
	class EvacuatedMessageAndSubWindows {
		constructor(messageWindow, goldWindow, nameBoxWindow, choiceListWindow, numberInputWindow) {
			this._messageWindow = messageWindow;
			this._goldWindow = goldWindow;
			this._nameBoxWindow = nameBoxWindow;
			this._choiceListWindow = choiceListWindow;
			this._numberInputWindow = numberInputWindow;
		}
		get messageWindow() {
			return this._messageWindow;
		}
		get goldWindow() {
			return this._goldWindow;
		}
		get nameBoxWindow() {
			return this._nameBoxWindow;
		}
		get choiceListWindow() {
			return this._choiceListWindow;
		}
		get numberInputWindow() {
			return this._numberInputWindow;
		}
	}
	function Game_Temp_TextLogMixIn(gameTemp) {
		const _initialize = gameTemp.initialize;
		gameTemp.initialize = function () {
			_initialize.call(this);
			this._evacuatedMessageAndSubWindows = null;
			this._eventTextLog = new Game_EventTextLog();
		};
		gameTemp.evacuatedMessageAndSubWindows = function () {
			return this._evacuatedMessageAndSubWindows;
		};
		gameTemp.setEvacuatedMessageAndSubWindows = function (windows) {
			this._evacuatedMessageAndSubWindows = windows;
		};
		gameTemp.clearEvacuatedMessageAndSubWindows = function () {
			this._evacuatedMessageAndSubWindows = null;
		};
		gameTemp.eventTextLog = function () {
			return this._eventTextLog;
		};
	}
	Game_Temp_TextLogMixIn(Game_Temp.prototype);
	class Game_EventTextLog {
		constructor() {
			this._messages = [];
		}
		get messages() {
			return this._messages;
		}
		pushLog(speakerName, text) {
			// ####################### 改造
			var reg = /^【([^【】]+)】/;
			var m2 = text.match(reg);
			//名前切り取り
			if (m2) {
				speakerName = m2[0];
				text = text.slice(m2[0].length);
			}
			// ####################### 改造

			this._messages.push(new Game_LogMessage(speakerName, text));
			if (settings.maxLogMessages < this._messages.length) {
				this._messages.splice(0, this._messages.length - settings.maxLogMessages);
			}
		}
		pushSplitter() {
			if (this._messages && this._messages[this._messages.length - 1]._message == settings.logSplitter) {
				return;
			}
			this.pushLog("", settings.logSplitter);
		}
	}
	class Game_LogMessage {
		constructor(speakerName, message) {
			this._speakerName = speakerName;
			this._message = message;
		}
		get speakerName() {
			if (this._speakerName) {
				return `【${this._speakerName}】`;
			} else {
				return this._speakerName;
			}
		}
		get message() {
			return this._message;
		}
		text() {
			return [this.speakerName, this.message].filter((text) => text).join("\n");
		}
	}
	function Game_Message_TextLogMixIn(gameMessage) {
		const _clear = gameMessage.clear;
		gameMessage.clear = function () {
			_clear.call(this);
			this._chosenIndex = null;
		};
		const _onChoice = gameMessage.onChoice;
		gameMessage.onChoice = function (n) {
			this._chosenIndex = n;
			_onChoice.call(this, n);
		};
		gameMessage.chosenIndex = function () {
			return this._chosenIndex || 0;
		};
		gameMessage.chosenText = function () {
			/**
			 * キャンセルした場合
			 */
			if (this.choiceCancelType() < 0 && this.chosenIndex() < 0) {
				return settings.choiceCancelText;
			}
			return this.choices()[this.chosenIndex()];
		};
	}
	Game_Message_TextLogMixIn(Game_Message.prototype);
	function Game_Interpreter_TextLogMixIn(gameInterpreter) {
		const _terminate = gameInterpreter.terminate;
		gameInterpreter.terminate = function () {
			if (this.mustSplitLogOnTeminate()) {
				if (settings.autoSplit) {
					$gameTemp.eventTextLog().pushSplitter();
				}
			}
			_terminate.call(this);
		};
		/**
		 * 終了時にイベントログを区切って過去ログ送りにする条件
		 * - 深さ0（イベントから呼び出されたコモンイベントでない）
		 * - 正のイベントIDを持つ（自動実行コモンイベント、並列実行コモンイベント、バトルイベントでない）
		 * - 並列実行イベントでない
		 * - 終了するイベントのテキストログが1件以上存在する
		 */
		gameInterpreter.mustSplitLogOnTeminate = function () {
			return this._depth === 0 && this._eventId > 0 && !this.isOnParallelEvent() && $gameTemp.eventTextLog().messages.length > 0;
		};
		/**
		 * マップ上の並列実行イベントで実行されているかどうか
		 */
		gameInterpreter.isOnParallelEvent = function () {
			return $gameMap.event(this._eventId)?.isTriggerIn([4]) && this.isOnCurrentMap();
		};
	}
	Game_Interpreter_TextLogMixIn(Game_Interpreter.prototype);
	class Scene_TextLog extends Scene_Base {
		create() {
			super.create();
			this.createBackground();
			this.createWindowLayer();
			this.createTextLogWindow();
			this.createButtons();
		}
		createBackground() {
			this._backgroundSprite = new Sprite();
			this._backgroundSprite.bitmap = this.backgroundImage();
			this.addChild(this._backgroundSprite);
		}
		backgroundImage() {
			if (settings.backgroundImage) {
				return ImageManager.loadBitmap("img/", settings.backgroundImage);
			}
			return SceneManager.backgroundBitmap();
		}
		createTextLogWindow() {
			this._textLogWindow = new Window_TextLog(this.textLogWindowRect());
			this._textLogWindow.setHandler("cancel", this.popScene.bind(this));
			if (!settings.showLogWindowFrame) {
				this._textLogWindow.setBackgroundType(2);
			}
			this.addWindow(this._textLogWindow);
		}
		textLogWindowRect() {
			const y = ConfigManager.touchUI ? this.buttonAreaBottom() : 0;
			return new Rectangle(0, y, Graphics.boxWidth, Graphics.boxHeight - y);
		}
		createButtons() {
			if (ConfigManager.touchUI) {
				this._cancelButton = new Sprite_Button("cancel");
				this._cancelButton.x = Graphics.boxWidth - this._cancelButton.width - 4;
				this._cancelButton.y = this.buttonY();
				this.addChild(this._cancelButton);
			}
		}
	}
	function Scene_Map_TextLogMixIn(sceneMap) {
		const _start = sceneMap.start;
		sceneMap.start = function () {
			_start.call(this);
			this.textLogCalling = false;
		};
		const _createAllWindows = sceneMap.createAllWindows;
		sceneMap.createAllWindows = function () {
			_createAllWindows.call(this);
			$gameTemp.clearEvacuatedMessageAndSubWindows();
		};
		const _createMessageWindow = sceneMap.createMessageWindow;
		sceneMap.createMessageWindow = function () {
			/**
			 * ログシーンからスムーズに戻るために、メッセージウィンドウ及びそのサブウィンドウを使い回す
			 * サブウィンドウ全てに似た処理を書くのは敗北感があるが、ひとまず許容する
			 */
			if (settings.smoothBackFromLog && $gameTemp.evacuatedMessageAndSubWindows()) {
				this._messageWindow = $gameTemp.evacuatedMessageAndSubWindows().messageWindow;
				this.addWindow(this._messageWindow);
			} else {
				_createMessageWindow.call(this);
			}
			if (settings.smoothBackFromLog) {
				/**
				 * destroyされると使い回せないため、処理を上書きしておく
				 */
				this._messageWindow.destroy = () => {};
			}
		};
		const _createGoldWindow = sceneMap.createGoldWindow;
		sceneMap.createGoldWindow = function () {
			if (settings.smoothBackFromLog && $gameTemp.evacuatedMessageAndSubWindows()) {
				this._goldWindow = $gameTemp.evacuatedMessageAndSubWindows().goldWindow;
				this.addWindow(this._goldWindow);
			} else {
				_createGoldWindow.call(this);
			}
			if (settings.smoothBackFromLog) {
				this._goldWindow.destroy = () => {};
			}
		};
		const _createNameBoxWindow = sceneMap.createNameBoxWindow;
		sceneMap.createNameBoxWindow = function () {
			if (settings.smoothBackFromLog && $gameTemp.evacuatedMessageAndSubWindows()) {
				this._nameBoxWindow = $gameTemp.evacuatedMessageAndSubWindows().nameBoxWindow;
				this.addWindow(this._nameBoxWindow);
			} else {
				_createNameBoxWindow.call(this);
			}
			if (settings.smoothBackFromLog) {
				this._nameBoxWindow.destroy = () => {};
			}
		};
		const _createChoiceListWindow = sceneMap.createChoiceListWindow;
		sceneMap.createChoiceListWindow = function () {
			if (settings.smoothBackFromLog && $gameTemp.evacuatedMessageAndSubWindows()) {
				this._choiceListWindow = $gameTemp.evacuatedMessageAndSubWindows().choiceListWindow;
				this.addWindow(this._choiceListWindow);
			} else {
				_createChoiceListWindow.call(this);
			}
			if (settings.smoothBackFromLog) {
				this._choiceListWindow.destroy = () => {};
			}
		};
		const _createNumberInputWindow = sceneMap.createNumberInputWindow;
		sceneMap.createNumberInputWindow = function () {
			if (settings.smoothBackFromLog && $gameTemp.evacuatedMessageAndSubWindows()) {
				this._numberInputWindow = $gameTemp.evacuatedMessageAndSubWindows().numberInputWindow;
				this.addWindow(this._numberInputWindow);
			} else {
				_createNumberInputWindow.call(this);
			}
			if (settings.smoothBackFromLog) {
				this._numberInputWindow.destroy = () => {};
			}
		};
		const _update = sceneMap.update;
		sceneMap.update = function () {
			_update.call(this);
			if (!SceneManager.isSceneChanging()) {
				this.updateCallTextLog();
			}
		};
		sceneMap.updateCallTextLog = function () {
			if (this.isTextLogEnabled()) {
				// if (this.isTextLogCalled() && $gameMessage.isBusy()) {
				if (this.isTextLogCalled()) {
					this.textLogCalling = true;
				}
				if (this.textLogCalling && !$gamePlayer.isMoving()) {
					this.callTextLog();
				}
			} else {
				this.textLogCalling = false;
			}
		};
		sceneMap.isTextLogEnabled = function () {
			return !settings.disableLogWindowSwitch || !$gameSwitches.value(settings.disableLogWindowSwitch);
		};
		sceneMap.isTextLogCalled = function () {
			if ($gameSwitches.value(144)) {
				return false;
			}
			return settings.openLogKeys.some((key) => Input.isTriggered(key));
		};
		sceneMap.callTextLog = function () {
			if (settings.smoothBackFromLog) {
				$gameTemp.setEvacuatedMessageAndSubWindows(
					new EvacuatedMessageAndSubWindows(
						this._messageWindow,
						this._goldWindow,
						this._nameBoxWindow,
						this._choiceListWindow,
						this._numberInputWindow
					)
				);
			}
			SoundManager.playCursor();
			SceneManager.push(Scene_TextLog);
			$gameTemp.clearDestination();
			this._mapNameWindow?.hide();
			this._waitCount = 2;
		};
	}
	Scene_Map_TextLogMixIn(Scene_Map.prototype);
	class LogMessageForView {
		constructor(message, height, heightFromBottom) {
			this._message = message;
			this._height = height;
			this._heightFromBottom = heightFromBottom;
		}
		get height() {
			return this._height;
		}
		get heightFromBottom() {
			return this._heightFromBottom;
		}
		text() {
			return this._message.text();
		}
	}
	/**
	 * Selectableは意味が違う。Scrollableのほうが正しい。
	 * ただし、handlerやキー操作の仕組みはSelectableのものを使いたい。
	 */
	class Window_TextLog extends Window_Selectable {
		initialize(rect) {
			super.initialize(rect);
			this.setupLogMessages();
			this._scrollY = this.maxScrollY();
			this.refresh();
			this.activate();
		}
		maxItems() {
			return this._messages.length;
		}
		itemHeight() {
			return this.lineHeight();
		}
		lineHeight() {
			return super.lineHeight() + settings.lineSpacing;
		}
		setupLogMessages() {
			let fromBottom = 0;
			this._messages = Array.from($gameTemp.eventTextLog().messages)
				.reverse()
				.map((message) => {
					const height = this.calcMessageHeight(message);
					fromBottom += height;
					return new LogMessageForView(message, height, fromBottom);
				})
				.reverse();
		}
		overallHeight() {
			return this._messages.length > 0 ? this._messages[0].heightFromBottom : this.innerHeight;
		}
		isCursorMovable() {
			return true;
		}
		cursorUp(wrap) {
			this.smoothScrollUp(settings.scrollSpeed);
		}
		cursorDown(wrap) {
			this.smoothScrollDown(settings.scrollSpeed);
		}
		cursorPageup() {
			this.smoothScrollUp(settings.scrollSpeedHigh);
		}
		cursorPagedown() {
			this.smoothScrollDown(settings.scrollSpeedHigh);
		}
		isCancelTriggered() {
			if (TouchInput.isTriggered()) {
				const x = TouchInput.x; // 画面上のX座標
				const y = TouchInput.y; // 画面上のY座標

				if (x >= 944 && x <= 970 && y >= 12 && y <= 39) {
					return true;
				}
			}

			return (
				super.isCancelTriggered() || this.isOkTriggered() || settings.openLogKeys.some((key) => Input.isTriggered(key))
				//super.isCancelTriggered() || this.isOkTriggered()
			);
		}
		paint() {
			if (this.contents) {
				this.contents.clear();
				this.drawTextLog();
			}
		}
		drawTextLog() {
			let height = 0;
			/**
			 * メッセージウィンドウのデフォルト4に合わせる
			 */
			const x = 280;
			this._messages.forEach((message) => {
				this.drawTextEx(message.text(), x, height + Math.floor(settings.lineSpacing / 2) - this.scrollBaseY());
				height += message.height;
			});
		}
		/**
		 * ログウィンドウに描画する上でのサイズ計算のため、X座標の初期位置指定をする必要がある。
		 * そのため、上書きする。
		 */
		textSizeEx(text) {
			this.resetFontSettings();
			const textState = this.createTextState(text, 4, 0, this.innerWidth);
			textState.drawing = false;
			this.processAllText(textState);
			return { width: textState.outputWidth, height: textState.outputHeight };
		}
		calcMessageHeight(message) {
			return this.textSizeEx(message.text()).height + settings.messageSpacing;
		}
		loadWindowskin() {
			this.windowskin = ImageManager.loadSystem("log_back");
		}
		_refreshBack() {
			const sprite = this._backSprite;
			// [Note] We use 95 instead of 96 here to avoid blurring edges.
			sprite.bitmap = this._windowskin;
		}
		updateBackOpacity() {
			this.backOpacity = 255;
		}
		_refreshFrame() {}
		select() {}
		update() {
			super.update();
			this.updateArrows();
		}
		processEscapeCharacter(code, textState) {
			super.processEscapeCharacter(code, textState);
			if (settings.escapeCharacterCodes.includes(code)) {
				this.obtainEscapeParamText(textState);
			}
		}
	}

	Object.defineProperty(Window_TextLog.prototype, "innerHeight", {
		get: function () {
			return Math.max(0, this._height - 64);
		},
		configurable: true
	});
	Window_TextLog.prototype._updateClientArea = function () {
		const pad = this._padding;
		this._clientArea.move(pad, pad);
		this._clientArea.x = pad - this.origin.x;
		this._clientArea.y = pad - this.origin.y + 44;
		if (this.innerWidth > 0 && this.innerHeight > 0) {
			this._clientArea.visible = this.isOpen();
		} else {
			this._clientArea.visible = false;
		}
	};
	// Window_TextLog.prototype._refreshBack = function () {
	// 	//const sprite = this._backSprite;
	// 	// [Note] We use 95 instead of 96 here to avoid blurring edges.
	// 	//sprite.bitmap = this._windowskin;
	// };

	Window_ObtainEscapeParamTextMixIn(Window_TextLog.prototype);
	function Window_Message_TextLogMixIn(windowClass) {
		const _terminateMessage = windowClass.terminateMessage;
		windowClass.startMessage = function () {
			const text = $gameMessage.allText();
			const textState = this.createTextState(text, 0, 0, 0);
			textState.x = this.newLineX(textState);
			textState.startX = textState.x + 300;
			this._textState = textState;
			this.newPage(this._textState);
			this.updatePlacement();
			this.updateBackground();
			this.open();
			this._nameBoxWindow.start();

			//NovelGameUIのセーブ画面とか開いたときログが再び登録されてしまう問題
			if (!SceneManager.CBR_load_log_flag) {
				$gameTemp
					.eventTextLog()
					.pushLog(this.convertEscapeCharacters($gameMessage.speakerName()), this.convertEscapeCharacters($gameMessage.allText()));
			} else {
				SceneManager.CBR_load_log_flag = false;
			}
		};
		/*
    windowClass.terminateMessage = function () {
      if (!settings.disableLoggingSwitch || !$gameSwitches.value(settings.disableLoggingSwitch)) {
        if ($gameMessage.allText()) {
          $gameTemp
            .eventTextLog()
            .pushLog(
              this.convertEscapeCharacters($gameMessage.speakerName()),
              this.convertEscapeCharacters($gameMessage.allText())
            );
        }*/
		/*if ($gameMessage.isChoice()) {
          $gameTemp
            .eventTextLog()
            .pushLog(
              '',
              settings.choiceFormat.replace(
                /{choice}/gi,
                `\x1bC[${settings.choiceColor}]${$gameMessage.chosenText()}\x1bC[0]`
              )
            );
        }*/
		/*}
      _terminateMessage.call(this);
    };*/
	}
	Window_Message_TextLogMixIn(Window_Message.prototype);
	globalThis.EvacuatedMessageAndSubWindows = EvacuatedMessageAndSubWindows;
	globalThis.Game_EventTextLog = Game_EventTextLog;
	globalThis.Game_LogMessage = Game_LogMessage;
	globalThis.Scene_TextLog = Scene_TextLog;
})();
