/********************************************************************************
					-------------------------
				 	 Ultra 64 MARIO Brothers
					-------------------------

					File		: pathob.s
					Description	: 
					Date		: 1995.
					Author		: H.yajima

 ********************************************************************************/


/*################*/
#ifdef ASSEMBLER
/*################*/


/********************************************************************************
		---------------------
		 Kago Teresa Program
		---------------------
 ********************************************************************************/

e_boss_teresa:
	p_initialize(enemyA)
	p_setbit( flag,stf_moveON | stf_YangleSAME | stf_playerdistON | stf_playerangleON )
	p_save_nowpos
	p_setd(ap,3)
	p_setdamagebox(80,120)
	p_sethitbox(180,140)
	p_setf(animepositionY,120/2)
	p_setmovedata(30,0,-50,1000,1000,200,0,0)
	p_program(s_kagoteresa_makekago)
	p_program(s_areastage_init)	
	p_while
		p_program(s_kagoteresa)
	p_loop



/********************************************************************************
		-----------------------
		 kaidan teresa program
		-----------------------
 ********************************************************************************/

e_kaidanteresa:
	p_initialize(enemyA)
	p_setbit( flag,stf_moveON | stf_YangleSAME | stf_playerdistON | stf_playerangleON )
	p_save_nowpos

	p_setd(ap,3)
	p_setdamagebox(80,120)
	p_sethitbox(180,140)
	p_setf(animepositionY,120/2)

	p_setmovedata(30,0,-50,1000,1000,200,0,0)

	p_program(s_areastage_init)	
	p_while
		p_program(s_kaidanteresa)
	p_loop


/********************************************************************************
		-----------
		 obake fly
		-----------
 ********************************************************************************/

e_obake_fly:
	p_initialize(option)
	p_shapeDISABLE								 
	p_program(s_make3teresa)
	p_killshape

/********************************************************************************
		mini teresa program
 ********************************************************************************/

e_miniteresa:
	p_initialize(enemyA)
	p_setbit( flag,stf_moveON | stf_YangleSAME | stf_playerdistON | stf_playerangleON )
	p_hitON
	p_save_nowpos
	p_setd(ap,2)
	p_sethitbox(140,80)
	p_setdamagebox(40,60)
	p_setf(animepositionY,60/2)
	p_program(s_areastage_init)
	p_makeshape(S_coin,e_obake_coin)
	p_setmovedata(30,0,-50,1000,1000,200,0,0)
	p_while
		p_program(s_oba)
	p_loop

/*################*/
#else
/*################*/


#define			oba_alphawork	(execstp->s[stw_work0].d)
#define			oba_scale	(execstp->s[stw_work1].f)
#define			oba_sinmoveY	(execstp->s[stw_work2].d)
#define			oba_damageANG	(execstp->s[stw_work3].d)
#define			oba_stockY	(execstp->s[stw_work4].f)
#define		oba_kaidanptr	(execstp->s[stw_work5].pointer)

/*------------------

---------------*/

#define	terecount(n)	(n->s[stw_work8].d)


/********************************************************************************
		Appear / No-Appear Check
 ********************************************************************************/

static int obake_appearcheck(void)
{

	if ( obj_areamap == -1 ){
	 	if ( obj_playerdist < 1500 )	return(1);
	} else {
		if ( obj_playerdist < 1500 && ( obj_areamap == map_areacode ) ) return(1);
	}
	
	return(0);
}

/********************************************************************************
		Effect Mini Teresa
 ********************************************************************************/

extern void s_make3teresa(void)
{	
	static  PositionRecord teredata[3] = {
		{    0,  50,   0 },
		{  210, 110, 210 },
		{ -210,  70,-210 },
	};

	int i;
 	StrategyRecord *stp;

	for (i=0;i<3;i++){
		stp = s_makeobj_chain(1,teredata[i].Xpos,
							    teredata[i].Ypos,
							    teredata[i].Zpos,
							    execstp,S_teresa,e_miniteresa);
		stp->s[stw_angleY].d = Randomd();
	}

}

