/********************************************************************************
					-------------------------
				 	 Ultra 64 MARIO Brothers
					-------------------------

					File		: pathmonky.s
					Description	: 
					Date		: 1995.9.14
					Author		: H.yajima

 ********************************************************************************/

/***************************************************************/
/*  ANIMATION HEADER DEFINE monky */
/***************************************************************/
#define ANM_monky_F_run         	0
#define ANM_monky_N_run         	1
#define ANM_monky_base_data     	2
#define ANM_monky_down          	3
#define ANM_monky_excite        	4
#define ANM_monky_hoping        	5
#define ANM_monky_jump          	6
#define ANM_monky_jump_end      	7
#define ANM_monky_jump_start    	8
#define ANM_monky_wait_A        	9
#define ANM_monky_wait_B        	10
#define ANM_monky_walk          	11
#define ANM_monky_hold	         	12
/*=============================================================*/
/*  END END */
/*=============================================================*/

/*################*/
#ifdef ASSEMBLER
/*################*/

e_monky:
	p_initialize(enemyA)
e_monky_common:
	p_setbit(flag,stf_moveON | stf_YangleSAME | stf_catchON | stf_playerdistON | stf_playerangleON )
	p_setd(objname,OBJNAME_TAKE)
	p_setd(enemyinfo,ENEMYINFO_FRIEND_ENEMY)
	p_sethitbox(40,40)
	p_hitON
	p_BGcheckYset
	p_set_pointer(skelanime,monky_anime)
	p_set_skelanime_number(0)
	p_setmovedata(30,-400,-50,0,0,200,0,0)
	p_save_nowpos
	p_program(s_monky_init)
	p_while
		p_program(s_monky)
	p_loop



/*################*/
#else
/*################*/

/********************************************************************************
		MONKY local work
 ********************************************************************************/

/*===== 2,3,4,5,6 (road program use) === */


#define			monky_randomf	(execstp->s[stw_work7].f)

#define		monky_anime_timer	(execstp->s[stw_work0].word[0])	
#define		monky_anime_repeat	(execstp->s[stw_work0].word[1])	

#define		monky_turnangle		(execstp->s[stw_work1].d)	

#define		monky_eventmode		(execstp->s[stw_work8].word[0])
#define		monky_eventtimer	(execstp->s[stw_work8].word[1])
#define		monky_timer			(execstp->s[stw_work9].word[0]) 	
#define		monky_eventflag		(execstp->s[stw_work9].word[1])

#define		MONKYHAT	1

enum {
 	mev_setmessage,
 	mev_checkmessage,
	mev_starsearch,
	mev_hatcatch,		/* hat catch 	 	*/
	mev_hathave,		/* hat have 	 	*/
	mev_hatend,			/* hat event end 	*/
	mev_wait,			/* wait			 	*/
 	mev_stealentry
};



/********************************************************************************
 ********************************************************************************/
/********************************************************************************
 ********************************************************************************/
/********************************************************************************
 ********************************************************************************/
/********************************************************************************
 ********************************************************************************/
/********************************************************************************
 ********************************************************************************/
/********************************************************************************
 ********************************************************************************/
 
static void monky_overarea_check(void)
{
	if ( obj_programselect == 1 ){
		if ( s_enemy_areaout() ){
			s_reset_posspeed();
			obj_mode = mode_monky_wait;
		} else if ( obj_movestatus & MOVESTAT_WATER ){
		 	obj_mode = mode_monky_outarea_wait;
		}
	}
}

static int monky_hatsearch_check(void)
{
	if ( obj_programselect == 1 ){
		if ( PL_IsPlayerWearingRedHat(marioWorks) )	return(1);	/* hatsearch check */
	}

	return(0);

}


/********************************************************************************
	#######
	 MONKY		monky head program
	#######
 ********************************************************************************/

extern unsigned long MonkyHead(int code,MapNode *node, void *data)
{


	if (code == MAP_CBACK_EXEC) {

		AffineMtx	 modelmtx;	
	  	StrategyRecord	*stp = (StrategyRecord *)hmsActiveShape;

		if ( stp->childobj != NULL ){
			s_calc_skeleton_glbmtx(&modelmtx,(AffineMtx *)data,hmsActiveCamera->matrix);
			s_calc_skeleton_glbpos(modelmtx,stp->childobj);
			s_copy_worldXYZmappos(stp->childobj);
		//	rmonpf(("hellow %f\n",stp->childobj->s[stw_worldY].f ));
		}

	}

	return(0);

}


