//=============================================================================
// 第10版 - 初版
// 第11版 - 対局開始判定スイッチと 対局開始無効化スイッチを追加
//          対局者選択のウィンドウでselectごとにrefreshを実行するように変更
//
//=============================================================================

/*:
 * @target MZ
 * @plugindesc 麻雀メニュー
 * @author 安比奈
 * @base AP1S_MajiangCore
 * @orderAfter AP1S_MajiangCore
 * @help
 * 
 * 麻雀メニュー
 * 
 * 
 * 麻雀メニュー画面を作成します
 * 
 * メニュー画面では予め作成したアクターのリストの中から
 * プレイヤーが自由に対局者を選出して対局を開始したり
 * 麻雀のルール解説文を作成し表示する等ができます
 * 
 * 
 * ・対局者リストについて
 * 
 * このプラグインを導入すると 内部で対局者リストという
 * 空のリストが作成されます
 * メニュー画面で対局者を変更可能にする場合 開く前にあらかじめ
 * 選出可能なアクターを設定します
 * 
 * 追加は プラグインコマンド「対局者リストにアクターを追加する」
 * で行ってください 
 * (必ず 麻雀プラグイン本体で雀士登録を行ったアクターのみを追加するように
 * してください)
 * 
 * そのほか「対局者リストからアクターを削除する」コマンドで
 * リストからアクターを削除できます
 * 
 * 
 * なお このリストの内容は 基本的にはセーブデータに含まれますが
 * 麻雀プラグイン本体の プラグイン設定「システムデータに干渉しない」
 * がONの場合は保存されず 起動ごとに初期化されますのでご注意ください
 * 
 * 
 * 
 * 
 * ・麻雀メニューを開く
 * 
 * 「麻雀メニューを開く」コマンドで麻雀メニューを開きます
 *  麻雀メニューで表示する内容等はこのコマンドの引数で設定します
 * 
 *  ・引数解説
 * 
 *   ・表示するコマンド
 *     メニュー画面でどのコマンドを表示するかを登録します
 *     
 *     ・対局開始
 *       表示されている対局者で対局を開始します
 * 
 *     ・対局者変更
 *       対局者を対局者リストの中から選んで編集できます
 *       
 *     ・ルール変更
 *       麻雀プラグイン本体の麻雀オプションを開きます
 *       表示される項目は本体の設定に依ります
 * 
 *     ・解説文n
 *       後述の麻雀ルール解説で登録した文章を開きます
 *       麻雀ルール解説は複数登録可能ですが
 *       このコマンドにある数字は その複数登録された解説文の
 *       リストから何番目のものを表示するかを表します
 *       (存在しない解説文を指定するとエラーが発生しますのでご注意ください)
 * 
 *     ・終了
 *       麻雀メニューを閉じてマップ画面に戻ります
 *       後述の「中断可能」の項目がONの場合は
 *       キャンセルボタンでもマップ画面に戻れますので
 *       このコマンドは必須ではありません
 * 
 * 
 * 
 * 
 *   ・初期対局者の指定
 *     初期対局者を指定します
 *     予め4つの変数に自家、下家、対面、上家になるアクターのIDが
 *     入った変数を用意しておき ここでそれぞれ指定します
 *     (二、三人麻雀の場合でも4つ指定を推奨します)
 *     三麻等で空席を用意する場合は 0が入った変数を指定してください
 *     
 *     ここで指定した変数には プレイヤーが対局者を編集した後 対局終了等で
 *     マップに戻った時点で その時の対局者のIDがそれぞれ代入されます
 * 
 *     そのため 変数にアクターIDを代入するのを初回実行時でのみ行うことにより
 *     以降メニューを開くたびに プレイヤーが
 *     最後に選択した対局者メンバーの復元が可能になります
 * 
 *     また 対局者リストに指定されていない対局者が指定された場合は
 *     メニューを開いた時点で自動で登録されます
 * 
 * 
 *   ・次の対局者を変更不可にする
 *     指定の対局者が 対局者変更による変更ができなくなります
 * 
 * 
 *   ・対局者を重複選択可能にする
 *     ONの場合 対局者変更の選択画面で 同じIDのアクターを
 *     重複して指定できるようになります
 * 
 * 
 *   ・選択可能な対局
 *     対局者変更により 空席がいくつ設定可能かを指定します
 * 
 * 
 *   ・中断可能
 *     OFFにすると 麻雀プラグイン本体での対局開始コマンドにある同項目と同様に
 *     キャンセルボタンによる中断ができなくなります
 *     
 *     また メニュー画面においても キャンセルボタンでマップに戻れなくなります
 * 
 * 
 *   ・席順をランダムにする
 *     ONにすると 麻雀プラグイン本体での対局開始コマンドにある同項目と同様に
 *     対局開始を選択するごとに 自家以外の席の場所がランダムに変更されます
 *     
 *     
 *   ・対局終了後の処理
 *     対局終了後 メニュー画面に戻るか メニューを閉じてマップにもどるかを
 *     指定します
 *     
 *     
 *   ・報酬コモンイベント 及び開始コモンイベント
 *     後述の報酬コモンイベント 及び開始コモンイベントの項目を参照してください
 *     
 *     
 *   ・補助文を表示する
 *     ONにすると メニュー画面に2行ほどの文章を表示するスペースが作成されます
 *     対局の設定等を表示するのにご使用ください
 *     
 *     
 *   ・補助文
 *     前項目がONの場合 表示される文章です
 *     最大2行まで表示できます
 * 
 * 
 * 
 * 
 * 
 * ・麻雀ルール解説文について
 * 
 * 麻雀のルールを書いた文章を作成し
 * メニュー画面で表示できます
 * 
 * 解説文は複数項目登録可能です
 * 基本ルールの解説と役の一覧等に分けて記述する用途を想定しています
 * 
 * 解説文を記述する際は 同梱の
 * 麻雀牌を制御文字で表示するプラグインも併せてご利用ください
 * 
 * 
 * 作成した解説文の表示方法は「麻雀メニューを開く」項目内の
 * 「表示するコマンド」の解説文を参照してください
 * 
 * 
 * 
 * 
 * ・報酬コモンイベント
 * 「報酬コモンイベント」でコモンイベントを指定すると
 *  対局が終了したときに 指定のコモンイベントが実行されます
 * 
 * 麻雀プラグイン本体の「対局結果出力変数」の内容を元に
 * 報酬の入手、及びその表示の処理を行うことを想定した機能です
 * 
 * このコモンイベントは 対局を中断して終了した場合も実行されます
 * そのため かならず
 * 麻雀プラグイン本体の「プラグイン設定」内で設定できる
 * 「中断判定スイッチ」を使用し
 * 対局が中断されたかを取得した上で処理を記述するようにしてください
 * 
 * 
 * 「対局終了後の処理」が「麻雀メニューに戻る」になっている場合
 * コモンイベントはメニュー画面の上で実行されることになりますが
 * 画像を表示する等 一部の処理は動作しなかったり
 * エラーが発生する可能性がありますので
 * メッセージの表示、所持金やアイテムの取得、変数の操作等 
 * 簡単な処理のみを記述するようにしてください
 * 
 * 
 * 
 * ・開始コモンイベント
 * 対局開始ボタンを押してから 実際に麻雀の画面に移行するまでの間に
 * 指定のコモンイベントを実行します
 * 
 * 麻雀イベントの登録、積み込み予約の登録、開始に必要な料金の差し引き
 * 等の利用を想定しています
 * 
 * このイベントは前項目における
 * 「対局終了後の処理」が「麻雀メニューに戻る」になっている場合
 * と同様に メニュー上で実行されますので
 * イベント内で使用するコマンドにご注意ください
 * 
 * 
 * 
 * 
 * ・所持金ウィンドウの表示
 * メニュー画面に所持金、または指定の変数の数値を表示できます
 * 「所持金を表示する」を指定した場合は現在の所持金が表示されます
 * 「指定の変数の値を表示する」を指定した場合は
 *  その下の項目で指定する「表示する変数」の内容が表示されます
 * 
 * 麻雀の勝敗で所持金や、変数で管理される点数の変動が存在する場合
 * その表示にご利用ください
 * 
 * この項目では 表示のみを行います
 * 終了時 プレイヤーの得点を自動で加算等はしませんので
 * 上述の「報酬コモンイベント」等を利用して 手動で変動させてください
 * 
 * 
 * 
 * 
 * 
 * 
 * ・対局実行判定
 * メニュー画面で対局開始が押されたときに指定のスイッチがONになります
 * メニュー開始コマンドの後の処理で 
 * 対局を一回も実行せずにキャンセルを押して戻ったのか 
 * を判定する等にご利用ください
 * 
 * 
 * ・対局開始無効化
 * 指定のスイッチがONの場合 対局開始スイッチが押せなくなります
 * 対局を開始するのに お金などが必要で かつそのお金が足りない場合
 * 対局開始を無効化するのにご利用ください
 * 
 * 料金不足の判定を行い その結果をスイッチに設定する処理は
 * 「麻雀メニューを開く」コマンドの前、
 * 及び 「対局終了後の処理」が「メニューに戻る」の場合は
 * 報酬コモンイベント内でも行ってください
 * 
 * また 設定された料金を所持金等から差し引く処理は
 * 開始コモンイベント内で行うようにしてください
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * @command start
 * @text 麻雀メニューを開く
 * @desc 
 * 
 * @arg commands
 * @text 表示するコマンド
 * @desc 表示されるコマンドを指定します 
 * @type select[]
 * @option 対局開始 @value start
 * @option 対局者変更 @value select
 * @option ルール変更 @value options
 * @option 解説文1 @value rule_1
 * @option 解説文2 @value rule_2
 * @option 解説文3 @value rule_3
 * @option 解説文4 @value rule_4
 * @option 解説文5 @value rule_5
 * @option 解説文6 @value rule_6
 * @option 解説文7 @value rule_7
 * @option 解説文8 @value rule_8
 * @option 解説文9 @value rule_9
 * @option 解説文10 @value rule_10
 * @option 終了 @value gameEnd
 * @default ["start","select","options","gameEnd"]
 * 
 * 
 * 
 * @arg members
 * @text 初期対局者の指定
 * @desc アクターIDの入った変数を4つ指定してください. 指定の詳細はプラグインヘルプを参照
 * @type struct<members>
 * @default {"zijia":"0","shimojia":"0","duimian":"0","kamijia":"0"}
 * 
 * 
 * 
 * 
 * @arg fixed
 * @text 次の対局者を変更不可にする
 * @desc 対局者変更コマンドで 次の対局者を変更不可に設定します
 * @type select[]
 * @option 自家 @value 0
 * @option 下家 @value 1
 * @option 対面 @value 2
 * @option 上家 @value 3
 * @default []
 * 
 * 
 * 
 * @arg canChongfu
 * @text 対局者を重複選択可能にする
 * @desc 同じアクターIDの対局者を対局者選択にて選択できるかを指定します
 * @type boolean
 * @default false
 * 
 * @arg battlerNum
 * @text 選択可能な対局
 * @desc 
 * @type select
 * @option 四麻のみ @value 4_4
 * @option 四麻と三麻 @value 4_3
 * @option 四麻と三麻と二人 @value 4_2
 * @option 三麻のみ @value 3_3
 * @option 二人のみ @value 2_2
 * @option 三麻と二人 @value 3_2
 * @default 4_4
 * 
 * @arg abstention
 * @text 中断可能
 * @desc 対局中キャンセルボタン等により中断できるかを指定します
 * @type boolean
 * @default true
 * 
 * @arg randomPosition
 * @text 席順をランダムにする
 * @desc 自家以外の雀士の座る位置をランダムに変更します
 * @type boolean
 * @default false
 * 
 * @arg prevScene
 * @text 対局終了後の処理
 * @desc 
 * @type select
 * @option 麻雀メニューに戻る @value menu
 * @option マップに戻る @value map
 * @default map
 * 
 * @arg endCommonId
 * @text 報酬コモンイベント
 * @desc 対局終了時 次のコモンイベントが実行されます(中断された場合も実行されます)
 * @type common_event
 * @default 0
 * 
 * @arg startCommonId
 * @text 開始コモンイベント
 * @desc 対局開始ボタンを押した時 次のコモンイベントが実行されてから対局が開始されます
 * @type common_event
 * @default 0
 * 
 * @arg echoHelp
 * @text 補助文を表示する
 * @desc 2行ほどの文章をメニュー画面で表示できます. ウマ等の表示用に
 * @type boolean
 * @default false
 * 
 * @arg helpText
 * @parent echoHelp
 * @text 補助文
 * @desc 上記がONの場合その内容になる文章です. 最大2行まで表示できます 
 * @type multiline_string
 * @default 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * @command addActors
 * @text 対局者リストにアクターを追加する
 * @desc 対局者変更画面にて プレイヤーが選択できるアクターを変更します
 * 
 * @arg actors
 * @text 追加するアクター
 * @desc 複数指定可能です
 * @type actor[]
 * @default []
 * 
 * @arg actorsVariable
 * @text 追加するアクター(変数指定)
 * @desc 複数指定可能です アクターIDの入った変数を指定してください
 * @type variable[]
 * @default []
 * 
 * 
 * 
 * 
 * @command deleteActors
 * @text 対局者リストからアクターを削除する
 * @desc 対局者変更画面にて プレイヤーが選択できるアクターを変更します
 * 
 * @arg actors
 * @text 削除するアクター
 * @desc 複数指定可能です
 * @type actor[]
 * @default []
 * 
 * @arg actorsVariable
 * @text 追加するアクター(変数指定)
 * @desc 複数指定可能です アクターIDの入った変数を指定してください
 * @type variable[]
 * @default []
 * 
 * 
 * @command clearActors
 * @text 対局者リストからアクターを全て削除する
 * @desc 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * @param gamerule
 * @text 麻雀ルール解説文の登録
 * @desc 
 * @type struct<gamerule>[]
 * @default []
 * 
 * @param gamerulePaddingHorz
 * @parent gamerule
 * @text 麻雀ルール解説文の水平パディング
 * @desc 解説文の文章の左右に 指定のピクセル文余白をつけます
 * @type number
 * @default 148
 * 
 * @param gamerulePaddingVert
 * @parent gamerule
 * @text 麻雀ルール解説文の垂直パディング
 * @desc 解説文の文章の上下に 指定のピクセル文余白をつけます
 * @type number
 * @default 0
 * 
 * 
 * @param gold
 * @text 所持金ウィンドウの表示
 * @desc 表示する場合 メニュー画面に現在の額面が表示されます
 * @type select
 * @option 非表示 @value 0
 * @option 所持金を表示する @value 1
 * @option 指定の変数の値を表示する @value 2
 * @default 0
 * 
 * @param goldVariableId
 * @parent gold
 * @text 表示する変数
 * @desc 上記で「指定の変数の値を表示する」を選択した場合 その変数を指定してください
 * @type variable
 * @default 0
 * 
 * 
 * @param currencyUnit
 * @parent gold
 * @text 変数の単位
 * @desc 上記で「指定の変数の値を表示する」を選択した場合 その変数の単位を記入してください
 * @type string
 * @default 点
 * 
 * 
 * @param duijuStarted
 * @text 対局実行判定
 * @desc メニュー画面で対局開始が押されたときに次のスイッチがONになります
 * @type switch
 * @default 0
 * 
 * 
 * @param duijuDisabled
 * @text 対局開始無効化
 * @desc このスイッチがONの場合 対局開始スイッチが押せなくなります
 * @type switch
 * @default 0
 * 
 * 
 * 
 * 
 * @param text
 * @text テキスト設定
 * @desc 
 * @type struct<text>
 * @default {"start":"対局開始","select":"対局者変更","options":"ルール変更","gameEnd":"麻雀を終了する","position_0":"自家","position_1":"下家","position_2":"対面","position_3":"上家","empty":"空席"}
 */
 