/********************************************************************************
		Effect Mini Teresa
 ********************************************************************************/

static void oba_effect(void)
{

	float s;

	if ( oba_alphawork != obj_alpha ){
		if ( oba_alphawork > obj_alpha ){
			obj_alpha += 20;
			if ( oba_alphawork < obj_alpha )	obj_alpha = oba_alphawork;
		} else {
			obj_alpha -= 20;
			if ( oba_alphawork > obj_alpha )	obj_alpha = oba_alphawork;
		}
	}

	s = ( (obj_alpha  / 255.0f) * 0.4 + 0.6 ) * oba_scale;
	s_scale( execstp , s );

}

/********************************************************************************
		Animation Scale
 ********************************************************************************/

static void oba_animation_scale(void)
{
	execstp->s[stw_animeangleX].d = sin(oba_sinmoveY)*0x400;

	if ( obj_alpha == 255 ){
		execstp->map.scale[0] = ( sin(oba_sinmoveY) * 0.08 + oba_scale); 
		execstp->map.scale[1] = (-sin(oba_sinmoveY) * 0.08 + oba_scale);
		execstp->map.scale[2] = execstp->map.scale[0];
		obj_gravity = sin(oba_sinmoveY) * oba_scale;

#if 0
        if ( ( obj_worldY - obj_animepositionY - obj_groundY ) < (50*oba_scale) ){
           if ( obj_gravity < 0 ) obj_gravity = -obj_gravity;
        }
#endif

		oba_sinmoveY	+= 0x400;
	}

}

/********************************************************************************
		mode check
 ********************************************************************************/

static int teresa_modecheck(void)
{

	short 	dangle1 = s_calc_dangle(obj_targetangle,player1stp->s[stw_animeangleY].d);
	short 	dangle2 = s_calc_dangle(obj_angleY,player1stp->s[stw_animeangleY].d);
	short 	data2	= 0x5000;
	short 	data3 	= 0x5000;
	int		flag 	= 0;

	obj_speedY = 0;

	if ( dangle1 < data2 || dangle2 < data3 ){
		oba_alphawork 	= 255;
		if ( obj_alpha > 180 )	flag = 1;
	} else {
		oba_alphawork 	= 40;
	}

	return(flag);

}

/********************************************************************************
		=================
		 ob roll
		=================
 ********************************************************************************/

#define	MT_ROLL_TIME			32			/* obake to player ga atatta toki!!		 */
#define	MT_PULU_TIME			8			/* obake to player ga atatta toki!!		 */
#define	MT_PULU_SPEED			0x400		
#define	MT_ROLL_SPEED_Y			3			/* rolling back speed Y 				 */

/*------------------------------------------------------------------------------*/

static void obroll_init(void)
{
	s_hitOFF();
	Mbitclr(obj_mainflag,stf_YangleSAME);
	oba_stockY = obj_angleY;
	if	( cos((short)obj_angleY-(short)obj_targetangle) < 0 ){
		oba_damageANG	 = obj_angleY;
	} else {
		oba_damageANG	 = (short)(obj_angleY+0x8000);
	}

}
/*------------------------------------------------------------------------------*/
static void obroll_roll(float sF)
{
	int 	time;
	time = (obj_timer+1)*( 0x10000/MT_ROLL_TIME );
	obj_speedF  = sF;		
	obj_speedY	= cos(time);
	obj_angleY	= oba_damageANG;
	execstp->s[stw_animeangleY].d += rotdata[obj_timer];
	execstp->s[stw_animeangleZ].d += rotdata[obj_timer];
}
/*------------------------------------------------------------------------------*/
static void obroll_rollend(void)
{
	int	time;
	time = (obj_timer-MT_ROLL_TIME+1) * 0x10000/MT_PULU_TIME;
	execstp->s[stw_animeangleY].d += cos(time) * MT_PULU_SPEED;
}
/*------------------------------------------------------------------------------*/
static void obroll_exit(void)
{
	obj_angleY = oba_stockY;
	Mbitset(obj_mainflag,stf_YangleSAME);
	Mbitclr(obj_mail,EMAIL_PLAYERHITALL);
}