/********************************************************************************
	#######
	 MONKY		monky wait animation !!
	#######
 ********************************************************************************/

static void monky_wait_animation(void)
{
	obj_speedF = 0;

	if ( obj_process == 0 ){
		obj_process 		= Randomf()*4+1;	/* random process	*/
		monky_anime_timer 	= 0;				/* timer			*/
		monky_anime_repeat	= Randomf()*4+2;	/* repeat count		*/
	}

	switch	(obj_process){
	 	case	1:
			s_set_skelanimeNo(ANM_monky_wait_A);
			if ( s_check_animeend() )	obj_process = 0;
			break;
	 	case	2:
			s_set_skelanimeNo(ANM_monky_excite);
			if ( s_check_animeend() )	monky_anime_timer++;
			if ( monky_anime_timer >= (monky_anime_repeat*2) ) 	obj_process = 0;
			break;		
	 	case	3:
			s_set_skelanimeNo(ANM_monky_hoping);
			if ( s_check_animeend() )	monky_anime_timer++;
			if ( monky_anime_timer >= monky_anime_repeat ) 	obj_process = 0;
			break;
	 	case	4:
			s_set_skelanimeNo(ANM_monky_wait_B);
			if ( s_check_animeend() )	obj_process = 0;
			break;
	}

}

/*------------------------------------------------------------------*/
/*		normal wait													*/
/*------------------------------------------------------------------*/
static void monky_wait(void)
{

 	monky_wait_animation();

	if ( monky_hatsearch_check() ){
		if ( obj_playerdist > 700 && obj_playerdist < 1000 ) obj_mode = mode_monky_runaway;
		else if ( obj_playerdist <= 700 && obj_playerdist > 200 ){
			if ( s_calc_dangle(obj_targetangle,obj_angleY) > 0x1000 ) obj_mode = mode_monky_look_player;
		}
	} else {
		if ( obj_playerdist < 300 ) obj_mode = mode_monky_runaway;
	}

	if ( monky_eventmode == mev_starsearch  ) obj_mode = mode_monky_rail_demo;

	/*----------------------------------------------------------------------*/
	if ( monky_eventmode == mev_hatcatch 	){

		obj_angleY	= (player1stp->s[stw_angleY].d+0x8000);
		if ( s_next_bgcheck(50,150) ){
			obj_mode = mode_monky_turnjump;
		} else {
			obj_angleY	= (player1stp->s[stw_angleY].d+0x4000);
			if ( s_next_bgcheck(50,150) ) obj_mode = mode_monky_turnjump;
			else {
				obj_angleY	= (player1stp->s[stw_angleY].d-0x4000);
				if ( s_next_bgcheck(50,150) ) obj_mode = mode_monky_turnjump;
			}
		}
		monky_eventmode = mev_hathave;

	}
	/*----------------------------------------------------------------------*/

	if ( obj_programselect == 1 ){
		if ( obj_worldY < -1550 ) obj_mode = mode_monky_return;
	}





}

/*------------------------------------------------------------------*/
/*		monky return												*/
/*------------------------------------------------------------------*/

static void monky_return(void)
{
	float	dist;

	s_set_skelanimeNo(ANM_monky_F_run);
	obj_angleY = s_calc_returnangle();
	obj_speedF = 10;
	if ( obj_worldY > -1550 ) 	 obj_mode = mode_monky_wait;

}


/*------------------------------------------------------------------*/
/*		normal outarea												*/
/*------------------------------------------------------------------*/
static void monky_outarea_wait(void)
{
 	monky_wait_animation();
	if ( s_enemy_areaout() ){
		s_reset_posspeed();
		obj_mode = mode_monky_wait;
	}
}

/*------------------------------------------------------------------*/
/*		stopwait													*/
/*------------------------------------------------------------------*/
static void monky_stopwait(void)
{
 	monky_wait_animation();
	if ( obj_process == 3 ) s_chase_angleY(obj_targetangle,0x400);

}