/*~struct~text:
 * 
 * @param start
 * @text 対局開始の表示
 * @desc 
 * @type string
 * @default 対局開始
 * 
 * @param select
 * @text 対局者変更の表示
 * @desc 
 * @type string
 * @default 対局者変更
 * 
 * @param options
 * @text ルール変更の表示
 * @desc 
 * @type string
 * @default ルール変更
 * 
 * 
 * @param gameEnd
 * @text 終了の表示
 * @desc 
 * @type string
 * @default 麻雀を終了する
 * 
 * @param position_0
 * @text 自家の表示
 * @desc 
 * @type string
 * @default 自家
 * 
 * @param position_1
 * @text 下家の表示
 * @desc 
 * @type string
 * @default 下家
 * 
 * @param position_2
 * @text 対面の表示
 * @desc 
 * @type string
 * @default 対面
 * 
 * @param position_3
 * @text 上家の表示
 * @desc 
 * @type string
 * @default 上家
 * 
 * @param empty
 * @text 空席の表示
 * @desc 
 * @type string
 * @default 空席
 * 
 * 
 */

/*~struct~gamerule:
 * 
 * @param title
 * @text 題目
 * @desc このページの題目です
 * @type string
 * @default 
 * 
 * @param pages
 * @text ページ
 * @desc 
 * @type struct<gameruleText>[]
 * @default []
 * 
 */
 