/*------------------------------------------------------------------------------*/
static int obake_roll(void)
{

	obj_speedF = 0;
	obj_speedY = 0;
	if 		( obj_timer == 0 )								obroll_init();
	if 		( obj_timer <  MT_ROLL_TIME )					obroll_roll(rotdata[obj_timer]/5000.0f);
	else if ( obj_timer < (MT_ROLL_TIME)+(MT_PULU_TIME) )	obroll_rollend();
	else {
		s_hitON();
		obroll_exit();
		obj_mode = mode_oba_playersearch;
		return(1);
	}

	return(0);
}


/********************************************************************************
		============
		 obake away
		============
 ********************************************************************************/

#define	MT_REMOVEDEMO_TIME	30

static int obake_hitaway(void)
{

	StrategyRecord *stp;

	if ( obj_timer == 0 ){ 
		obj_speedF 			= 40;
		obj_angleY			= player1stp->s[stw_angleY].d;
		execstp->s[stw_imm].d = 1;	/* set message */
		Mbitclr(execstp->s[stw_flag].d,stf_YangleSAME);
	} else {
		if ( obj_timer == MT_REMOVEDEMO_TIME-25 )	oba_alphawork = 0;
		if ( obj_timer > MT_REMOVEDEMO_TIME || obj_movestatus & MOVESTAT_WALL ){
			s_kemuri();
			execstp->s[stw_imm].d = 2;	/* set message */
			if ( oba_kaidanptr != NULL ){
			 	stp = (StrategyRecord *)oba_kaidanptr;
				terecount(stp)++;
			}
			return(1);
		}
	}

	obj_speedY 			= 5;
	obj_animeangleZ += 0x800;
	obj_animeangleY += 0x800;

	return(0);

}


/********************************************************************************

		ob hitcheck

		flag ... 0  safe
				 1  Hit Win  !!
				-1	Hit Lost !!

 ********************************************************************************/

static int oba_hitcheck(void)
{

	int flag = 0;

	if ( (obj_mail & EMAIL_PLAYERHIT) != 0 ){
		if ( obj_mail & EMAIL_PLAYERATTACK ){
			s_hitOFF();
			Mbitclr(obj_mail,EMAIL_PLAYERHITALL);
			objsound(NA_SE3_TEREAWAY);
			flag = 1;
		} else	{
			objsound(NA_SE3_TERECRASH);
			Mbitclr(obj_mail,EMAIL_PLAYERHITALL);
			flag = -1;
		}

	}

	return(flag);

}


/********************************************************************************

		obake mainmove program

 ********************************************************************************/


static void obake_mainmove(float ymin,short anglespeed)
{

 	float	Ydist;
	short	angle;

	if ( teresa_modecheck() ){
	 	s_set_objname(PUNCHATTACK);		/* punch attack enemy */

		if ( s_calc_playerscope() > 1500 ) angle = s_calc_returnangle();
		else							   angle = obj_targetangle;
		s_chase_angleY(angle,anglespeed);

		obj_speedY = 0;
		if(	s_check_playerjump() == 0 ){
			Ydist =  obj_worldY - player_worldY;
			if (  ( ymin < Ydist ) && ( Ydist < 500 ) ){
				obj_speedY = s_chase_set_speedY(obj_worldY,(player_worldY+60*oba_scale),10,2);
			}
		}
		s_chase_playerspeed(10,0.5);

		if ( obj_speedF != 0 ) oba_animation_scale();

	} else {
	 	s_set_objname(0);	/* hitcheck off	*/
		obj_speedF  = 0;
		obj_speedY  = 0;
		obj_gravity = 0;
	}

}