/********************************************************************************
	#######
	 MONKY		look player
	#######
 ********************************************************************************/

static void monky_look_player(void)
{

	int	  sameflag;

	if ( obj_timer == 0 )	obj_speedF = 2 + Randomf()*3;
	s_set_skelanimeNo(ANM_monky_walk);	
	sameflag = s_chase_angleY(obj_targetangle,0x800);	
	if (sameflag)	obj_mode = mode_monky_wait;

	if ( monky_hatsearch_check() ){
		if ( obj_playerdist > 500 ) obj_mode = mode_monky_runaway;
	} else {
		if ( obj_playerdist < 300 ) obj_mode = mode_monky_runaway;
	}
}


/********************************************************************************
	#######
	 MONKY		runaway
	#######
 ********************************************************************************/

static void monky_runaway(void)
{

	int		flag  = 1; 
	short	angle = obj_targetangle+0x8000;


	if ( monky_hatsearch_check() ){
		flag  = 0;
		angle = obj_targetangle;
	}

	if ( obj_timer == 0 ) monky_randomf = 350+Randomf()*100;

	s_set_skelanimeNo(ANM_monky_F_run);
	s_chase_angleY(angle,0x800);
	s_chase_playerspeed(20.0,0.9);

	if ( flag ){
		if ( obj_playerdist > monky_randomf ) obj_mode = mode_monky_look_player;
	} else {
		if ( obj_playerdist < monky_randomf ) obj_mode = mode_monky_look_player;
	}

	
	if ( flag ){
		if ( obj_playerdist < 200 ){
			if ( 		( obj_movestatus & MOVESTAT_WALL ) && ( s_check_playerslow(10) ) ){
				obj_mode 	= mode_monky_turnjump;
				obj_angleY	= obj_wallangleY;
			} else if ( ( obj_movestatus & MOVESTAT_GAKE ) && ( s_check_playerslow(10) ) ){
				obj_mode 	= mode_monky_turnjump;
				obj_angleY	+= 0x8000;
			}
		}
	}


}

/********************************************************************************
		<< turn jump >> 
 ********************************************************************************/
static void monky_turnjump(void)
{

	obj_speedF = 10;
	s_hitOFF();

	if ( obj_process == 0 ){
		if ( obj_timer == 0 ){
			s_set_jumpstart(45+Randomf()*10,ANM_monky_jump_start);
		} else {
			if ( obj_movestatus & ( MOVESTAT_STOP | MOVESTAT_BGBOUND ) ){
				 obj_process++;
				 obj_speedY = 0;
			}
		}
	} else {
		obj_speedF = 0;
		s_set_skelanimeNo(ANM_monky_jump_end);
		s_hitON();
		if ( s_check_animeend() ){
			obj_mode = mode_monky_runaway;
		}
	}	

}

/********************************************************************************
	##########################
		MAINPROGRAM MONKY
	##########################
 ********************************************************************************/

static short monky_rail[] = {
 0,1011,2306,-285,
 0,1151,2304,-510,
 0,1723,1861,-964,
 0,2082,1775,-1128,
 0,2489,1717,-1141,
 0,2662,1694,-1140,
 0,2902,1536,-947,
 0,2946,1536,-467,
 0,2924,1536,72,
 0,2908,1536,536,
 0,2886,1536,783,
 -1,
};

