----##### th105_ai_lib_20090105SetInputの代わり(追加変更点は最下部) #####
require("WaitEx.txt")			--damaged , waitEx , waitEx2 , waitTachi , waitMotion

--SetInput		改変版




--機能：引数commandで与えられた文字列を元にコマンド入力する
--SetInput=function( command [, exception [, motion [, ...] ] ] )
--
--		コマンド入力中は引数exceptionで与えられた関数に'...'を与えて呼び出し、戻り値が偽の場合はキーリセットしてコマンド入力を中断します
--		引数motionにモーション値を与えた場合、コマンド入力完了後キー状態そのままで待機し、指定したモーションになったら終了します
--		(↑一定時間経過してもそのモーションにならない場合、キーリセットして立ち状態になるのを待ちます)
--		引数motionに"."を与えた場合、コマンド入力完了後に即終了します
--		引数exeptionとmotionは順番が逆の方が自然ですが、改変前との互換を考えてこんな感じにしてみました
--
--使用例
--	①：	SetInput("236B");
--	②：	SetInput("236B",nil,500);
--	③：	SetInput("236B",nil,".");
--	④：	SetInput("252BH5(50)252CH5(50)");
--	⑤：	SetInput("252BH5(50)252CH5(50)",nil,0);
--	⑥：	SetInput("2A(8)A(8)A(8)6A(13)",get_fflags(TAG_ENEMY,8));
--	⑦：	SetInput("252BH5(50)252CH5(50)4AE5(55)b2A5(55)cx4A5");
--	⑧：	waitTime=8;	SetInput("2A("..waitTime..")6A");
--	⑨：	SetInput("252BH5",nil,0);	--22+Bのモーション＞硬直解除に時間がかかるため、危険。"252B5(20)"とかするべき。
--
--(使用例解説)
--	①……スキル236+Bを入力します。入力後はキーリセットして、立ちモーションになるまで待機します。
--	②……スキル236+Bを入力します。入力後はキー状態そのままで、モーション値が500になるまで待機します。
--	③……スキル236+Bを入力します。入力後はキー状態そのままで即終了します。
--	④……スキル22+B(ホールド),22+C(ホールド)を連続で入力します。入力後はキーリセットするので、ホールドは解除されます。
--	⑤……スキル22+B(ホールド),22+C(ホールド)を連続で入力します。入力後はキー状態そのままなので、ホールドは継続されます。
--	⑥……(2A)*3＞6Aの連携を入力します。連携途中で相手が空中にいたらその時点でキーリセットして入力を中断します。
--	⑦……ホールドを使って複数のボタンを同時に操作してみた例。
--	⑧……SetInput("2A(8)6A");	と同じ。文字列は'..'で連結できるし、変数の数値を使うこともできます。
--	⑨……バカ


--################################################# コマンド入力規則(改変前とほぼ同様) #################################################
--##<<コマンド入力に使える文字列は、以下の文字を任意に並べたものです>>
--##
--##・レバー文字{ "1","2","3","4","5","6","7","8","9" }
--##	その文字に対応する方向へレバー入力します。
--##	入力前に「yield＞全方向key_off」が実行されます。
--##	入力後は自動的にホールドされます。ホールドは次のレバー文字が来るまで続きます。
--##	レバーニュートラルが必要なときは"5"を書かなければなりません。
--##
--##・ボタン文字{ "A","B","C","D","E","F" }
--##	その文字に対応するボタンを入力します("E"はACT_AB,"F"はACT_BCに対応)。
--##	直前の文字が"H"でない限り、入力後に「ホールド中でない全ボタンkey_reset＞yield」が実行されます。
--##
--##・ホールド文字{ "H" }
--##	直前のレバー文字に対応するボタンをホールドします。
--##	ホールドは次の(対応する)ホールド解除文字が来るまで続きます。
--##
--##・ホールド解除文字{ "a","b","c","d","e","f" }
--##	対応するボタンのホールドを解除します。
--##	入力後に「yield」が実行されます。
--##
--##・待機文字{ "("..n..")" }	……nは任意正数
--##	数字nを()で括ると待機文字になります。
--##	キー状態そのままでnフレーム待機します。
--##	例えば"(26)"とすれば26フレーム待機します。
--##
--##・固定待機文字{ "_","v","x" }
--##	それぞれ"(1)","(5)","(10)"と同じ働きをします。
--##
--##
--##
--##
--##※改変前との差異
--##	改変前は一つのボタンしかホールドできず、複数のボタンを同時に押した状態にできません。改変後は複数のボタンに対応しています。
--##	改変前はACT_BCについての一部動作(ホールドなど)に対応していません。改変後は他のボタンと同等に扱っています。
--##	
--######################################################################################################################################





