code:
//=============================================================================
// RPGツクールMZ - LL_StandingPictureBattle.js v1.8.0
//-----------------------------------------------------------------------------
// ルルの教会 (Lulu's Church)
// https://nine-yusha.com/
//
// URL below for license details.
// https://nine-yusha.com/plugin/
//=============================================================================

/*:
 * @target MZ
 * @plugindesc 戦闘中に立ち絵を自動表示します。
 * @author ルルの教会
 * @url https://nine-yusha.com/plugin-sbpicture/
 *
 * @help LL_StandingPictureBattle.js
 *
 * 戦闘中、下記のタイミングで立ち絵を自動表示します。
 *   ・戦闘開始時 (戦う・逃げる選択時)
 *   ・コマンド選択時
 *   ・被ダメージ時
 *   ・回避時
 *   ・攻撃、防御、スキル発動時
 *   ・反撃、魔法反射時
 *   ・アイテム使用時
 *   ・戦闘勝利時
 *
 * 下記のようにステート、スイッチ、変数条件で表示する立ち絵を複数定義できます。
 *   ・スイッチ1がONかつ毒状態の立ち絵
 *   ・変数1が10以上かつ毒状態の立ち絵
 *   ・スイッチ1がONの時の立ち絵
 *   ・毒状態の立ち絵
 *   ・スイッチ・ステート・変数条件なしの通常立ち絵 (最低限必要)
 *
 * 残りHP％で立ち絵を切り替える:
 *   まず「残りHP％」を「100」に設定した立ち絵リストを作成します。
 *   上記をコピーして「残りHP％」を「50」に変更し、立ち絵リストを複製します。
 *   これでHPが半分以下になった場合、「50」に設定した立ち絵が呼ばれます。
 *   残りHP％毎に、複数立ち絵を定義することも可能です。
 *
 * 画像ファイルの表示優先順:
 *   1. ステートID、スイッチID、変数条件全てに一致するもの
 *   2. ステートID、スイッチID両方に一致するもの
 *   3. ステートID、変数条件両方に一致するもの
 *   4. ステートIDのみ一致するもの
 *   5. スイッチID、変数条件両方に一致するもの
 *   6. スイッチIDのみ一致するもの
 *   7. 変数条件のみ一致するもの
 *   8. 条件なし (ステートID、スイッチID、変数条件全て設定なし)
 *   (上記の中で、残りHP％が最も低いものが優先して表示されます)
 *
 * 画像を反転させたい場合:
 *   X拡大率に「-100」と入力すると画像が反転します。
 *   (原点を左上にしている場合、X座標が画像横幅分左にずれます)
 *
 * 反撃、魔法反射時の立ち絵表示:
 *   反撃時は、攻撃のスキルに割り当てられた立ち絵が表示されます。
 *   魔法反射時は、反射したスキルに割り当てられた立ち絵が表示されます。
 *
 * プラグインコマンド:
 *   立ち絵表示ON・OFF: 立ち絵の表示・非表示を一括制御します。
 *
 * 利用規約:
 *   ・著作権表記は必要ございません。
 *   ・利用するにあたり報告の必要は特にございません。
 *   ・商用・非商用問いません。
 *   ・R18作品にも使用制限はありません。
 *   ・ゲームに合わせて自由に改変していただいて問題ございません。
 *   ・プラグイン素材としての再配布（改変後含む）は禁止させていただきます。
 *
 * 作者: ルルの教会
 * 作成日: 2022/6/3
 *
 * @command setEnabled
 * @text 立ち絵表示ON・OFF
 * @desc 立ち絵の表示・非表示を一括制御します。
 *
 * @arg enabled
 * @text 立ち絵表示
 * @desc OFFにすると立ち絵が表示されなくなります。
 * @default true
 * @type boolean
 *
 * @param pictureListSettings
 * @text 立ち絵リスト
 * @desc ※この項目は使用しません
 *
 * @param sbCommandPictures
 * @text コマンド選択時
 * @desc コマンド選択中に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbCommandPictures>[]
 * @parent pictureListSettings
 *
 * @param sbDamagePictures
 * @text ダメージ時
 * @desc ダメージ時に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbDamagePictures>[]
 * @parent pictureListSettings
 *
 * @param sbEvasionPictures
 * @text 回避時
 * @desc 回避時に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbEvasionPictures>[]
 * @parent pictureListSettings
 *
 * @param sbWinPictures
 * @text 勝利時
 * @desc 戦闘勝利時に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbWinPictures>[]
 * @parent pictureListSettings
 *
 * @param sbActionPictures
 * @text 攻撃、防御、スキル、反撃
 * @desc 攻撃、スキル、アイテム使用時に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbActionPictures>[]
 * @parent pictureListSettings
 *
 * @param sbItemPictures
 * @text アイテム使用時
 * @desc アイテム使用時に表示する立ち絵を定義します。
 * ステート、スイッチ、残HP％毎に立ち絵を複数定義できます。
 * @default []
 * @type struct<sbItemPictures>[]
 * @parent pictureListSettings
 *
 * @param counterSettings
 * @text 反撃時の設定
 * @desc ※この項目は使用しません
 *
 * @param showCounterAttack
 * @text 反撃時に立ち絵を表示
 * @desc 反撃時に立ち絵を表示します。
 * 攻撃のスキルに割り当てられた立ち絵が表示されます。
 * @default true
 * @type boolean
 * @parent counterSettings
 *
 * @param showMagicReflection
 * @text 魔法反射時に立ち絵を表示
 * @desc 魔法反射時に立ち絵を表示します。
 * 反射したスキルに割り当てられた立ち絵が表示されます。
 * @default true
 * @type boolean
 * @parent counterSettings
 *
 * @param startActorType
 * @text 戦闘開始時の表示アクター
 * @desc 戦う・逃げる選択時に表示されるアクターを選択してください。
 * コマンド選択時の立ち絵が表示されます。
 * @type select
 * @default none
 * @option 表示しない
 * @value none
 * @option 先頭のアクター
 * @value firstActor
 * @option ランダム
 * @value randomActor
 *
 * @param winActorType
 * @text 戦闘勝利時の表示アクター
 * @desc 戦闘勝利時に表示されるアクターを選択してください。
 * @type select
 * @default lastActor
 * @option 表示しない
 * @value none
 * @option 最後に行動したアクター
 * @value lastActor
 * @option 先頭のアクター
 * @value firstActor
 * @option ランダム
 * @value randomActor
 *
 * @param hiddenEnemyWindow
 * @text 敵選択時は非表示
 * @desc 敵選択時は立ち絵を非表示にします。
 * @default true
 * @type boolean
 *
 * @param hiddenActorWindow
 * @text 対象アクター選択時は非表示
 * @desc 対象アクター選択時は立ち絵を非表示にします。
 * @default false
 * @type boolean
 *
 * @param deathBeforeStates
 * @text 死亡時の直前ステート判定
 * @desc 死亡時に直前のステート状態で立ち絵を判定します。
 * 死亡時に専用の立ち絵を表示する場合はオフにしてください。
 * @default false
 * @type boolean
 */

/*~struct~sbCommandPictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default floatrightfast
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~sbDamagePictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default damage
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~sbEvasionPictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default stepright
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~sbWinPictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default floatright
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~sbActionPictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param itemId
 * @text スキルID
 * @desc このスキルが発動された時に立ち絵が表示されます。
 * なしの場合、攻撃、防御含め全スキル発動時に表示されます。
 * @type skill
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default floatrightfast
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~sbItemPictures:
 *
 * @param memo
 * @text メモ欄
 * @desc リスト一覧で確認しやすいようにメモを記載できます。
 * この項目は機能に一切影響しません。
 * @type string
 *
 * @param actorId
 * @text アクターID
 * @desc アクターIDです。立ち絵を定義するアクターを選択してください。
 * @type actor
 *
 * @param itemId
 * @text アイテムID
 * @desc このアイテムを使用した時に立ち絵が表示されます。
 * なしにすると全アイテム使用時に表示されます。
 * @type item
 *
 * @param stateId
 * @text ステートID
 * @desc 特定ステートで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type state
 *
 * @param switchId
 * @text スイッチID
 * @desc スイッチONで立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は空白(なし)で設定してください。
 * @type switch
 *
 * @param variableCase
 * @text 変数条件
 * @desc 変数条件で立ち絵を変更したい場合に使用します。
 * @default
 * @type struct<variableCase>
 *
 * @param hpPercentage
 * @text 残りHP％
 * @desc 残りHP％で立ち絵を変更したい場合に使用します。
 * 通常時の立ち絵は100％で設定してください。
 * @default 100
 * @min 0
 * @max 100
 * @type number
 *
 * @param imageName
 * @text 画像ファイル名
 * @desc 立ち絵として表示する画像ファイルを選択してください。
 * @dir img/pictures
 * @type file
 * @require 1
 *
 * @param origin
 * @text 原点
 * @desc 立ち絵の原点です。
 * @default upperleft
 * @type select
 * @option 左上
 * @value upperleft
 * @option 中央
 * @value center
 *
 * @param x
 * @text X座標
 * @desc 立ち絵の表示位置(X)です。
 * @default 464
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param y
 * @text Y座標
 * @desc 立ち絵の表示位置(Y)です。
 * @default 96
 * @min -9999
 * @max 9999
 * @type number
 *
 * @param scaleX
 * @text X拡大率
 * @desc 立ち絵の拡大率(X)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param scaleY
 * @text Y拡大率
 * @desc 立ち絵の拡大率(Y)です。
 * @default 100
 * @min -2000
 * @max 2000
 * @type number
 *
 * @param motion
 * @text モーション
 * @desc 再生モーションを選択してください。
 * @default floatrightfast
 * @type select
 * @option なし
 * @value none
 * @option 右からフロートイン (コマンド)
 * @value floatrightfast
 * @option 左からフロートイン (コマンド)
 * @value floatleftfast
 * @option 頷く
 * @value yes
 * @option ジャンプ
 * @value jump
 * @option 繰り返しジャンプ
 * @value jumploop
 * @option ガクガクし続ける
 * @value shakeloop
 * @option 横に揺れ続ける
 * @value noslowloop
 * @option 息づかい風
 * @value breathing
 * @option 息づかい風 (伸縮)
 * @value breathing2
 * @option 揺れる (ダメージ)
 * @value damage
 * @option 右からフロートイン (勝利)
 * @value floatright
 * @option 左からフロートイン (勝利)
 * @value floatleft
 * @option 左へスライド (攻撃)
 * @value stepleft
 * @option 右へスライド (攻撃)
 * @value stepright
 * @option 頭を下げる (防御)
 * @value headdown
 */

/*~struct~variableCase:
 *
 * @param id
 * @text 変数ID
 * @desc 条件に使用する変数IDです。
 * @type variable
 *
 * @param type
 * @text 変数条件
 * @desc 変数IDとの比較条件です。
 * @default equal
 * @type select
 * @option 一致する
 * @value equal
 * @option 以上
 * @value higher
 * @option 以下
 * @value lower
 *
 * @param value
 * @text 変数比較数値
 * @desc 変数IDと比較する数値です。
 * @default 0
 * @min -99999999
 * @max 99999999
 * @type number
 */

