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

	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を設定しておくと
	その位置でチェックを行います。


			