----#### 関数本体 ####
--使用カスタマイズ関数：waitEx2(), waitTachi() , waitMotion()
--使用定数：キー：ACT_UP～ACT_BC
function SetInput( command , exception , motion , ... )
	local counter = 1	--現在何番目の文字を処理しているか
	local oldInput = ""	--文字列比較を行うため、nil以外の初期値を設定する
	local waitProc		--waitフレーム数指定文字列作成中か。作成中ならtrue
	local hold_btn={}	--各ボタンのホールド状況
	
	--引数で与えられたコマンド1文字ずつについて入力処理を行う
	for input in string.gmatch( command, ".") do
	
	--直前の値に対する処理
		--直前がA～Fの場合
		if oldInput >= "A" and oldInput <= "F" then
			--現在の値が"H"なら、直前の入力をkey_offせずホールド(押しっぱ)する。
			if input == "H" then
				--新しくホールドするボタンを追加
				hold_btn[oldInput]=true;
			
			--現在の値が"H"以外なら、A～Fの後にyieldとkey_offとyieldをはさむ。("6C"は同時押しできる。"AxA"はxの前にA離す)
			else
				--1フレより2フレのほうが、キー抜け(コマンド失敗)の確率が低い
				if not waitEx2(2, exception, ...) then
					return false;
				end
				--A～Fのうちホールド中でないものをkey_offする。
				if not hold_btn.A then	key_off( ACT_A );	end
				if not hold_btn.B then	key_off( ACT_B );	end
				if not hold_btn.C then	key_off( ACT_C );	end
				if not hold_btn.D then	key_off( ACT_D );	end
				if not hold_btn.E then	key_off( ACT_AB );	end	--E
				if not hold_btn.F then	key_off( ACT_BC );	end	--F
				--現在の値に関わらず、その前にyieldする
				--1フレより2フレのほうが、キー抜け(コマンド失敗)の確率が低い
				if not waitEx2(2, exception, ...) then
					return false;
				end
			end
		
		--直前がa～fの場合
		elseif oldInput >= "a" and oldInput <= "f" then
			--ホールド状態を削除
			hold_btn[oldInput]=false;
			--現在の値に関わらず、その前にyieldする
			if not waitEx2(1, exception, ...) then
				return false;
			end
		end
		
	--現在の値に対する処理
		--waitフレーム数指定用文字列作成中の場合
		if waitProc then
			if input >= "0" and input <= "9" then
				--"0"～"9"を元にwaitフレーム数指定用文字列を作成する
				waitString = waitString .. input
			elseif input == ")" then
				--括弧で囲まれた文字を数値としてwaitする
				if not waitEx2(tonumber(waitString), exception, ...) then
					return false;
				end
				waitProc = false;
			end
		
		--上記以外の場合
		--(通常の場合)
		else
			--現在1～9の場合
			--1～9の前にkey_offとyieldをはさむ。("236C"ができる。)
			if input >= "1" and input <= "9" then
				--1～9の前にyieldする(ただし1文字目はyieldしない)
				if counter > 1 then
					--1フレより2フレのほうが、キー抜け(コマンド失敗)の確率が低い
					if not waitEx2(2, exception, ...) then
						return false;
					end
				end
				--1～9の前に全方向key_offする
				key_off( ACT_UP );
				key_off( ACT_DOWN );
				key_off( ACT_LEFT );
				key_off( ACT_RIGHT );
				--key_off( ACT_DLEFT );
				--key_off( ACT_DRIGHT );
				--key_off( ACT_ULEFT );
				--key_off( ACT_URIGHT );
			end
			
			--"1"～"9", "A～E"などの文字を元にキー入力を行う
			if input == "1" then
				key_on( d_back )
			elseif input == "2" then
				key_on( ACT_DOWN )
			elseif input == "3" then
				key_on( d_front )
			elseif input == "4" then
				key_on( back )
			elseif input == "5" then
				--レバーニュートラル(別途"1"～"9"共通処理にて処理済)
			elseif input == "6" then
				key_on( front )
			elseif input == "7" then
				key_on( u_back )
			elseif input == "8" then
				key_on( ACT_UP )
			elseif input == "9" then
				key_on( u_front )
			--ボタン押し
			elseif input == "A" then
				key_on( ACT_A )
			elseif input == "B" then
				key_on( ACT_B )
			elseif input == "C" then
				key_on( ACT_C )
			elseif input == "D" then
				key_on( ACT_D )
			elseif input == "E" then
				key_on( ACT_AB )
			elseif input == "F" then
				key_on( ACT_BC )
			elseif input == "H" then
				--ホールド(別途処理済)
			--ホールド(押しっぱ)解除
			elseif input == "a" then
				key_off( ACT_A )
				hold_btn.A=false;
			elseif input == "b" then
				key_off( ACT_B )
				hold_btn.B=false;
			elseif input == "c" then
				key_off( ACT_C )
				hold_btn.C=false;
			elseif input == "d" then
				key_off( ACT_D )
				hold_btn.D=false;
			elseif input == "e" then
				key_off( ACT_AB )
				hold_btn.E=false;
			elseif input == "f" then
				key_off( ACT_BC )
				hold_btn.F=false;
			--yield
			elseif input == "(" then
				waitProc = true
				waitString = ""	--初期化
			elseif input == "_" then
				if not waitEx2(1, exception, ...) then
					return false;
				end
			elseif input == "v" then
				if not waitEx2(5, exception, ...) then
					return false;
				end
			elseif input == "x" then
				if not waitEx2(10, exception, ...) then
					return false;
				end
			end
		end
		
		--1文字前の入力コマンドの値を保存する
		oldInput = input
		--何番目の文字を処理しているかの変数をカウントアップする
		counter = counter + 1
	end
	