(() => {
  "use strict";
  const pluginName = "LL_StandingPictureBattle";

  const parameters = PluginManager.parameters(pluginName);
  const paramJsonParse = function (key, value) {
    try {
      return JSON.parse(value);
    } catch (e) {
      return value;
    }
  };

  const sbCommandPictures = String(parameters["sbCommandPictures"] || "[]");
  const sbDamagePictures = String(parameters["sbDamagePictures"] || "[]");
  const sbEvasionPictures = String(parameters["sbEvasionPictures"] || "[]");
  const sbWinPictures = String(parameters["sbWinPictures"] || "[]");
  const sbActionPictures = String(parameters["sbActionPictures"] || "[]");
  const sbItemPictures = String(parameters["sbItemPictures"] || "[]");
  const startActorType = String(parameters["startActorType"] || "none");
  const winActorType = String(parameters["winActorType"] || "lastActor");
  const hiddenEnemyWindow = eval(parameters["hiddenEnemyWindow"] || "true");
  const hiddenActorWindow = eval(parameters["hiddenActorWindow"] || "false");
  const deathBeforeStates = eval(parameters["deathBeforeStates"] || "false");

  // 反撃時の設定
  const showCounterAttack = eval(parameters["showCounterAttack"] || "true");
  const showMagicReflection = eval(parameters["showMagicReflection"] || "true");

  const sbCommandPictureLists = JSON.parse(
    JSON.stringify(sbCommandPictures, paramJsonParse)
  );
  const sbDamagePictureLists = JSON.parse(
    JSON.stringify(sbDamagePictures, paramJsonParse)
  );
  const sbEvasionPictureLists = JSON.parse(
    JSON.stringify(sbEvasionPictures, paramJsonParse)
  );
  const sbWinPictureLists = JSON.parse(
    JSON.stringify(sbWinPictures, paramJsonParse)
  );
  const sbActionPictureLists = JSON.parse(
    JSON.stringify(sbActionPictures, paramJsonParse)
  );
  const sbItemPictureLists = JSON.parse(
    JSON.stringify(sbItemPictures, paramJsonParse)
  );

  // Plugin Command
  PluginManager.registerCommand(pluginName, "setEnabled", (args) => {
    const enabled = eval(args.enabled || "true");
    $gameSystem._StandingPictureBattleDisabled = !enabled;
  });

  // 独自変数定義
  let animationCount = 0;
  let refSbPicture = false;
  let motionSbPicture = "";
  let showDamageActorId = null;
  let showActionActorId = null;
  let showEvasionActorId = null;
  let activeCommandActorId = null;
  let activeDamageActorId = null;
  let activeActionActorId = null;
  let activeActionItemId = null;
  let activeActionDataClass = null;

  // アニメーションフレーム数定義
  const animationFrame = {
    yes: 24,
    yesyes: 48,
    no: 24,
    noslow: 48,
    jump: 24,
    jumpjump: 48,
    jumploop: 48,
    shake: 1,
    shakeloop: 1,
    runleft: 1,
    runright: 1,
    damage: 1,
    floatrightfast: 12,
    floatright: 48,
    floatleftfast: 12,
    floatleft: 48,
    noslowloop: 96,
    breathing: 96,
    breathing2: 96,
    stepleft: 24,
    stepright: 24,
    headdown: 12,
    none: 0,
  };

  //-----------------------------------------------------------------------------
  // 画像ファイル名を取得
  //-----------------------------------------------------------------------------
  const getImageName = (actorId, pictureLists, itemId = null) => {
    if (!pictureLists) return;

    // アクターのステート情報を取得
    let actorStates = [];
    if (actorId) {
      actorStates = $gameActors.actor(actorId)._states;

      // 死亡時に直前のステートIDで判定するか？
      if (actorStates.indexOf(1) !== -1 && deathBeforeStates) {
        actorStates = $gameActors.actor(actorId).beforeStates();
      }
    }
    let specificPicture = null;

    // アクターIDが一致する立ち絵を検索
    pictureLists = pictureLists.filter(function (item) {
      if (Number(item.actorId) == actorId) {
        return true;
      }
    });

    // アイテムID(スキルID)が指定されているか？
    // (処理を共通化するため、ここではskillIdも便宜的にitemIdとして扱う)
    if (itemId !== null) {
      pictureLists = pictureLists.filter(function (item) {
        if (Number(item.itemId) == itemId) {
          return true;
        }
      });
    }

    // ステートにかかっているか？
    if (actorStates.length) {
      // ステートID・スイッチID・変数IDが有効な立ち絵リストを検索
      specificPicture = pictureLists.filter(function (item) {
        if (item.variableCase) {
          if (
            actorStates.indexOf(Number(item.stateId)) !== -1 &&
            $gameSwitches.value(Number(item.switchId)) &&
            ((String(item.variableCase.type) == "equal" &&
              $gameVariables.value(Number(item.variableCase.id)) ==
                Number(item.variableCase.value)) ||
              (String(item.variableCase.type) == "higher" &&
                $gameVariables.value(Number(item.variableCase.id)) >=
                  Number(item.variableCase.value)) ||
              (String(item.variableCase.type) == "lower" &&
                $gameVariables.value(Number(item.variableCase.id)) <=
                  Number(item.variableCase.value)))
          ) {
            return true;
          }
        }
      });
      if (specificPicture.length)
        return checkHpPercentage(actorId, specificPicture);
      // ステートID・スイッチIDが有効な立ち絵リストを検索
      specificPicture = pictureLists.filter(function (item) {
        if (
          actorStates.indexOf(Number(item.stateId)) !== -1 &&
          $gameSwitches.value(Number(item.switchId)) &&
          !item.variableCase
        ) {
          return true;
        }
      });
      if (specificPicture.length)
        return checkHpPercentage(actorId, specificPicture);
      // ステートID・変数IDが有効な立ち絵リストを検索
      specificPicture = pictureLists.filter(function (item) {
        if (item.variableCase) {
          if (
            actorStates.indexOf(Number(item.stateId)) !== -1 &&
            (Number(item.switchId) === 0 || !item.switchId) &&
            ((String(item.variableCase.type) == "equal" &&
              $gameVariables.value(Number(item.variableCase.id)) ==
                Number(item.variableCase.value)) ||
              (String(item.variableCase.type) == "higher" &&
                $gameVariables.value(Number(item.variableCase.id)) >=
                  Number(item.variableCase.value)) ||
              (String(item.variableCase.type) == "lower" &&
                $gameVariables.value(Number(item.variableCase.id)) <=
                  Number(item.variableCase.value)))
          ) {
            return true;
          }
        }
      });
      if (specificPicture.length)
        return checkHpPercentage(actorId, specificPicture);
      // ステートIDが有効な立ち絵リストを検索
      specificPicture = pictureLists.filter(function (item) {
        if (
          actorStates.indexOf(Number(item.stateId)) !== -1 &&
          (Number(item.switchId) === 0 || !item.switchId) &&
          !item.variableCase
        ) {
          return true;
        }
      });
      if (specificPicture.length)
        return checkHpPercentage(actorId, specificPicture);
    }

    // スイッチID・変数IDが有効な立ち絵リストを検索
    specificPicture = pictureLists.filter(function (item) {
      if (item.variableCase) {
        if (
          (Number(item.stateId) === 0 || !item.stateId) &&
          $gameSwitches.value(Number(item.switchId)) &&
          ((String(item.variableCase.type) == "equal" &&
            $gameVariables.value(Number(item.variableCase.id)) ==
              Number(item.variableCase.value)) ||
            (String(item.variableCase.type) == "higher" &&
              $gameVariables.value(Number(item.variableCase.id)) >=
                Number(item.variableCase.value)) ||
            (String(item.variableCase.type) == "lower" &&
              $gameVariables.value(Number(item.variableCase.id)) <=
                Number(item.variableCase.value)))
        ) {
          return true;
        }
      }
    });
    if (specificPicture.length)
      return checkHpPercentage(actorId, specificPicture);
    // スイッチIDが有効な立ち絵リストを検索
    specificPicture = pictureLists.filter(function (item) {
      if (
        (Number(item.stateId) === 0 || !item.stateId) &&
        $gameSwitches.value(Number(item.switchId)) &&
        !item.variableCase
      ) {
        return true;
      }
    });
    if (specificPicture.length)
      return checkHpPercentage(actorId, specificPicture);
    // 変数IDが有効な立ち絵リストを検索
    specificPicture = pictureLists.filter(function (item) {
      if (item.variableCase) {
        if (
          (Number(item.stateId) === 0 || !item.stateId) &&
          (Number(item.switchId) === 0 || !item.switchId) &&
          ((String(item.variableCase.type) == "equal" &&
            $gameVariables.value(Number(item.variableCase.id)) ==
              Number(item.variableCase.value)) ||
            (String(item.variableCase.type) == "higher" &&
              $gameVariables.value(Number(item.variableCase.id)) >=
                Number(item.variableCase.value)) ||
            (String(item.variableCase.type) == "lower" &&
              $gameVariables.value(Number(item.variableCase.id)) <=
                Number(item.variableCase.value)))
        ) {
          return true;
        }
      }
    });
    if (specificPicture.length)
      return checkHpPercentage(actorId, specificPicture);

    // 上記で見つからなかった場合、通常の立ち絵を検索
    let normalPicture = pictureLists.filter(function (item) {
      if (
        (Number(item.stateId) === 0 || !item.stateId) &&
        (Number(item.switchId) === 0 || !item.switchId) &&
        !item.variableCase
      )
        return true;
    });
    if (normalPicture.length) return checkHpPercentage(actorId, normalPicture);
  };

  const checkHpPercentage = (actorId, pictureLists) => {
    // アクターの残HP％を取得
    let hpRate = getHpRate(actorId);
    // 最もHP%が低い立ち絵を適用する
    let minHpRate = 100;
    let result = null;
    pictureLists.forEach(function (item) {
      if (
        hpRate <= Number(item.hpPercentage) &&
        minHpRate >= Number(item.hpPercentage)
      ) {
        result = item;
        minHpRate = Number(item.hpPercentage);
      } else if (!item.hpPercentage && minHpRate >= 100) {
        // プラグインパラメータが更新されていない場合、便宜的に100として扱う
        result = item;
        minHpRate = Number(item.hpPercentage);
      }
    });
    return result;
  };

  // アクターのHPレートを取得
  const getHpRate = (actorId) => {
    if (!$gameActors.actor(actorId)) return 0;
    return $gameActors.actor(actorId).mhp > 0
      ? ($gameActors.actor(actorId).hp / $gameActors.actor(actorId).mhp) * 100
      : 0;
  };

  // Battle Managerを拡張
  BattleManager.isPhase = function () {
    return this._phase;
  };

  // Game Partyを拡張
  Game_Party.prototype.aliveBattleMembers = function () {
    return this.allMembers()
      .slice(0, this.maxBattleMembers())
      .filter((actor) => actor.isAppeared())
      .filter((actor) => actor.isAlive());
  };
  Game_Party.prototype.firstBattleMember = function () {
    return this.allMembers()
      .slice(0, 1)
      .filter((actor) => actor.isAppeared());
  };
  Game_Party.prototype.randomBattleMenber = function () {
    let r = Math.randomInt(this.maxBattleMembers());
    return this.allMembers()
      .slice(r, r + 1)
      .filter((actor) => actor.isAppeared());
  };

  const _Game_Battler_performActionStart =
    Game_Battler.prototype.performActionStart;
  Game_Battler.prototype.performActionStart = function (action) {
    _Game_Battler_performActionStart.apply(this, arguments);
    // スキルIDを取得
    activeActionItemId = action._item._itemId;
    activeActionDataClass = action._item._dataClass;
    // アクターIDを取得
    showActionActorId = action._subjectActorId;
    // リフレッシュ
    activeActionActorId = null;
  };

  const _Game_Battler_performDamage = Game_Battler.prototype.performDamage;
  Game_Battler.prototype.performDamage = function () {
    _Game_Battler_performDamage.apply(this, arguments);
    // ダメージを受けたアクターIDを取得
    showDamageActorId = this._actorId;
    showEvasionActorId = null;
    // リフレッシュ
    activeDamageActorId = null;
  };

  const _Game_Battler_performEvasion = Game_Battler.prototype.performEvasion;
  Game_Battler.prototype.performEvasion = function () {
    _Game_Battler_performEvasion.apply(this, arguments);
    // アクターIDを取得
    showEvasionActorId = this._actorId;
    showDamageActorId = null;
    // リフレッシュ
    activeDamageActorId = null;
  };

  // 死亡時の直前ステートIDを保持するため、Game_BattlerBaseを拡張
  const _Game_BattlerBase_initMembers = Game_BattlerBase.prototype.initMembers;
  Game_BattlerBase.prototype.initMembers = function () {
    _Game_BattlerBase_initMembers.apply(this, arguments);

    this._beforeStates = [];
  };

  const _Game_BattlerBase_die = Game_BattlerBase.prototype.die;
  Game_BattlerBase.prototype.die = function () {
    this._beforeStates = this._states;

    _Game_BattlerBase_die.apply(this, arguments);
  };

  Game_BattlerBase.prototype.beforeStates = function () {
    return this._beforeStates;
  };

  const _BattleManager_invokeCounterAttack = BattleManager.invokeCounterAttack;
  BattleManager.invokeCounterAttack = function (subject, target) {
    _BattleManager_invokeCounterAttack.apply(this, arguments);

    if (!showCounterAttack) return;

    if (target) {
      // スキルIDを取得
      activeActionItemId = target.attackSkillId();
      activeActionDataClass = "skill";
      // アクターIDを取得
      showActionActorId = target._actorId;
      showDamageActorId = null;
      // リフレッシュ
      activeActionActorId = null;
    }
  };

  const _BattleManager_invokeMagicReflection =
    BattleManager.invokeMagicReflection;
  BattleManager.invokeMagicReflection = function (subject, target) {
    _BattleManager_invokeMagicReflection.apply(this, arguments);

    if (!showMagicReflection) return;

    if (target) {
      // スキルIDを取得
      activeActionItemId = this._action._item._itemId;
      activeActionDataClass = this._action._item._dataClass;
      // アクターIDを取得
      showActionActorId = target._actorId;
      showDamageActorId = null;
      // リフレッシュ
      activeActionActorId = null;
    }
  };

  //-----------------------------------------------------------------------------
  // ExStandingPictureBattle
  //
  // 戦闘中立ち絵を表示する独自のクラスを追加定義します。

  class ExStandingPictureBattle {
    static create(elm) {
      // 立ち絵1
      elm._spbSprite = new Sprite_LL_SPicture();
      elm.addChild(elm._spbSprite);
      // バトル開始・終了フラグをオフ
      this._battleStart = false;
      this._battleEnd = false;
    }

    static update(elm) {
      // 初期設定
      let sbPicture = null;
      let isPhase = BattleManager.isPhase();
      let isInputting = BattleManager.isInputting();
      let isEscaped = BattleManager.isEscaped();
      let isAllDead = $gameParty.isAllDead();
      let commandActor = BattleManager.actor();
      if (BattleManager._action) {
        if (BattleManager._action._subjectActorId) {
          this._lastActionActorId = BattleManager._action._subjectActorId;
        }
      }
      //-----------------------------------------------------------------------------
      // ターン開始時
      //-----------------------------------------------------------------------------
      if (isPhase == "start") {
        if (!this._battleStart) {
          // 生存しているアクターを取得
          this._aliveBattleMembers = $gameParty.aliveBattleMembers();
          // 先頭アクターIDを取得
          this._firstActorId =
            this._aliveBattleMembers.length > 0
              ? this._aliveBattleMembers[0]._actorId
              : null;
          // ランダムアクターID抽選
          this._randomActorId =
            this._aliveBattleMembers.length > 0
              ? this._aliveBattleMembers[
                  Math.floor(Math.random() * this._aliveBattleMembers.length)
                ]._actorId
              : null;
          this._battleStart = true;
        }
      }
      //-----------------------------------------------------------------------------
      // ターン終了時
      //-----------------------------------------------------------------------------
      if (isPhase == "turnEnd") {
        // 生存しているアクターを取得
        this._aliveBattleMembers = $gameParty.aliveBattleMembers();
        // 先頭アクターIDを取得
        this._firstActorId =
          this._aliveBattleMembers.length > 0
            ? this._aliveBattleMembers[0]._actorId
            : null;
        // ランダムアクターID抽選
        this._randomActorId =
          this._aliveBattleMembers.length > 0
            ? this._aliveBattleMembers[
                Math.floor(Math.random() * this._aliveBattleMembers.length)
              ]._actorId
            : null;
      }

      // 立ち絵を非表示に設定している場合、処理を中断
      if ($gameSystem._StandingPictureBattleDisabled) {
        elm._spbSprite.opacity = 0;
        return;
      }

      //-----------------------------------------------------------------------------
      // 戦闘終了時
      //-----------------------------------------------------------------------------
      if (isPhase == "battleEnd") {
        if (isEscaped) {
          // 逃走
        } else if (isAllDead) {
          // 全滅
        } else {
          if (!this._battleEnd) {
            // 生存しているアクターを取得
            let aliveBattleMembers = $gameParty.aliveBattleMembers();
            // 先頭アクターIDを取得
            this._firstActorId =
              aliveBattleMembers.length > 0
                ? aliveBattleMembers[0]._actorId
                : null;
            // ランダムアクターID抽選
            this._randomActorId =
              aliveBattleMembers.length > 0
                ? aliveBattleMembers[
                    Math.floor(Math.random() * aliveBattleMembers.length)
                  ]._actorId
                : null;
          }
          if (winActorType == "lastActor") {
            sbPicture = getImageName(
              this._lastActionActorId,
              sbWinPictureLists
            );
          } else if (winActorType == "randomActor") {
            sbPicture = getImageName(this._randomActorId, sbWinPictureLists);
          } else if (winActorType == "firstActor") {
            sbPicture = getImageName(this._firstActorId, sbWinPictureLists);
          }
          if (!this._battleEnd) {
            if (sbPicture) {
              refSbPicture = true;
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;
            }
          }
        }
        this._battleEnd = true;
      }
      //-----------------------------------------------------------------------------
      // 被ダメージ時
      //-----------------------------------------------------------------------------
      if (showDamageActorId) {
        if (isPhase == "action") {
          sbPicture = getImageName(showDamageActorId, sbDamagePictureLists);
          if (sbPicture) {
            if (activeDamageActorId != showDamageActorId) {
              activeDamageActorId = showDamageActorId;
              refSbPicture = true;
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;
            }
          }
        } else {
          showDamageActorId = null;
          sbPicture = null;
        }
      }
      //-----------------------------------------------------------------------------
      // 回避時
      //-----------------------------------------------------------------------------
      if (showEvasionActorId) {
        if (isPhase == "action") {
          sbPicture = getImageName(showEvasionActorId, sbEvasionPictureLists);
          if (sbPicture) {
            if (activeDamageActorId != showEvasionActorId) {
              activeDamageActorId = showEvasionActorId;
              refSbPicture = true;
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;
            }
          }
        } else {
          showEvasionActorId = null;
          sbPicture = null;
        }
      }
      //-----------------------------------------------------------------------------
      // アクション時
      //-----------------------------------------------------------------------------
      if (!showDamageActorId && !showEvasionActorId) {
        if (isPhase == "action") {
          // スキル発動時
          if (activeActionDataClass == "skill") {
            sbPicture = getImageName(
              showActionActorId,
              sbActionPictureLists,
              activeActionItemId
            );
            // 見つからなかった場合、スキルIDなしの立ち絵を再検索
            if (!sbPicture)
              sbPicture = getImageName(
                showActionActorId,
                sbActionPictureLists,
                0
              );
          }
          // アイテム使用時
          if (activeActionDataClass == "item") {
            sbPicture = getImageName(
              showActionActorId,
              sbItemPictureLists,
              activeActionItemId
            );
            // 見つからなかった場合、アイテムIDなしの立ち絵を再検索
            if (!sbPicture)
              sbPicture = getImageName(
                showActionActorId,
                sbItemPictureLists,
                0
              );
          }
          if (sbPicture) {
            if (activeActionActorId != showActionActorId) {
              activeActionActorId = showActionActorId;
              refSbPicture = true;
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;

              activeCommandActorId = null;
            }
          }
        } else {
          showActionActorId = null;
        }
      }
      //-----------------------------------------------------------------------------
      // 戦う or 逃げる 選択時
      //-----------------------------------------------------------------------------
      if (isPhase == "turn" || isPhase == "input") {
        if (!commandActor && isInputting) {
          let selectStartActorId = null;
          if (startActorType == "firstActor") {
            sbPicture = getImageName(this._firstActorId, sbCommandPictureLists);
            selectStartActorId = this._firstActorId;
          } else if (startActorType == "randomActor") {
            sbPicture = getImageName(
              this._randomActorId,
              sbCommandPictureLists
            );
            selectStartActorId = this._randomActorId;
          }
          if (sbPicture) {
            sbPicture = JSON.parse(JSON.stringify(sbPicture));
            if (activeCommandActorId != selectStartActorId) {
              activeCommandActorId = selectStartActorId;
              refSbPicture = true;
              // 通常
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;
            }
          }
        }
      }
      //-----------------------------------------------------------------------------
      // コマンド入力時
      //-----------------------------------------------------------------------------
      if (isPhase == "turn" || isPhase == "input") {
        if (commandActor) {
          sbPicture = getImageName(
            commandActor._actorId,
            sbCommandPictureLists
          );
          // HPレートを取得
          let hpRate =
            commandActor.mhp > 0
              ? (commandActor.hp / commandActor.mhp) * 100
              : 0;
          if (sbPicture) {
            sbPicture = JSON.parse(JSON.stringify(sbPicture));
            if (activeCommandActorId != commandActor._actorId) {
              activeCommandActorId = commandActor._actorId;
              refSbPicture = true;
              // 通常
              motionSbPicture = sbPicture.motion;
              animationCount = animationFrame[motionSbPicture];
              elm._spbSprite.opacity = 0;
            }
            // 敵選択時は非表示にする
            if (hiddenEnemyWindow) {
              if (elm._enemyWindow) {
                elm._spbSprite.visible = !elm._enemyWindow.active;
              }
            }

            // 対象アクター選択時は非表示にする
            if (hiddenActorWindow && elm._spbSprite.visible === true) {
              if (elm._actorWindow) {
                elm._spbSprite.visible = !elm._actorWindow.active;
              }
            }
          }
        }
      }

      // 立ち絵ピクチャ作成
      if (sbPicture && refSbPicture) {
        this.refresh(elm._spbSprite, sbPicture);
        refSbPicture = false;
      }

      // フェード処理
      if (sbPicture) {
        this.fadeIn(elm._spbSprite, sbPicture);
      } else {
        this.fadeOut(elm._spbSprite, sbPicture);
      }

      // 立ち絵モーション再生
      if (animationCount > 0) {
        animationCount = this.animation(
          elm._spbSprite,
          motionSbPicture,
          animationCount
        );
      }
    }

    static refresh(sSprite, sPicture) {
      sSprite.setPicture(sPicture);
      sSprite.showing = false;
      let calcScaleX = Number(sPicture.scaleX);
      let calcScaleY = Number(sPicture.scaleY);
      // 画像が読み込まれたあとに実行
      sSprite.bitmap.addLoadListener(
        function () {
          if (
            Number(sPicture.origin) != 1 &&
            String(sPicture.origin) != "center"
          ) {
            // 左上原点
            sSprite.x = Number(sPicture.x);
            sSprite.y = Number(sPicture.y);
            sSprite.originX = Number(sPicture.x);
            sSprite.originY = Number(sPicture.y);
          } else {
            // 中央原点
            sSprite.x =
              Number(sPicture.x) - (sSprite.width * calcScaleX) / 100 / 2;
            sSprite.y =
              Number(sPicture.y) - (sSprite.height * calcScaleY) / 100 / 2;
            sSprite.originX =
              Number(sPicture.x) - (sSprite.width * calcScaleX) / 100 / 2;
            sSprite.originY =
              Number(sPicture.y) - (sSprite.height * calcScaleY) / 100 / 2;
          }
          // 切替効果
          if (sSprite.opacity == 0) {
            //
          }
          sSprite.scale.x = calcScaleX / 100;
          sSprite.scale.y = calcScaleY / 100;
          sSprite.showing = true;
          // 非表示状態リセット
          sSprite.visible = true;
        }.bind(this)
      );
    }

    static fadeIn(sSprite, sPicture) {
      if (!sSprite.showing) return;
      if (sSprite.opacity >= 255) {
        sSprite.opening = false;
        sSprite.opacity = 255;
        return;
      }
      sSprite.opening = true;
      sSprite.closing = false;
      sSprite.opacity += 24;
    }

    static fadeOut(sSprite, sPicture) {
      if (sSprite.opacity == 0) {
        activeCommandActorId = null;
        activeDamageActorId = null;
        activeActionActorId = null;
        sSprite.closing = false;
        return;
      }
      sSprite.closing = true;
      if (!sPicture) {
        //sSprite.opacity = 0;
        //return;
      }
      sSprite.opacity -= 24;
    }

    static animation(sSprite, sMotion, animationCount) {
      if (!sSprite.showing) return animationCount;
      if (sMotion == "yes") {
        if (animationCount > 12) {
          sSprite.y += 2;
        } else {
          sSprite.y -= 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "yesyes") {
        if (animationCount > 36) {
          sSprite.y += 2;
        } else if (animationCount > 24) {
          sSprite.y -= 2;
        } else if (animationCount > 12) {
          sSprite.y += 2;
        } else {
          sSprite.y -= 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "no") {
        if (animationCount > 18) {
          sSprite.x += 2;
        } else if (animationCount > 6) {
          sSprite.x -= 2;
        } else {
          sSprite.x += 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "noslow") {
        if (animationCount > 36) {
          sSprite.x += 1;
        } else if (animationCount > 12) {
          sSprite.x -= 1;
        } else {
          sSprite.x += 1;
        }
        animationCount -= 1;
      }
      if (sMotion == "jump") {
        if (animationCount > 12) {
          sSprite.y -= 2;
        } else {
          sSprite.y += 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "jumpjump") {
        if (animationCount > 36) {
          sSprite.y -= 2;
        } else if (animationCount > 24) {
          sSprite.y += 2;
        } else if (animationCount > 12) {
          sSprite.y -= 2;
        } else {
          sSprite.y += 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "jumploop") {
        if (animationCount > 36) {
          sSprite.y -= 2;
        } else if (animationCount > 24) {
          sSprite.y += 2;
        }
        animationCount -= 1;
        if (animationCount == 0) animationCount = animationFrame["jumploop"];
      }
      if (sMotion == "shake") {
        if (animationCount <= 2) {
          sSprite.x -= 2;
          animationCount += 1;
        } else if (animationCount <= 4) {
          sSprite.y -= 2;
          animationCount += 1;
        } else if (animationCount <= 6) {
          sSprite.x += 4;
          sSprite.y += 4;
          animationCount += 1;
        } else if (animationCount <= 8) {
          sSprite.y -= 2;
          animationCount += 1;
        } else if (animationCount == 9) {
          sSprite.x -= 2;
          animationCount += 1;
        } else if (animationCount == 10) {
          sSprite.x -= 2;
          animationCount = 0;
        }
      }
      if (sMotion == "shakeloop") {
        if (animationCount <= 2) {
          sSprite.x -= 1;
          animationCount += 1;
        } else if (animationCount <= 4) {
          sSprite.y -= 1;
          animationCount += 1;
        } else if (animationCount <= 6) {
          sSprite.x += 2;
          sSprite.y += 2;
          animationCount += 1;
        } else if (animationCount <= 8) {
          sSprite.y -= 1;
          animationCount += 1;
        } else if (animationCount <= 10) {
          sSprite.x -= 1;
          animationCount += 1;
        }
        if (animationCount > 10) animationCount = 1;
      }
      if (sMotion == "runleft") {
        sSprite.x -= 16;
        if (sSprite.x < -2000) animationCount = 0;
      }
      if (sMotion == "runright") {
        sSprite.x += 16;
        if (sSprite.x > 2000) animationCount = 0;
      }
      //
      if (sMotion == "damage") {
        if (animationCount <= 2) {
          sSprite.x -= 4;
          animationCount += 1;
        } else if (animationCount <= 4) {
          sSprite.y -= 4;
          animationCount += 1;
        } else if (animationCount <= 6) {
          sSprite.x += 8;
          sSprite.y += 8;
          animationCount += 1;
        } else if (animationCount <= 8) {
          sSprite.y -= 4;
          animationCount += 1;
        } else if (animationCount == 9) {
          sSprite.x -= 4;
          animationCount += 1;
        } else if (animationCount == 10) {
          sSprite.x -= 4;
          animationCount = 0;
        }
      }
      if (sMotion == "floatrightfast") {
        if (animationCount == 12) {
          sSprite.x += 22;
        } else {
          sSprite.x -= 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "floatright") {
        if (animationCount == 48) {
          sSprite.x += 47;
        } else {
          sSprite.x -= 1;
        }
        animationCount -= 1;
      }
      if (sMotion == "floatleftfast") {
        if (animationCount == 12) {
          sSprite.x -= 22;
        } else {
          sSprite.x += 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "floatleft") {
        if (animationCount == 48) {
          sSprite.x -= 47;
        } else {
          sSprite.x += 1;
        }
        animationCount -= 1;
      }
      if (sMotion == "noslowloop") {
        if (animationCount > 72) {
          sSprite.x += 0.25;
        } else if (animationCount > 24) {
          sSprite.x -= 0.25;
        } else {
          sSprite.x += 0.25;
        }
        animationCount -= 1;
        if (animationCount == 0) animationCount = animationFrame["noslowloop"];
      }
      if (sMotion == "breathing") {
        if (animationCount > 72) {
          sSprite.y += 0.5;
        } else if (animationCount > 48) {
          sSprite.y -= 0.5;
        } else {
        }
        animationCount -= 1;
        if (animationCount == 0) animationCount = animationFrame["breathing"];
      }
      if (sMotion == "breathing2") {
        if (animationCount > 48) {
          // sSprite.anchor.y = 1;
          sSprite.y -= sSprite.height * 0.0003;
          sSprite.scale.y += 0.0003;
        } else {
          // sSprite.anchor.y = 1;
          sSprite.y += sSprite.height * 0.0003;
          sSprite.scale.y -= 0.0003;
        }
        animationCount -= 1;
        if (animationCount == 0) animationCount = animationFrame["breathing2"];
      }
      if (sMotion == "stepleft") {
        if (animationCount > 12) {
          sSprite.x -= 2;
        } else {
          sSprite.x += 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "stepright") {
        if (animationCount > 12) {
          sSprite.x += 2;
        } else {
          sSprite.x -= 2;
        }
        animationCount -= 1;
      }
      if (sMotion == "headdown") {
        sSprite.y += 2;
        animationCount -= 1;
      }
      return animationCount;
    }
  }

  const _Scene_Battle_update = Scene_Battle.prototype.update;
  Scene_Battle.prototype.update = function () {
    _Scene_Battle_update.apply(this, arguments);
    ExStandingPictureBattle.update(this);
  };

  const _Scene_Battle_createSpriteset = Scene_Battle.prototype.createSpriteset;
  Scene_Battle.prototype.createSpriteset = function () {
    _Scene_Battle_createSpriteset.apply(this, arguments);
    ExStandingPictureBattle.create(this);
  };

  //-----------------------------------------------------------------------------
  // Sprite_LL_SPicture
  //
  // 立ち絵を表示するための独自のスプライトを追加定義します。

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

  Sprite_LL_SPicture.prototype = Object.create(Sprite.prototype);
  Sprite_LL_SPicture.prototype.constructor = Sprite_LL_SPicture;

  Sprite_LL_SPicture.prototype.initialize = function () {
    Sprite.prototype.initialize.call(this);

    this.bitmap = null;
    this.opacity = 0;
    this.opening = false;
    this.closing = false;
    this.originX = 0;
    this.originY = 0;
    this.showing = false;

    this.setOverlayBitmap();
    this.initMembers();
  };

  Sprite_LL_SPicture.prototype.setOverlayBitmap = function () {
    //
  };

  Sprite_LL_SPicture.prototype.initMembers = function () {
    //
  };

  Sprite_LL_SPicture.prototype.update = function () {
    Sprite.prototype.update.call(this);
  };

  Sprite_LL_SPicture.prototype.setPicture = function (sPicture) {
    // ベース画像
    this.bitmap = null;
    this.bitmap = ImageManager.loadPicture(sPicture.imageName);
  };

  Sprite_LL_SPicture.prototype.setBlendColor = function (color) {
    Sprite.prototype.setBlendColor.call(this, color);
  };

  Sprite_LL_SPicture.prototype.setColorTone = function (tone) {
    Sprite.prototype.setColorTone.call(this, tone);
  };

  Sprite_LL_SPicture.prototype.setBlendMode = function (mode) {
    this.blendMode = mode;
  };
})();

repo_name: dazed/translations

license: unknown


code:
//=============================================================================
// RPGツクールMZ - LL_VariableWindow.js v1.0.0
//-----------------------------------------------------------------------------
// ルルの教会 (Lulu's Church)
// https://nine-yusha.com/
//
// URL below for license details.
// https://nine-yusha.com/plugin/
//=============================================================================

/*:
 * @target MZ
 * @plugindesc 変数を画面にウィンドウで表示します。
 * @author ルルの教会
 * @url https://nine-yusha.com/plugin-variablewindow/
 *
 * @help LL_VariableWindow.js
 *
 * 変数を画面にウィンドウで表示します。
 * ウィンドウは同時に4つまで表示することができます。
 *
 * プラグインコマンド:
 *    ウィンドウを表示: 変数をウィンドウで表示します。
 *    ウィンドウを消去: 表示しているウィンドウを消去します。
 *
 * 利用規約:
 *   ・著作権表記は必要ございません。
 *   ・利用するにあたり報告の必要は特にございません。
 *   ・商用・非商用問いません。
 *   ・R18作品にも使用制限はありません。
 *   ・ゲームに合わせて自由に改変していただいて問題ございません。
 *   ・プラグイン素材としての再配布（改変後含む）は禁止させていただきます。
 *
 * 作者: ルルの教会
 * 作成日: 2022/5/14
 *
 * @command showWindow
 * @text ウィンドウを表示
 * @desc 変数の値をウィンドウで表示します。
 *
 * @arg windowId
 * @text ウィンドウ番号
 * @desc どのウィンドウ番号に表示するか選択します。
 * 同時に4つまで表示することが可能です。
 * @type select
 * @default 1
 * @option 1
 * @value 1
 * @option 2
 * @value 2
 * @option 3
 * @value 3
 * @option 4
 * @value 4
 *
 * @arg variableId
 * @text 変数
 * @desc ウィンドウに表示する変数です。
 * @type variable
 *
 * @arg windowX
 * @text X座標
 * @desc ウィンドウの表示位置(X)です。(autoと入力すると中央表示)
 * @default 408
 * @type string
 *
 * @arg windowY
 * @text Y座標
 * @desc ウィンドウの表示位置(Y)です。(autoと入力すると中央表示)
 * @default 60
 * @type string
 *
 * @arg windowWidth
 * @text 横幅
 * @desc ウィンドウの横幅です。
 * @default 400
 * @type number
 *
 * @command hideWindow
 * @text ウィンドウを消去
 * @desc 表示したウィンドウを消去します。
 *
 * @arg windowId
 * @text ウィンドウ番号
 * @desc どのウィンドウ番号を消去するか選択します。
 * @type select
 * @default 1
 * @option 1
 * @value 1
 * @option 2
 * @value 2
 * @option 3
 * @value 3
 * @option 4
 * @value 4
 */

(function () {
  "use strict";
  var pluginName = "LL_VariableWindow";
  var parameters = PluginManager.parameters(pluginName);

  // 変数名の横幅割合
  const variableWindowLabelWidth = 0.6;

  // ウィンドウを表示
  PluginManager.registerCommand(pluginName, "showWindow", (args) => {
    const windowId = Number(args.windowId || 1);
    const variableId = Number(args.variableId || 0);
    const x = String(args.windowX || 0);
    const y = String(args.windowY || 0);
    const width = Number(args.windowWidth || 400);

    // 旧セーブデータ対策
    if (!$gameSystem._LL_VariableWindow) {
      $gameSystem._LL_VariableWindow = {};
      $gameSystem._LL_VariableWindow[1] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[2] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[3] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[4] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
    }

    $gameSystem._LL_VariableWindow[windowId] = {
      variableId: variableId,
      x: x,
      y: y,
      width: width,
    };
  });

  // ウィンドウを消去
  PluginManager.registerCommand(pluginName, "hideWindow", (args) => {
    const windowId = Number(args.windowId || 1);

    // 旧セーブデータ対策
    if (!$gameSystem._LL_VariableWindow) {
      $gameSystem._LL_VariableWindow = {};
      $gameSystem._LL_VariableWindow[1] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[2] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[3] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
      $gameSystem._LL_VariableWindow[4] = {
        variableId: null,
        x: 0,
        y: 0,
        width: 0,
      };
    }

    $gameSystem._LL_VariableWindow[windowId] = {
      variableId: null,
      x: 0,
      y: 0,
      width: 0,
    };
  });

  //-----------------------------------------------------------------------------
  // Game_System
  //
  // 変数ウィンドウ制御用の独自配列を追加定義します。

  const _Game_System_initialize = Game_System.prototype.initialize;
  Game_System.prototype.initialize = function () {
    _Game_System_initialize.apply(this, arguments);

    this._LL_VariableWindow = {};
    this._LL_VariableWindow[1] = { variableId: null, x: 0, y: 0, width: 0 };
    this._LL_VariableWindow[2] = { variableId: null, x: 0, y: 0, width: 0 };
    this._LL_VariableWindow[3] = { variableId: null, x: 0, y: 0, width: 0 };
    this._LL_VariableWindow[4] = { variableId: null, x: 0, y: 0, width: 0 };
  };

  //-----------------------------------------------------------------------------
  // Scene_Map
  //

  const _Scene_Map_stop = Scene_Map.prototype.stop;
  Scene_Map.prototype.stop = function () {
    this._exVariableWindow1.hide();
    this._exVariableWindow2.hide();
    this._exVariableWindow3.hide();
    this._exVariableWindow4.hide();
    _Scene_Map_stop.apply(this, arguments);
  };

  const _Scene_Map_terminate = Scene_Map.prototype.terminate;
  Scene_Map.prototype.terminate = function () {
    _Scene_Map_terminate.apply(this, arguments);
    if (!SceneManager.isNextScene(Scene_Battle)) {
      this._exVariableWindow1.hide();
      this._exVariableWindow2.hide();
      this._exVariableWindow3.hide();
      this._exVariableWindow4.hide();
    }
  };

  const _Scene_Map_createAllWindows = Scene_Map.prototype.createAllWindows;
  Scene_Map.prototype.createAllWindows = function () {
    _Scene_Map_createAllWindows.apply(this, arguments);
    this.createExVariableWindow();
  };

  Scene_Map.prototype.createExVariableWindow = function () {
    this._exVariableWindow1 = new Window_ExVariableWindow();
    this._exVariableWindow1.setWindowId(1);
    this.addWindow(this._exVariableWindow1);
    this._exVariableWindow2 = new Window_ExVariableWindow();
    this._exVariableWindow2.setWindowId(2);
    this.addWindow(this._exVariableWindow2);
    this._exVariableWindow3 = new Window_ExVariableWindow();
    this._exVariableWindow3.setWindowId(3);
    this.addWindow(this._exVariableWindow3);
    this._exVariableWindow4 = new Window_ExVariableWindow();
    this._exVariableWindow4.setWindowId(4);
    this.addWindow(this._exVariableWindow4);
  };

  const _Scene_Map_callMenu = Scene_Map.prototype.callMenu;
  Scene_Map.prototype.callMenu = function () {
    _Scene_Map_callMenu.apply(this, arguments);
    this._exVariableWindow1.hide();
    this._exVariableWindow2.hide();
    this._exVariableWindow3.hide();
    this._exVariableWindow4.hide();
  };

  //-----------------------------------------------------------------------------
  // Window_ExVariableWindow
  //
  // 変数を表示するウィンドウです。

  function Window_ExVariableWindow() {
    this.initialize(...arguments);
  }

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

  Window_ExVariableWindow.prototype.initialize = function () {
    const rect = new Rectangle(0, 0, Graphics.boxWidth, Graphics.boxHeight);
    Window_Base.prototype.initialize.call(this, rect);

    this.width = 0;
    this.height = 0;
    this._windowId = null;
  };

  Window_ExVariableWindow.prototype.setWindowId = function (id) {
    this._windowId = id;
  };

  Window_ExVariableWindow.prototype.update = function () {
    Window_Base.prototype.update.call(this);

    this.refresh();
  };

  Window_ExVariableWindow.prototype.windowWidth = function () {
    if ($gameSystem._LL_VariableWindow) {
      return $gameSystem._LL_VariableWindow[this._windowId].width;
    }
    return 400;
  };

  Window_ExVariableWindow.prototype.labelWidth = function () {
    return Math.floor(this.windowWidth() * variableWindowLabelWidth);
  };

  Window_ExVariableWindow.prototype.windowHeight = function () {
    return this.fittingHeight(1);
  };

  Window_ExVariableWindow.prototype.getVariableId = function () {
    if ($gameSystem._LL_VariableWindow) {
      return $gameSystem._LL_VariableWindow[this._windowId].variableId;
    }
    return null;
  };

  Window_ExVariableWindow.prototype.getX = function () {
    if ($gameSystem._LL_VariableWindow) {
      return $gameSystem._LL_VariableWindow[this._windowId].x;
    }
    return 0;
  };

  Window_ExVariableWindow.prototype.getY = function () {
    if ($gameSystem._LL_VariableWindow) {
      return $gameSystem._LL_VariableWindow[this._windowId].y;
    }
    return 0;
  };

  Window_ExVariableWindow.prototype.refresh = function () {
    if (this.getVariableId()) {
      this.width = this.windowWidth();
      this.height = this.windowHeight();
      if (this.getX() === "auto") {
        this.x = (Graphics.boxWidth - this.windowWidth()) / 2;
      } else {
        this.x = Number(this.getX() || 0);
      }
      if (this.getY() === "auto") {
        this.y = (Graphics.boxHeight - this.windowHeight()) / 2;
      } else {
        this.y = Number(this.getY() || 0);
      }

      this.contents.clear();
      this.changeTextColor(this.systemColor());
      this.drawText(
        $dataSystem.variables[this.getVariableId()],
        this.itemPadding(),
        0,
        this.labelWidth()
      );
      this.resetTextColor();
      this.drawText(
        $gameVariables.value(this.getVariableId()),
        this.labelWidth() + this.itemPadding(),
        0,
        this.innerWidth - this.labelWidth() - this.itemPadding() * 2,
        "right"
      );
    } else {
      this.width = 0;
      this.height = 0;
    }
  };
})();


code:
/*:
 * @target MZ
 * @url https://raw.githubusercontent.com/munokura/MNKR-MZ-plugins/master/MNKR_HenshinMZ.js
 * @plugindesc プラグインコマンドでアクターを入れ替えられます。
 * @author munokura
 *
 * @help
 * プラグインコマンドでアクターを入れ替えられます。
 * パーティの並び順がそのままで入れ替わります。
 *
 * マップでも戦闘中でも入れ替えられます。
 * 主人公の入換や変身を表現する等への使用を想定しています。
 *
 *
 * プラグインコマンド
 * henshin 変身前アクターID 変身後アクターID
 *
 * 使用例
 * henshin 1 8
 * ID1のアクターがID8のアクターと入れ替わります。
 *
 * 注意点
 * 下記の状況では、何も起こりません。
 * - パーティに変身前のアクターがいない場合
 * - パーティに変身後のアクターがいる場合
 *
 *
 * 利用規約:
 *   MITライセンスです。
 *   https://licenses.opensource.jp/MIT/MIT.html
 *   作者に無断で改変、再配布が可能で、
 *   利用形態（商用、18禁利用等）についても制限はありません。
 *
 *
 * @command henshin
 * @text アクター入れ替え
 * @desc アクターを並び順を変えずに入れ替えます。
 *
 * @arg ActorId1
 * @text 入換前のアクターID
 * @desc 入換前のアクターIDを指定します。
 * @type actor
 * @default
 *
 * @arg ActorId2
 * @text 入換後のアクターID
 * @desc 入換後のアクターIDを指定します。
 * @type actor
 * @default
 */


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

/*:
 * @target MV MZ
 * @plugindesc Extend the functionality of your choices.
 * @author Mokusei Penguin
 * @url
 *
 * @help [version 4.3.3]
 * This plugin is for RPG Maker MV and MZ.
 *
 * ▼ Plugin command
 *  - 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.
 *  - It is basically preferable to execute the plugin command before
 *    [Show Choices].
 *  - If you want to use the plug-in command while the message window is
 *    displayed, execute it before [Display text].
 *
 *  〇 MV / MZ
 *
 *  〇 ChoicePos x y row  / choicePos
 *       x   : X coordinate of choice window
 *       y   : Y coordinate of choice window
 *       row : The number of lines in the choice window. Show all if not set
 *   - Specify the position (x, y) and the number of rows of the next choice
 *     to display.
 *
 *  〇 ChoiceVariableId varId  / choiceVariableId
 *       varId : Variable number
 *   - Set the default position of the next choice to display to the value of
 *     the variable.
 *   - In addition, put the current cursor position in a variable.
 *   - The cursor position is 0 to 5 for the first option from the top,
 *     10 to 15 for the next option, and +10 for each option.
 *
 *  〇 ChoiceRect x y width height  / choiceRect
 *       x      : X coordinate
 *       y      : Y coordinate
 *       width  : width
 *       height : height
 *   - Specify the coordinates and size of the next choice to display.
 *   - For items that have not been set or for which -1 is specified,
 *     normal values will be applied.
 *
 *  〇 ChoiceInMessage  / ChoiceInMessage
 *   - The next choice to display is displayed in the message window.
 *   - This function will not work unless it is used in combination with
 *     [Display Text].
 *   - Please execute before [Display text].
 *
 * ▼ More choices
 *  - If you place the event command [Display Choices] in succession,
 *    they will be combined into one choice.
 *  - If you don't want to put them together, you can separate them as usual by
 *    inserting annotations in between.
 *  - For the "default" process, the one set other than none is applied.
 *  - For the "Cancel" process, the ones other than prohibited are applied.
 *  - In both cases, the setting of the option that follows takes precedence.
 *  - For "Background" and "Window position", the settings of the options that
 *    follow are applied.
 *
 * ▼ Setting conditions for displaying items
 *  - If you enter
 *      if(condition)
 *    in the text of the choice and the condition becomes false,
 *    the item will not be displayed.
 *  - The operation when the "Default" item is not displayed can be set in the
 *    [Disabled Index] of the plug-in parameter.
 *  - If the "Cancel" item is not displayed, the same processing as prohibition
 *    is performed.
 *  - Within the condition, you can refer to the switch with "s" and
 *    the variable with "v".
 *     Example: When set to if(s[1])
 *                => Switch No. 1 is ON for display and OFF for non-display.
 *              When set to if(!s[2])
 *                => Switch 2 is displayed when it is OFF,
 *                   and is hidden when it is ON.
 *              When set to if(v[5]>0)
 *                => Display if variable 5 is greater than 0,
 *                   hide if variable 5 is less than 0.
 *
 *     Inequalities that can be used in variables
 *       === : equal
 *       !== : Not equal
 *       <   : Smaller
 *       <=  : Less than or equal to
 *       >   : Greater
 *       >=  : Greater than or equal to
 *
 * ▼ Setting conditions for displaying items semi-transparently
 *  - Enter
 *      en(condition)
 *    in the text of the choice, and if the condition is false,
 *    the item will be displayed semi-transparently.
 *  - Items that are semi-transparent cannot be selected.
 *  - The conditions are the same as "Setting the conditions for displaying
 *    items" above.
 *  - If the "Cancel" item is semi-transparent, you cannot cancel it.
 *
 * ▼ Display help message
 *  - You can put
 *      ChoiceHelp
 *    in the [Comment] below each choice item to indicate the following text
 *    as a help message when you hover over it.
 *  - Help messages use the same functionality as View Text, so you can use
 *    control characters. (\! And \^ cannot be used)
 *  - The above command name can be changed with the plugin parameter.
 *
 * ================================
 * Mail : wood_penguin＠yahoo.co.jp (＠ is half-width)
 * Blog : http://woodpenguin.blog.fc2.com/
 * License : MIT license
 *
 *  @command choicePos
 *      @desc Specify the position and number of lines for the next choice to display.
 *      @arg x
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default 0
 *      @arg y
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default 0
 *      @arg row
 *          @desc 0: Show all
 *          @type number
 *              @min 0
 *              @max 99
 *          @default 0
 *
 *
 *  @command choiceVariableId
 *      @desc Set the default position of the next choice to display to the value of the variable. In addition, put the current cursor position in a variable.
 *      @arg varId
 *          @desc
 *          @type variable
 *          @default 0
 *
 *  @command choiceRect
 *      @desc Specify the coordinates and size of the next choice to display.
 * Normal values are applied to unset items.
 *      @arg x
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg y
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg width
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg height
 *          @desc -1: Default
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *
 *  @command choiceInMessage
 *      @desc The next choice to display is displayed in the message window.
 * It will not work unless it is used in combination with [Display text].
 *
 *
 *  @param Max Page Row
 *      @desc Maximum number of lines displayed on one page
 *      @type number
 *          @min 1
 *          @max 99
 *      @default 6
 *
 *  @param Disabled Position
 *      @desc Cursor position when the default choice is not displayed
 *      @type select
 *          @option none
 *          @option top
 *      @default none
 *
 *  @param Choice Help Commands
 *      @desc
 *      @type string[]
 *      @default ["ChoiceHelp","<ChoiceHelp>"]
 *
 */

/*:ja
 * @target MV MZ
 * @plugindesc 選択肢の機能を拡張します。
 * @author 木星ペンギン
 * @url
 *
 * @help [version 4.3.3]
 * このプラグインはRPGツクールMVおよびMZ用です。
 *
 * ▼ プラグインコマンド
 *  - MVでは数値を入力する項目で v[N] と記述することで変数N番を参照します。
 *  - MZでは数値を入力する項目で、テキストを選択して v[N] と記述することで
 *    変数N番を参照します。
 *  - プラグインコマンドは基本的に[選択肢の表示]の前に実行するのが好ましいです。
 *  - メッセージウィンドウを表示したままプラグインコマンドを使いたい場合、
 *    [文章の表示]の前に実行してください。
 *
 *  〇 MV / MZ
 *
 *  〇 ChoicePos x y row  / 選択肢位置設定
 *       x   : 選択肢ウィンドウのX座標
 *       y   : 選択肢ウィンドウのY座標
 *       row : 選択肢ウィンドウの行数。未設定の場合はすべて表示
 *   - 次に表示する選択肢の位置(x,y)と行数(row)指定します。
 *
 *  〇 ChoiceVariableId varId  / カーソル位置設定
 *       varId : 変数番号
 *   - 次に表示する選択肢のデフォルト位置を変数の値にします。
 *   - さらに現在のカーソル位置を変数に入れます。
 *   - カーソル位置は最初の選択肢が上から0～5、次の選択肢は10～15と、
 *     選択肢毎に+10されます。
 *
 *  〇 ChoiceRect x y width height  / 選択肢サイズ設定
 *       x      : X座標
 *       y      : Y座標
 *       width  : 幅
 *       height : 高さ
 *   - 次に表示する選択肢の座標とサイズを指定します。
 *   - 未設定もしくは-1を指定した項目は、通常の値が適用されます。
 *
 *  〇 ChoiceInMessage  / メッセージ内表示
 *   - 次に表示する選択肢をメッセージウィンドウ内に表示させます。
 *   - この機能は[文章の表示]と併用しなければ機能しません。
 *   - [文章の表示]の前に実行してください。
 *
 * ▼ 選択肢を増やす
 *  - イベントコマンド『選択肢の表示』を続けて配置すると
 *    一つの選択肢にまとめられます。
 *  - まとめたくない場合は、間に注釈などを入れることで
 *    通常通り分けることができます。
 *  - 『デフォルト』の処理は、なし以外を設定したものが適用されます。
 *  - 『キャンセル』の処理は、禁止以外を設定したものが適用されます。
 *  - どちらも後にある選択肢の設定が優先されます。
 *  - 『背景』と『ウィンドウ位置』は後にある選択肢の設定が適用されます。
 *
 * ▼ 項目が表示される条件の設定
 *  - 選択肢の文章中に
 *      if(条件)
 *    と入れ、その条件が偽になると項目が表示されなくなります。
 *  - 『デフォルト』の項目が表示されない場合の動作は、
 *    プラグインパラメータの[Disabled Index]にて設定できます。
 *  - 『キャンセル』の項目が表示されない場合、禁止と同じ処理をします。
 *  - 条件内では s でスイッチ、v で変数を参照できます。
 *     例：if(s[1]) とした場合
 *          => スイッチ１番がONで表示、OFFで非表示。
 *        if(!s[2]) とした場合
 *          => スイッチ２番がOFFで表示、ONで非表示。
 *        if(v[5]>0) とした場合
 *          => 変数５番が0より大きければ表示、0以下で非表示。
 *
 *     変数で使える不等号
 *       === : 等しい
 *       !== : 等しくない
 *       <   : より小さい
 *       <=  : より小さいまたは等しい
 *       >   : より大きい
 *       >=  : より大きいまたは等しい
 *
 * ▼ 項目を半透明で表示する条件の設定
 *  - 選択肢の文章中に
 *      en(条件)
 *    と入れ、その条件が偽になると項目が半透明で表示されます。
 *  - 半透明となった項目は選択できなくなります。
 *  - 条件は上の『項目が表示される条件の設定』と同じです。
 *  - 『キャンセル』の項目が半透明の場合、キャンセルできなくなります。
 *
 * ▼ ヘルプメッセージの表示
 *  - 各選択肢項目の下に[注釈]で
 *      選択肢ヘルプ
 *    と入れると、続きの文章をヘルプメッセージとしてカーソルを合わせたときに
 *    標示させることができます。
 *  - ヘルプメッセージは[文章の表示]と同じ機能を使っているため、
 *    制御文字が使用できます。(\!と\^は使用できません)
 *  - 上記のコマンド名はプラグインパラメータで変更できます。
 *
 * ================================
 * Mail : wood_penguin＠yahoo.co.jp (＠は半角)
 * Blog : http://woodpenguin.blog.fc2.com/
 * License : MIT license
 *
 *  @command choicePos
 *      @text 選択肢位置設定
 *      @desc 次に表示する選択肢の位置と行数を指定します。
 *      @arg x
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default 0
 *      @arg y
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default 0
 *       @arg row
 *          @text 行数
 *          @desc 0: 全て表示
 *          @type number
 *              @min 0
 *              @max 99
 *          @default 0
 *
 *  @command choiceVariableId
 *      @text カーソル位置設定
 *      @desc 次に表示する選択肢のデフォルト位置を変数の値にします。
 * さらに現在のカーソル位置を変数に入れます。
 *      @arg varId
 *          @text 変数
 *          @desc
 *          @type variable
 *          @default 0
 *
 *  @command choiceRect
 *      @text 選択肢サイズ設定
 *      @desc 次に表示する選択肢の座標とサイズを指定します。
 * 未設定の項目は通常の値が適用されます。
 *      @arg x
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg y
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg width
 *          @text 幅
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *      @arg height
 *          @text 高さ
 *          @desc -1: デフォルト
 *          @type number
 *              @min -1
 *              @max 9999
 *          @default
 *
 *  @command choiceInMessage
 *      @text メッセージ内表示
 *      @desc 次に表示する選択肢をメッセージウィンドウ内に表示させます。
 * [文章の表示]と併用しなければ機能しません。
 *
 *
 *  @param Max Page Row
 *      @text 最大表示行数
 *      @desc 1ページに表示される最大行数
 *      @type number
 *          @min 1
 *          @max 99
 *      @default 6
 *
 *  @param Disabled Position
 *      @text 無効時のカーソル位置
 *      @desc [デフォルト]となる選択肢が表示されない場合のカーソル位置
 *      @type select
 *          @option なし
 *              @value none
 *          @option 先頭
 *              @value top
 *      @default none
 *
 *  @param Choice Help Commands
 *      @text [選択肢ヘルプ]呼び出し名
 *      @desc
 *      @type string[]
 *      @default ["ChoiceHelp","<ChoiceHelp>","選択肢ヘルプ","<選択肢ヘルプ>"]
 *
 */

(() => {
  "use strict";

  const pluginName = "MPP_ChoiceEX";

  // Plugin Parameters
  const parameters = PluginManager.parameters(pluginName);
  const param_MaxPageRow = Number(parameters["Max Page Row"] || 6);
  const param_DisabledPosition = parameters["Disabled Position"] || "none";
  const param_ChoiceHelpCommands = JSON.parse(
    parameters["Choice Help Commands"] || "[]"
  );

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

  // JsExtensions 代替
  const MathExt = (() => {
    // Number.prototype.clamp と違い、下限優先
    const clamp = (x, min, max) => Math.max(Math.min(x, max), min);
    const mod = (x, n) => ((x % n) + n) % n;
    return { clamp, mod };
  })();

  //-------------------------------------------------------------------------
  // PluginManager

  if (!PluginManager.registerCommand) {
    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 _registerCommand =
      PluginManager.registerCommand || PluginManager.registerCommandMV;

    _registerCommand.call(PluginManager, pluginName, "choicePos", (args) => {
      const x = PluginManager.mppValue(args.x);
      const y = PluginManager.mppValue(args.y);
      const row = PluginManager.mppValue(args.row) || 99;
      $gameMessage.setChoicePos(x, y, row);
    });

    _registerCommand.call(
      PluginManager,
      pluginName,
      "choiceVariableId",
      (args) => {
        const variableId = PluginManager.mppValue(args.varId);
        $gameMessage.setChoiceVariableId(variableId);
      }
    );

    _registerCommand.call(PluginManager, pluginName, "choiceRect", (args) => {
      const x = args.x ? PluginManager.mppValue(args.x) : -1;
      const y = args.y ? PluginManager.mppValue(args.y) : -1;
      const width = args.width ? PluginManager.mppValue(args.width) : -1;
      const height = args.height ? PluginManager.mppValue(args.height) : -1;
      $gameMessage.setChoiceRect(x, y, width, height);
    });

    _registerCommand.call(PluginManager, pluginName, "choiceInMessage", () => {
      $gameMessage.requestChoiceInMessage();
    });
  }

  PluginManager.mppValue = function (value) {
    const match = /^V\[(\d+)\]$/i.exec(value);
    return match ? $gameVariables.value(+match[1]) : +value;
  };

  //-------------------------------------------------------------------------
  // Game_Message

  Object.defineProperties(Game_Message.prototype, {
    choiceX: {
      get() {
        return this._choiceX;
      },
      configurable: true,
    },
    choiceY: {
      get() {
        return this._choiceY;
      },
      configurable: true,
    },
    choiceWidth: {
      get() {
        return this._choiceWidth;
      },
      configurable: true,
    },
    choiceHeight: {
      get() {
        return this._choiceHeight;
      },
      configurable: true,
    },
  });

  const _Game_Message_clear = Game_Message.prototype.clear;
  Game_Message.prototype.clear = function () {
    _Game_Message_clear.apply(this, arguments);
    this._choiceEnables = [];
    this._choiceResults = [];
    this._helpTexts = [];
    this._choiceX = -1;
    this._choiceY = -1;
    this._choiceWidth = -1;
    this._choiceHeight = -1;
    this._choiceMaxRow = param_MaxPageRow;
    this._choiceVariableId = 0;
    this._choiceInMessage = false;
  };

  Game_Message.prototype.choiceMaxRow = function () {
    return this._choiceMaxRow;
  };

  Game_Message.prototype.setTexts = function (texts) {
    this._texts = texts;
  };

  Game_Message.prototype.setChoiceEnables = function (enables) {
    this._choiceEnables = enables;
  };

  Game_Message.prototype.choiceEnables = function () {
    return this._choiceEnables;
  };

  Game_Message.prototype.setChoiceResults = function (results) {
    this._choiceResults = results;
  };

  Game_Message.prototype.choiceResults = function () {
    return this._choiceResults;
  };

  Game_Message.prototype.setChoiceHelpTexts = function (texts) {
    this._helpTexts = texts;
  };

  Game_Message.prototype.isChoiceHelp = function () {
    return !this._choiceInMessage && this._helpTexts.length > 0;
  };

  Game_Message.prototype.helpTexts = function () {
    return this._helpTexts;
  };

  Game_Message.prototype.setChoicePos = function (x, y, row) {
    this._choiceX = x;
    this._choiceY = y;
    this._choiceWidth = -1;
    this._choiceHeight = -1;
    this._choiceMaxRow = row;
  };

  Game_Message.prototype.setChoiceRect = function (x, y, width, height) {
    this._choiceX = x;
    this._choiceY = y;
    this._choiceWidth = width;
    this._choiceHeight = height;
  };

  Game_Message.prototype.setChoiceVariableId = function (id) {
    this._choiceVariableId = id;
  };

  Game_Message.prototype.lowerChoiceHeight = function (height) {
    this._choiceY += height;
    this._choiceHeight -= height;
  };

  Game_Message.prototype.requestChoiceInMessage = function () {
    this._choiceInMessage = true;
  };

  Game_Message.prototype.choiceVariableId = function () {
    return this._choiceVariableId;
  };

  Game_Message.prototype.isChoiceInMessage = function () {
    return this._choiceInMessage;
  };

  //-----------------------------------------------------------------------------
  // Game_Interpreter

  Game_Interpreter.prototype.setupChoices = function (params) {
    const data = {
      choices: [],
      enables: [],
      results: [],
      helpTexts: [],
      cancelType: -1,
      defaultType: -1,
      positionType: 0,
      background: 0,
    };
    this.addChoices(params, this._index, data, 0);
    if (data.choices.length > 0) {
      const helpTexts = this.choiceHelpTexts(data);
      const cancelType = this.choiceCancelType(data);
      const defaultType = this.choiceDefaultType(data);
      $gameMessage.setChoices(data.choices, defaultType, cancelType);
      $gameMessage.setChoiceEnables(data.enables);
      $gameMessage.setChoiceResults(data.results);
      $gameMessage.setChoiceHelpTexts(helpTexts);
      $gameMessage.setChoiceBackground(data.background);
      $gameMessage.setChoicePositionType(data.positionType);
      $gameMessage.setChoiceCallback((n) => {
        this._branch[this._indent] = n < 0 ? data.cancelType : data.results[n];
      });
    } else {
      this._branch[this._indent] = -1;
    }
  };

  Game_Interpreter.prototype.addChoices = function (params, index, data, d) {
    const choices = [...params[0]];
    const cancelType = params[1] < choices.length ? params[1] : -2;
    const defaultType = params[2] || 0;
    const nextCommand = this.nextCommandOfChoice(index + 1);
    this.checkChoiceConditions(choices, data, d);
    if (cancelType !== -1) data.cancelType = cancelType + d;
    if (defaultType >= 0) data.defaultType = defaultType + d;
    data.positionType = params.length > 3 ? params[3] : 2;
    data.background = params[4] || 0;
    this.setupHelpText(index + 1, data, d);
    if (nextCommand && nextCommand.code === 102) {
      const nextIndex = this._list.indexOf(nextCommand);
      this.addChoices(nextCommand.parameters, nextIndex, data, d + 10);
    }
  };

  Game_Interpreter.prototype.checkChoiceConditions = function (
    choices,
    data,
    d
  ) {
    const regIf = /\s?if\((.+?)\)/;
    const regEn = /\s?en\((.+?)\)/;
    for (const [i, text] of choices.entries()) {
      if (this.meetsChoiceConditions(text, regIf)) {
        const realText = text.replace(regIf, "").replace(regEn, "");
        data.choices.push(realText);
        data.enables.push(this.meetsChoiceConditions(text, regEn));
        data.results.push(i + d);
      }
    }
  };

  Game_Interpreter.prototype.meetsChoiceConditions = function (text, reg) {
    const match = reg.exec(text);
    return !match || this.evalChoice(match[1]);
  };

  Game_Interpreter.prototype.evalChoice = function (condition) {
    try {
      const s = $gameSwitches._data;
      const realCondition = condition.replace(/V\[(\d+)\]/gi, (_, n) =>
        $gameVariables.value(+n)
      );
      return !!eval(realCondition);
    } catch (e) {
      console.log("条件エラー \n " + condition);
      return true;
    }
  };

  Game_Interpreter.prototype.setupHelpText = function (index, data, d) {
    for (const [i, command] of this._list.slice(index).entries()) {
      if (command.indent === this._indent) {
        if (command.code === 402) {
          const type = command.parameters[0] + d;
          const helpTexts = this.extractHelpTexts(i + index + 1);
          if (helpTexts) data.helpTexts[type] = helpTexts;
        } else if (command.code === 404) {
          return;
        }
      }
    }
  };

  Game_Interpreter.prototype.extractHelpTexts = function (index) {
    const command = this._list[index];
    if (
      command.code === 108 &&
      param_ChoiceHelpCommands.includes(command.parameters[0])
    ) {
      return this.getCommentHelpTexts(index + 1);
    }
    return null;
  };

  Game_Interpreter.prototype.getCommentHelpTexts = function (index) {
    const result = [];
    for (const command of this._list.slice(index)) {
      if (command.code === 408) {
        result.push(command.parameters[0]);
      } else {
        break;
      }
    }
    return result;
  };

  Game_Interpreter.prototype.choiceHelpTexts = function (data) {
    const helpTexts = data.helpTexts;
    return helpTexts.length > 0 ? data.results.map((i) => helpTexts[i]) : [];
  };

  Game_Interpreter.prototype.choiceCancelType = function (data) {
    if (data.cancelType === -1) {
      return -1;
    } else if (MathExt.mod(data.cancelType, 10) === 8) {
      return -2;
    }
    return data.results.indexOf(data.cancelType);
  };

  Game_Interpreter.prototype.choiceDefaultType = function (data) {
    const vId = $gameMessage.choiceVariableId();
    const index = vId > 0 ? $gameVariables.value(vId) : data.defaultType;
    const defaultType = data.results.indexOf(index);
    if (index >= 0 && defaultType < 0 && param_DisabledPosition === "top") {
      return 0;
    }
    return defaultType;
  };

  Game_Interpreter.prototype.nextCommandOfChoice = function (index) {
    const i = this._list
      .slice(index)
      .findIndex(
        (command) => command.indent === this._indent && command.code === 404
      );
    return i >= 0 ? this._list[index + i + 1] : null;
  };

  // overwrite
  Game_Interpreter.prototype.command403 = function () {
    if (this._branch[this._indent] !== -2) {
      this.skipBranch();
    }
    return true;
  };

  Game_Interpreter.prototype.command404 = function () {
    if (this.nextEventCode() === 102) {
      this._branch[this._indent] -= 10;
      this._index++;
    }
    return true;
  };

  const _mzCommands = {
    ChoicePos: { name: "choicePos", keys: ["x", "y", "row"] },
    ChoiceVariableId: { name: "choiceVariableId", keys: ["varId"] },
    ChoiceRect: { name: "choiceRect", keys: ["x", "y", "width", "height"] },
    ChoiceInMessage: { name: "choiceInMessage", keys: [] },
  };
  Object.assign(_mzCommands, {
    選択肢位置設定: _mzCommands.ChoicePos,
    カーソル位置設定: _mzCommands.ChoiceVariableId,
    選択肢サイズ設定: _mzCommands.ChoiceRect,
    メッセージ内表示: _mzCommands.ChoiceInMessage,
  });

  const _Game_Interpreter_pluginCommand =
    Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function (command, args) {
    _Game_Interpreter_pluginCommand.apply(this, arguments);
    const mzCommand = _mzCommands[command];
    if (mzCommand) {
      const args2 = Object.assign(
        {},
        ...mzCommand.keys.map((key, i) => ({ [key]: args[i] }))
      );
      PluginManager.callCommandMV(this, pluginName, mzCommand.name, args2);
    }
  };

  //-----------------------------------------------------------------------------
  // Window_ChoiceList

  const _Window_ChoiceList_select = __base(
    Window_ChoiceList.prototype,
    "select"
  );
  Window_ChoiceList.prototype.select = function (index) {
    const variableId = $gameMessage.choiceVariableId();
    if (index !== this.index() && variableId > 0) {
      const results = $gameMessage.choiceResults();
      $gameVariables.setValue(variableId, results[index]);
    }
    _Window_ChoiceList_select.apply(this, arguments);
  };

  const _Window_ChoiceList_updatePlacement =
    Window_ChoiceList.prototype.updatePlacement;
  Window_ChoiceList.prototype.updatePlacement = function () {
    _Window_ChoiceList_updatePlacement.apply(this, arguments);
    const {
      choiceX: x,
      choiceY: y,
      choiceWidth: width,
      choiceHeight: height,
    } = $gameMessage;
    if (width >= 0) {
      this.width = MathExt.clamp(width, 1, Graphics.boxWidth);
    }
    if (height >= 0) {
      this.height = MathExt.clamp(height, 1, Graphics.boxHeight);
    }
    if (x >= 0) this.x = Math.min(x, Graphics.boxWidth - this.width);
    if (y >= 0) this.y = Math.min(y, Graphics.boxHeight - this.height);
    this._isWindow = !$gameMessage.isChoiceInMessage();
  };

  // overwrite
  Window_ChoiceList.prototype.numVisibleRows = function () {
    const choices = $gameMessage.choices();
    const maxLines = $gameMessage.choiceMaxRow();
    return Math.min(choices.length, maxLines);
  };

  // overwrite
  Window_ChoiceList.prototype.makeCommandList = function () {
    const enables = $gameMessage.choiceEnables();
    for (const [i, choice] of $gameMessage.choices().entries()) {
      this.addCommand(choice, "choice", enables[i]);
    }
  };

  const _Window_ChoiceList_drawItem = Window_ChoiceList.prototype.drawItem;
  Window_ChoiceList.prototype.drawItem = function (index) {
    this.changePaintOpacity(this.isCommandEnabled(index));
    _Window_ChoiceList_drawItem.apply(this, arguments);
  };

  const _Window_ChoiceList_callOkHandler =
    Window_ChoiceList.prototype.callOkHandler;
  Window_ChoiceList.prototype.callOkHandler = function () {
    _Window_ChoiceList_callOkHandler.apply(this, arguments);
    this._messageWindow.forceClear();
    this._helpIndex = null;
  };

  const _Window_ChoiceList_callCancelHandler =
    Window_ChoiceList.prototype.callCancelHandler;
  Window_ChoiceList.prototype.callCancelHandler = function () {
    _Window_ChoiceList_callCancelHandler.apply(this, arguments);
    this._messageWindow.forceClear();
    this._helpIndex = null;
  };

  const _Window_ChoiceList_processCancel = __base(
    Window_ChoiceList.prototype,
    "processCancel"
  );
  Window_ChoiceList.prototype.processCancel = function () {
    const cancelType = $gameMessage.choiceCancelType();
    if (
      cancelType >= 0 &&
      this.isCancelEnabled() &&
      !this.isCommandEnabled(cancelType)
    ) {
      this.playBuzzerSound();
      return;
    }
    _Window_ChoiceList_processCancel.apply(this, arguments);
  };

  Window_ChoiceList.prototype.callUpdateHelp = function () {
    if (
      this.active &&
      this._messageWindow &&
      $gameMessage.isChoiceHelp() &&
      this._helpIndex !== this.index()
    ) {
      this._helpIndex = this.index();
      this.updateHelp();
    }
  };

  Window_ChoiceList.prototype.updateHelp = function () {
    this._messageWindow.forceClear();
    const texts = $gameMessage.helpTexts()[this.index()];
    $gameMessage.setTexts(texts ? [...texts] : [""]);
    this._messageWindow.startMessage();
  };

  //-----------------------------------------------------------------------------
  // Window_Message

  const _Window_Message_initialize = Window_Message.prototype.initialize;
  Window_Message.prototype.initialize = function (rect) {
    _Window_Message_initialize.apply(this, arguments);
    this.updatePlacement();
  };

  const _Window_Message_updatePlacement =
    Window_Message.prototype.updatePlacement;
  Window_Message.prototype.updatePlacement = function () {
    _Window_Message_updatePlacement.apply(this, arguments);
    this.clearInChoice();
  };

  Window_Message.prototype.clearInChoice = function () {
    if ($gameMessage.isChoiceInMessage()) {
      const x = this.x + this.choiceStartX();
      const y = this.y + 4;
      const height = this.height;
      $gameMessage.setChoiceRect(x, y, -1, height);
    }
  };

  Window_Message.prototype.choiceStartX = function () {
    if ("left" in this._textState) {
      return this.standardPadding() + this._textState.left;
    } else {
      return $gameSystem.windowPadding() + this._textState.startX;
    }
  };

  const _Window_Message_processNewLine = __base(
    Window_Message.prototype,
    "processNewLine"
  );
  Window_Message.prototype.processNewLine = function (textState) {
    if ($gameMessage.isChoiceInMessage()) {
      $gameMessage.lowerChoiceHeight(textState.height);
    }
    _Window_Message_processNewLine.apply(this, arguments);
  };

  const _Window_Message_updateInput = Window_Message.prototype.updateInput;
  Window_Message.prototype.updateInput = function () {
    if ($gameMessage.isChoiceHelp() && this._textState) {
      return false;
    }
    return _Window_Message_updateInput.apply(this, arguments);
  };

  const _Window_Message_onEndOfText = Window_Message.prototype.onEndOfText;
  Window_Message.prototype.onEndOfText = function () {
    const choiceWindow = this._choiceWindow || this._choiceListWindow;
    if (!choiceWindow.active && $gameMessage.isChoiceHelp()) {
      this.startInput();
    } else {
      _Window_Message_onEndOfText.apply(this, arguments);
    }
  };

  const _Window_Message_startInput = Window_Message.prototype.startInput;
  Window_Message.prototype.startInput = function () {
    const choiceWindow = this._choiceWindow || this._choiceListWindow;
    if (choiceWindow.active) return true;
    if (this._textState && this.isLowerChoice()) {
      $gameMessage.lowerChoiceHeight(this._textState.height);
    }
    return _Window_Message_startInput.apply(this, arguments);
  };

  Window_Message.prototype.isLowerChoice = function () {
    const textState = this._textState;
    const startX = "left" in textState ? textState.left : textState.startX;
    return (
      $gameMessage.isChoice() &&
      $gameMessage.isChoiceInMessage() &&
      textState.x !== startX
    );
  };

  Window_Message.prototype.forceClear = function () {
    this._textState = null;
    this.close();
    this._goldWindow.close();
  };

  const _Window_Message_newPage = Window_Message.prototype.newPage;
  Window_Message.prototype.newPage = function (textState) {
    _Window_Message_newPage.apply(this, arguments);
    this.clearInChoice();
  };
})();