/*-------------------------------------------------------------



	control.txt

	コントロールシステムのオーバービューおよび

	game/control.c内関数のリファレンス



	2000/03/28 M.Sonoyama

	$Id: control.txt,v 1.1.1.3 2002/11/19 11:41:41 Yoshizawa1 Exp $

	

	Metal Gear Solid2 Project for PlayStation2



--------------------------------------------------------------*/	



■コントロールシステム概要

	コントロールシステムは、キャラクタの移動を制御するシステムです。

	具体的には、キャラクタの現在の位置・方向と、移動量・目標方向を設定しておくと、

	壁・床との当たりチェックを行い、適当な位置・方向にキャラクタの位置・方向を

	更新します。さらに、その更新後の値を用いて、トラップイベント処理、マップ間移動処理

	アドレス更新処理、メッセージ受信処理も同時に行います。



■コントロール構造体

	game/g_struct.h内に定義



■コントロール初期設定

	コントロールを初期化する手順は、基本的には

	以下のようになります。

	（個々の関数については後述。）



	//コントロールシステムに登録

	GM_InitControl( CONTROL *ctrl, int name, int map ) ;

	//位置・方向を初期化

	GM_ConfigControlPosition( CONTROL *ctrl, FVECTOR *pos, SVECTOR *rot ) ;

	//当たりチェックパラメータ設定

	GM_ConfigControlHazard( CONTROL *ctrl, int height, int r_sphere, int s_sphere ) ;



	//以下、必要に応じて、



	//当たり判定高さ設定( control->mov.vy ではなく、base + height でチェックする。

	//		      base はチェック毎に更新される。）

	GM_ConfigControlHzxHeight( CONTROL *, float height, float base ) ;

	//トラップイベント処理を行う。

	GM_ConfigControlTrapCheck( CONTROL * ) ;

	//メッセージ受信処理を行う。

	GM_ConfigControlMessageCheck( CONTROL * ) ;

	//マップ変更チェック処理を行う。

	GM_ConfigControlMapCheck( CONTROL * ) ;

	//アドレス更新処理を行う。

	GM_ConfigControlAddressCheck( CONTROL * ) ;

	//カメラトラップをチェックする。（シナリオで -cameraオプションのついたトラップを

	//				  実行する。）

	GM_ConfigCameraTrapCheck( CONTROL * ) ;



■コントロール処理の方法

	毎フレームのキャラクタ移動処理の具体的な方法は

	基本的に以下のようになります。



	CONTROL		*control ;



	//移動量設定

	control->step = （そのフレームでの移動量） ;

	//目標方向設定

	control->turn = （目標方向） ;

	//キャラクタの床からの高さを設定

	//（床の上に立った時、control->mov.vyの値が床からどれだけの高さにあるか）

	control->height = （床からの高さ） ;

	//キャラクタ移動処理実行

	GM_ActControl( control ) ;



■ActControlの挙動

	・GM_CurrentMapをセット

	・モーション変更時、height調節処理

	・壁チェック

		・有効桁数落ち防止の為、チェックＹ座標を整数化する。

		・近接壁チェック

			・移動直線ハザード交差チェック

			・skip_flag & CTRL_NEAR_CHECK2 != 0 ならば、近接壁チェック２

	・床チェック

	・ゾーンアドレ更新

	・マップ変更チェック

		・マップ変更の場合、近接壁チェックに戻る。

	・向き更新

	・トラップ進入チェック

		・トラップ処理でマップ変更の場合、もう一度トラップチェックする。

	・メッセージ受信

	・DG_SetPos2( &ctrl->mov, &ctrl->rot ) ;



■関数リファレンス



-----------------------------------------------------------------------



	CONTROL	*GM_SearchWhere( int name ) ;



	＜引数＞ 	： キャラクタの名前

	＜返り値＞	： CONTROL へのポインタ、なかった場合はＮＵＬＬ

	＜説明＞

		CONTROLリストに登録されている中から、

		nameという名前のものを検索し、ポインタを返す。