static void monky_rail_demo(void)
{

	StrategyRecord *stp;
	float 			dist  = 0;
	short			angle = 0;

	if ( ( stp = s_find_obj(e_monky_check)) != NULL ){
		dist  = s_distanceXZ_obj2obj(execstp,stp->motherobj);
		angle = s_calc_targetangle(execstp,stp->motherobj);
	}

	s_hitOFF();
	Mbitset(obj_mainflag,stf_alldispON);

	switch(obj_process){
		case 0:
			s_set_skelanimeNo(ANM_monky_F_run);
			road_root(execstp) = monky_rail;
			if ( s_road_move(0) != -1 ){
				obj_speedF = 10;
				s_chase_angleY(road_angleY(execstp),0x400);
				obj_worldY = obj_groundY;
			} else {
				obj_speedF = 0;
				obj_process++;
			}
			break;

		case 1:
			s_set_skelanimeNo(ANM_monky_hoping);
			s_chase_angleY(obj_targetangle,0x400);
			if (  s_hitcheck_message_entry( 200, 30 ,0x7fff ) ){
				 obj_process++;			/* Go Next Process */
			} else {
				break;
			}

		case 2:
			s_set_skelanimeNo(ANM_monky_wait_B);
			if ( s_call_talkdemo(DLOG_LOOKDOWN,ENEMYDEMO_LOOKPLAYER,CAM_DEMO_TALK,80) ) obj_process++;
			break;

		case 3:
			s_set_skelanimeNo(ANM_monky_F_run);
			if ( s_chase_angleY(angle,0x400)){
				obj_speedF = 10;
				obj_process++;
			}
			break;

		case 4:
			s_set_jumpstart(45+10,ANM_monky_jump_start);
			obj_speedF = 10+26;
			obj_process++;
			break;

		case 5:
			if ( dist < 50 ) obj_speedF = 0;
			if ( obj_movestatus & MOVESTAT_BGBOUND ){
				Na_NazoClearBgm();
				s_set_skelanimeNo(ANM_monky_hoping);
				obj_process++;
				monky_timer = 32;
				stp->motherobj->s[stw_imm].d = 1;
				obj_speedF = 0;
			}
			break;

		case 6:
			obj_angleY += 0x800;
			monky_timer--;
			if ( monky_timer < 0 ){ 
				obj_process++;
				stp->motherobj->s[stw_imm].d = 2;
			}
			break;

		case 7:
			if ( obj_worldY < -1300 ) s_remove_obj(execstp);
			break;
	}



}
		




/********************************************************************************
	##########################
		MAINPROGRAM MONKY
	##########################
 ********************************************************************************/

static EnemySoundRecord monky_sound[] = {
	{ 1,1,10,NA_SE3_MONKEYRUNNING 	}, 		/* ANM_monky_F_run         	0		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_N_run         	1		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_base_data     	2		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_down          	3		*/
	{ 1,0,-1,NA_SE3_MONKEYVOICE1 	}, 	 	/* ANM_monky_excite        	4		*/
	{ 1,0,-1,NA_SE3_MONKEYVOICE0 	}, 	   	/* ANM_monky_hoping        	5		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_jump          	6		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_jump_end      	7		*/
	{ 1,0,-1,NA_SE3_MONKEYVOICE0 	}, 	    /* ANM_monky_jump_start    	8		*/
	{ 1,0,-1,NA_SE3_MONKEYSCRATCH 	}, 	   	/* ANM_monky_wait_A        	9		*/
	{ 1,0,-1,NA_SE3_MONKEYVOICE2 	}, 	 	/* ANM_monky_wait_B        	10		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_walk          	11		*/
	{ 0,0,0,0 }, 	    					/* ANM_monky_hold	        12		*/
};

static void *monky_modejmp[] = {
	
	 monky_wait,
	 monky_runaway,
	 monky_look_player,
	 monky_turnjump,
	 monky_rail_demo,
	 monky_outarea_wait,
	 monky_stopwait,
	 monky_return
	
};

static void s_monky_main(void)
{
	int ang;

		s_enemybgcheck();
		s_modejmp(monky_modejmp);
		if ( obj_mode == mode_monky_rail_demo || obj_mode == mode_monky_return ) ang = -88;
		else																	 ang = -20;
		s_enemymove(ang);

		monky_overarea_check();

		if ( ( obj_movestatus & MOVESTAT_WATER ) == 0 ){
			s_enemysound(monky_sound);	/* monky sound */
		}


}

/********************************************************************************
	##########################
		MAINPROGRAM MONKY
	##########################
 ********************************************************************************/

static void s_eye_anime(void)
{
	if ( ( frameCounter % 50 )  < 7 )	obj_animecounter = 1;
	else								obj_animecounter = 0;
}


/********************************************************************************
		star event monky
 ********************************************************************************/