/*~struct~gameruleText:
 * 
 * @param text
 * @text 本文
 * @desc 
 * @type multiline_string
 * @default 
 * 
 * 
 * @param face
 * @text 顔画像登録
 * @desc 指定の場所に顔画像を配置できます
 * @type struct<face>[]
 * @default []
 * 
 * @param picture
 * @text 画像登録
 * @desc 指定の場所に画像を配置できます
 * @type struct<picture>[]
 * @default []
 */
 
/*~struct~face:
 * 
 * @param x
 * @text X座標
 * @desc 画像を配置するX座標です
 * @type number
 * @default 0
 * 
 * @param y
 * @text Y座標
 * @desc 画像を配置するY座標です
 * @type number
 * @default 0
 * 
 * @param file
 * @text 画像
 * @desc 
 * @dir img/faces
 * @type file
 * @default 
 * 
 * @param index
 * @text 顔画像のインデックス
 * @desc 左上の顔画像が0 その右が1と続き 右下が7になります
 * @type number
 * @default 0
 * 
 * 
 */
 
/*~struct~picture:
 * 
 * @param x
 * @text X座標
 * @desc 画像を配置するX座標です
 * @type number
 * @default 0
 * 
 * @param y
 * @text Y座標
 * @desc 画像を配置するY座標です
 * @type number
 * @default 0
 * 
 * @param file
 * @text 画像
 * @desc 
 * @dir img/pictures
 * @type file
 * @default 
 * 
 * 
 * 
 */

/*~struct~members:
 * 
 * @param zijia
 * @text 自家
 * @desc 自家になるアクターのIDが入った変数を指定します 
 * @type variable
 * @default 0
 * 
 * @param shimojia
 * @text 下家
 * @desc 下家になるアクターのIDが入った変数を指定します 
 * @type variable
 * @default 0
 * 
 * @param duimian
 * @text 対面
 * @desc 対面になるアクターのIDが入った変数を指定します 
 * @type variable
 * @default 0
 * 
 * @param kamijia
 * @text 上家
 * @desc 上家になるアクターのIDが入った変数を指定します 
 * @type variable
 * @default 0 
 * 
 * 
 * 
 */
 
 
