lust-oni/www/js/plugins/MPP_MessageEX.js
2025-10-26 23:43:42 -05:00

2313 lines
78 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//=============================================================================
// MPP_MessageEX.js
//=============================================================================
// Copyright (c) 2016 - 2024 Mokusei Penguin
// Released under the MIT license
// http://opensource.org/licenses/mit-license.php
//=============================================================================
/*:
* @target MV MZ
* @plugindesc Extend the text display function and add display effects.
* @author Mokusei Penguin
* @url
*
* @help [version 4.4.1]
* This plugin is for RPG Maker MV and MZ.
*
* ▼ [Display text] control characters
* \SP[n] # Text speed(characters per second / 0:Instant display)
* \AT[n] # Change animation type to n(※1)
* \SET[n] # Convert to the set string set(※2)
* \CO[S] # Display character string S as one character
* \RB[S,R] # Display character string S with ruby R(※3)
* \MX[n] # Shift the next letter X coordinate by n pixels
* \MY[n] # Shift the next letter Y coordinate by n pixels
* \PX[n] # Change the X coordinate of the next character to n
* \PY[n] # Change the Y coordinate of the next character to n
* \SW[n] # Turn on switch n
* \SN[n] # Replace with the name of skill ID n
* \SIN[n] # Replace with icon and name of skill ID n
* \IN[n] # Replace with the name of item ID n
* \IIN[n] # Replace with the icon and name of item ID n
* \WN[n] # Replace with the name of weapon ID n
* \WIN[n] # Replace with icon and name of weapon ID n
* \AN[n] # Replace with the name of armor ID n
* \AIN[n] # Replace with icon and name of armor ID n
* \WE # Wait until the event production is over(※4)
* \C[r,g,b] # Specify the font color in RGB
* \FS[n] # Change font size to n / Default:MV=28,MZ=26
* \FB # Invert font bold flag
* \FI # Invert font italic flag
* \OP[n] # Character opacity(0255) / Default:255
* \OC[n] # Change the color of the character edge to n / 0:Default
* \OC[r,g,b] # Specify the border color of characters in RGB
* \OC[r,g,b,a] # Specify the border color of characters with RGBA(※5)
* \OW[n] # Change the thickness of the character edge / Default:4
* \RC[n] # Changed ruby color to n / 0:Default
* \RC[r,g,b] # Specify ruby color in RGB
* \RC[r,g,b,a] # Specify ruby color with RGBA(※5)
* \DF # Return the text display setting to the default value(※6)
* \SV # Memorize the current text display settings(※6)
* \LD # Calling the settings memorized by \SV(※6)
*
* - The following applies if it is included in the text
* \A # Prohibition of skipping with enter key or shift key
* \ES # Temporarily enable skipping event production(※7)
* \FO[n] # Temporarily change the fade-out type(※8)
*
* - All control characters can be in either case
*
* ▼ Control character details
* ※1: \AT[n] (Change animation type to n)
* - The default animation type is as follows.
* 0: Default
* 1: Letters emerge while sliding to the right
* 2: Characters are displayed while spreading horizontally
* 3: Characters are displayed while expanding
* 4: Display characters from the left side(Text speed 6 recommended)
*
* ※2: \SET[n] (Convert to the set string set)
* - Converts to the character string specified by the plug-in parameter
* [Text Set].
* - Control characters can also be set.
*
* ※3: \RB[S,R] (Display character string S with ruby R)
* - Character strings with ruby characters are displayed together,
* not individually.
*
* ※4: \WE (Wait until the event production is over)
* - Wait until the production of the event set in the plug-in parameter
* [Wait Effects] is completed.
* - Even if you skip sentences, weight will be applied.
*
* ※5: \OC[r,g,b,a] (Specify the border color of characters with RGBA)
* - Specify the alpha value (a) from 0.0 to 1.0.
*
* ※6: \DF, \SV, \LD (Initialize / save / recall text display settings)
* - The following information is applicable.
* - Text speed
* - Anime type
* - Font color
* - Font size
* - Font bold flag
* - Font italic flag
* - Text opacity
* - Text outline color
* - Text outline width
* - Ruby color
*
*
* ※7: \ES (Temporarily enable skipping event production)
* - See the plugin command SetEffectSkip for details.
*
* ※8: \FO[n] (Temporarily change the fade-out type)
* - See the plugin command SetMesFadeOut for details.
*
* ▼ Plugin command details
* - In MV, the variable N is referred to by writing v [N] in the item for
* inputting a numerical value.
* - In MZ, in the item to enter a numerical value, select the text and
* write v [N] to refer to the variable N.
*
* MV / MZ
*
* SetMesRow row / messageRow
* row : Number of lines in the message window
* - Change the number of lines displayed in the message window.
*
* SetMesFadeOut type / messageFadeOut
* type : Fade out type
* - Change the fade-out type.
* - The types to specify are as follows.
* 0: Default
* 1: Gradually disappear (fast)
* 2: Gradually disappear (slow)
* 3: Scroll up
* 4: Add text below (Only when Op3 is introduced)
*
* SetEffectSkip bool / effectSkip
* bool : Enabled with true, disabled with false
* - When you skip a sentence, you can change whether to skip the production.
* - The default setting is invalid.
* - The effect to skip can be set in the plug-in parameter [Skip Effects].
* - The control character \ES is temporary, but it is always applied after
* the command is executed.
*
* ================================
* Mail : wood_penguinyahoo.co.jp ( is half-width)
* Blog : http://woodpenguin.blog.fc2.com/
* License : MIT license
*
* @command messageRow
* @desc
* @arg row
* @desc
* @type number
* @min 1
* @max 99
* @default 4
*
* @command messageFadeOut
* @desc
* @arg type
* @desc
* @type select
* @option 0:Default
* @value 0
* @option 1:Gradually disappear (fast)
* @value 1
* @option 2:Gradually disappear (slow)
* @value 2
* @option 3:Scroll up
* @value 3
* @option 4:Op3| Add text below
* @value 4
* @default 0
*
* @command effectSkip
* @desc
* @arg boolean
* @desc
* @type boolean
* @default true
*
*
* @----------------
*
* @param Text Set
* @desc An array of sets of strings to call with \SET
* (From the top, \SET[1], \SET[2] ...)
* @type string[]
* @default []
*
* @param Wait Effects
* @desc \WE Directing to wait for the end when executing
* @type struct<WaitEffects>
* @default {"Scroll Map":"true","Set Movement Route":"true","Show Animation":"true","Show Balloon Icon":"true","Move Picture":"true","Tint Picture":"true","Tint Screen":"true","Flash Screen":"true","Shake Screen":"false","Set Weather Effect":"false","Fadeout BGM":"false","Fadeout BGS":"false","Play ME":"false"}
*
* @param Skip Effects
* @desc A production that skips sentences at the same time when skipping sentences
* @type struct<SkipEffects>
* @default {"Scroll Map":"true","Set Movement Route":"true","Move Picture":"true","Tint Picture":"true","Tint Screen":"false","Flash Screen":"false","Shake Screen":"false","Set Weather Effect":"false"}
*
* @param Skip Effects Timing
* @desc
* @type select
* @option skip
* @option end of text
* @default skip
* @parent Skip Effects
*
* @param Ruby Font Size
* @desc
* @type number
* @min 4
* @max 99
* @default 14
*
* @param Ruby Oy
* @desc
* @type number
* @min -9999
* @max 9999
* @default 0
*
* @param Ruby Outline Width
* @desc
* @type number
* @min 0
* @max 99
* @default 2
*
* @param Always Leave Ruby Height
* @desc
* @type boolean
* @default false
*
* @param Default
* @desc
* @type struct<Default>
* @default {"Anime Type":"1","Message Row":"4","FadeOut Type":"0","Text Speed":"60","Outline Color":"0,0,0,0.5","Outline Width":"4","Ruby Color":"255,255,255"}
*
*/
/*~struct~WaitEffects:
* @param Scroll Map
* @desc
* @type boolean
* @default true
*
* @param Set Movement Route
* @desc Excludes [Repeat operation]
* @type boolean
* @default true
*
* @param Show Animation
* @desc
* @type boolean
* @default true
*
* @param Show Balloon Icon
* @desc
* @type boolean
* @default true
*
* @param Move Picture
* @desc
* @type boolean
* @default true
*
* @param Tint Picture
* @desc
* @type boolean
* @default true
*
* @param Tint Screen
* @desc
* @type boolean
* @default true
*
* @param Flash Screen
* @desc
* @type boolean
* @default true
*
* @param Shake Screen
* @desc
* @type boolean
* @default false
*
* @param Set Weather Effect
* @desc
* @type boolean
* @default false
*
* @param Fadeout BGM
* @desc
* @type boolean
* @default false
*
* @param Fadeout BGS
* @desc
* @type boolean
* @default false
*
* @param Play ME
* @desc
* @type boolean
* @default false
*
*/
/*~struct~SkipEffects:
* @param Scroll Map
* @desc
* @type boolean
* @default true
*
* @param Set Movement Route
* @desc Excludes [Repeat operation]
* @type boolean
* @default true
*
* @param Move Picture
* @desc
* @type boolean
* @default true
*
* @param Tint Picture
* @desc
* @type boolean
* @default true
*
* @param Tint Screen
* @desc
* @type boolean
* @default false
*
* @param Flash Screen
* @desc
* @type boolean
* @default false
*
* @param Shake Screen
* @desc
* @type boolean
* @default false
*
* @param Set Weather Effect
* @desc
* @type boolean
* @default false
*
*/
/*~struct~Default:
* @param Anime Type
* @desc
* @type number
* @min 0
* @max 999
* @default 1
*
* @param Message Row
* @desc
* @type number
* @min 1
* @max 99
* @default 4
*
* @param FadeOut Type
* @desc
* @type select
* @option 0:Default
* @value 0
* @option 1:Gradually disappear (fast)
* @value 1
* @option 2:Gradually disappear (slow)
* @value 2
* @option 3:Scroll up
* @value 3
* @option 4:Op3| Add text below
* @value 4
* @default 0
*
* @param Text Speed
* @desc
* @type number
* @min 0
* @max 999
* @default 60
*
* @param Outline Color
* @desc Specified by RGBA / Alpha value is specified from 0 - 1.0
* @default 0,0,0,0.5
*
* @param Outline Width
* @desc
* @type number
* @min 0
* @max 99
* @default 4
*
* @param Ruby Color
* @desc Specified by RGB
* @default 255,255,255
*
*/
/*:ja
* @target MV MZ
* @plugindesc 文章表示の機能を拡張したり表示の演出を追加します。
* @author 木星ペンギン
* @url
*
* @help [version 4.4.1]
* このプラグインはRPGツクールMVおよびMZ用です。
*
* ▼ [文章の表示]の制御文字
* \SP[n] # 文章の表示速度(秒間描写文字数n / 0:瞬間表示)
* \AT[n] # アニメーションタイプをn番に変更(※1)
* \SET[n] # 設定した文字列に変換(※2)
* \CO[S] # 文字列Sを文字として表示
* \RB[S,R] # 文字列SにルビRを付けて表示(※3)
* \MX[n] # 次に表示する文字のX座標をnピクセルずらす
* \MY[n] # 次に表示する文字のY座標をnピクセルずらす
* \PX[n] # 次に表示する文字のX座標をnに変更
* \PY[n] # 次に表示する文字のY座標をnに変更
* \SW[n] # スイッチn番をONにする
* \SN[n] # スキルID n 番の名前に置き換える
* \SIN[n] # スキルID n 番のアイコンと名前に置き換える
* \IN[n] # アイテムID n 番の名前に置き換える
* \IIN[n] # アイテムID n 番のアイコンと名前に置き換える
* \WN[n] # 武器ID n 番の名前に置き換える
* \WIN[n] # 武器ID n 番のアイコンと名前に置き換える
* \AN[n] # 防具ID n 番の名前に置き換える
* \AIN[n] # 防具ID n 番のアイコンと名前に置き換える
* \WE # イベントの演出が終了するまでウェイト(※4)
* \C[r,g,b] # 文字色をRGBで指定
* \FS[n] # 文字サイズをnに変更 / デフォルト値:MV=28,MZ=26
* \FB # 文字の太字フラグを反転
* \FI # 文字の斜体フラグを反転
* \OP[n] # 文字の不透明度(0255) / デフォルト値:255
* \OC[n] # 文字の縁の色をn番に変更 / 0:デフォルト(黒)
* \OC[r,g,b] # 文字の縁の色をRGBで指定
* \OC[r,g,b,a] # 文字の縁の色をRGBAで指定(※5)
* \OW[n] # 文字の縁の太さを変更 / デフォルト値:4
* \RC[n] # ルビの色をn番に変更 / 0:デフォルト
* \RC[r,g,b] # ルビの色をRGBで指定
* \RC[r,g,b,a] # ルビの色をRGBAで指定(※5)
* \DF # 文章表示の設定をデフォルト値に戻す(※6)
* \SV # 現在の文章表示の設定を記憶(※6)
* \LD # \SVで記憶した設定の呼び出し(※6)
*
* - 以下は文章内に含まれていた場合に適用
* \A # 決定キーやシフトキーによるスキップの禁止
* \ES # イベントの演出のスキップを一時的に有効にする(※7)
* \FO[n] # フェードアウトタイプを一時的に変更する(※8)
*
* - すべての制御文字は大文字小文字どちらでも可能
*
* ▼ 制御文字詳細
* ※1: \AT[n] (アニメーションタイプをn番に変更)
* - アニメーションタイプのデフォルトは以下のようになります。
* 0: デフォルト
* 1: 文字が右にスライドしながら浮かび上がる
* 2: 文字が横に広がりながら表示される
* 3: 文字が拡大しながら表示される
* 4: 文字を左側から表示する(表示速度6推奨)
*
* ※2: \SET[n] (設定した文字列に変換)
* - プラグインパラメータ[Text Set]で指定した文字列に変換します。
* - 制御文字も設定可能です。
*
* ※3: \RB[S,R] (文字列SにルビRを付けて表示)
* - ルビを振った文字列は一文字ずつではなくまとめて表示されます。
*
* ※4: \WE (演出が終了するまでウェイト)
* - プラグインパラメータ[Wait Effects]で設定したイベントの演出が終了するまで
* ウェイトを行います。
* - 文章のスキップを行ってもウェイトがかかります。
*
* ※5: \OC[r,g,b,a] (文字の縁の色をRGBAで指定)
* - アルファ値(a)は0.01.0で指定してください。
*
* ※6: \DF, \SV, \LD (文章表示の設定を初期化/保存/呼び出し)
* - 以下の情報が対象となります。
* - 文章の表示速度
* - アニメーションタイプ
* - 文字色
* - 文字サイズ
* - 文字の太字フラグ
* - 文字の斜体フラグ
* - 文字の不透明度
* - 文字の縁の色
* - 文字の縁の太さ
* - ルビの色
*
* ※7: \ES (イベントの演出のスキップを一時的に有効にする)
* - 詳細はプラグインコマンドの SetEffectSkip を参照。
*
* ※8: \FO[n] (フェードアウトタイプを一時的に変更する)
* - 詳細はプラグインコマンドの SetMesFadeOut を参照。
*
* ▼ プラグインコマンド詳細
* - MVでは数値を入力する項目で v[N] と記述することで変数N番を参照します。
* - MZでは数値を入力する項目で、テキストを選択して v[N] と記述することで
* 変数N番を参照します。
*
* MV / MZ
*
* SetMesRow row / メッセージ行数設定
* row : メッセージウィンドウの行数
* - メッセージウィンドウの表示行数をn行に変更します。
*
* SetMesFadeOut type / メッセージフェードアウト
* type : フェードアウトのタイプ
* - フェードアウトのタイプを変更します。
* - 指定するタイプは以下の通りです。
* 0: デフォルト
* 1: 徐々に消える(早め)
* 2: 徐々に消える(遅め)
* 3: 上にスクロール
* 4: 下に文章を追加(Op3 導入時のみ)
*
* SetEffectSkip bool / 演出スキップ
* bool : trueで有効, falseで無効
* - 文章のスキップを行った際、演出のスキップをするかどうかを変更できます。
* - 初期設定は無効です。
* - スキップする演出はプラグインパラメータ[Skip Effects]にて設定できます。
* - 制御文字 \ES は一時的なものですが、こちらはコマンド実行後、常に適用されます。
*
* ================================
* Mail : wood_penguinyahoo.co.jp (@は半角)
* Blog : http://woodpenguin.blog.fc2.com/
* License : MIT license
*
* @command messageRow
* @text メッセージ行数設定
* @desc
* @arg row
* @desc
* @type number
* @min 1
* @max 99
* @default 4
*
* @command messageFadeOut
* @text メッセージフェードアウト
* @desc
* @arg type
* @desc
* @type select
* @option 0:デフォルト(瞬時に消える)
* @value 0
* @option 1:徐々に消える(早め)
* @value 1
* @option 2:徐々に消える(遅め)
* @value 2
* @option 3:上にスクロール
* @value 3
* @option 4:Op3| 下に文章を追加
* @value 4
* @default 0
*
* @command effectSkip
* @text 演出スキップ
* @desc
* @arg boolean
* @desc
* @type boolean
* @default true
*
*
* @----------------
*
* @param Text Set
* @text 文字列セット
* @desc \SETにて呼び出す文字列のセットの配列
* (上から \SET[1],\SET[2]... となります)
* @type string[]
* @default []
*
* @param Wait Effects
* @text 終了待ちする演出
* @desc \WE実行時に終了待ちをする演出
* @type struct<WaitEffects>
* @default {"Scroll Map":"true","Set Movement Route":"true","Show Animation":"true","Show Balloon Icon":"true","Move Picture":"true","Tint Picture":"true","Tint Screen":"true","Flash Screen":"true","Shake Screen":"false","Set Weather Effect":"false","Fadeout BGM":"false","Fadeout BGS":"false","Play ME":"false"}
*
* @param Skip Effects
* @text スキップする演出
* @desc 文章のスキップをした際、同時にスキップを行う演出
* @type struct<SkipEffects>
* @default {"Scroll Map":"true","Set Movement Route":"true","Move Picture":"true","Tint Picture":"true","Tint Screen":"false","Flash Screen":"false","Shake Screen":"false","Set Weather Effect":"false"}
*
* @param Skip Effects Timing
* @text 演出スキップのタイミング
* @desc
* @type select
* @option スキップ時
* @value skip
* @option 文章の表示終了時
* @value end of text
* @default skip
* @parent Skip Effects
*
* @param Ruby Font Size
* @text ルビの文字サイズ
* @desc
* @type number
* @min 4
* @max 99
* @default 14
*
* @param Ruby Oy
* @text ルビY軸補正値
* @desc
* @type number
* @min -9999
* @max 9999
* @default 0
*
* @param Ruby Outline Width
* @text ルビの縁の太さ
* @desc
* @type number
* @min 0
* @max 99
* @default 2
*
* @param Always Leave Ruby Height
* @text 常にルビの高さを空ける
* @desc
* @type boolean
* @default false
* @parent Ruby
*
* @param Default
* @text デフォルト値
* @desc
* @type struct<Default>
* @default {"Anime Type":"1","Message Row":"4","FadeOut Type":"0","Text Speed":"60","Outline Color":"0,0,0,0.5","Outline Width":"4","Ruby Color":"255,255,255"}
*
*/
/*~struct~WaitEffects:ja
* @param Scroll Map
* @text マップのスクロール
* @desc
* @type boolean
* @default true
*
* @param Set Movement Route
* @text 移動ルートの設定
* @desc [動作を繰り返す]は除く
* @type boolean
* @default true
*
* @param Show Animation
* @text アニメーションの表示
* @desc
* @type boolean
* @default true
*
* @param Show Balloon Icon
* @text フキダシアイコンの表示
* @desc
* @type boolean
* @default true
*
* @param Move Picture
* @text ピクチャの移動
* @desc
* @type boolean
* @default true
*
* @param Tint Picture
* @text ピクチャの色調変更
* @desc
* @type boolean
* @default true
*
* @param Tint Screen
* @text 画面の色調変更
* @desc
* @type boolean
* @default true
*
* @param Flash Screen
* @text 画面のフラッシュ
* @desc
* @type boolean
* @default true
*
* @param Shake Screen
* @text 画面のシェイク
* @desc
* @type boolean
* @default false
*
* @param Set Weather Effect
* @text 天候の設定
* @desc
* @type boolean
* @default false
*
* @param Fadeout BGM
* @text BGMのフェードアウト
* @desc
* @type boolean
* @default false
*
* @param Fadeout BGS
* @text BGSのフェードアウト
* @desc
* @type boolean
* @default false
*
* @param Play ME
* @text MEの演奏
* @desc
* @type boolean
* @default false
*
*/
/*~struct~SkipEffects:ja
* @param Scroll Map
* @text マップのスクロール
* @desc
* @type boolean
* @default true
*
* @param Set Movement Route
* @text 移動ルートの設定
* @desc [動作を繰り返す]は除く
* @type boolean
* @default true
*
* @param Move Picture
* @text ピクチャの移動
* @desc
* @type boolean
* @default true
*
* @param Tint Picture
* @text ピクチャの色調変更
* @desc
* @type boolean
* @default true
*
* @param Tint Screen
* @text 画面の色調変更
* @desc
* @type boolean
* @default false
*
* @param Flash Screen
* @text 画面のフラッシュ
* @desc
* @type boolean
* @default false
*
* @param Shake Screen
* @text 画面のシェイク
* @desc
* @type boolean
* @default false
*
* @param Set Weather Effect
* @text 天候の設定
* @desc
* @type boolean
* @default false
*
*/
/*~struct~Default:ja
* @param Anime Type
* @text アニメーションタイプ
* @desc
* @type number
* @min 0
* @max 999
* @default 1
*
* @param Message Row
* @text メッセージ行数
* @desc [メッセージウィンドウの表示行数]のデフォルト値
* @type number
* @min 1
* @max 99
* @default 4
*
* @param FadeOut Type
* @text フェードアウトタイプ
* @desc
* @type select
* @option 0:デフォルト(瞬時に消える)
* @value 0
* @option 1:徐々に消える(早め)
* @value 1
* @option 2:徐々に消える(遅め)
* @value 2
* @option 3:上にスクロール
* @value 3
* @option 4:Op3| 下に文章を追加
* @value 4
* @default 0
*
* @param Text Speed
* @text 文章の表示速度
* @desc
* @type number
* @min 0
* @max 999
* @default 60
*
* @param Outline Color
* @text 文字の縁の色
* @desc RGBAで指定 / アルファ値は 01.0 で指定
* @default 0,0,0,0.5
*
* @param Outline Width
* @text 文字の縁の太さ
* @desc
* @type number
* @min 0
* @max 99
* @default 4
*
* @param Ruby Color
* @text ルビの色
* @desc RGBで指定
* @default 255,255,255
*
*/
(() => {
'use strict';
const pluginName = 'MPP_MessageEX';
// Plugin Parameters
const parameters = PluginManager.parameters(pluginName);
const paramReplace = (key, value) => {
try {
return JSON.parse(value);
} catch (e) {
return value;
}
};
const param_TextSet = JSON.parse(parameters['Text Set'] || '[]');
const param_WaitEffects = JSON.parse(parameters['Wait Effects'] || '{}', paramReplace);
const param_SkipEffects = JSON.parse(parameters['Skip Effects'] || '{}', paramReplace);
const param_SkipEffectsTiming = parameters['Skip Effects Timing'] || 'skip';
const param_RubyFontSize = Number(parameters['Ruby Font Size'] || 14);
const param_RubyOy = Number(parameters['Ruby Oy'] || 0);
const param_RubyOutlineWidth = Number(parameters['Ruby Outline Width'] || 2);
const param_AlwaysLeaveRubyHeight = parameters['Always Leave Ruby Height'] === 'true';
const param_Default = JSON.parse(parameters['Default'] || '{}', paramReplace);
const getDefaultParam = (name, def = null) => {
return name in param_Default ? param_Default[name] : def;
};
const param_MaxEffectSkipCount = 99;
// Dealing with other plugins
const __base = (obj, prop) => {
if (obj.hasOwnProperty(prop)) {
return obj[prop];
} else {
const proto = Object.getPrototypeOf(obj);
return function () { return proto[prop].apply(this, arguments); };
}
};
const _importedPlugin = (...names) => {
return names.some(name => PluginManager._scripts.includes(name));
};
// MPP_Patch.js
let param_Patch6 = false;
if (_importedPlugin('MPP_Patch')) {
const patchParameters = PluginManager.parameters('MPP_Patch');
param_Patch6 = patchParameters['Patch6 enabled?'] === 'true';
}
// MathExt
const MathExt = (() => {
// Number.prototype.clamp と違い、下限優先
const clamp = (x, min, max) => Math.max(Math.min(x, max), min);
return { clamp };
})();
// RPG Maker Param
const getTextColor = function(index) {
return checkRMName('MV')
? this.textColor(index)
: ColorManager.textColor(index);
};
/**
* Checks whether the current RPG Maker name.
*
* @param {string} name - RPG Maker name. "MV" or "MZ".
* @returns {boolean} True if the current name is the same as the specified
* name.
*/
const checkRMName = function(name) {
return Utils.RPGMAKER_NAME === name;
};
//-----------------------------------------------------------------------------
// Bitmap
if (!Bitmap.prototype.destroy) {
Bitmap.prototype.destroy = function() {
if (this._baseTexture) {
this._baseTexture.destroy();
this.__baseTexture = null;
}
this._destroyCanvas();
};
Bitmap.prototype._destroyCanvas = function() {
if (this._canvas) {
this._canvas.width = 0;
this._canvas.height = 0;
this.__canvas = null;
}
};
}
//-------------------------------------------------------------------------
// WebAudio
WebAudio.prototype.realVolume = function() {
return this._gainNode ? this._gainNode.gain.value : 0;
};
//-------------------------------------------------------------------------
// Html5Audio
if (checkRMName('MV')) {
Html5Audio.realVolume = function() {
return this._audioElement ? this._audioElement.volume : 0;
};
}
//-------------------------------------------------------------------------
// AudioManager
AudioManager.isBgmFadeOuting = function() {
return (
this._bgmBuffer &&
!this._currentBgm &&
this._bgmBuffer.realVolume() > 0
);
};
AudioManager.isBgsFadeOuting = function() {
return (
this._bgsBuffer &&
!this._currentBgs &&
this._bgsBuffer.realVolume() > 0
);
};
AudioManager.isMePlaying = function() {
return this._meBuffer && this._meBuffer.isPlaying();
};
//-----------------------------------------------------------------------------
// Game_Character
Game_Character.prototype.isMoveRouteForcingNr = function() {
return this.isMoveRouteForcing() && !this._moveRoute.repeat;
};
//-------------------------------------------------------------------------
// Game_Map
Game_Map.prototype.isAnyMoveRouteForcingNr = function() {
return (
this.events().some(e => e.isMoveRouteForcingNr()) ||
$gamePlayer.isMoveRouteForcingNr()
);
};
Game_Map.prototype.isAnyAnimationPlaying = function() {
return (
this.events().some(e => e.isAnimationPlaying()) ||
$gamePlayer.isAnimationPlaying()
);
};
Game_Map.prototype.isAnyBalloonPlaying = function() {
return (
this.events().some(e => e.isBalloonPlaying()) ||
$gamePlayer.isBalloonPlaying()
);
};
//-------------------------------------------------------------------------
// Game_Screen
Game_Screen.prototype.isAnyPictureMoving = function() {
return this._pictures.some(p => p && p.isMoving());
};
Game_Screen.prototype.isAnyPictureTinting = function() {
return this._pictures.some(p => p && p.isTinting());
};
Game_Screen.prototype.isTinting = function() {
return this._toneDuration > 0;
};
Game_Screen.prototype.isFlashing = function() {
return this._flashDuration > 0;
};
Game_Screen.prototype.isShaking = function() {
return this._shakeDuration > 0;
};
Game_Screen.prototype.isWeatherChanging = function() {
return this._weatherDuration > 0;
};
//-------------------------------------------------------------------------
// Game_Picture
Game_Picture.prototype.isMoving = function() {
return this._duration > 0;
};
Game_Picture.prototype.isTinting = function() {
return this._toneDuration > 0;
};
//-------------------------------------------------------------------------
// Game_Message
const _Game_Message_initialize = Game_Message.prototype.initialize;
Game_Message.prototype.initialize = function() {
_Game_Message_initialize.apply(this, arguments);
this._messageRow = getDefaultParam('Message Row', 4);
this._fadeOutType = getDefaultParam('FadeOut Type', 0);
this._effectSkip = false;
};
const _Game_Message_clear = Game_Message.prototype.clear;
Game_Message.prototype.clear = function() {
_Game_Message_clear.apply(this, arguments);
this._sceneEffectSkip = false;
};
Game_Message.prototype.clearSceneEffectSkip = function() {
this._sceneEffectSkip = false;
};
Game_Message.prototype.requestSceneEffectSkip = function() {
this._sceneEffectSkip = true;
};
Game_Message.prototype.messageRow = function() {
return this._messageRow;
};
Game_Message.prototype.fadeOutType = function() {
return this._fadeOutType;
};
Game_Message.prototype.effectSkip = function() {
return this._effectSkip;
};
Game_Message.prototype.sceneEffectSkip = function() {
return this._sceneEffectSkip;
};
Game_Message.prototype.setMessageRow = function(row) {
this._messageRow = row;
};
Game_Message.prototype.setFadeOutType = function(type) {
this._fadeOutType = type;
};
Game_Message.prototype.setEffectSkip = function(skip) {
this._effectSkip = skip;
};
const _Game_Message_isBusy = Game_Message.prototype.isBusy;
Game_Message.prototype.isBusy = function() {
return (
_Game_Message_isBusy.apply(this, arguments) ||
this._sceneEffectSkip
);
};
//-----------------------------------------------------------------------------
// Game_Interpreter
const _mzCommands = {
SetMesRow: { name:'messageRow', keys:['row'] },
SetMesFadeOut: { name:'messageFadeOut', keys:['type'] },
SetEffectSkip: { name:'effectSkip', keys:['boolean'] }
};
Object.assign(_mzCommands, {
'メッセージ行数設定': _mzCommands.SetMesRow,
'メッセージフェードアウト': _mzCommands.SetMesFadeOut,
'演出スキップ': _mzCommands.SetEffectSkip
});
const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args) {
_Game_Interpreter_pluginCommand.apply(this, arguments);
const params = _mzCommands[command];
if (params) {
const args2 = Object.assign(
{}, ...params.keys.map((k, i) => ({ [k]: args[i] }))
);
PluginManager.callCommandMV(this, pluginName, params.name, args2);
}
};
//-------------------------------------------------------------------------
// PluginManager
if (!PluginManager.registerCommand && !PluginManager.registerCommandMV) {
PluginManager._commandsMV = PluginManager._commandsMV || {};
PluginManager.registerCommandMV = function(pluginName, commandName, func) {
const key = pluginName + ':' + commandName;
this._commandsMV[key] = func;
};
PluginManager.callCommandMV = function(self, pluginName, commandName, args) {
const key = pluginName + ':' + commandName;
const func = this._commandsMV[key];
if (typeof func === 'function') {
func.bind(self)(args);
}
};
}
const _registerCommandName = PluginManager.registerCommand
? 'registerCommand'
: 'registerCommandMV';
PluginManager[_registerCommandName](pluginName, 'messageRow', args => {
$gameMessage.setMessageRow(PluginManager.mppValue(args.row));
});
PluginManager[_registerCommandName](pluginName, 'messageFadeOut', args => {
$gameMessage.setFadeOutType(PluginManager.mppValue(args.type));
});
PluginManager[_registerCommandName](pluginName, 'effectSkip', args => {
$gameMessage.setEffectSkip(args.boolean === 'true');
});
PluginManager.mppValue = function(value) {
const match = /^V\[(\d+)\]$/i.exec(value);
return match ? $gameVariables.value(+match[1]) : +value;
};
//-------------------------------------------------------------------------
// Sprite_TextCharacter
function Sprite_TextCharacter() {
this.initialize.apply(this, arguments);
}
Sprite_TextCharacter.prototype = Object.create(Sprite.prototype);
Sprite_TextCharacter.prototype.constructor = Sprite_TextCharacter;
Sprite_TextCharacter.prototype.initialize = function() {
Sprite.prototype.initialize.call(this);
this._rect = null;
this._list = null;
this._index = -1;
this._waitCount = 0;
};
Sprite_TextCharacter.prototype.setCallback = function(callback) {
this._drawCallback = callback;
};
Sprite_TextCharacter.prototype.setup = function(bitmap, rect, list) {
this.bitmap = bitmap;
this._rect = rect;
this._list = list;
this._index = 0;
this._waitCount = 0;
this.initBasic();
this.initMove();
this.initScale();
this.initOpacity();
this.initTone();
this.initRotation();
this.initFrame();
this.x = rect.x;
this.y = rect.y;
this.scale.x = 1.0;
this.scale.y = 1.0;
this.opacity = 255;
this.anchor.x = 0;
this.anchor.y = 0;
this.setColorTone([0, 0, 0, 0]);
this.rotation = 0;
this.update();
};
Sprite_TextCharacter.prototype.initBasic = function() {
this._origin = 0;
this._offsetX = 0;
this._offsetY = 0;
};
Sprite_TextCharacter.prototype.initMove = function() {
this._targetX = 0;
this._targetY = 0;
this._moveDuration = 0;
};
Sprite_TextCharacter.prototype.initScale = function() {
this._targetScaleX = 1;
this._targetScaleY = 1;
this._scaleDuration = 0;
};
Sprite_TextCharacter.prototype.initOpacity = function() {
this._targetOpacity = 255;
this._opacityDuration = 0;
};
Sprite_TextCharacter.prototype.initTone = function() {
this._tone = null;
this._toneTarget = null;
this._toneDuration = 0;
};
Sprite_TextCharacter.prototype.initRotation = function() {
this._angle = 0;
this._targetAngle = 0;
this._angleDuration = 0;
};
Sprite_TextCharacter.prototype.initFrame = function() {
const bitmap = this._bitmap;
if (bitmap) {
this.setFrame(0, 0, bitmap.width, bitmap.height);
} else {
this.setFrame(0, 0, 0, 0);
}
this._frame2 = null;
this._frame2Target = null;
this._frame2Duration = 0;
};
Sprite_TextCharacter.prototype.isPlaying = function() {
return !!this._list;
};
Sprite_TextCharacter.prototype.isEffecting = function() {
return (
this._moveDuration > 0 ||
this._scaleDuration > 0 ||
this._opacityDuration > 0 ||
this._toneDuration > 0 ||
this._angleDuration > 0 ||
this._frame2Duration > 0
);
};
Sprite_TextCharacter.prototype.update = function() {
Sprite.prototype.update.call(this);
if (this.isPlaying() && this.updateCommand()) {
this.updateMove();
this.updateScale();
this.updateOpacity();
this.updateTone();
this.updateRotation();
this.updateFrame2();
}
};
Sprite_TextCharacter.prototype.updateCommand = function() {
for (;;) {
if (this.updateWaitCount()) {
return true;
}
const code = this._list[this._index];
if (code) {
const [command, ...args] = code.split(' ');
this.callMethod(command, args.map(Number));
} else {
this.draw();
return false;
}
this._index++;
}
};
Sprite_TextCharacter.prototype.updateWaitCount = function() {
if (this._waitCount < 0) {
if (this.isEffecting()) return true;
this._waitCount = 0;
} else if (this._waitCount > 0) {
this._waitCount--;
return true;
}
return false;
};
Sprite_TextCharacter.prototype.callMethod = function(command, args) {
switch (command) {
case 'show':
this.commandShow(args);
break;
case 'move':
this.commandMove(args);
break;
case 'scale':
this.commandScale(args);
break;
case 'opacity':
this.commandOpacity(args);
break;
case 'rotate':
this.commandRotate(args);
break;
case 'tone':
this.commandTone(args);
break;
case 'frame':
this.commandFrame(args);
break;
case 'wait':
this.commandWait(args);
break;
case 'finish':
this.commandFinish(args);
break;
}
};
Sprite_TextCharacter.prototype.updateMove = function() {
if (this._moveDuration > 0) {
const d = this._moveDuration;
this._offsetX = (this._offsetX * (d - 1) + this._targetX) / d;
this._offsetY = (this._offsetY * (d - 1) + this._targetY) / d;
this._moveDuration--;
}
this.x = this._rect.x + this._offsetX;
this.y = this._rect.y + this._offsetY;
if (this._origin === 1) {
this.x += this._rect.width / 2;
this.y += this._rect.height / 2;
}
this.refreshAnchor();
};
Sprite_TextCharacter.prototype.updateScale = function() {
if (this._scaleDuration > 0) {
const d = this._scaleDuration;
this.scale.x = (this.scale.x * (d - 1) + this._targetScaleX) / d;
this.scale.y = (this.scale.y * (d - 1) + this._targetScaleY) / d;
this._scaleDuration--;
}
};
Sprite_TextCharacter.prototype.updateOpacity = function() {
if (this._opacityDuration > 0) {
const d = this._opacityDuration;
this.opacity = (this.opacity * (d - 1) + this._targetOpacity) / d;
this._opacityDuration--;
}
};
Sprite_TextCharacter.prototype.updateTone = function() {
if (this._toneDuration > 0) {
const d = this._toneDuration;
for (const [i, target] of this._toneTarget.entries()) {
this._tone[i] = (this._tone[i] * (d - 1) + target) / d;
}
this._toneDuration--;
}
if (this._tone) this.setColorTone(this._tone);
};
Sprite_TextCharacter.prototype.updateRotation = function() {
if (this._angleDuration > 0) {
const d = this._angleDuration;
this._angle = (this._angle * (d - 1) + this._targetAngle) / d;
this._angleDuration--;
}
this.rotation = this._angle * Math.PI / 180;
};
Sprite_TextCharacter.prototype.updateFrame2 = function() {
if (this._frame2Duration > 0) {
const d = this._frame2Duration;
for (const [i, target] of this._frame2Target.entries()) {
this._frame2[i] = (this._frame2[i] * (d - 1) + target) / d;
}
this._frame2Duration--;
this.refreshFrame2();
this.refreshAnchor();
}
};
Sprite_TextCharacter.prototype.refreshFrame2 = function() {
const { width, height } = this.bitmap;
const frame = this._frame2;
const fx = Math.round(width * frame[0] / 100);
const fy = Math.round(height * frame[1] / 100);
const fw = Math.max(Math.round(width * frame[2] / 100) - fx, 0);
const fh = Math.max(Math.round(height * frame[3] / 100) - fy, 0);
this.setFrame(fx, fy, fw, fh);
};
Sprite_TextCharacter.prototype.refreshAnchor = function() {
const ox = (this._origin === 0 ? 0 : this._rect.width / 2) + 4;
const oy = this._origin === 0 ? 0 : this._rect.height / 2;
this.anchor.x = this.width > 0 ? ox / this.width : 0;
this.anchor.y = this.height > 0 ? oy / this.height : 0;
};
Sprite_TextCharacter.prototype.draw = function() {
if (this._drawCallback) {
this._drawCallback(this.bitmap, this._rect);
}
this.delete();
};
Sprite_TextCharacter.prototype.delete = function() {
this.parent.removeChild(this);
this.bitmap.destroy();
this.bitmap = null;
this._list = null;
};
Sprite_TextCharacter.prototype.commandShow = function(args) {
this._origin = MathExt.clamp(args[0] || 0, 0, 1);
this._offsetX = args[1] || 0;
this._offsetY = args[2] || 0;
this.scale.x = args.length > 3 ? args[3] / 100 : 1;
this.scale.y = args.length > 4 ? args[4] / 100 : 1;
this.opacity = args.length > 5 ? args[5] : 255;
this.initMove();
this.initScale();
this.initOpacity();
this.initTone();
this.initRotation();
this.initFrame();
};
Sprite_TextCharacter.prototype.commandMove = function(args) {
this._targetX = args[0] || 0;
this._targetY = args[1] || 0;
this._moveDuration = Math.max(args[2] || 0, 0);
if (this._moveDuration === 0) {
this._offsetX = this._targetX;
this._offsetY = this._targetY;
}
};
Sprite_TextCharacter.prototype.commandScale = function(args) {
this._targetScaleX = args.length > 0 ? args[0] / 100 : 1;
this._targetScaleY = args.length > 0 ? args[1] / 100 : 1;
this._scaleDuration = Math.max(args[2] || 0, 0);
if (this._scaleDuration === 0) {
this.scale.x = this._targetScaleX;
this.scale.y = this._targetScaleY;
}
};
Sprite_TextCharacter.prototype.commandOpacity = function(args) {
this._targetOpacity = args.length > 0 ? MathExt.clamp(args[0], 0, 255) : 255;
this._opacityDuration = Math.max(args[1] || 0, 0);
if (this._opacityDuration === 0) {
this.opacity = this._targetOpacity;
}
};
Sprite_TextCharacter.prototype.commandRotate = function(args) {
this._targetAngle = args[0] || 0;
this._angleDuration = Math.max(args[1] || 0, 0);
if (this._angleDuration === 0) {
this._angle = this._targetAngle;
}
};
Sprite_TextCharacter.prototype.commandTone = function(args) {
if (!this._tone) this._tone = [0, 0, 0, 0];
this._toneTarget = [];
for (let i = 0; i < 4; i++) {
this._toneTarget[i] = MathExt.clamp(args[i] || 0, -255, 255);
}
this._toneDuration = Math.max(args[4] || 0, 0);
if (this._toneDuration === 0) {
this._tone = this._toneTarget.clone();
this.setColorTone(this._tone);
}
};
Sprite_TextCharacter.prototype.commandFrame = function(args) {
if (!this._frame2) this._frame2 = [0, 0, 100, 100];
this._frame2Target = [];
this._frame2Target[0] = args.length > 0 ? MathExt.clamp(args[0], 0, 100) : 0;
this._frame2Target[1] = args.length > 1 ? MathExt.clamp(args[1], 0, 100) : 0;
this._frame2Target[2] = args.length > 2 ? MathExt.clamp(args[2], 0, 100) : 100;
this._frame2Target[3] = args.length > 3 ? MathExt.clamp(args[3], 0, 100) : 100;
this._frame2Duration = Math.max(args[4] || 0, 0);
if (this._frame2Duration === 0) {
this._frame2 = this._frame2Target.clone();
this.refreshFrame2();
}
};
Sprite_TextCharacter.prototype.commandWait = function(args) {
this._waitCount = args.length > 0 ? Math.max(args[0], 0) : -1;
};
Sprite_TextCharacter.prototype.commandFinish = function(args) {
const count = Math.max(args[0] || 0, 0);
this.commandMove([0, 0, count]);
this.commandScale([100, 100, count]);
this.commandOpacity([255, count]);
this.commandRotate([0, count]);
this.commandTone([0, 0, 0, 0, count]);
this.commandFrame([0, 0, 100, 100, count]);
this.commandWait([count]);
};
//-----------------------------------------------------------------------------
// Window_Base
const _Window_Base_convertEscapeCharacters = Window_Base.prototype.convertEscapeCharacters;
Window_Base.prototype.convertEscapeCharacters = function(text) {
return _Window_Base_convertEscapeCharacters.apply(this, arguments)
.replace(/\x1bSET\[(\d+)\]/gi, (_, p1) => {
const index = +p1;
const setText = index > 0 ? param_TextSet[index - 1] : null;
return setText ? this.convertEscapeCharacters(setText) : '';
})
.replace(/\x1b([SIWA])(I?)N\[(\d+)\]/gi, (_, p1, p2, p3) => {
return this.mppConvertItemName(p1, p2 !== '', +p3);
});
};
Window_Base.prototype.mppConvertItemName = function(type, icon, itemId) {
let text = '';
let item;
switch (type.toUpperCase()) {
case 'S':
item = $dataSkills[itemId];
break;
case 'I':
item = $dataItems[itemId];
break;
case 'W':
item = $dataWeapons[itemId];
break;
case 'A':
item = $dataArmors[itemId];
break;
}
if (item) {
if (icon) text += `\x1bI[${item.iconIndex}]`;
text += item.name;
}
return text;
};
//-------------------------------------------------------------------------
// Window_Message
Window_Message.ANIMATIONS = [
null,
[ // type 1
'show 0 -6 0 100 100 0',
'finish 15'
],
[ // type 2
'show 0 0 0 0 100',
'scale 75 100 6',
'wait',
'finish 6'
],
[ // type 3
'show 1 0 0 0 0',
'scale 60 60 7',
'wait',
'scale 100 100 7',
'wait',
'scale 120 120 8',
'wait',
'finish 8'
],
[ // type 4
'show',
'frame 0 0 0 100 0',
'finish 10'
],
];
const _Window_Message_initialize = Window_Message.prototype.initialize;
Window_Message.prototype.initialize = function() {
this._messageRow = $gameMessage.messageRow();
this._textInfo = [];
this._rubyBitmap = new Bitmap();
_Window_Message_initialize.apply(this, arguments);
this.createCharacterContainer();
this._characterSprites = [];
this._waitEffect = false;
};
const _Window_Message_destroy = __base(Window_Message.prototype, 'destroy');
Window_Message.prototype.destroy = function(options) {
this._rubyBitmap.destroy();
_Window_Message_destroy.apply(this, arguments);
};
Window_Message.prototype.createCharacterContainer = function() {
if (checkRMName('MV')) {
this._characterContainer = new Sprite();
this.addChild(this._characterContainer);
this.updateCharacterContainer();
}
};
const _Window_Message_fittingHeight = __base(Window_Message.prototype, 'fittingHeight');
Window_Message.prototype.fittingHeight = function(numLines) {
let height = _Window_Message_fittingHeight.apply(this, arguments);
if (param_AlwaysLeaveRubyHeight) {
height += this.baseRubyHeight() * numLines;
}
return height;
};
const _Window_Message_resetFontSettings = __base(Window_Message.prototype, 'resetFontSettings');
Window_Message.prototype.resetFontSettings = function() {
_Window_Message_resetFontSettings.apply(this, arguments);
const rubyRgb = getDefaultParam('Ruby Color');
const rubyColor = rubyRgb ? `rgb(${rubyRgb})` : getTextColor.call(this, 0);
const outlineColor = `rgba(${getDefaultParam('Outline Color', '0, 0, 0, 0.5')})`;
this.contents.fontBold = false;
this.contents.fontItalic = false;
this.contents.paintOpacity = 255;
this._paintOpacity = 255;
this.contents.outlineColor = outlineColor;
this.contents.outlineWidth = getDefaultParam('Outline Width', 4);
this._rubyBitmap.textColor = rubyColor;
this._rubyBitmap.fontSize = param_RubyFontSize;
this._rubyBitmap.outlineWidth = param_RubyOutlineWidth;
this._rubyBitmap.outlineColor = outlineColor;
};
const _Window_Message_initMembers = Window_Message.prototype.initMembers;
Window_Message.prototype.initMembers = function() {
_Window_Message_initMembers.apply(this, arguments);
this.clearMessageExFlags();
};
// overwrite mv
Window_Message.prototype.windowHeight = function() {
return this.fittingHeight(this.numVisibleRows());
};
const _Window_Message_clearFlags = Window_Message.prototype.clearFlags;
Window_Message.prototype.clearFlags = function() {
_Window_Message_clearFlags.apply(this, arguments);
this.clearMessageExDefault();
this._lastBottomY = 0;
this._messageCount = 0;
};
Window_Message.prototype.clearMessageExFlags = function() {
this._auto = false;
this._effectSkip = $gameMessage.effectSkip();
this._fadeOut = false;
this._fadeOutType = $gameMessage.fadeOutType();
};
Window_Message.prototype.clearMessageExDefault = function() {
this._speed = getDefaultParam('Text Speed', 60);
this._animeType = getDefaultParam('Anime Type', 0);
};
Window_Message.prototype.numVisibleRows = function() {
return this._messageRow;
};
Window_Message.prototype.getAnimationList = function() {
return Window_Message.ANIMATIONS[this._animeType];
};
Window_Message.prototype.isCharacterAnimation = function() {
return this.getAnimationList() && !this._showFast && !this._lineShowFast;
};
Window_Message.prototype.getTextCharacterSprite = function() {
let sprite = this._characterSprites.find(sprite => !sprite.isPlaying());
if (!sprite) {
sprite = new Sprite_TextCharacter();
sprite.setCallback(this.drawTextCharacter.bind(this));
this._characterSprites.push(sprite);
}
if (this._characterContainer) {
this._characterContainer.addChild(sprite);
} else {
this.addInnerChild(sprite);
}
return sprite;
};
Window_Message.prototype.drawTextCharacter = function(bitmap, rect) {
this.contents.blt(bitmap, 0, 0, bitmap.width, bitmap.height, rect.x - 4, rect.y);
};
const _Window_Message_flushTextState = __base(Window_Base.prototype, 'flushTextState');
Window_Message.prototype.flushTextState = function(textState) {
if (textState.drawing && this.isCharacterAnimation()) {
this.flushTextStateForAnimation(textState);
} else {
this.contents.paintOpacity = this._paintOpacity;
_Window_Message_flushTextState.apply(this, arguments);
this.contents.paintOpacity = 255;
}
};
Window_Message.prototype.flushTextStateForAnimation = function(textState) {
const list = this.getAnimationList();
const text = textState.buffer;
const rtl = textState.rtl;
const { y, height } = textState;
const width = this.textWidth(text);
const x = rtl ? textState.x - width : textState.x;
const bitmap = this.createCharacterBitmap(width + 8, height);
bitmap.drawText(text, 4, 0, width + 4, height);
const sprite = this.getTextCharacterSprite();
const rect = new Rectangle(x, y, width, height);
sprite.setup(bitmap, rect, list);
textState.x += rtl ? -width : width;
textState.buffer = this.createTextBuffer(rtl);
const outputWidth = Math.abs(textState.x - textState.startX);
if (textState.outputWidth < outputWidth) {
textState.outputWidth = outputWidth;
}
textState.outputHeight = y - textState.startY + height;
};
const _Window_Message_convertEscapeCharacters = __base(Window_Message.prototype, 'convertEscapeCharacters');
Window_Message.prototype.convertEscapeCharacters = function(text) {
return _Window_Message_convertEscapeCharacters.apply(this, arguments)
.replace(/\x1bA(?![NIT])/gi, () => {
this._auto = true;
return '';
})
.replace(/\x1bES/gi, () => {
this._effectSkip = true;
return '';
});
};
const _Window_Message_update = Window_Message.prototype.update;
Window_Message.prototype.update = function() {
_Window_Message_update.apply(this, arguments);
this.updateCharacterContainer();
};
Window_Message.prototype.updateCharacterContainer = function() {
if (this._characterContainer) {
const pad = this._padding;
this._characterContainer.move(pad, pad);
}
};
const _Window_Message_startMessage = Window_Message.prototype.startMessage;
Window_Message.prototype.startMessage = function() {
this.clearMessageExFlags();
_Window_Message_startMessage.apply(this, arguments);
if (this.contents.height !== this.contentsHeight()) {
this.createContents();
}
};
const _Window_Message_updatePlacement = Window_Message.prototype.updatePlacement;
Window_Message.prototype.updatePlacement = function() {
this._messageRow = $gameMessage.messageRow();
this.height = this.windowHeight();
_Window_Message_updatePlacement.apply(this, arguments);
};
const _Window_Message_terminateMessage = Window_Message.prototype.terminateMessage;
Window_Message.prototype.terminateMessage = function() {
if (!this.isOpen() || this._fadeOutType === 0) {
this.terminateMessageEx();
} else {
this._fadeOut = true;
}
};
Window_Message.prototype.terminateMessageEx = function() {
_Window_Message_terminateMessage.call(this);
if (this._effectSkip && param_SkipEffectsTiming === 'end of text') {
$gameMessage.requestSceneEffectSkip();
}
};
const _Window_Message_updateWait = Window_Message.prototype.updateWait;
Window_Message.prototype.updateWait = function() {
return (
_Window_Message_updateWait.apply(this, arguments) ||
this.updateFadeOut() ||
this.updateWaitEffects()
);
};
const _Window_Message_updateMessage = Window_Message.prototype.updateMessage;
Window_Message.prototype.updateMessage = function() {
if (this._textState) {
this.updateShowFast();
this._messageCount += this._speed;
while (this.isContinueMessage()) {
if (_Window_Message_updateMessage.apply(this, arguments)) {
this._messageCount = Math.max(this._messageCount - 60, 0);
} else {
break;
}
}
return true;
}
return this._characterSprites.some(sprite => sprite.isPlaying());
};
Window_Message.prototype.isContinueMessage = function() {
return (this._messageCount >= 60 || this._speed === 0) && !this.isWaiting();
};
Window_Message.prototype.updateFadeOut = function() {
if (this._fadeOut) {
if (this.updateFadeOutMove()) {
this._fadeOut = false;
this.terminateMessageEx();
}
return true;
}
return false;
};
Window_Message.prototype.updateFadeOutMove = function() {
switch (this._fadeOutType) {
case 1:
this.contentsOpacity -= 8;
return (this.contentsOpacity === 0);
case 2:
this.contentsOpacity -= 3;
return (this.contentsOpacity === 0);
case 3:
this.origin.y += 6;
return (this.origin.y >= this._lastBottomY);
}
return true;
};
Window_Message.prototype.updateWaitEffects = function() {
if (this._waitEffect) {
if (param_Patch6) this.updateShowFast();
this._waitEffect = this.isEffectingEx(param_WaitEffects);
return true;
}
return false;
};
const _Window_Message_areSettingsChanged = Window_Message.prototype.areSettingsChanged;
Window_Message.prototype.areSettingsChanged = function() {
return (
_Window_Message_areSettingsChanged.apply(this, arguments) ||
this._messageRow !== $gameMessage.messageRow()
);
};
const _Window_Message_updateShowFast = Window_Message.prototype.updateShowFast;
Window_Message.prototype.updateShowFast = function() {
const lastShowFast = this._showFast;
if (!this._auto) {
_Window_Message_updateShowFast.apply(this, arguments);
}
if (!lastShowFast && this._showFast) {
if (this._effectSkip && param_SkipEffectsTiming === 'skip') {
$gameMessage.requestSceneEffectSkip();
}
for (const item of this._characterSprites) {
if (item.isPlaying()) item.draw();
}
}
};
const _Window_Message_newPage = Window_Message.prototype.newPage;
Window_Message.prototype.newPage = function(textState) {
for (const item of this._characterSprites) {
if (item.isPlaying()) item.delete();
}
_Window_Message_newPage.apply(this, arguments);
this.contentsOpacity = 255;
this.origin.y = 0;
textState.rubyHeight = this.realRubyHeight(textState);
textState.y += textState.rubyHeight;
this._lastBottomY = 0;
};
Window_Message.prototype.realRubyHeight = function(textState) {
const line = textState.text.slice(textState.index).split('\n')[0];
if (param_AlwaysLeaveRubyHeight || /\x1bRB\[.+?\]/i.test(line)) {
return this.baseRubyHeight();
}
return 0;
};
Window_Message.prototype.baseRubyHeight = function() {
return Math.max(param_RubyFontSize - param_RubyOy, 0);
};
const _Window_Message_processCharacter = __base(Window_Message.prototype, 'processCharacter');
Window_Message.prototype.processCharacter = function(textState) {
_Window_Message_processCharacter.apply(this, arguments);
this._lastBottomY = textState.y + textState.height;
};
const _Window_Message_processNewLine = Window_Message.prototype.processNewLine;
Window_Message.prototype.processNewLine = function(textState) {
if (this.isEndOfText(textState) && textState.x === textState.left) {
return;
}
_Window_Message_processNewLine.apply(this, arguments);
textState.rubyHeight = this.realRubyHeight(textState);
textState.y += textState.rubyHeight;
if (this.needsNewPage(textState)) {
this.startPause();
}
};
const _Window_Message_processEscapeCharacter = Window_Message.prototype.processEscapeCharacter;
Window_Message.prototype.processEscapeCharacter = function(code, textState) {
switch (code) {
case 'SP':
this._speed = this.obtainEscapeParam(textState);
break;
case 'AT':
this._animeType = this.obtainEscapeParam(textState);
break;
case 'CO':
this.processGroupCharacter(textState, this.obtainEscapeTexts(textState));
break;
case 'RB':
this.processRubyCharacter(textState, this.obtainEscapeTexts(textState));
break;
case 'MX':
textState.x += this.obtainEscapeParam2(textState);
break;
case 'MY':
textState.y += this.obtainEscapeParam2(textState);
break;
case 'PX':
textState.x = this.obtainEscapeParam(textState);
break;
case 'PY':
textState.y = this.obtainEscapeParam(textState);
break;
case 'SW':
$gameSwitches.setValue(this.obtainEscapeParam(textState), true);
break;
case 'WE':
this.waitForEffect();
break;
case 'C':
this.contents.textColor = this.obtainEscapeColor(textState);
break;
case 'FS':
this.contents.fontSize = this.obtainEscapeParam(textState);
break;
case 'FB':
this.contents.fontBold = !this.contents.fontBold;
break;
case 'FI':
this.contents.fontItalic = !this.contents.fontItalic;
break;
case 'OP':
this._paintOpacity = this.obtainEscapeParam(textState);
break;
case 'OC': {
const color = this.obtainEscapeColor(textState, 'rgba(0,0,0,0.5)');
this.contents.outlineColor = color;
this._rubyBitmap.outlineColor = color;
break;
}
case 'OW':
this.contents.outlineWidth = this.obtainEscapeParam(textState);
break;
case 'RC':
const rubyRgb = getDefaultParam('Ruby Color');
const rubyColor = rubyRgb ? `rgb(${rubyRgb})` : getTextColor.call(this, 0);
this._rubyBitmap.textColor = this.obtainEscapeColor(textState, rubyColor);
break;
case 'DF':
this.defaultTextInfo();
break;
case 'SV':
this.saveTextInfo();
break;
case 'LD':
this.loadTextInfo();
break;
case 'FO':
this._fadeOutType = this.obtainEscapeParam(textState);
break;
default:
_Window_Message_processEscapeCharacter.apply(this, arguments);
break;
}
};
Window_Message.prototype.waitForEffect = function() {
if (this.isEffectingEx(param_WaitEffects)) {
this._waitEffect = true;
this._waitCount = 1;
}
};
Window_Message.prototype.obtainEscapeParam2 = function(textState) {
const arr = /^\[-?\d+\]/.exec(textState.text.slice(textState.index));
if (arr) {
textState.index += arr[0].length;
return parseInt(arr[0].slice(1));
}
return '';
};
Window_Message.prototype.obtainEscapeTexts = function(textState) {
const arr = /^\[(.+?)\]/.exec(textState.text.slice(textState.index));
if (arr) {
textState.index += arr[0].length;
return arr[1].split(',');
}
return [];
};
Window_Message.prototype.obtainEscapeColor = function(textState, defaultColor) {
const arr = /^\[([\d\s,\.]+)\]/.exec(textState.text.slice(textState.index));
if (arr) {
textState.index += arr[0].length;
switch (arr[1].split(',').length) {
case 1:
const index = +arr[1];
return index === 0
? defaultColor || getTextColor.call(this, 0)
: getTextColor.call(this, index);
case 3:
return `rgb(${arr[1]})`;
case 4:
return `rgba(${arr[1]})`;
}
}
return '';
};
Window_Message.prototype.defaultTextInfo = function() {
this.clearMessageExDefault();
this.resetFontSettings();
};
Window_Message.prototype.saveTextInfo = function() {
this._textInfo[0] = this._speed;
this._textInfo[1] = this._animeType;
this._textInfo[2] = this.contents.textColor;
this._textInfo[3] = this.contents.fontSize;
this._textInfo[4] = this.contents.fontBold;
this._textInfo[5] = this.contents.fontItalic;
this._textInfo[6] = this._paintOpacity;
this._textInfo[7] = this.contents.outlineColor;
this._textInfo[8] = this.contents.outlineWidth;
this._textInfo[9] = this._rubyBitmap.textColor;
this._textInfo[10] = this._rubyBitmap.outlineColor;
};
Window_Message.prototype.loadTextInfo = function() {
if (this._textInfo.length > 0) {
this._speed = this._textInfo[0];
this._animeType = this._textInfo[1];
this.contents.textColor = this._textInfo[2];
this.contents.fontSize = this._textInfo[3];
this.contents.fontBold = this._textInfo[4];
this.contents.fontItalic = this._textInfo[5];
this._paintOpacity = this._textInfo[6];
this.contents.outlineColor = this._textInfo[7];
this.contents.outlineWidth = this._textInfo[8];
this._rubyBitmap.textColor = this._textInfo[9];
this._rubyBitmap.outlineColor = this._textInfo[10];
}
};
Window_Message.prototype.isEffectingEx = function(info) {
return (
(info['Scroll Map'] && $gameMap.isScrolling()) ||
(info['Set Movement Route'] && $gameMap.isAnyMoveRouteForcingNr()) ||
(info['Show Animation'] && $gameMap.isAnyAnimationPlaying()) ||
(info['Show Balloon Icon'] && $gameMap.isAnyBalloonPlaying()) ||
(info['Move Picture'] && $gameScreen.isAnyPictureMoving()) ||
(info['Tint Picture'] && $gameScreen.isAnyPictureTinting()) ||
(info['Tint Screen'] && $gameScreen.isTinting()) ||
(info['Flash Screen'] && $gameScreen.isFlashing()) ||
(info['Shake Screen'] && $gameScreen.isShaking()) ||
(info['Set Weather Effect'] && $gameScreen.isWeatherChanging()) ||
(info['Fadeout BGM'] && AudioManager.isBgmFadeOuting()) ||
(info['Fadeout BGS'] && AudioManager.isBgsFadeOuting()) ||
(info['Play ME'] && AudioManager.isMePlaying())
);
};
const _Window_Message_processNormalCharacter = __base(Window_Message.prototype, 'processNormalCharacter');
Window_Message.prototype.processNormalCharacter = function(textState) {
if (this.isCharacterAnimation()) {
this.processNormalCharacterForAnimation(textState);
} else {
this.contents.paintOpacity = this._paintOpacity;
_Window_Message_processNormalCharacter.apply(this, arguments);
this.contents.paintOpacity = 255;
}
};
Window_Message.prototype.processNormalCharacterForAnimation = function(textState) {
const list = this.getAnimationList();
const c = textState.text[textState.index++];
const { x, y, height } = textState;
const width = this.textWidth(c);
const bitmap = this.createCharacterBitmap(width + 8, height);
bitmap.drawText(c, 4, 0, width + 4, height);
const sprite = this.getTextCharacterSprite();
const rect = new Rectangle(x, y, width, height);
sprite.setup(bitmap, rect, list);
textState.x += width;
};
// overwrite
Window_Message.prototype.processDrawIcon = function(iconIndex, textState) {
const pw = Window_Base._iconWidth || ImageManager.iconWidth;
const ph = Window_Base._iconHeight || ImageManager.iconHeight;
if (checkRMName('MV') || textState.drawing) {
if (this.isCharacterAnimation()) {
this.processDrawIconForAnimation(iconIndex, textState);
} else {
const offsetY = Math.floor(textState.height - ph) / 2;
this.contents.paintOpacity = this._paintOpacity;
this.drawIcon(iconIndex, textState.x + 2, textState.y + offsetY);
this.contents.paintOpacity = 255;
}
}
textState.x += pw + 4;
};
Window_Message.prototype.processDrawIconForAnimation = function(iconIndex, textState) {
const pw = Window_Base._iconWidth || ImageManager.iconWidth;
const ph = Window_Base._iconHeight || ImageManager.iconHeight;
const { x, y, height } = textState;
const offsetY = Math.floor(height - ph) / 2;
const list = this.getAnimationList();
const bitmap = this.createCharacterBitmap(pw + 12, height);
const iconSet = ImageManager.loadSystem('IconSet');
const sx = iconIndex % 16 * pw;
const sy = Math.floor(iconIndex / 16) * ph;
bitmap.blt(iconSet, sx, sy, pw, ph, 6, offsetY);
const sprite = this.getTextCharacterSprite();
const rect = new Rectangle(x, y, pw + 4, height);
sprite.setup(bitmap, rect, list);
};
Window_Message.prototype.processGroupCharacter = function(textState, texts) {
const c = texts[0];
const width = this.textWidth(c);
if (checkRMName('MV') || textState.drawing) {
if (this.isCharacterAnimation()) {
this.processGroupCharacterForAnimation(textState, texts);
} else {
const { x, y, height } = textState;
this.contents.paintOpacity = this._paintOpacity;
this.contents.drawText(c, x, y, width * 2, height);
this.contents.paintOpacity = 255;
}
}
textState.x += width;
};
Window_Message.prototype.processGroupCharacterForAnimation = function(textState, texts) {
const c = texts[0];
const width = this.textWidth(c);
const { x, y, height } = textState;
const list = this.getAnimationList();
const bitmap = this.createCharacterBitmap(width + 8, height);
bitmap.drawText(c, 4, 0, width + 4, height);
const sprite = this.getTextCharacterSprite();
const rect = new Rectangle(x, y, width, height);
sprite.setup(bitmap, rect, list);
};
Window_Message.prototype.processRubyCharacter = function(textState, texts) {
const [ c, r ] = texts;
const { x, y, height } = textState;
const cw = this.textWidth(c);
const rubyBitmap = this._rubyBitmap;
rubyBitmap.fontBold = this.contents.fontBold;
rubyBitmap.fontItalic = this.contents.fontItalic;
const rw = rubyBitmap.measureTextWidth(r);
const rh = textState.rubyHeight;
const rs = rubyBitmap.fontSize;
const width = Math.max(cw, rw);
if (checkRMName('MV') || textState.drawing) {
rubyBitmap.clear();
rubyBitmap.resize(rw + 16, rs + 8);
rubyBitmap.drawText(r, 4, 0, rw + 4, rs + 8);
if (this.isCharacterAnimation()) {
const list = this.getAnimationList();
const bitmap = this.createCharacterBitmap(width + 8, height + rh);
const cx = (width - cw) / 2;
const rx = (width - rw) / 2;
const ry = -4;
bitmap.drawText(c, cx + 4, rh, width + 4, height);
bitmap.blt(rubyBitmap, 0, 0, rw + 8, rs + 8, rx, ry);
const sprite = this.getTextCharacterSprite();
const rect = new Rectangle(x, y - rh, width, height);
sprite.setup(bitmap, rect, list);
} else {
const cx = x + (width - cw) / 2;
const rx = x + (width - rw) / 2;
const ry = y - rh - 4;
this.contents.paintOpacity = this._paintOpacity;
this.contents.drawText(c, cx, y, cw + 4, height);
this.contents.blt(rubyBitmap, 0, 0, rw + 8, rs + 8, rx - 4, ry);
this.contents.paintOpacity = 255;
}
}
textState.x += width;
};
Window_Message.prototype.createCharacterBitmap = function(width, height) {
const bitmap = new Bitmap(width, height);
bitmap.fontFace = this.contents.fontFace;
bitmap.fontSize = this.contents.fontSize;
bitmap.fontBold = this.contents.fontBold;
bitmap.fontItalic = this.contents.fontItalic;
bitmap.textColor = this.contents.textColor;
bitmap.paintOpacity = this._paintOpacity;
bitmap.outlineColor = this.contents.outlineColor;
bitmap.outlineWidth = this.contents.outlineWidth;
return bitmap;
};
const _Window_Message_calcTextHeight = Window_Message.prototype.calcTextHeight;
Window_Message.prototype.calcTextHeight = function(textState, all) {
if (checkRMName('MZ')) {
return _Window_Message_calcTextHeight.apply(this, arguments);
}
const lines = textState.text.slice(textState.index).split('\n');
const regExp = /\x1bFS\[(\d+)\]/gi;
let maxFontSize = this.contents.fontSize;
for (;;) {
const arr = regExp.exec(lines[0]);
if (arr) {
maxFontSize = Math.max(maxFontSize, +arr[1]);
} else {
break;
}
}
const height = _Window_Message_calcTextHeight.apply(this, arguments);
return Math.max(height, maxFontSize + 8);
};
if (!Window_Message.prototype.isWaiting) {
Window_Message.prototype.isWaiting = function() {
return this.pause || this._waitCount > 0;
};
}
const _Window_Message_isWaiting = Window_Message.prototype.isWaiting;
Window_Message.prototype.isWaiting = function() {
return _Window_Message_isWaiting.apply(this, arguments) || this._waitEffect;
};
//-------------------------------------------------------------------------
// Scene_Map
const _Scene_Map_updateMainMultiply = Scene_Map.prototype.updateMainMultiply;
Scene_Map.prototype.updateMainMultiply = function() {
_Scene_Map_updateMainMultiply.apply(this, arguments);
if ($gameMessage.sceneEffectSkip()) {
for (let i = 1; i < param_MaxEffectSkipCount; i++) {
if (this._messageWindow.isEffectingEx(param_SkipEffects)) {
this.updateMain();
} else {
$gameMessage.clearSceneEffectSkip();
break;
}
}
}
};
})();