-----------------------------------------------------------------------



	int	GM_InitControl( CONTROL *ctrl, int name, int map ) ;

		

	＜引数＞ 	： CONTROLへのポインタ、登録名、存在マップ

	＜返り値＞	： 正常終了 ０、異常終了 －１

	＜説明＞	ctrlで示されるCONTROL構造体をCONTROLリストに

				nameという名前で登録します。

				同時に、mapで示されるマップ情報をctrlに接続します。

	＜注意＞	name == 0のときはリストへの登録を行いません。

			また、デフォルトでは、CONTROLは以下の様に初期化されます。

				・トラップイベント処理なし

				・メッセージ受信処理なし

				・マップ変更チェック処理なし

				・アドレス変更チェック処理なし



-----------------------------------------------------------------------



	void	GM_ActControl( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	キャラクタ移動処理

	＜注意＞	上記、■コントロール処理の方法を参照



-----------------------------------------------------------------------



	void	GM_FreeControl( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	CONTROLリストから削除します。

	＜注意＞	キャラクタの終了処理でコールしてください。



-----------------------------------------------------------------------



	void		GM_ConfigControlObject( CONTROL *ctrl, OBJECT *object ) 



	＜引数＞ 	： CONTROLへのポインタ、OBJECTへのポインタ

	＜返り値＞	： なし

	＜説明＞	オブジェクト構造体へのポインタを接続する。

	＜注意＞	



-----------------------------------------------------------------------

	

	void	GM_ConfigControlNoSegmentArea( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	CONTROL構造体内の、検出壁・床格納領域を解放します。

	＜注意＞	当たりチェックを一切行わないキャラクタの場合に、

				GM_InitControlコール後に、この関数をコールしてください。



-----------------------------------------------------------------------



	void	GM_ConfigControlMapID( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	ctrl->movから、そのキャラがどのマップにいるかを

			取得し、ctrl構造体にセットします。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlPosition( CONTROL *ctrl, FVECTOR *pos, SVECTOR *rot ) ;



	＜引数＞ 	： CONTROLへのポインタ、初期位置、初期方向

	＜返り値＞	： なし

	＜説明＞	ctrl構造体に位置と方向をセットします。

	＜注意＞	上記のGM_ConfigControlMapIDはこの関数内からコールされます。



-----------------------------------------------------------------------



	void	GM_ConfigControlHazard( CONTROL *ctrl, int height, int r_sphere, int s_sphere ) ;



	＜引数＞ 	： CONTROLへのポインタ、初期高さ、反発半径、検出半径

	＜返り値＞	： なし

	＜説明＞	ctrl構造体に当たりチェックパラメータをセットします。

	＜注意＞	引数の意味は以下の通りです。

			・初期高さ：床からctrl->movまでの高さ（キャラの足から腰までの高さ）

			・反発半径：壁に当たった時、この値だけ壁から離れた位置にキャラクタを

			  	    移動させます。

			・検出半径：キャラからこの値を半径とする水平円内から壁を検出します。

	

-----------------------------------------------------------------------



	void	GM_ConfigControlHzxHeight( CONTROL *ctrl, float height, float base ) ;



	＜引数＞ 	： CONTROLへのポインタ、壁チェック高さ、床チェック基準高さ

	＜返り値＞	： なし

	＜説明＞	ctrl構造体に当たりチェックパラメータをセットします。

	＜注意＞	引数の意味は以下の通りです。

			・壁チェック高さ：キャラの最低位置からこの値だけ上の位置の

			  		  水平円内から壁を検出します。

					  この関数がコールされてない場合は、

					  control->mov.vyの位置の水平円で検出します。

			・床チェック基準高さ：キャラの初期位置での床の高さです。

					      移動処理毎に更新されます。



-----------------------------------------------------------------------



	void	GM_ConfigControlHzxCheckFlag( CONTROL *ctrl, int segflag, int flrflag )



	＜引数＞ 	： CONTROLへのポインタ、壁チェックフラグ、床チェックフラグ

	＜返り値＞	： なし

	＜説明＞	ctrl構造体に当たりチェックパラメータをセットします。

	＜注意＞	GM_ActControl処理で当たりチェック関連の関数に、segflag, flrflagが渡され

				るようになります。



-----------------------------------------------------------------------



	void	GM_ConfigControlMapCheck( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	そのキャラがマップ変更チェック処理をする場合にコールしてください。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlAddressCheck( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	そのキャラがアドレス変更チェック処理をする場合にコールしてください。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlTrapCheck( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	そのキャラがトラップイベント処理をする場合にコールしてください。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlMessageCheck( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	そのキャラがメッセージ受信処理をする場合にコールしてください。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlCameraTrapCheck( CONTROL *ctrl ) ;



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： なし

	＜説明＞	そのキャラがカメライベント処理をする場合にコールしてください。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ConfigControlAttribute( CONTROL *ctrl, int atr )



	＜引数＞ 	： CONTROLへのポインタ、アトリビュート

	＜返り値＞	： なし

	＜説明＞	アトリビュートを設定します。

	＜注意＞	各アトリビュートは、g_struct.hに記載。



-----------------------------------------------------------------------

	void	GM_ConfigControlNearCheck2( CONTROL *ctrl, float height )	



	＜引数＞ 	： CONTROLへのポインタ、２つめの近接壁チェック高さ

	＜返り値＞	： なし

	＜説明＞	近接壁チェック高さをもう一つ設定します。

	＜注意＞	２点で近接壁チェックをするときにコールしてください。

				リセットされるので、毎実行時にコールしてください。

				例えば、GM_ConfigControlHzxHeightのheightに750をセットして、

				GM_ActControlをコールする前に、

				GM_ConfigControlNearCheck2( ctrl, 250.0F ) をコールすると、

				高さ ctrl->hzx_base + 750.0F と ctrl->hzx_base + 250.0F の		

				2点で近接壁チェックをして、近いほうの結果を格納します。

				

-----------------------------------------------------------------------



	void	GM_ResetControlPosition( CONTROL *ctrl, FVECTOR *pos ) ;



	＜引数＞ 	： CONTROLへのポインタ、移動位置

	＜返り値＞	： なし

	＜説明＞	そのキャラの位置をposに強制移動します。

	＜注意＞	



-----------------------------------------------------------------------



	void	GM_ResetControlPositionAndGroup( CONTROL *ctrl, FVECTOR *pos, HZX_GROUP_ID hzx_id ) ;



	＜引数＞ 	： CONTROLへのポインタ、移動位置、当たりグループ

	＜返り値＞	： なし

	＜説明＞	そのキャラの位置をposに強制移動します。

			新位置でのマップグループとゾーンの更新も行います。

	＜注意＞	



-----------------------------------------------------------------------



	int	GM_CheckInsideTrap( CONTROL *, u_int *traps, int n_traps, int mode ) ;



	＜引数＞ 	： CONTROLへのポインタ、トラップリスト、トラップリスト内トラップ数、モード

	＜返り値＞	： トラップ侵入情報（ビットフラグ）侵入していれば１。

			   リストの１番に侵入していると、0x0001

			   リストの２番に侵入していると、0x0002

			   リストの３番に侵入していると、0x0004 というふうになります。

	＜説明＞	トラップリスト内のトラップに侵入しているかをチェックします。

	＜注意＞	モードが０の時、名前ありトラップは区別しません。

			(trap:01 trap:02 ・・・は全て、trap という名前でチェックします。）

			モードが１の時は、名前も区別します。



-----------------------------------------------------------------------



	int		GM_CtrlWorldLimit( CONTROL *ctrl )



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： ０、１

	＜説明＞	ctrl->mov.vy が GM_WORLD_LIMIT_UPPER以上か、

				GM_WORLD_LIMIT_LOWER以下のとき１を返します。

	＜注意＞	



-----------------------------------------------------------------------



	void		GM_ControlResetHeightMotion( CONTROL *ctrl )



	＜引数＞ 	： CONTROLへのポインタ

	＜返り値＞	： 

	＜説明＞	コールすると、

	   	 		次のモーション切り替え時に、GM_ActControl処理の最初で、

				ctrl->heightを設定しなおします。

	＜注意＞	ctrl->object->m_ctrlがNULLだとハングします。



-----------------------------------------------------------------------



■当たり情報の取得方法

	GM_ActControlコール後には、

	CONTROL構造体には、キャラの接触した当たりの情報が入っています。

	それらは以下の通りです。



	control->n_touches 	： 検出壁数（最大２）

	control->atrs[ 2 ]	： 検出壁アトリビュート

	control->vecs[ 2 ]	： 検出壁最近点へのベクトル

	control->segs[ 2 ]	： 検出壁（ＨＺＸ＿ＳＥＧ構造体へのポインタ）



	control->grounded	： 0x01:床に接地、0x02:天井に接地（？）

	control->levels[ 2 ]	： 検出床・天井高さ

	control->level_found	： 床検出フラグ、0x01:床あり、0x02:天井あり

	control->flr_atrs[ 2 ]	： 検出床・天井アトリビュート

	control->level[ 2 ]	： 検出床（ＨＺＸ＿ＦＬＲ構造体へのポインタ）



■特殊な使い方



	◆skip_flagの仕様



	CONTROL構造体のメンバ skip_flag を設定することで、

	以下の様な事を行うことができます。

	適切にフラグを設定することで全体の処理を軽く出来ます。



	skip_flag |= CTRL_SKIP_SEG_CHECK	： 壁当たりチェックを行わない。

	skip_flag |= CTRL_SKIP_FLR_CHECK	： 床当たりチェックを行わない。

	skip_flag |= CTRL_SKIP_TRAP			： トラップイベント処理を行わない。

	skip_flag |= CTRL_SKIP_MESSAGE		： メッセージ受信処理を行わない。

	skip_flag |= CTRL_SKIP_CHANGE_MAP	： マップ変更処理を行わない。

	skip_flag |= CTRL_SKIP_GET_ADDRESS	： アドレス変更処理を行わない。

	skip_flag |= CTRL_SKIP_NEAR_CHECK	： 近接壁チェックを行わない。

	skip_flag |= CTRL_SKIP_ONLINE_CHECK	： 移動直線当たりチェックを行わない。



	以下はさらに特殊です。

	

	skip_flag |= CTRL_RESET_HZX_BASE	： キャラの最低高さをリセットします。

						   高さの大きく異なるモーションに変更したとき、

						   次モーションの基準高さが０であるときにのみ

						   有効です。



	また、トラップイベント処理を行わないキャラクタの場合、

	CONTROL構造体の替わりに、CONTROL_NOEVT構造体を用いることで、

	メモリが少しだけ節約できます。



	◆定時間回転



	目標方向を指定しておくと、キャラクタは徐々にその方向を向きますが、

	何フレームでその方向に向き終わるかは不定です。

	そこで、control->interpを設定しておくと、control->interpフレームだけ

	かけて、目標方向を向くようになります。

	ただし、0 < control.interp <= 16 です。



	◆トラップチェック位置



	トラップ侵入チェックは、control->movの位置で行われますが、

	( FVECTOR * )control->root_offsetを設定しておくと、

	control->mov + control->root_offsetの位置でチェックを行います。



	◆アドレス変更チェック位置



	アドレス変更チェックは、control->movの位置で行われますが、

	( FVECTOR * )control->addr_movを設定しておくと

	その位置でチェックを行います。





			