static void starevent_monky(void)
{

	if ( obj_worldY - obj_attY > -100 ){
		switch(monky_eventmode){
		 	case mev_setmessage:
				if ( CtrlPlayerDialog(DLOG_LOOKUP) == DLOG_RESULT_READY ){
					CallMessageYesNo(79);
				 	monky_eventmode = mev_checkmessage;
				}
				break;
		 	case mev_checkmessage:
			 	if ( messageAnsNo != 0 ){
					CtrlPlayerDialog(DLOG_DONE);
					if ( messageAnsNo == 1 ){
						Mbitset(obj_enemyinfo,ENEMYINFO_CATCH_OFF_REQUEST);
						monky_eventmode = mev_starsearch;
					} else {
						monky_eventmode  = mev_wait;
						monky_eventtimer = 60;
					}
				}
				break;
			case mev_starsearch:
				break;
			case mev_wait:
				if ( monky_eventtimer-- < 0 ) monky_eventmode = 0;
				break;
	
		}
	} else {
		monky_eventmode = 0;
		obj_timer 		= 0;
		obj_mode  		= mode_monky_outarea_wait;
	}

}


/********************************************************************************
		hat event monky
 ********************************************************************************/

static void hatevent_monky(void)
{

	switch(monky_eventmode){

		/*---- hat steal mode -----*/
		case mev_setmessage:
			if ( PL_StealMariosHat(MONKEY_STEAL_HAT) ){
				monky_eventmode = mev_stealentry;
				Mbitset(monky_eventflag,MONKYHAT);
			}
			else {
			//	Mbitset(obj_enemyinfo,ENEMYINFO_CATCH_OFF_REQUEST);
			}
			break;
			/* next */
		case mev_stealentry:
			if ( s_call_enemydemo(DLOG_LOOKUP,ENEMYDEMO_SETMESSAGE,100,0) ){
				Mbitset(obj_enemyinfo,ENEMYINFO_CATCH_OFF_REQUEST);
				monky_eventmode = mev_hatcatch;
			}
			break;
	 	
		case mev_hatcatch:
			break;

		/*---- hat have mode -----*/
 		case mev_hathave:
			if ( s_call_enemydemo(DLOG_LOOKUP,ENEMYDEMO_SETMESSAGE+ENEMYDEMO_DLOG_NOSTOP,101,0) ){ 
				PL_ReturnMariosHat();					/* Hat Return */
				CtrlPlayerDialog(DLOG_DONE);
				Mbitclr(monky_eventflag,MONKYHAT);
			 	monky_eventmode = mev_hatend;
			}
			break;
			
		case mev_hatend:
			monky_eventmode = 0;
			obj_mode 		= 0;
			break;
	}

}


/********************************************************************************

		Monky Main Program

 ********************************************************************************/

/********************************************************************************
		monky initialize
 ********************************************************************************/

extern void s_monky_init(void)
{
	if ( obj_programselect == 1 ){
		if ( BuGetItemFlag() & BU_ITEM_MONKEYHAT ){
			monky_eventmode = mev_hathave;
			Mbitset(monky_eventflag,MONKYHAT);
		}
	}
}

/********************************************************************************
		monky main program
 ********************************************************************************/

extern void s_monky(void)
{



	switch(execstp->s[stw_actionmode].d){
		case	CHILEDMODE_NO_CATCH:
			monky_eventtimer = 0;
			s_monky_main();
			break;
		case	CHILEDMODE_CATCH:
			s_mode_catch(ANM_monky_hold,mode_monky_wait);
			s_copy_worldXYZ(execstp,player1stp);	
			if 		( obj_programselect == 1 )	hatevent_monky();
			else 								starevent_monky();
			break;
		case	CHILEDMODE_THROW:
		case	CHILEDMODE_DROP:
			s_mode_drop();
			break;
	}

	/* s_eye_anime(); */

	if ( monky_eventflag & MONKYHAT )	obj_animecounter = 2;
	else								obj_animecounter = 0;

	obj_mail = 0;

	dbErrPrint("mode   %d\n",obj_mode);
	dbErrPrint("action %d\n",execstp->s[stw_actionmode].d);

}


/*################*/
#endif
/*################*/


/*===============================================================================
		end end end end end end end end 
===============================================================================*/