--文字列loop後
	
	--最後のキー入力を成立させるためyieldする
	--1フレより2フレのほうが、キー抜け（コマンド失敗）の確率が低い
	if not waitEx2(2, exception, ...) then
		return false;
	end

--[[
	--方向キーもボタンも離す
	--問題：ホールド(押しっぱ)終了ができない。対策：押しっぱ部分はSetInputを使わず、押しっぱ直前までの入力にし、押しっぱは別途記述する
	key_reset()
	--yieldする。問題：最後Cだと最速ではない(1フレ余分)。最速欲しいなら別途関数作って対処
	if not waitEx2(1, exception, ...) then
		return false;
	end
--]]
----※↑キーリセットはwaitTachi()に任せて、ここでは実行しないようにする……キー状態そのままで終了できる

	--指定したモーションになるまで待つ(指定がなければ立ち状態)
	--ここに融通を利かせたかったので、引数をあんな感じにしてみた
	--waitTachi()が必要ならばそのときにやれば良い、ということで
	return motion==nil and waitTachi() or motion=="." and true or waitMotion(motion);
end

----#### fin...関数本体 ####





----#### 追加変更点 ####
----・関数exceptionに任意の引数を渡せるように変更
----・戻り値をtrue(完遂)又はfalse(中断)に変更
----・経過フレーム数を記録するelapsedFrameを削除……exceptionの引数は可変引数'...'とする
----・関数exceptionの戻り値を記録するexcCodeを削除……中断の判定はexception(...)の真偽で直接判定する
----・立ち状態に限らず好きなモーションで終了できるように変更
----・キー状態そのままで終了できるように変更
----・実行中に被ダメ等があったらすぐに中断するよう変更
----・ACT_DOWNLEFTなどをACT_DLEFTなどに変更(ただし未使用)