/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------*/


/********************************************************************************
		 ob init 
 ********************************************************************************/

static void oba_init(void)
{

	s_copy_initpos();
	oba_kaidanptr	= (void *)s_find_obj(e_kaidanteresa);	/* kaidan pointer */
	oba_scale 		= 1.0;									/* scale 		  */
	oba_alphawork	= 255;
	if ( obake_appearcheck() ) obj_mode = mode_oba_playersearch;

}

/********************************************************************************
		 ob playersearch
 ********************************************************************************/

static void oba_playersearch(void)
{

	int		flag;
	obake_mainmove(-100,0x200+effect_p3);
	flag = oba_hitcheck();

	if ( execstp->status & OBJECT_AREAOUT ) obj_mode = mode_oba_init;
	if ( flag == -1 )	obj_mode = mode_oba_roll;
	if ( flag ==  1 )	obj_mode = mode_oba_hitaway;

}

/********************************************************************************
		 oba roll
 ********************************************************************************/

static void oba_roll(void)
{
	if ( obake_roll() ) obj_mode = mode_oba_playersearch;
}

/********************************************************************************
		 oba hitaway
 ********************************************************************************/

static void oba_hitaway(void)
{
	if ( obake_hitaway() ){
		if ( obj_programselect )	s_remove_obj(execstp);
		else {		
			obj_mode = mode_oba_endmessage;
			s_shape_hide();
			s_hitOFF();
		}
	}
}

/********************************************************************************
		 oba hitaway
 ********************************************************************************/

static void oba_endmessage(void)
{

	if ( s_call_enemydemo(DLOG_LOOKUP,ENEMYDEMO_SETMESSAGE,99,0) ){
		s_remove_obj(execstp);
	}

}



/********************************************************************************
	======================
	 mini teresa program
	======================
 ********************************************************************************/

static void *oba_modejmp[] = {
	
	 oba_init,
	 oba_playersearch,
	 oba_roll,
	 oba_hitaway,
	 oba_endmessage
	
};

/*-----------------------------------------------------------------------------*/
extern void s_oba(void)
{

	s_enemybgcheck();
	s_modejmp(oba_modejmp);
	s_enemymove(-78);
	oba_effect();

}

/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/





/********************************************************************************
	======================
	 kaidan teresa program
	======================
 ********************************************************************************/


/*------------------------------------------------------------------------------*/
/*		kaidan teresa initialize												*/
/*------------------------------------------------------------------------------*/
static void kaidanteresa_init(void)
{

	oba_kaidanptr	= NULL;
	if ( terecount(execstp) == (5+effect_p1) ){
		s_copy_initpos();
		s_shape_disp();
		oba_alphawork = 255;
		oba_scale	  = 2;
		s_set_scale(2);
		s_hitON();	
		if ( obake_appearcheck() ) obj_mode = mode_kaidanteresa_main;
	} else {
		s_shape_hide();
	}

}

/*------------------------------------------------------------------------------*/
/*		kaidan teresa mainprogram												*/
/*------------------------------------------------------------------------------*/
static void kaidanteresa_main(void)
{
 
	int		flag;
	obake_mainmove(100+effect_p0,0x200);
	flag = oba_hitcheck();

	if ( execstp->status & OBJECT_AREAOUT ) obj_mode = mode_kaidanteresa_init;
	if ( flag == -1 )						obj_mode = mode_kaidanteresa_roll;
	if ( flag ==  1 )						obj_mode = mode_kaidanteresa_hitaway;

}

/*------------------------------------------------------------------------------*/
/*		kaidan teresa mainprogram												*/
/*------------------------------------------------------------------------------*/
static void kaidanteresa_roll(void)
{
	if ( obake_roll() ) obj_mode = mode_kaidanteresa_main;
}