( function()
{
	"use strict";
    
	const P_name = decodeURIComponent(document.currentScript.src).match(/([^\/]+)\.js$/)[1]; //プラグイン名
	
	const GP = PluginManager.parameters(P_name);
	const PP = {};
	
	PP.maxVolume = 10;
	
	(() =>
	{
		PP.text = JSON.parse(GP.text || "{}"); 
    	
		PP.gamerulePaddingHorz = Number(GP.gamerulePaddingHorz); 
		PP.gamerulePaddingVert = Number(GP.gamerulePaddingVert); 
		
		PP.gold = Number(GP.gold);
		
		PP.goldVariableId = Number(GP.goldVariableId);
    	
		
		
		PP.currencyUnit = GP.currencyUnit;
		
		
		
		PP.duijuStarted = Number(GP.duijuStarted);
		
		PP.duijuDisabled = Number(GP.duijuDisabled);
		
		function parseImg(string)
		{
			return JSON.parse(string || "[]").map(d =>
			{
				const ret = JSON.parse(d || "{}");
	    		
				ret.x = Number(ret.x);
				ret.y = Number(ret.y);
	    		
				return ret;
			});
		}
    	
		function parsePage(string)
		{
			return JSON.parse(string || "[]").map(d =>
			{
				const ret = JSON.parse(d || "{}");
    			
				ret.face = parseImg(ret.face);
				ret.picture = parseImg(ret.picture);
    			
				return ret;
			});
		}
    	
    	
    	
		PP.gamerule = JSON.parse(GP.gamerule || "[]").map(d =>
		{
			const ret = JSON.parse(d || "{}");
    		
			ret.pages = parsePage(ret.pages);
			return ret;
		});
	})();
	
	$dataMajiangSystem.menuData = {};
	
	
	
	function PF_data()
	{
		const data = $gameMajiangSystem.loadSystemData("menu");
		data.actors ??= [];
		return data;
	}
	
	
	
	
	function Scene_MajiangGamerule() 
	{
		this.initialize(...arguments);
	}
	
	Scene_MajiangGamerule.prototype = Object.create(Scene_MenuBase.prototype);
	Scene_MajiangGamerule.prototype.constructor = Scene_MajiangGamerule;
	
	Scene_MajiangGamerule.prototype.create = function() 
	{
		Scene_MenuBase.prototype.create.call(this);
		
		this.createTitleWindow();
		this.createTextWindow();
		this.createPageWindow();
		
	};
	
	Scene_MajiangGamerule.prototype.helpAreaHeight = function() 
	{
    	return 0;
	};
	
	Scene_MajiangGamerule.prototype.start = function() 
	{
		Scene_MenuBase.prototype.start.call(this);
		this._textWindow.refresh();
		this._pageWindow.select(0);
    	this._pageWindow.activate();
	};
	
	
	
	Scene_MajiangGamerule.prototype.pageWindowHeight = function() 
	{
		return this.calcWindowHeight(1,true);
	};
	
	Scene_MajiangGamerule.prototype.titleWindowHeight = function() 
	{
		return this.calcWindowHeight(1,false);
	};
	
	Scene_MajiangGamerule.prototype.volume = function() 
	{
		return $dataMajiangSystem.menuData.volume;
	};
	
	Scene_MajiangGamerule.prototype.createTitleWindow = function() 
	{
    	const rect = this.titleWindowRect();
    	
    	this._titleWindow = new Window_MajiangMenuTextTitle(rect);
    	this._titleWindow.setVolume(this.volume());
    	this.addWindow(this._titleWindow);
	};
	
	Scene_MajiangGamerule.prototype.titleWindowRect = function() 
	{
    	const ww = Graphics.boxWidth;
    	const wh = this.titleWindowHeight();
    	const wx = 0;
    	const wy = this.mainAreaTop();
    	return new Rectangle(wx, wy, ww, wh);
	};
    
    Scene_MajiangGamerule.prototype.createTextWindow = function() 
	{
    	const rect = this.textWindowRect();
    	
    	this._textWindow = new Window_MajiangMenuText(rect);
    	this._textWindow.setVolume(this.volume());
    	this.addWindow(this._textWindow);
	};
	
	Scene_MajiangGamerule.prototype.textWindowRect = function() 
	{
    	const ww = Graphics.boxWidth;
    	const wh = this.mainAreaHeight() - this.pageWindowHeight() - this.titleWindowHeight();
    	const wx = 0;
    	const wy = this.mainAreaTop() + this.titleWindowHeight();
    	return new Rectangle(wx, wy, ww, wh);
	};
	
	
	
	Scene_MajiangGamerule.prototype.createPageWindow = function() 
	{
    	const rect = this.pageWindowRect();
    	
    	const pageWindow = new Window_MajiangMenuPage(rect);
    	
    	pageWindow.setVolume(this.volume());
    	
    	pageWindow.setHandler("cancel", this.popScene.bind(this));
    	
    	pageWindow.setHelpWindow(this._textWindow);
    	this._pageWindow = pageWindow;
    	this.addWindow(pageWindow);
	};
	
	Scene_MajiangGamerule.prototype.pageWindowRect = function() 
	{
    	const ww = Graphics.boxWidth;
    	const wh = this.pageWindowHeight();
    	const wx = 0;
    	const wy = this.mainAreaTop() + this.mainAreaHeight() - wh;
    	return new Rectangle(wx, wy, ww, wh);
	};
	
	Scene_MajiangGamerule.prototype.needsPageButtons = function() 
	{
    	return true;
	};
	
	
	
	Scene_MajiangGamerule.prototype.nextActor = function()
	{
		this._pageWindow.changePage(true);
	};
	Scene_MajiangGamerule.prototype.previousActor = function()
	{
		this._pageWindow.changePage();
	};
	
	
	
	
	
	function Window_MajiangMenuTextTitle() 
	{
    	this.initialize(...arguments);
	}
	
	Window_MajiangMenuTextTitle.prototype = Object.create(Window_Base.prototype);
	Window_MajiangMenuTextTitle.prototype.constructor = Window_MajiangMenuTextTitle;
    
    Window_MajiangMenuTextTitle.prototype.initialize = function(rect) 
	{
    	Window_Base.prototype.initialize.call(this,rect);
    	this._volume = 0;
	};
	
	Window_MajiangMenuTextTitle.prototype.setVolume = function(volume) 
	{
		this._volume = volume;
		this.refresh();
	};
	
	Window_MajiangMenuTextTitle.prototype.refresh = function() 
	{
    	this.contents.clear();
    	this.drawTitle();
	};
    Window_MajiangMenuTextTitle.prototype.drawTitle = function()
    {
    	const rect = this.baseTextRect();
    	const title = PP.gamerule[this._volume].title;
    	this.drawText(title,rect.x,rect.y,rect.width,"center");
	};
    
    
    
    
    
	function Window_MajiangMenuText() 
	{
    	this.initialize(...arguments);
	}
	
	Window_MajiangMenuText.prototype = Object.create(Window_Base.prototype);
	Window_MajiangMenuText.prototype.constructor = Window_MajiangMenuText;
    
    Window_MajiangMenuText.prototype.initialize = function(rect) 
	{
    	Window_Base.prototype.initialize.call(this,rect);
    	this._page = 0;
    	this._volume = 0;
    	this._isReady = false;
	};
	
	
	Window_MajiangMenuText.prototype.setVolume = function(volume) 
	{
		this._volume = volume;
	};
	
	Window_MajiangMenuText.prototype.setPage = function(page)
	{
		this._page = page;
		this.refresh();
	};
	
	Window_MajiangMenuText.prototype.refresh = function() 
	{
		this._isReady = false;
    	this.contents.clear();
    	this.drawPageText();
	};
	
	
	
	Window_MajiangMenuText.prototype.drawPageText = function() 
	{
		const data = PP.gamerule[this._volume].pages[this._page];
		if(data)
		{
			const rect = this.baseTextRect();
			
			rect.pad(-PP.gamerulePaddingHorz,-PP.gamerulePaddingVert)
			
			this.drawTextEx(data.text,rect.x,rect.y,rect.width);
			
			this.drawAllFaces(data.face);
			this.drawAllPictures(data.picture);
		}
		
	};
	
	Window_MajiangMenuText.prototype.drawAllFaces = function(allData)
	{
		const width = ImageManager.faceWidth;
		const height = width;
		for(const data of allData)
		{
			this.drawFace(data.file,data.index,data.x,data.y,width,height);
		};
	};
	
	Window_MajiangMenuText.prototype.drawAllPictures = function(allData)
	{
		for(const data of allData)
		{
			this.drawPicture(data.file,data.x,data.y);
		};
	};
	
	Window_MajiangMenuText.prototype.drawPicture = function(file, x, y)
	{
    	const bitmap = ImageManager.loadPicture(file);
    	const pw = bitmap.width ;
    	const ph = bitmap.height;
    	
    	
    	this.contents.blt(bitmap, 0, 0, pw, ph, x, y);
	};
	
	Window_MajiangMenuText.prototype.update = function()
	{
		Window_Base.prototype.update.call(this);
		
		if(!this._isReady)
		{
			if(ImageManager.isReady())
			{
				this.refresh();
				this._isReady = true;
			}
		}
	};
	
	
	
	
	
	
	
	
	function Window_MajiangMenuPage() 
	{
    	this.initialize(...arguments);
	}
	
	
	Window_MajiangMenuPage.prototype = Object.create(Window_HorzCommand.prototype);
	Window_MajiangMenuPage.prototype.constructor = Window_MajiangMenuPage;
    
    Window_MajiangMenuPage.prototype.initialize = function(rect) 
	{
    	Window_HorzCommand.prototype.initialize.call(this,rect);
    	this._page = 0;
    	this._volume = 0;
    	this._length = 0;
	};
	
	Window_MajiangMenuPage.prototype.maxCols = function() 
	{
    	return this._length;
	};
	
	Window_MajiangMenuPage.prototype.setVolume = function(volume) 
	{
		this._volume = volume;
		this._length = PP.gamerule[this._volume].pages.length;
		this.refresh();
	};
	
	Window_MajiangMenuPage.prototype.makeCommandList = function() 
	{
        for(let i = 0; i < this._length ; i++)
        {
        	const name = (i + 1) + "";
        	this.addCommand(name , name , true, i );
	    }
	};
	
	Window_MajiangMenuPage.prototype.setPage = function(page)
	{
		this._page = page;
		this.refresh();
	};
	
	Window_MajiangMenuPage.prototype.updateHelp = function() 
	{
		if(this._helpWindow) 
		{
			this.refreshTextWindow(this.index());
		}
	};
	
	
	Window_MajiangMenuPage.prototype.refreshTextWindow = function(index) 
	{
		this._helpWindow.setPage(index);
	};
	
	Window_MajiangMenuPage.prototype.itemWidth = function() 
	{
		const a = Math.floor(this.itemHeight() * 1.5);
		const b =  Window_Selectable.prototype.itemWidth.call(this);
		return Math.min(a,b);
	};
	
	
	Window_MajiangMenuPage.prototype.cursorPageup = function()
	{
		this.cursorLeft(true);
	};
	
	Window_MajiangMenuPage.prototype.cursorPagedown = function()
	{
		this.cursorRight(true);
	};
	
	
	Window_MajiangMenuPage.prototype.isOkEnabled = function() 
	{
    	return false;
	};
	
	Window_MajiangMenuPage.prototype.itemRect = function(index) 
	{
		const rect = Window_Selectable.prototype.itemRect.call(this,index);
		const width = (this.maxCols() * this.itemWidth());
		rect.x += (this.innerWidth - width) / 2;
    	return rect;
	};
	
	
    Window_MajiangMenuPage.prototype.changePage = function(down)
	{
		
		const lastIndex = this.index();
		if(down)
		{
			this.cursorPagedown();
		}
		else
		{
			this.cursorPageup();
		}
		if (this.index() !== lastIndex) 
		{
            this.playCursorSound();
        }
		this.refresh();
	};
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    //-----------------------
    
    function PF_terminate ()
    {
    	$dataMajiangSystem.menuData.membersVariableId.forEach(function(varId,i)
    	{
    		const actorId = $dataMajiangSystem.menuData.members[i];
    		$gameVariables.setValue(varId,actorId);
    	});
    	$gameMajiangSystem.clearTempActorData();
		$dataMajiangSystem.menuData = {};
	}
    
    
    
    function Scene_MajiangMenu() 
    {
    	this.initialize(...arguments);
	}
	
	Scene_MajiangMenu.prototype = Object.create(Object.assign(Scene_Message.prototype,Scene_MenuBase.prototype));
	Scene_MajiangMenu.prototype.constructor = Scene_MajiangMenu;
	
	Scene_MajiangMenu.prototype.initialize = function() 
	{
    	Scene_MenuBase.prototype.initialize.call(this);
    	this._selectIndex = 0;
    	this._resultStack = null;
    	this._interpreter = new Game_Interpreter();
    	this._eventRunning = false;
    	this._applyStart = false;
	};
	
	
	Scene_MajiangMenu.prototype.create = function() 
	{
		Scene_MenuBase.prototype.create.call(this);
		if(PP.gold)
		{
			this.createMajiangGoldWindow();
		}
		this.createCommandWindow();
		this.createStatusWindow();
		this.createBattlersWindow();
		this.createAllWindows();
		if($dataMajiangSystem.menuData.echoHelp)
		{
			this.createHelpWindow();
		}
	};
	
	Scene_MajiangMenu.prototype.createHelpWindow = function()
	{
		const rect = this.helpWindowRect();
		this._helpWindow = new Window_MajiangHelp(rect);
    	this._helpWindow.setText($dataMajiangSystem.menuData.helpText);
		this.addWindow(this._helpWindow);
	};
	
	
	Scene_MajiangMenu.prototype.helpAreaHeight = function() 
	{
		if($dataMajiangSystem.menuData.echoHelp)
    	{
    		return this.calcWindowHeight(2,false);
    	}
    	return 0;
    	
	};
	
	Scene_MajiangMenu.prototype.start = function() 
	{
    	Scene_MenuBase.prototype.start.call(this);
    	this._statusWindow.refresh();
    	
    	this.startCommonEvent();
	};
	Scene_MajiangMenu.prototype.startCommonEvent = function() 
	{
		if(this._interpreter.setupReservedCommonEvent())
    	{
    		this._eventRunning = true;
    	}
    	else
    	{
    		this.eventFinished();
    	}
    	this.updateCancelButton();
	}
	
	Scene_MajiangMenu.prototype.update = function() 
	{
		Scene_MenuBase.prototype.update.call(this);
		if(this._eventRunning)
		{
			if(this._interpreter.isRunning())
			{
				this.updateEvent();
			}
			else
			{
				this._eventRunning = false;
				this.eventFinished();
			}
		}
		this.updateCancelButton();
	};
	Scene_MajiangMenu.prototype.updateEvent = function() 
	{
		this._interpreter.update();
		if(this._majiangGoldWindow)
		{
			this._majiangGoldWindow.refresh();
		}
		
		this._commandWindow.updateDuijuEnabled();
	};
	
	
	
	
	Scene_MajiangMenu.prototype.updateCancelButton = function() 
	{
    	if (this._cancelButton) 
    	{
			this._cancelButton.visible = (!this._eventRunning 
				&& ($dataMajiangSystem.menuData.abstention
					|| !this._commandWindow.active
				)
			);
		}
	};
	
	Scene_MajiangMenu.prototype.eventFinished = function() 
	{
		if(this._applyStart)
		{
			this.startDuiju();
		}
		else
		{
			this._commandWindow.activate();
		}
	};
	
	Scene_MajiangMenu.prototype.updateActor = function() 
	{
    	this._actor = null;
	};
	
	
	Scene_MajiangMenu.prototype.popScene = function()
	{
		PF_terminate();
		Scene_MenuBase.prototype.popScene.call(this);
	};
	
	
	
	Scene_MajiangMenu.prototype.commandSelect = function() 
	{
		Window_MajiangMenuStatus.initSelectLast();
		this.startSelect();
		
	};
	
	Scene_MajiangMenu.prototype.startSelect = function() 
	{
		
		this._statusWindow.selectLast();
		this._statusWindow.activate();
		this._statusWindow.refresh();
		this._statusWindow.setHandler("ok", this.onSelectOk.bind(this));
		this._statusWindow.setHandler("cancel", this.onSelectCancel.bind(this));
	};
	
	
	
	
	Scene_MajiangMenu.prototype.onSelectOk = function() 
	{
		this._selectIndex = this._statusWindow.index();
		
		
		this._statusWindow.deselect();
		const zijia = (this._selectIndex === 0);
		const compensate = ($dataMajiangSystem.menuData.members[this._selectIndex] === 0);
		this._battlersWindow.setZijia(zijia);
		this._battlersWindow.setCompensate(compensate);
		this._battlersWindow.select(0);
		this._battlersWindow.refresh();
		
		this._battlersWindow.open();
		
    	this._battlersWindow.activate();
	};
	
	Scene_MajiangMenu.prototype.onSelectCancel = function() 
	{
		
		this._statusWindow.deselect();
		this._statusWindow.refresh();
    	this._commandWindow.activate();
	};
	
	
	Scene_MajiangMenu.prototype.commandRule = function() 
	{
		const volume = this._commandWindow.currentExt()
		$dataMajiangSystem.menuData.volume = volume;
		SceneManager.push(Scene_MajiangGamerule);
	};
	
	Scene_MajiangMenu.prototype.createCommandWindow = function() 
	{
    	const rect = this.commandWindowRect();
    	
    	const commandWindow = new Window_MajiangMenuCommand(rect);
    	
    	commandWindow.setHandler("start", this.commandStart.bind(this));
    	commandWindow.setHandler("options", this.commandOptions.bind(this));
    	commandWindow.setHandler("select", this.commandSelect.bind(this));
    	for(let i = 0 ; i < PP.maxVolume; i++)
    	{
    		const volume = i + 1;
    		commandWindow.setHandler("rule_" + volume, this.commandRule.bind(this));
    	}
    	commandWindow.setHandler("gameEnd", this.popScene.bind(this));
    	if($dataMajiangSystem.menuData.abstention)
    	{
    		commandWindow.setHandler("cancel", this.popScene.bind(this));
    	}
    	this.addWindow(commandWindow);
    	this._commandWindow = commandWindow;
	};
	
	
	Scene_MajiangMenu.prototype.commandWindowRect = function() 
	{
    	const ww = this.mainCommandWidth();
    	const wh = this.mainAreaHeight() - ((this._majiangGoldWindow) ? this._majiangGoldWindow.height : 0);
    	const wx = this.isRightInputMode() ? Graphics.boxWidth - ww : 0;
    	const wy = this.mainAreaTop();
    	return new Rectangle(wx, wy, ww, wh);
	};
	
	Scene_MajiangMenu.prototype.onBattlerOk = function() 
	{
		const actorId = this._battlersWindow.actorId();
		const index = this._selectIndex;
		
		this.changeFormation(index,actorId,$dataMajiangSystem.menuData.canChongfu);
		
		
		this._battlersWindow.close();
		
		this._statusWindow.refresh();
		this.startSelect();
	};
	
	Scene_MajiangMenu.prototype.changeFormation = function(index,actorId,canChongfu)
	{
		const members = $dataMajiangSystem.menuData.members;
		
		const gpIndex = (actorId === 0) ? -1 : members.indexOf(actorId);
		const fixed = $dataMajiangSystem.menuData.fixed;
		if(gpIndex === index)
		{
			return ;
		}
		const battlerNum = members.reduce(function(r,c)
    	{
    		return (c !== 0) ? (r + 1) : r;
	    },0);
	    
	    if(actorId === 0)
	    {
	    	if(members[index] !== 0 && battlerNum <= this.minBattlerNum())
	    	{
	    		const emptyIndex = members.findIndex(function(b,i)
	    		{
	    			return (b === 0 && !fixed.includes(i));
	    		});
	    		members[emptyIndex] = members[index];
		    }
	    }
		else
		{
			if(!canChongfu && gpIndex !== -1)
			{
				if(fixed.includes(gpIndex) || (gpIndex === 0 && members[index] === 0))
				{
					return;
				}
				members[gpIndex] = members[index];
			}
			if(members[gpIndex] !== 0 && members[index] === 0 && battlerNum >= this.maxBattlerNum())
			{
				const actorIndex = members.findIndex(function(b,i)
	    		{
	    			return (b !== 0 && !fixed.includes(i) && i !== index && i !== 0);
	    		});
	    		
			   	members[actorIndex] = 0;
			}
		}
		
		members[index] = actorId;
	};
	
	Scene_MajiangMenu.prototype.maxBattlerNum = function()
	{
		return $dataMajiangSystem.menuData.maxBattlerNum;
	};
	
	Scene_MajiangMenu.prototype.minBattlerNum = function()
	{
		return $dataMajiangSystem.menuData.minBattlerNum;
	};
	
	
	Scene_MajiangMenu.prototype.onBattlerCancel = function() 
	{
		this._battlersWindow.close();
		this.startSelect();
	};
	
	
	
	
	
	
	
	Scene_MajiangMenu.prototype.createStatusWindow = function() 
	{
    	const rect = this.statusWindowRect();
    	
    	this._statusWindow = new Window_MajiangMenuStatus(rect);
    	
    	this.addWindow(this._statusWindow);
	};
	Scene_MajiangMenu.prototype.statusWindowRect = function() 
	{
    	const ww = Graphics.boxWidth - this.mainCommandWidth();
    	const wh = this.mainAreaHeight();
    	const wx = this.isRightInputMode() ? 0 : Graphics.boxWidth - ww;
    	const wy = this.mainAreaTop();
    	return new Rectangle(wx, wy, ww, wh);
	};
	
	Scene_MajiangMenu.prototype.createBattlersWindow = function() 
	{
    	const rect = this.statusWindowRect();
    	
    	this._battlersWindow = new Window_MajiangMenuBattlers(rect);
    	
    	this._battlersWindow.setHandler("ok", this.onBattlerOk.bind(this));
		this._battlersWindow.setHandler("cancel", this.onBattlerCancel.bind(this));
    	this.addWindow(this._battlersWindow);
	};
	
	
	Scene_MajiangMenu.prototype.createMajiangGoldWindow = function() 
	{
    	const rect = this.majiangGoldWindowRect();
    	this._majiangGoldWindow = new Window_MajiangGold(rect);
    	this.addWindow(this._majiangGoldWindow);
	};
	
	Scene_MajiangMenu.prototype.majiangGoldWindowRect = function() 
	{
	    const ww = this.mainCommandWidth();
	    const wh = this.calcWindowHeight(1, true);
	    const wx = this.isRightInputMode() ? Graphics.boxWidth - ww : 0;
	    const wy = this.mainAreaBottom() - wh;
	    return new Rectangle(wx, wy, ww, wh);
	};
	
	
	Scene_MajiangMenu.prototype.commandStart = function()
	{
		const commonId = $dataMajiangSystem.menuData.startCommonId;
		if(commonId)
		{
			$gameTemp.reserveCommonEvent(commonId);
			this._applyStart = true;
			this.startCommonEvent();
		}
		else
		{
			this.startDuiju();
		}
	}
	Scene_MajiangMenu.prototype.startDuiju = function()
	{
		$gameSwitches.setValue(PP.duijuStarted,true);
		$dataMajiangSystem.menuData.started = true;
		$dataMajiangSystem.menuData.resultText = [];
		$gameMajiangSystem.start();
		
		const abstention = $dataMajiangSystem.menuData.abstention;
		
		const randomPosition = $dataMajiangSystem.menuData.randomPosition;
		
		$gameMajiangSystem.setCondition(...$dataMajiangSystem.menuData.members,randomPosition,4,-1,abstention);
		
		if($gameMajiangSystem.gotError())
		{
			throw new Error($gameMajiangSystem.makeErrorText());
		}
		else
		{
			MajiangManager.start();
			this.setTerminationFunc();
			SceneManager.push(Scene_MajiangBattle);
			
			switch($dataMajiangSystem.menuData.prevScene)
			{
				case "map" :
					PF_terminate();
					$gameMajiangSystem.setPrevScene(Scene_Map);
				break;
				
			}
		}
	};
	
	Scene_MajiangMenu.prototype.setTerminationFunc = function()
	{
		const commonId = $dataMajiangSystem.menuData.endCommonId;
		if(commonId)
		{
			const func = function(abstention)
			{
				$gameTemp.reserveCommonEvent(commonId);
			};
			$gameMajiangSystem.pushTerminationFunc(func);
		}
	};
	
	Scene_MajiangMenu.prototype.commandOptions = function()
	{
		SceneManager.push(Scene_MajiangOptions);
	};
	
	
	
	
	
	function Window_MajiangGold() 
	{
    	this.initialize(...arguments);
	}
	
	Window_MajiangGold.prototype = Object.create(Window_Selectable.prototype);
	Window_MajiangGold.prototype.constructor = Window_MajiangGold;
	
	Window_MajiangGold.prototype.initialize = function(rect)
	{
		Window_Selectable.prototype.initialize.call(this, rect);
		this._currentValue = null;
		this.refresh();
		
	};
	
	Window_MajiangGold.prototype.colSpacing = function()
	{
    	return 0;
	};
	
	Window_MajiangGold.prototype.refresh = function()
	{
		const value = this.value();
		if(this._currentValue !== value)
		{
			const rect = this.itemLineRect(0);
			const x = rect.x;
			const y = rect.y;
			const width = rect.width;
			this.contents.clear();
			this.drawCurrencyValue(value,this.currencyUnit(),x,y,width);
		}
	};
	
	
	Window_MajiangGold.prototype.value = function()
	{
		if(PP.gold === 1)
		{
			return $gameParty.gold();
		}
		else
		{
			return $gameVariables.value(PP.goldVariableId);
		}
	};
	
	Window_MajiangGold.prototype.currencyUnit = function()
	{
		if(PP.gold === 1)
		{
			return TextManager.currencyUnit;
		}
		else
		{
    		return PP.currencyUnit;
		}
	};
	
	Window_MajiangGold.prototype.open = function()
	{
    	this.refresh();
    	Window_Selectable.prototype.open.call(this);
	};
	
	
	
	
	
	
	
	function Window_MajiangMenuCommand() 
	{
    	this.initialize(...arguments);
	}
	
	Window_MajiangMenuCommand.prototype = Object.create(Window_Command.prototype);
	Window_MajiangMenuCommand.prototype.constructor = Window_MajiangMenuCommand;
	
	Window_MajiangMenuCommand.prototype.initialize = function(rect)
	{
		Window_Selectable.prototype.initialize.call(this, rect);
	    this.refresh();
	    this.selectLast();
	    this._canRepeat = false;
	};
	
	Window_MajiangMenuCommand._lastCommandSymbol = null;
	
	Window_MajiangMenuCommand.initCommandPosition = function() 
	{
    	this._lastCommandSymbol = null;
	};
	
	Window_MajiangMenuCommand.prototype.processOk = function() 
	{
    	Window_MajiangMenuCommand._lastCommandSymbol = this.currentSymbol();
    	Window_Command.prototype.processOk.call(this);
	};
	
	Window_MajiangMenuCommand.prototype.makeCommandList = function()
	{
		for(const command of $dataMajiangSystem.menuData.commands)
		{
			const commandData = command.split("_");
			const key = commandData[0];
			const ruleVolume = Number(commandData[1]) - 1;
			if(key === "rule")
			{
				const title = PP.gamerule[ruleVolume].title;
				this.addCommand(title, command, true,ruleVolume);
			}
			else if (key === "start")
			{
				this.addCommand(PP.text[key], command,this.duijuEnabled());
			}
			else
			{
				this.addCommand(PP.text[key],command,true);
			}
		}
	};
	
	Window_MajiangMenuCommand.prototype.selectLast = function() 
	{
    	this.selectSymbol(Window_MajiangMenuCommand._lastCommandSymbol);
	};
	
	Window_MajiangMenuCommand.prototype.duijuEnabled = function()
	{
		return (!PP.duijuDisabled || !$gameSwitches.value(PP.duijuDisabled));
	};
	
	Window_MajiangMenuCommand.prototype.updateDuijuEnabled = function()
	{
		const startCommand = this._list.find(c => c.symbol === "start")
		if(startCommand && startCommand.enabled !== this.duijuEnabled())
		{
			this.refresh();
		}
	};
	
	
	
	function PF_minUnfixedActorIndex()
	{
		const value = [0,1,2,3].filter(v => !$dataMajiangSystem.menuData.fixed.includes(v));
		return Math.min(...value) || 0;
	}
	
	
	
	
	function Window_MajiangMenuStatus() 
	{
	    this.initialize(...arguments);
	}
	
	Window_MajiangMenuStatus.prototype = Object.create(Window_Selectable.prototype);
	Window_MajiangMenuStatus.prototype.constructor = Window_MajiangMenuStatus;
	
	Window_MajiangMenuStatus.prototype.initialize = function(rect) 
	{
    	Window_Selectable.prototype.initialize.call(this, rect);
    	this._actors = [];
    	this.refresh();
	};
	
	Window_MajiangMenuStatus._selectLast = null;
	
	
	Window_MajiangMenuStatus.initSelectLast = function() 
	{
    	this._selectLast = PF_minUnfixedActorIndex();
    	
	};
	
	
	
	Window_MajiangMenuStatus.prototype.processOk = function() 
	{
    	Window_MajiangMenuStatus._selectLast = this.index();
    	Window_Selectable.prototype.processOk.call(this);
	};
	
	Window_MajiangMenuStatus.prototype.maxItems = function() 
	{
    	return 4;
	};
	
	Window_MajiangMenuStatus.prototype.itemHeight = function() 
	{
    	return Math.floor(this.innerHeight / this.maxItems());
	};
	
	Window_MajiangMenuStatus.prototype.isCurrentItemEnabled = function() 
	{
    	return this.isEnabled(this.index());
	};
	
	Window_MajiangMenuStatus.prototype.isEnabled = function(index) 
	{
		if(!this.active ) return true;
    	return (!$dataMajiangSystem.menuData.fixed.includes(index));
	};
	
	
	
	Window_MajiangMenuStatus.prototype.refresh = function()
	{
		this._actors = $dataMajiangSystem.menuData.members;
		Window_Selectable.prototype.refresh.call(this);
	};
	
	
	
	
	
	
	Window_MajiangMenuStatus.prototype.drawItem = function(index) 
	{
		this.changePaintOpacity(this.isEnabled(index));
    	const actorId = this._actors[index];
    	const actor = $gameMajiangSystem.actorData(actorId);
    	const rect = this.itemRect(index);
    	const padding = this.itemPadding();
    	let x = rect.x + padding;
    	
    	const textY = rect.y + ((rect.height - this.lineHeight()) / 2);
    	const statusText = PP.text["position_" + index];
    	
    	const statusWidth = Math.floor(rect.height / 2);
    	if(!$dataMajiangSystem.menuData.randomPosition || index === 0)
    	{
    		this.drawText(statusText,x,textY,statusWidth,"center");
    	}
    	x += statusWidth + padding;
    	const imgWidth = ImageManager.faceWidth;
    	const imgHeight = rect.height - 2;
    	
    	if(actor)
    	{
    		this.drawActorFace(actor, x + 1, rect.y + 1, imgWidth, imgHeight);
    	}
    	x += imgWidth + padding;
    	const nameText = (actor) ? actor.name() : PP.text.empty;
    	
    	const nameWidth = rect.width - (x - rect.x);
    	this.drawText(nameText,x, textY,nameWidth);
    	this.changePaintOpacity(true);
	};
	
	Window_MajiangMenuStatus.prototype.drawActorFace = function(
    actor, x, y, width, height
	) 
	{
    	this.drawFace(actor.faceName(), actor.faceIndex(), x, y, width, height);
	};
	
	Window_MajiangMenuStatus.prototype.selectLast = function()
	{
		this.forceSelect(Window_MajiangMenuStatus._selectLast || 0);
	};
	
	
	
	
	
	
	function Window_MajiangMenuBattlers() 
	{
	    this.initialize(...arguments);
	}
	
	Window_MajiangMenuBattlers.prototype = Object.create(Window_Selectable.prototype);
	Window_MajiangMenuBattlers.prototype.constructor = Window_MajiangMenuBattlers;
	
	Window_MajiangMenuBattlers.prototype.initialize = function(rect) 
	{
		this._actors = [];
		this._isZijia = false;
		this._isReady = false;
		this._compensate = false;
    	Window_Selectable.prototype.initialize.call(this, rect);
    	this.openness = 0;
    	
    	this.refresh();
	};
	
	Window_MajiangMenuBattlers.prototype.maxItems = function() 
	{
    	return this._actors.length || 0;
	};
	
	Window_MajiangMenuBattlers.prototype.itemHeight = function() 
	{
    	return Math.floor(this.itemWidth());
	};
	
	
	
	Window_MajiangMenuBattlers.prototype.maxCols = function() 
	{
    	return 4;
	};
	
	Window_MajiangMenuBattlers.prototype.actorId = function() 
	{
    	return this._actors[this.index()];
	};
	
	Window_MajiangMenuBattlers.prototype.setZijia = function(value) 
	{
    	this._isZijia = value;
	};
	Window_MajiangMenuBattlers.prototype.setCompensate = function(value) 
	{
    	this._compensate = value;
	};
	
	
	Window_MajiangMenuBattlers.prototype.setActors = function() 
	{
    	let actors = [...$dataMajiangSystem.menuData.actors];
    	
    	const members =  $dataMajiangSystem.menuData.members;
    	
    	const fixed = $dataMajiangSystem.menuData.fixed;
	    
	    if(!$dataMajiangSystem.menuData.canChongfu)
	    {
	    	const fixedMembers = fixed.map(id => members[id]);
	    	
	    	actors = actors.filter(a => !fixedMembers.includes(a));
	    	if(!this._zijia && this._compensate)
	    	{
	    		actors = actors.filter(a => a !== members[0]);
		    }
	    }
	    const fixedEmptyNum = members.reduce(function(r,c,i)
	    {
	    	if(c === 0 && fixed.includes(i))
	    	{
	    		return r + 1;
	    	}
			return r;
		},0)
		
	    
	    
	    
    	if((this.maxEmptyNum() > fixedEmptyNum) && !this._isZijia)
    	{
    		actors.unshift(0);
	    }
    	this._actors = actors;
	};
	
	Window_MajiangMenuBattlers.prototype.maxEmptyNum = function()
	{
		return 4 - $dataMajiangSystem.menuData.minBattlerNum;
	}
	
	Window_MajiangMenuBattlers.prototype.refresh = function()
	{
		this._isReady = false;
		this.setActors();
		Window_Selectable.prototype.refresh.call(this);
	};
	
	Window_MajiangMenuBattlers.prototype.isCurrentItemEnabled = function() 
	{
		const actorId = this.actorId();
    	return (actorId || actorId === 0);
	};
	
	
	
	
	Window_MajiangMenuBattlers.prototype.drawItem = function(index) 
	{
    	const actorId = this._actors[index];
    	const actor = $gameMajiangSystem.actorData(actorId);
    	const rect = this.itemRect(index);
    	const padding = this.itemPadding();
    	const x = rect.x;
    	const width = rect.width - 2;
    	const textHeight = this.lineHeight();
    	const imgHeight = (rect.height - 2) - textHeight;
    	const textY = rect.y + (rect.height - (textHeight + 1));
    	
    	if(actor)
    	{
    		this.drawActorFace(actor, x + 1, rect.y + 1, width, imgHeight);
    	}
    	
    	const nameText = (actor) ? actor.name() : PP.text.empty;
    	
    	
    	this.drawText(nameText,x, textY,width,"center");
	};
	
	Window_MajiangMenuBattlers.prototype.drawActorFace = function(
    actor, x, y, width, height
	) 
	{
    	this.drawFace(actor.faceName(), actor.faceIndex(), x, y, width, height);
	};
	
	Window_MajiangMenuBattlers.prototype.select = function(index)
	{
		Window_Selectable.prototype.select.call(this,index);
		this.refresh();
	};
	
	Window_MajiangMenuBattlers.prototype.update = function()
	{
		Window_Selectable.prototype.update.call(this);
		
		if(!this._isReady)
		{
			if(ImageManager.isReady())
			{
				
				this.refresh();
				this._isReady = true;
			}
			
		}
	};
	
	
	
	function Window_MajiangHelp() 
	{
    	this.initialize(...arguments);
	}
	
	Window_MajiangHelp.prototype = Object.create(Window_Base.prototype);
	Window_MajiangHelp.prototype.constructor = Window_MajiangHelp;
	
	
	Window_MajiangHelp.prototype.initialize = function(rect)
	{
		Window_Base.prototype.initialize.call(this, rect);
	};
	
	
	Window_MajiangHelp.prototype.setText = function(text)
	{
		const rect = this.baseTextRect();
		this.contents.clear();
		this.drawTextEx(text, rect.x, rect.y, rect.width);
	};
	
	
	
	
	
	
	
	
	
	function PF_parseBoolean(data,gp,keys)
	{
		for(const key of keys)
		{
			data[key] = (gp[key] === "true");
		}
	}
	
	function PF_addActors(actorIdArray)
	{
		const data = PF_data();
		for(const actorId of actorIdArray)
		{
			if(actorId && !data.actors.includes(actorId))
			{
				data.actors.push(actorId);
			}
		}
		data.actors.sort((a,b) => a- b);
	}
	
	function PF_deleteActors(actorIdArray)
	{
		const data = PF_data();
		data.actors = data.actors.filter(a => !actorIdArray.includes(a))
	}
	
	function PF_parseMembers(string)
	{
		const data = JSON.parse(string || "{}");
		
		const members = [];
		const membersVariableId = [];
		for(const position of ["zijia","shimojia","duimian","kamijia"])
		{
			const varId = Number(data[position]);
			const actorId = $gameVariables.value(varId) || 0;
			members.push(actorId);
			membersVariableId.push(varId);
		}
		$dataMajiangSystem.menuData.members = members;
		$dataMajiangSystem.menuData.membersVariableId = membersVariableId;
		
	}
	
	
	
    
	PluginManager.registerCommand(P_name,"start",args =>  
	{
		const data = PF_data();
		
		$gameSwitches.setValue(PP.duijuStarted,false);
		
		$dataMajiangSystem.menuData.actors = data.actors;
		
		$dataMajiangSystem.menuData.commands = JSON.parse(args.commands || "[]");
		
		$dataMajiangSystem.menuData.endCommonId = Number(args.endCommonId);
		$dataMajiangSystem.menuData.startCommonId = Number(args.startCommonId);
		
		
		PF_parseBoolean($dataMajiangSystem.menuData,args,[
			"canChongfu" ,"abstention","loadMembers","randomPosition","echoHelp"
		]);
		
		
		$dataMajiangSystem.menuData.prevScene = args.prevScene;
		
		$dataMajiangSystem.menuData.fixed = JSON.parse(args.fixed || "[]").map(v => Number(v));
		
		const battlerNum = args.battlerNum.split("_");
		
		$dataMajiangSystem.menuData.maxBattlerNum = Number(battlerNum[0]);
		$dataMajiangSystem.menuData.minBattlerNum = Number(battlerNum[1]);
		
		PF_parseMembers(args.members);
		
		PF_addActors($dataMajiangSystem.menuData.members);
		
		
		
		$dataMajiangSystem.menuData.helpText = args.helpText;
		
		Window_MajiangMenuCommand.initCommandPosition();
		SceneManager.push(Scene_MajiangMenu);
		
		
	});
	
	PluginManager.registerCommand(P_name,"addActors",args =>  
	{
		const actors1 = JSON.parse(args.actors || "[]").map(v => Number(v));
		const actors2 = JSON.parse(args.actorsVariable || "[]").map(v => $gameVariables.value(Number(v)));
		const actors = actors1.concat(actors2);
		
		PF_addActors(actors);
	});
	
	PluginManager.registerCommand(P_name,"deleteActors",args =>  
	{
		const actors1 = JSON.parse(args.actors || "[]").map(v => Number(v));
		const actors2 = JSON.parse(args.actorsVariable || "[]").map(v => $gameVariables.value(Number(v)));
		const actors = actors1.concat(actors2);
		
		PF_deleteActors(actors);
	});
	
	
	PluginManager.registerCommand(P_name,"clearActors",args =>  
	{
		const data = PF_data();
		data.actors = [];
		
	});
	
	
	
	
	
})();