/*------------------------------------------------------------------------------*/
/*		kaidan teresa mainprogram												*/
/*------------------------------------------------------------------------------*/
static void kaidanteresa_hitaway(void)
{
	if ( obake_hitaway() ){
		obj_mode = mode_kaidanteresa_demo;
		s_set_world(execstp,973,0,717);
		s_set_angle(execstp,0,0,0);
		s_makeobj_chain(0,0,0,   0,execstp,S_movebg00,e_teretrap_kaidan);
		s_makeobj_chain(1,0,0,-200,execstp,S_movebg00,e_teretrap_kaidan);
		s_makeobj_chain(2,0,0, 200,execstp,S_movebg00,e_teretrap_kaidan);
	}

}

/*------------------------------------------------------------------------------*/
/*		kaidan teresa demo														*/
/*------------------------------------------------------------------------------*/
static void kaidanteresa_demo(void)
{

	if ( obj_timer == 100 ){
	 	s_makeobj_absolute(execstp,0,S_polystar,e_tripstar,972,819+200,292,0,0,0);
		s_remove_obj(execstp);
	}

}

/*-----------------------------------------------------------------------------*/

static void *kaidanteresa_modejmp[] = {
	
	 kaidanteresa_init,
	 kaidanteresa_main,
	 kaidanteresa_roll,
	 kaidanteresa_hitaway,
	 kaidanteresa_demo
	
};

/*-----------------------------------------------------------------------------*/

extern void s_kaidanteresa(void)
{

	s_enemybgcheck();
	s_modejmp(kaidanteresa_modejmp);
	s_enemymove(-78);
	oba_effect();

}

/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/





/********************************************************************************
	======================
	 kago teresa program
	======================
 ********************************************************************************/


/*------------------------------------------------------------------------------*/
/*		kago teresa initialize													*/
/*------------------------------------------------------------------------------*/
static void kagoteresa_init(void)
{
	oba_kaidanptr	= NULL;
	oba_alphawork = 255;
	oba_scale	  = 2;
	s_set_scale(2);
	s_hitON();	
	if ( obake_appearcheck() ) obj_mode = mode_kagoteresa_main;

}

/*------------------------------------------------------------------------------*/
/*		kago teresa mainprogram													*/
/*------------------------------------------------------------------------------*/
static void kagoteresa_main(void)
{
 
	int		flag;
	obake_mainmove(100+effect_p0,0x200);
	flag = oba_hitcheck();

	if ( execstp->status & OBJECT_AREAOUT ) obj_mode = mode_kagoteresa_init;
	if ( flag == -1 )						obj_mode = mode_kagoteresa_roll;
	if ( flag ==  1 )						obj_mode = mode_kagoteresa_hitaway;

}

/*------------------------------------------------------------------------------*/
/*		kago teresa mainprogram													*/
/*------------------------------------------------------------------------------*/
static void kagoteresa_roll(void)
{
	if ( obake_roll() ) obj_mode = mode_kagoteresa_main;
}


/*------------------------------------------------------------------------------*/
/*		kago teresa mainprogram													*/
/*------------------------------------------------------------------------------*/
static void kagoteresa_hitaway(void)
{

	if ( obake_hitaway() ) s_remove_obj(execstp);

}


/*-----------------------------------------------------------------------------*/

static void *kagoteresa_modejmp[] = {
	
	 kagoteresa_init,
	 kagoteresa_main,
	 kagoteresa_roll,
	 kagoteresa_hitaway
	
};

/*-----------------------------------------------------------------------------*/

extern void s_kagoteresa_makekago(void)
{
	StrategyRecord *stp = s_makeobj_nowpos(execstp,S_teresakago,e_teresa_kago);
	stp->s[stw_actorcode].d = execstp->s[stw_actorcode].d;	
}

extern void s_kagoteresa(void)
{

	s_enemybgcheck();
	s_modejmp(kagoteresa_modejmp);
	s_enemymove(-78);
	oba_effect();

}

/*################*/
#endif
/*################*/
/*===============================================================================
		end end end end end end end end 
===============================================================================*/



