/********************************************************************************
					-------------------------
				 	 Ultra 64 MARIO Brothers
					-------------------------

					File		: pathkopa.s
					Description	: enemy kopa program
					Date		: 1995.9.5
					Author		: H.yajima

 ********************************************************************************/



/********************************************************************************
		Kopa Number ( obj_programselect )
 ********************************************************************************/

#define		KOPA_1GOU	0		/* kopa No(0)	*/
#define		KOPA_YOGAN	1		/* kopa No(1)	*/  
#define		KOPA_LAST	2		/* kopa No(2)	*/  

/********************************************************************************
		Kopa Parameter
 ********************************************************************************/

#define	KOPALIMIT		   1000
#define	KIRAI_DIST			800
#define	kopabg				307

/****************************************************************/
/*  ANIMATION HEADER DEFINE kopa 								*/
/****************************************************************/

#define	KOPA_SWINGSPEED				70.0f

#define ANM_kopa_G_swing_down   	0
#define ANM_kopa_G_swing_down2  	1
#define ANM_kopa_G_swing_help   	2
#define ANM_kopa_G_swing_start  	3
#define ANM_kopa_body_tmp       	4
#define ANM_kopa_down           	5
#define ANM_kopa_fire           	6
#define ANM_kopa_jump           	7
#define ANM_kopa_jump_end       	8
#define ANM_kopa_jump_start     	9
#define ANM_kopa_punch          	10
#define ANM_kopa_scream         	11
#define ANM_kopa_wait           	12
#define ANM_kopa_walk           	13
#define ANM_kopa_walk_end       	14
#define ANM_kopa_walk_start     	15
#define	ANM_kopa_dead_start			16
#define	ANM_kopa_dead_end			17

#define ANM_kopa_dash_start			18
#define ANM_kopa_dash				19
#define ANM_kopa_dash_end			20
#define ANM_kopa_dash_slip			21

#define	ANM_kopa_small_fire			22

#define	ANM_kopa_cliff_dance		23
#define	ANM_kopa_cliff_dance_end	24

#define	ANM_kopa_safe_down_start	25
#define	ANM_kopa_safe_down_end		26


/*################*/
#ifdef ASSEMBLER
/*################*/

/********************************************************************************
		-------------------------------
		 ENEMY BOSS KOPA HITCHECK TAIL
		-------------------------------
 ********************************************************************************/

e_kopa_fusen:
	p_initialize(enemyA)
	p_sethitbox2(100,50,-50)		/* hitting cube */
	p_hitON
	p_shapeDISABLE
	p_while
		p_program(s_kopa_fusen)
	p_loop


/********************************************************************************
		-----------------
		 ENEMY BOSS KOPA
		-----------------
 ********************************************************************************/

e_kopa:
	p_initialize(enemyA)
	p_setbit(flag,stf_moveON | stf_YangleSAME | stf_catchON | stf_playerdistON | stf_playerangleON | stf_alldispON )
	p_setd(objname,OBJNAME_TAKE)
	p_sethitbox(400,400)
	p_BGcheckYset
	p_save_nowpos
	p_set_pointer(skelanime,kopa_anime)
	p_makeshape(S_NULL,e_kopa_damagecube)
	p_makeshape(S_kopafire,e_kopafire)
	p_makeobj_child(S_NULL,e_kopa_fusen)
	p_setd(havecoin,50)
	p_setmovedata(0,-400,-70,1000,1000,200,0,0)
	p_save_nowpos
	p_program(s_kopa_init)
	p_while
		p_program(s_kopa)
	p_loop


/********************************************************************************
		---------------------------------
		 ENEMY BOSS KOPA DAMAGE STARTEGY
		---------------------------------
 ********************************************************************************/

e_kopa_damagecube:
	p_initialize(enemyA)
	p_setbit(flag,stf_moveON)
	p_sethitbox(100,300)

	p_setobjname(DAMAGE)
	p_setd(enemyinfo,ENEMYINFO_KUPPA)

	p_shapeDISABLE
	p_setd(ap,2)
	p_hitON
	p_while
		p_program(s_kopa_damagecube)
	p_loop


/********************************************************************************
		-----------------------------
		 ENEMY BOSS KOPA FIREPROGRAM
		-----------------------------
 ********************************************************************************/

e_kopafire:
	p_initialize(option)
	p_setbit(flag,stf_moveON)
	p_changeshape(imm,S_NULL)
	p_while
		p_program(s_kopafire)
	p_loop


/*==============================================================================*/
/*		End End End																*/
/*==============================================================================*/

/*################*/
#else
/*################*/


#define		mode_kopaeye_normal	0
#define		mode_kopaeye_damage	1


/********************************************************************************
	   -------------------------
		ENEMY KOPA FUSEN PROGRAM
	   -------------------------
 ********************************************************************************/

/*------------ kopa_tail ------------------*/

static void kopatail_nohit(void)
{
	StrategyRecord *mother = execstp->motherobj;
	s_hitON();
	s_set_scale(1.0);								/* set scale */

	if ( mother->s[stw_mode].d == mode_s_kopa_bg_rotate ){
		mother->s[stw_hit_timer].d = -1;	   		/* mother 	hit OFF			*/
	} else {
		if ( s_hitcheck(execstp,player1stp) ){
			mother->s[stw_hit_timer].d = 0;			/* mother 	hit ON 			*/
			obj_mode = mode_kopatail_hit;
		} else {
			mother->s[stw_hit_timer].d = -1;		/* mother 	hit OFF			*/
		}
	}
}

/*------------ kopa_tail ------------------*/

static void kopatail_wait(void)
{
	if (obj_timer > 30 ) obj_mode = mode_kopatail_nohit;
}

static void kopatail_hit(void)
{
	if ( execstp->motherobj->s[stw_mode].d == mode_s_kopa_bg_rotate ){
		execstp->motherobj->s[stw_hit_timer].d = -1;	   		/* mother 	hit OFF			*/
		obj_mode = mode_kopatail_nohit;
	}
	s_hitOFF();
}

/*------------ kopa_tail ------------------*/


static void *kopatail_modejmp[] = {
	
	 kopatail_nohit,
	 kopatail_wait,
	 kopatail_hit
	
};

extern void s_kopa_fusen(void)
{

	s_modejmp(kopatail_modejmp);
	execstp->s[stw_skeletonX].f = 90;

	if ( execstp->motherobj->s[stw_mode].d == mode_s_kopa_dead ){
		execstp->motherobj->s[stw_hit_timer].d = -1;
	}

	obj_mail = 0;

}

/********************************************************************************
	   -------------------------
		ENEMY KOPA FIRE PROGRAM
	   -------------------------
 ********************************************************************************/

extern void s_kopafire(void)
{


	StrategyRecord *kp = execstp->motherobj;
	int		 		animeframe;
	float			ox,oz;
	float 			cosy 		= cos((kp->s[stw_angleY].d));
	float 			siny 		= sin((kp->s[stw_angleY].d));
	short			*firedata 	= (short *)SegmentToVirtual(kopadata);

	if ( kp->s[stw_skelanimeNo].d  == ANM_kopa_fire ){

		/*----- kopa animation frame -----*/
		animeframe 		= (float)(kp->map.skelanim.frame) + 1;
		if ( animeframe == (kp->map.skelanim.anime->nframes) ) animeframe = 0;
		/*--------------------------------*/

		if ( 45 < animeframe && animeframe < 85 ){

			objsound_level(NA_LSE3_KUPAFIRE);
			ox 		   = *(firedata+animeframe*5+0);
			oz 		   = *(firedata+animeframe*5+2);
			obj_worldX = (kp->s[stw_worldX].f) + ( oz*siny+ox*cosy			 );
			obj_worldY = (kp->s[stw_worldY].f) + ( *(firedata+animeframe*5+1));
			obj_worldZ = (kp->s[stw_worldZ].f) + ( oz*cosy-ox*siny			 );
			execstp->s[stw_angleX].d = *(firedata+animeframe*5+4)+3072;
			execstp->s[stw_angleY].d = *(firedata+animeframe*5+3)+(short)(kp->s[stw_angleY].d);
			if ( ( animeframe % 2 ) == 0 )	s_makeobj_nowpos(execstp,S_fireball_yellow,e_fireball);

		} 

	} 

}


/********************************************************************************
	   --------------------------------
		ENEMY BOSS KOPA PROGRAM DAMAGE
	   --------------------------------
 ********************************************************************************/

extern void s_kopa_damagecube(void)
{

	s_copy_worldXYZ_angleXYZ(execstp,execstp->motherobj);

	if ( execstp->motherobj->s[stw_mode].d == mode_s_kopa_dead ){
		if ( execstp->motherobj->s[stw_process].d  == 11 ) obj_objname = 0;
		else											   obj_objname = OBJNAME_FRIEND;
	} else {
		obj_objname = OBJNAME_DAMAGE;
		if ( execstp->motherobj->s[stw_alpha].d  < 100 )	s_hitOFF();
		else												s_hitON();
	}

	if ( execstp->motherobj->s[stw_actionmode].d != 0  ) s_hitOFF();

	obj_mail = 0;

}


/********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
	   -------------------------
		ENEMY BOSS KOPA PROGRAM
	   -------------------------
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
*********************************************************************************
********************************************************************************/

/* obj_playerdist */
/* obj_targetnagle */

#define		KOPA_LOOKPLAYER		(1<<1)
#define		KOPA_LOOKCENTER		(1<<2)
#define		KOPA_NEARPLAYER		(1<<3)
#define		KOPA_NEARCENTER		(1<<4)

#define		KOPA_SUPERJUMP		(1<<16)
#define		KOPA_SKYFIRE		(1<<17)

#define		kopa_status	(execstp->s[stw_work0].d)
#define		kopa_timer	(execstp->s[stw_work1].d)
#define		kopa_centerdist	(execstp->s[stw_work2].f)


#define		kopa_work				(execstp->s[stw_work4].word[0])
#define		kopa_ai_level			(execstp->s[stw_work4].word[1])
#define		kopa_random				(execstp->s[stw_work5].word[0]) 
#define		kopa_throwangleX		(execstp->s[stw_work5].word[1]) 
#define		kopa_throwangleYspeed	(execstp->s[stw_work6].word[0])
#define		kopa_throwflag			(execstp->s[stw_work6].word[1])
#define		kopa_ai_mode			(execstp->s[stw_work7].word[0])
#define		kopa_centerangle		(execstp->s[stw_work7].word[1])
#define		kopa_alpha				(execstp->s[stw_work8].word[0])
#define		kopa_eyetimer(n)		      (n->s[stw_work8].word[1])
#define		kopa_eyemode(n)			      (n->s[stw_work9].word[0])
#define		kopa_lightmode(n)		      (n->s[stw_work9].word[1])


/********************************************************************************
	#####
	#####	library
	#####	
 ********************************************************************************/

static int make_firering(void)
{
	StrategyRecord *stp;
	if ( obj_programselect == KOPA_LAST ){ 
		stp = s_makeobj_nowpos( execstp, S_firering , e_firering );
		stp->s[stw_worldY].f = obj_groundY;
		return(1);
	}
	return(0);

}



static void kopa_boundsound(long *timer)
{


	if ( obj_movestatus & MOVESTAT_BGBOUND ){
		 (*timer)++;
		if ( *timer < 4 ){
			s_set_camerainfo(execstp,BATTLE_KUPPA_BOUND);
			s_burneffect(0,0,60);
			objsound(NA_SE3_KUPAWALK);
		}
	}		

}


/********************************************************************************
	#####
	#####	kopa walk sub
	#####	
 ********************************************************************************/

/*-------------------------------------------------------------------------------
		<< walk start >>
-------------------------------------------------------------------------------*/

static int kopa_walk_start(void)
{
	s_set_skelanimeNo(ANM_kopa_walk_start);	
	if ( s_check_animenumber(21) )	obj_speedF	= 3;

	if ( s_check_animeend() )		return(1);
	else							return(0);

}

/*-------------------------------------------------------------------------------
		<< walk walk loop >>
-------------------------------------------------------------------------------*/

static int kopa_walk_loop(void)
{
	obj_speedF	= 3;
	s_set_skelanimeNo(ANM_kopa_walk);

	if ( s_check_animeend() )	return(1);
	else						return(0);
}

/*-------------------------------------------------------------------------------
		<< walk walk end >>
-------------------------------------------------------------------------------*/

static int kopa_walk_end(void)
{

	s_set_skelanimeNo(ANM_kopa_walk_end);
	if ( s_check_animenumber(20) )	obj_speedF	= 0;

	if ( s_check_animeend() ) return(1);
	else					  return(0);

}




/********************************************************************************
	#####
	#####	kopa demo program
	#####	
 ********************************************************************************/

static void kopa_demomode_check(void)
{
	if 		( obj_imm == 0 )	obj_mode = mode_s_kopa_demo_wait;
	else if ( obj_imm == 1 )	obj_mode = mode_s_kopa_demo_walk;
	else {
		if ( obj_programselect == KOPA_YOGAN ) obj_mode = mode_s_kopa_jump_atom;
		else								   obj_mode = mode_s_kopa_wait;
	}

}

static void s_kopa_demo_wait(void)
{
	obj_speedF = 0;
	s_set_skelanimeNo(ANM_kopa_wait);
	kopa_demomode_check();
}

static void s_kopa_demo_walk(void)
{

	if ( obj_process == 0 ){
		if ( kopa_walk_start() ) obj_process++;
	} else if ( obj_process == 1 ){
		if ( kopa_walk_loop()  ) obj_process++;
	} else {
		if ( kopa_walk_end() ){
			if ( obj_imm == 1 ) obj_imm = 0;
			kopa_demomode_check();
		}
	}

}




/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/

static char kopamode_table[] = {
	mode_s_kopa_dash,			/* 0  dash          mode */
	mode_s_kopa_sky_fire,		/* 1  skyfire       mode */
	mode_s_kopa_small_fire,		/* 2  smallfire     mode */
	mode_s_kopa_safe_return,	/* 3  safe return   mode */
	mode_s_kopa_jump_atom,		/* 4  jump atom     mode */
	mode_s_kopa_search_walk,	/* 5  normal search mode */
	mode_s_kopa_normal_fire,	/* 6  normal search mode */
	mode_s_kopa_dead,			/* 7  kopa dead     mode */
	mode_s_kopa_punch,			/* 8  kopa punch    mode */
	mode_s_kopa_erasemove,		/* 9  kopa erase    mode */
	mode_s_kopa_jump,			/* 10 kopa punch    mode */
	mode_s_kopa_bg_rotate,		/* 11 kopa bg rotate mode */
	mode_s_kopa_punch,			/* 12 kopa punch    mode */
	mode_s_kopa_punch,			/* 13 kopa punch    mode */
	mode_s_kopa_punch,			/* 14 kopa punch    mode */
	mode_s_kopa_punch,			/* 15 kopa punch    mode */
};

/********************************************************************************
	debugkopa program
 ********************************************************************************/

static void kopa_debug_program(void)
{
	if ( enemy_p1 ){
		obj_mode = kopamode_table[enemy_p2 & 0xf];
		enemy_p1 = 0;
	}
}

/********************************************************************************
	kopa(1) program
 ********************************************************************************/

static void kopa_1_program(void)
{

	float random = Randomf();

	if ( kopa_ai_mode == 0 ){

		if ( kopa_status & KOPA_LOOKPLAYER ){
			if ( obj_playerdist < 1500 ) obj_mode = mode_s_kopa_normal_fire;
			else 						 obj_mode = mode_s_kopa_jump;
		} else {
		 	obj_mode = mode_s_kopa_search_walk;
		}
		kopa_ai_mode++;

	} else {
		kopa_ai_mode = 0;
	
		if ( autoDemoPtr == NULL ){
			if 		( random < 0.1 )	obj_mode = mode_s_kopa_punch;
			else						obj_mode = mode_s_kopa_search_walk;
		} else {
			obj_mode = mode_s_kopa_search_walk;
		}
	}


}

/********************************************************************************
	kopa(2) program
 ********************************************************************************/

static void kopa_2_program(void)
{

	float random = Randomf();

	if ( kopa_ai_mode == 0 ){

		if ( kopa_status & KOPA_LOOKPLAYER ){
			if ( obj_playerdist < 1300 ){
				if ( random < 0.5 )	obj_mode = mode_s_kopa_erasemove;
				else				obj_mode = mode_s_kopa_small_fire;
			} else {
				obj_mode = mode_s_kopa_dash;
				if ( 500 < kopa_centerdist && kopa_centerdist < 1500 ){
				 	if ( random < 0.5 ) obj_mode = mode_s_kopa_jump_atom;
				}
			}
		} else {
		 	obj_mode = mode_s_kopa_search_walk;
		}

		kopa_ai_mode++;

	} else {
		kopa_ai_mode = 0;
		obj_mode = mode_s_kopa_search_walk;
	}

}

/********************************************************************************
	kopa(3) program
 ********************************************************************************/

#define		ai_normal			0
#define		ai_search			1


/*--------------------------------------------------------------------------------
		level (0) action
--------------------------------------------------------------------------------*/

static void kopa_3_level_0(void)
{
	float random = Randomf();


	if ( kopa_status & KOPA_LOOKPLAYER ){
		if ( obj_playerdist < 1000 ){
			if 		( random < 0.4 ) obj_mode = mode_s_kopa_small_fire;
			else if ( random < 0.8 ) obj_mode = mode_s_kopa_sky_fire;
			else					 obj_mode = mode_s_kopa_normal_fire;
		} else {
		 	if ( random < 0.5 ) obj_mode = mode_s_kopa_jump_atom;
			else				obj_mode = mode_s_kopa_dash;
		}
	} else {
	 	obj_mode = mode_s_kopa_search_walk;
	}


}

/*--------------------------------------------------------------------------------
		level (1) action
--------------------------------------------------------------------------------*/
static void kopa_3_level_1(void)
{
	obj_mode = mode_s_kopa_jump_atom;
}


/*--------------------------------------------------------------------------------
		kopa 3 program
--------------------------------------------------------------------------------*/

static void kopa_3_program(void)
{

	switch(kopa_ai_mode){
		case	ai_normal:
			if ( kopa_ai_level == 0 )	kopa_3_level_0();
			else						kopa_3_level_1();
			kopa_ai_mode = ai_search;
			break;
		case	ai_search:
			kopa_ai_mode = ai_normal;
			obj_mode = mode_s_kopa_search_walk;
			break;
	}



}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa jump error program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void kopa_jump_error_check(void)
{
	if ( obj_speedY < 0 && obj_worldY < obj_attY-300 ){
		obj_worldX = obj_worldZ = 0;
		obj_worldY = obj_attY+2000;
		obj_speedY = 0;
		obj_speedF = 0;
	}			
}


/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa wait program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_normal_wait(void)
{
	if ( s_setanime_endcheck(ANM_kopa_wait) ) obj_mode = mode_s_kopa_wait;
}


/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa wait program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_wait(void)
{

	kopa_eyemode(execstp) = mode_kopaeye_normal;	/* eye mode normal */
	s_set_skelanimeNo(ANM_kopa_wait);
	obj_anglespeedY = 0;
	obj_speedF = 0;
	obj_speedY = 0;	
	
	/*--------------------- set wait staus -----------------------*/


#if	DEBUGSW

	if ( enemy_p0 == 0 ){
		if ( obj_programselect == 0 )		kopa_1_program();
		else if ( obj_programselect == 1 )	kopa_2_program();
		else								kopa_3_program();
	} else {
		kopa_debug_program();
	}

#else 

	if ( obj_programselect == 0 )		kopa_1_program();
	else if ( obj_programselect == 1 )	kopa_2_program();
	else								kopa_3_program();

#endif


}


/********************************************************************************
	#####	===================================================================
	#####
	#####	 kopa normal fire
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_normal_fire(void)
{

	obj_speedF	= 0;
	if ( obj_timer == 0 )						objsound(NA_SE3_KUPABREATH);
	if ( s_setanime_endcheck(ANM_kopa_fire)	)	obj_mode = mode_s_kopa_wait;

}


/********************************************************************************
	#####	===================================================================
	#####
	#####	 kopa search walk program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_search_walk(void)
{


	int 	sameflag;
	short	angspeed;

	short dangle = s_calc_dangle(obj_angleY,obj_targetangle);

	if ( obj_programselect == KOPA_YOGAN ){
		angspeed = 0x400;
	} else {
		if 		( obj_hp > 2  ) angspeed = 0x400;
		else if ( obj_hp == 2 ) angspeed = 0x300;
		else					angspeed = 0x200;
	}

	sameflag = s_chase_angleY(obj_targetangle,angspeed);

	
	if ( obj_process == 0 ){
		kopa_timer = 0;
		if ( kopa_walk_start() ) obj_process++;
	} else if ( obj_process == 1 ){
		if ( kopa_walk_loop()  ){
			kopa_timer++;
			if ( kopa_status & KOPA_SKYFIRE ){
				if ( kopa_timer >= 5 ) Mbitclr(kopa_status,KOPA_SKYFIRE);
			} else {
				if ( dangle < 0x2000 ) obj_process++;
			}
		}	
	} else {
		if ( kopa_walk_end() ){
			obj_mode = mode_s_kopa_wait;
		}
	}


}



/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa skyfire program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_erasemove(void)
{

	switch(obj_process){
	
		case 0:
			s_hitOFF();
			kopa_alpha = 0;					/* disp OFF */
			kopa_timer = 30;
			if ( obj_timer == 0 )	objsound(NA_SE3_TEREPORT);
			if ( obj_alpha == 0 ){
				obj_process++;
				obj_angleY = obj_targetangle;
			}
			break;
		case 1:
			if ( kopa_timer-- ){
				obj_speedF = 100;
			} else {
			 	obj_process = 2;
				obj_angleY = obj_targetangle;
			}

			if (   s_calc_dangle(obj_angleY,obj_targetangle) > 0x4000  && obj_playerdist > 500 ){
				obj_process = 2;
				obj_angleY = obj_targetangle;
				objsound(NA_SE3_TEREPORT);
			}

			break;
		case 2:
			obj_speedF = 0;
			kopa_alpha = 255;				/* disp ON  */
			if ( obj_alpha == 255 ) obj_mode = mode_s_kopa_wait;
			s_hitON();
			break;

	}



}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa skyfire program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_sky_fire(void)
{

	int	anime_frame;
	s_set_skelanimeNo(ANM_kopa_scream);
	anime_frame = execstp->map.skelanim.frame;

	if ( 24 < anime_frame  && anime_frame < 36 ){

		objsound_level(NA_LSE3_KUPAFIRE);
		if ( anime_frame == 35 ) s_makeobj_chain(1,0,400,100,execstp,S_fireball_yellow,e_kopafire_super);
		else					 s_makeobj_chain(0,0,400,100,execstp,S_fireball_yellow,e_kopafire_super);

	}
	// dbErrPrint("%d\n",anime_frame);
	if ( s_check_animeend() )	obj_mode = mode_s_kopa_wait;
	Mbitset(kopa_status,KOPA_SKYFIRE);

}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa safe return
	#####
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_safe_return(void)
{
	
	if ( obj_timer == 0 ){
		obj_speedF 	= -400;
		obj_speedY 	= 100;
		obj_angleY	= kopa_centerangle+0x8000;
		kopa_eyemode(execstp) = mode_kopaeye_damage;
	}

	if ( obj_process == 0 ){

		s_set_skelanimeNo(ANM_kopa_safe_down_start);
		obj_process++;
		kopa_timer = 0;

	} else if ( obj_process == 1 ){

		s_set_skelanimeNo(ANM_kopa_safe_down_start);
		s_stop_animeend();
		kopa_boundsound(&kopa_timer);
		if ( kopa_timer >= 3 ){
			s_set_skelanimeNo(ANM_kopa_safe_down_end);
			obj_speedY = 0;
			obj_speedF = 0;
			obj_process++;
		}

	} else if ( obj_process == 2 ){

		if ( s_check_animeend() ){
			if ( obj_hp == 1 ) obj_mode = mode_s_kopa_punch;
			else			   obj_mode = mode_s_kopa_wait;
			kopa_eyemode(execstp) = mode_kopaeye_normal;
		}

	} else {


	}


}

/********************************************************************************
	==================================================================
	==================================================================
		jump check common program
	==================================================================
	==================================================================
 ********************************************************************************/

static int kopa_jump_check(void)
{
	s_set_skelanimeNo(ANM_kopa_jump_start);
	if ( s_check_animenumber(11) )	return(1);
	else							return(0);

}

static int kopa_jumpend_check(void)
{

	if ( (obj_movestatus & MOVESTAT_BGBOUND) ){
		obj_speedF = 0;
		obj_speedY = 0;

		s_burneffect(0,0,60);
		s_set_skelanimeNo(ANM_kopa_jump_end);
		execstp->map.skelanim.frame = 0;

		s_set_camerainfo(execstp,BATTLE_KUPPA_JUMPEND);

		if ( obj_programselect == KOPA_1GOU ){
			if ( obj_playerdist < 850 )	Mbitset(player1stp->s[stw_mail].d,PLAYERMAIL_KOPA_JUMPEND_NEAR);
			else 						Mbitset(player1stp->s[stw_mail].d,PLAYERMAIL_KOPA_JUMPEND_FAR);
		}

 		return(1);
	} else {
		return(0);
	}

}

/********************************************************************************
	#####	=============================
	#####
	#####	kopa jump atom << mode >>
	#####
	#####	=============================
 ********************************************************************************/

static kopa_center_jump(void)
{

	if ( ( obj_programselect == KOPA_LAST ) && ( kopa_status & KOPA_SUPERJUMP) ){
		if ( kopa_centerdist > 1000 ) obj_speedF = 60;
	}

}

static void s_kopa_jump_atom(void)
{

	StrategyRecord *stp;

	if ( obj_process == 0 ){
		if ( kopa_jump_check() ){
			if ( ( obj_programselect == KOPA_LAST ) && ( kopa_status & KOPA_SUPERJUMP) ){
				obj_speedY = 70;
			} else {
				obj_speedY = 80;
			}
			kopa_timer = 0;
			kopa_center_jump();
			obj_process++;
		}
	} else if ( obj_process == 1 ){

		if ( ( obj_programselect == KOPA_LAST ) && ( kopa_status & KOPA_SUPERJUMP) ){
			kopa_jump_error_check();
		}

		if ( kopa_jumpend_check() ){
			Mbitclr(kopa_status,KOPA_SUPERJUMP);
			obj_speedF = 0;
			obj_process++;
			make_firering();
			if ( obj_programselect == KOPA_YOGAN )  obj_mode = mode_s_kopa_bg_rotate;
		} else {

		}
	} else {
		if ( s_check_animeend() )	obj_mode = mode_s_kopa_wait;
	}

}

/********************************************************************************
	#####	=============================
	#####
	#####	kopa jump normal << mode >>
	#####
	#####	=============================
 ********************************************************************************/

static short speed_Y_data[] = { 60 };
static short speed_F_data[] = { 50 };

static void s_kopa_jump(void)
{

	float	speedY = speed_Y_data[0];
	float	speedF = speed_F_data[0];

	if ( obj_process == 0 ){
		if ( kopa_jump_check() ){
			obj_speedY = speedY;	/* speed(Y)	*/
			obj_speedF = speedF;	/* speed(F)	*/
			kopa_timer = 0;
			obj_process++;
		}
	} else if ( obj_process == 1 ){
		if ( kopa_jumpend_check() )	obj_process++;
	} else {
		if ( s_check_animeend() )	obj_mode = mode_s_kopa_wait;
	}

}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa cliff dance
	#####
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_cliff_dance(void)
{

	obj_speedF = 0;
	if (obj_timer == 0 )	kopa_timer = 0;

	switch(obj_process){
		case 0:
			s_set_skelanimeNo(ANM_kopa_cliff_dance);
			if ( s_check_animeend() )  	kopa_timer++;
			if ( kopa_timer >= 1 )	obj_process++;	
			break;
		case 1:
			s_set_skelanimeNo(ANM_kopa_cliff_dance_end);
			if ( s_check_animeend() )  	obj_mode = mode_s_kopa_turn;
			break;
	}


}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa small fire program
	#####	
	#####	===================================================================
 ********************************************************************************/

static void s_kopa_small_fire(void)
{

	extern void i_set_fireball(short ox, short oy, short oz, float scale, int shape, float initial_speed, float to_speed,short angleX);

	if ( playerMeter.power < 4 ) 	kopa_random = 3;
	else							kopa_random = Randomf()*3+1;

	s_set_skelanimeNo(ANM_kopa_small_fire);

	if ( s_check_animenumber(5) ){
	    i_set_fireball(0,200,180,7,S_fireball_yellow, 30,10, 0x1000 );
	}

	if ( s_check_animeend() ) obj_process++;
	if ( obj_process >= kopa_random ) obj_mode = mode_s_kopa_wait;

}


/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa random turn
	#####	
	#####	===================================================================
 ********************************************************************************/

static int kopaturn(int time,short speed)
{
	if 	   ( obj_process == 0 ){
		if ( s_setanime_endcheck(ANM_kopa_walk_start)	) obj_process++;
	} else if ( obj_process == 1 ){
		if ( s_setanime_endcheck(ANM_kopa_walk_end)		) obj_process++;
	} else {
		s_set_skelanimeNo(ANM_kopa_wait);
	}

	obj_speedF = 0;
	obj_angleY += speed;

	if ( obj_timer >= time ) return(1);
	else					return(0);

}


static int s_kopa_turn(void)
{

	if ( kopaturn(63,0x200) ) obj_mode = mode_s_kopa_wait;

}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa dash program
	#####	
	#####	===================================================================
 ********************************************************************************/

/*

	#define ANM_kopa_dash_start		18
	#define ANM_kopa_dash			19
	#define ANM_kopa_dash_end		20
	#define ANM_kopa_dash_slip		21

*/

#define	KOPADASH_START		0
#define	KOPADASH_DASH		1
#define	KOPADASH_END		2
#define	KOPADASH_SLIP		3
#define	KOPADASH_TURN		4



static void s_kopa_dash(void)
{

	int	timer;
	if ( obj_timer == 0 )	obj_speedF = 0;
	
	switch(obj_process){

		case KOPADASH_START:
			kopa_timer = 0;
			if ( s_setanime_endcheck(ANM_kopa_dash_start) ) obj_process = KOPADASH_DASH;	
			break;

		case KOPADASH_DASH:	
			obj_speedF = 50;
			if ( s_setanime_endcheck(ANM_kopa_dash)){
				kopa_timer++;
				if ( kopa_timer > 5 ) obj_process = KOPADASH_SLIP;
				if ( kopa_timer >= 2 ){
					if ( s_calc_dangle(obj_targetangle,obj_angleY) > 0x2000  ){
						obj_process = KOPADASH_SLIP;
					}
				}
			}
			s_chase_angleY( obj_targetangle,0x200 );
			break;

		case KOPADASH_SLIP:	
			kopa_timer = 0;
			s_set_skelanimeNo(ANM_kopa_dash_slip);
			s_makeobj_chain_scale(0, 100, -50, 0, 3,execstp,S_dust,e_kemuri);
			s_makeobj_chain_scale(0,-100, -50, 0, 3,execstp,S_dust,e_kemuri);
			if ( s_chase_speed(&obj_speedF,0,-1) ) obj_process = KOPADASH_END;
			s_stop_animeend();
			break;

		case KOPADASH_END:						/* Dash Animation End */ 
			obj_speedF = 0;
			s_set_skelanimeNo(ANM_kopa_dash_end);
			if ( s_check_animeend() ){
				if ( obj_programselect == KOPA_LAST )	timer = 10;
				else									timer = 30;
				if ( kopa_timer > timer ) obj_mode = mode_s_kopa_wait;
				kopa_timer++;
			}
			s_stop_animeend();
			
			break;

	}

	if ( obj_movestatus & MOVESTAT_GAKE ) obj_mode = mode_s_kopa_cliff_dance;

}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa swing start ( fly )
	#####
	#####	===================================================================
 ********************************************************************************/

static int kirai_damagecheck(void)
{
	StrategyRecord *stp; 	/* strategy pointer  */
	float			dist;	/* strategy distance */

	stp = s_search_nearobject(e_kirai,&dist);
	if ( stp != NULL ){
		if ( dist < KIRAI_DIST ){
			stp->s[stw_mail].d |= EMAIL_KOPADOWN;
			return(1);
		}
	}

	return(0);
}

extern void s_kopa_swingstart(void)
{

	int	count;

	if ( obj_timer < 2 )	kopa_timer = 0;

	if ( obj_process == 0 ){

	//	if ( s_abs_f(obj_groundY-obj_attY) > 100  ) s_chase_speed(&obj_speedF,0,-4);

		s_set_skelanimeNo(ANM_kopa_G_swing_help);
		kopa_boundsound(&kopa_timer);				/* Set Bound Sound 		*/
		if ( (obj_movestatus & MOVESTAT_BGTOUCH) ){
			obj_speedF	= 0;
			obj_process++;
		}

	} else {
		if ( s_setanime_endcheck(ANM_kopa_G_swing_down) )	obj_mode = mode_s_kopa_wait;
	}

	/*------- kirai damage check ---------*/

	if ( kirai_damagecheck() ){
		obj_hp--;
		if ( obj_hp <= 0 )	obj_mode = mode_s_kopa_dead;
		else 				obj_mode = mode_s_kopa_safe_return;
	}

	/*------------------------------------*/


}


/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa super jump !! 
	#####
	#####	===================================================================
 ********************************************************************************/

static void kopa_areaover_stop(void)
{
	kopa_alpha = 0;							/* kopa erase */
	if ( obj_alpha == 0 ){
		obj_speedF = 0;
		obj_speedY = 0;
		obj_worldY = (obj_attY-KOPALIMIT);
	}
}

static void s_kopa_superjumpstart(void)
{

	int flag;
	StrategyRecord  *stp;
	BGCheckData		*bgdata = (BGCheckData *)obj_bgpointer;

	if ( ( bgdata != NULL ) && (( bgdata->BGstatus ) & BGTYPE_MOVEBG ) ) flag = 1;
	else																 flag = 0;


	Mbitset(kopa_status,KOPA_SUPERJUMP);

	switch(obj_process){
		case 0:

			if ( obj_timer == 0 ){
				obj_animeangleX = 0;
				obj_animeangleZ = 0;
			}
			obj_animeangleX += 0x800;
			obj_animeangleZ += 0x800;
			if ( (( obj_animeangleX )& 0xffff) == 0 ) obj_process++;
			kopa_areaover_stop();
			break;

		case 1:

			s_set_skelanimeNo(ANM_kopa_jump_start);
			if ( s_check_animenumber(11) ){
				obj_angleY = kopa_centerangle;
				obj_speedY = 150;
				kopa_alpha = 255;			/* kopa appear */
				kopa_timer = 0;				/* timer reset */
				obj_process++;
			} else {
				kopa_areaover_stop();
			}
			break;

		case 2:

			if ( obj_worldY > obj_attY ){
				obj_air_fric = 0;
				if ( kopa_centerdist < 2500 ){
					if ( s_abs_f(obj_groundY-obj_attY) < 100 ) s_chase_speed(&obj_speedF,0,-5);
				    else 									   s_chase_speedF(150,2);
				} else {
					s_chase_speedF(150,2);
				}								  
			}

			if ( kopa_jumpend_check() ){
				obj_air_fric = 10;
			    obj_process++;
				if ( flag == 0 )	make_firering();
				else if ( obj_programselect == KOPA_LAST ) obj_mode = mode_s_kopa_jump_atom;
		
				if ( obj_programselect == KOPA_YOGAN )	obj_mode = mode_s_kopa_bg_rotate;

			}

		/*========= Error Check !! =============*/
			kopa_jump_error_check();

		/*======================================*/

			break;

		case 3:
			if ( s_check_animeend() ){
				obj_mode = mode_s_kopa_wait;
				Mbitclr(kopa_status,KOPA_SUPERJUMP);
				s_stop_animeend();
			}
			break;
	}


	dbErrPrint("sp %d",(int)obj_speedF);
}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa punch
	#####
	#####	===================================================================
 ********************************************************************************/

static char punchsound_tab[] = { 24,42,60,-1 };
extern void s_kopa_punch(void)
{

	if ( s_check_chartable(obj_timer,punchsound_tab) ) 	objsound(NA_SE3_KUPAWALK); 
	if ( s_setanime_endcheck(ANM_kopa_punch) 		 )	obj_mode = mode_s_kopa_wait;

}


/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa dead program
	#####
	#####	===================================================================
 ********************************************************************************/

static void	kopa_dead_makekey(void)
{


	if ( obj_programselect == KOPA_LAST ){
		camBOSSstp = s_makeobj_nowpos(execstp,S_polystar,e_kopa_laststar);
	} else {
		camBOSSstp = s_makeobj_nowpos(execstp,S_kopakey,e_kopa_key);
		objsound(NA_SE2_KUPPA_KEY_FALL);
	}
	camBOSSstp->s[stw_anglespeedY].d = obj_anglespeedY;

}


/********************************************************************************/
/********************************************************************************/
/********************************************************************************/

/*------------------------------------------------------------------------------------------*/
/*		dead start																			*/
/*------------------------------------------------------------------------------------------*/
static int kopadead_start(void)
{
	s_set_skelanimeNo(ANM_kopa_dead_start);

	if ( obj_programselect == KOPA_LAST ) 	obj_speedF = -400;
	else									obj_speedF = -200;
	obj_speedY =  100;

	obj_angleY	= kopa_centerangle+0x8000;
	kopa_timer 	= 0;
	obj_process++;
}

/*------------------------------------------------------------------------------------------*/
/*		dead entry																			*/
/*------------------------------------------------------------------------------------------*/
static int kopadead_entry(void)
{
	kopa_eyemode(execstp) = mode_kopaeye_damage;
	kopa_boundsound(&kopa_timer);
	if ( (obj_movestatus & MOVESTAT_BGBOUND ) )	objsound(NA_SE3_KUPAWALK);
	if ( (obj_movestatus & MOVESTAT_BGTOUCH) ){
		obj_speedF	= 0;
		obj_process++;
	}
}

/*------------------------------------------------------------------------------------------*/
/*		dead wait process																	*/
/*------------------------------------------------------------------------------------------*/
static int kopadead_wait(void)
{
	int	flag = 0;
	s_hitOFF();
	if ( s_setanime_endcheck(ANM_kopa_dead_end) ){
		if ( obj_playerdist < 700 && ( s_calc_dangle(player1stp->s[stw_angleY].d,obj_targetangle) > 0x6000 ) ){
			flag = 1;
		}
	}
	s_stop_animeend();
	kopa_timer 	= 0;
	return(flag);
}

/*------------------------------------------------------------------------------------------*/
/*		dead keydemo process																*/
/*------------------------------------------------------------------------------------------*/

static int kopadead_keydemo_entry(void)
{
	int flag = 0;
	if ( execstp->map.scale[0] < 0.8 ) obj_anglespeedY += 0x80;
	if ( execstp->map.scale[0] > 0.2 ){
		execstp->map.scale[0] -= 0.02;
		execstp->map.scale[2] -= 0.02;
	} else {
		execstp->map.scale[1] -= 0.01;
		obj_speedY   = 20;
		obj_gravity  = 0;
	}
	if ( execstp->map.scale[1] < 0.5 )	flag = 1;

	obj_angleY += obj_anglespeedY;			/* add anglespeed 	*/
	if ( obj_alpha > 2 ) obj_alpha -= 2;	/* change alpha		*/

	return(flag);
}



static short kopadead_message[] = { 119,120,121 };


static void s_erase_kopa(void)
{
	s_set_scale(0);
	obj_speedF 	= 0;
	obj_speedY 	= 0;
	obj_gravity	= 0;
}


static int kopadead_keydemo(void)
{

	int	flag = 0;

	if ( kopa_timer <= 1 ){

		if ( kopa_timer == 0 ){ Na_MusicMuteOn(); kopa_timer++; }
		if 	( s_call_enemydemo(DLOG_LOOKUP,ENEMYDEMO_SETMESSAGE+ENEMYDEMO_DLOG_NOSTOP,kopadead_message[obj_programselect],0) ){
		 	kopa_timer++;
			objsound(NA_SE2_KUPPA_DISAPPEAR);
			Na_MusicMuteOff();
			Na_KuppaBgmFadeOut();
		}
	} else {
		if ( kopadead_keydemo_entry() ){
			s_erase_kopa();
			s_boxeffect(20,S_coin,1.0,0);
			kopa_dead_makekey();
			CtrlPlayerDialog(DLOG_DONE);
			flag = 1;
		}
	}

	return(flag);

}

/*------------------------------------------------------------------------------------------*/
/*		dead stardemo process																*/
/*------------------------------------------------------------------------------------------*/



static int kopadead_stardemo(void)
{


	int	i;
	int	flag = 0;

	int messageNo;

	if ( kopa_timer <= 1 ){

		if ( playerMeter.star < 120 ) 	messageNo = 121;
		else							messageNo = 163;

		if ( kopa_timer == 0 ){ Na_MusicMuteOn(); kopa_timer++; }

		if 	( s_call_enemydemo(DLOG_LOOKUP,ENEMYDEMO_SETMESSAGE+ENEMYDEMO_DLOG_NOSTOP,messageNo,0) ){
			s_change_shape(S_kopa_noshadow);
			Na_MusicMuteOff();
			Na_KuppaBgmFadeOut();
			kopa_dead_makekey();		/* ending star Make */
	 		kopa_timer++;
		}
	} else {
		if ( obj_alpha > 4  ){
			obj_alpha -= 4;	/* change alpha		*/
		} else {
			s_erase_kopa();
			flag = 1;
		//	CtrlPlayerDialog(DLOG_DONE);
		}
	}


	return(flag);

}

/*------------------------------------------------------------------------------------------*/
/*		main dead																			*/
/*------------------------------------------------------------------------------------------*/
static void s_kopa_dead(void)
{

	switch(obj_process){
		case	0:	kopadead_start();	break;
		case	1:	kopadead_entry();	break;
		case	2:	
			if ( kopadead_wait() ){
				kopa_timer = 0;	
				if ( obj_programselect == KOPA_LAST )	obj_process = 10;
				else {
					Mbitset(execstp->status,OBJECT_DITHER);
					obj_process++;
				}
			}
			break;
		case	3:
			if ( kopadead_keydemo() ) obj_process++;
			break;
		case	4:
			break;
		case	10:
			if ( kopadead_stardemo() ) obj_process++;
			break;
		case	11:
			break;

	}

}

/********************************************************************************
	#####	===================================================================
	#####
	#####	kopa swing start ( fly )
	#####
	#####	===================================================================
 ********************************************************************************/


static void s_rotate_entry(StrategyRecord *stp,short speed)
{
	short	angle	= kopa_centerangle+0x8000;
	stp->s[stw_anglespeedX].d = speed *  cos(angle);
	stp->s[stw_anglespeedZ].d = speed * -sin(angle);
}

typedef struct {
	short	code;
	short	speed;
 	short	time;
} KopaBGRotRecord;

#if 0
static KopaBGRotRecord kopabg_timedata[] = {
	{ 	  1,  10,	34							},
	{  	  0,   0,	34+34						},
	{	 -1, -10,	34+34+34					},
	{	  1, -20,	34+34+34+17                 },
	{	 -1,  20,	34+34+34+17+17				},
	{	  1,  40,	34+34+34+17+17+8			},
	{	 -1, -40,	34+34+34+17+17+8+8			},
	{	  1, -80,	34+34+34+17+17+8+8+4		},
	{ 	 -1,  80,	34+34+34+17+17+8+8+4+4		},
	{	  1, 160,	34+34+34+17+17+8+8+4+4+2	},
    {	 -1,-160,	34+34+34+17+17+8+8+4+4+2	},
	{	  1,   0,	0							},
};
#endif

static KopaBGRotRecord kopabg_timedata[] = {
	{ 	  1,  10,	40							},
	{  	  0,   0,	40+34						},
	{	 -1, -10,	40+34+40					},
	{	  1, -20,	40+34+40+20       	        },
	{	 -1,  20,	40+34+40+20+20				},
	{	  1,  40,	40+34+40+20+20+10			},
	{	 -1, -40,	40+34+40+20+20+10+10		},
	{	  1, -80,	40+34+40+20+20+10+10+5		},
	{ 	 -1,  80,	40+34+40+20+20+10+10+5+5	},
	{	  1, 160,	40+34+40+20+20+10+10+5+5+2	},
    {	 -1,-160,	40+34+40+20+20+10+10+5+5+2	},
	{	  1,   0,	0							},
};

static void s_kopa_bg_rotate(void)
{

 	StrategyRecord *stp 	= s_find_obj(e_kopa2_moveBG);
	short			angle	= kopa_centerangle+0x8000;
	short			speed;
	int				spd;
	int				dp;
	int				flag;

	if (stp == NULL )	obj_mode = mode_s_kopa_wait;
	else {

		dp 	= 0;
		flag = 1;
		while( ( kopabg_timedata[dp].time ) != 0 ){
			
			if ( obj_timer < kopabg_timedata[dp].time ){
				speed = kopabg_timedata[dp].speed;
				if ( kopabg_timedata[dp].code > 0 )	speed = speed * ( kopabg_timedata[dp].time-1-obj_timer );
				else								speed = speed * ( obj_timer - (kopabg_timedata[dp-1].time) );
				s_rotate_entry(stp,speed);
				if ( speed != 0 ) Na_LevelSound(stp,NA_LSE2_STAGE_SLOPE);
				flag = 0;
				break;
			}
			dp++;
		}

		if ( flag ){
			 obj_mode = mode_s_kopa_wait;
			 stp->s[stw_anglespeedX].d = 0;
			 stp->s[stw_anglespeedZ].d = 0;
			 stp->s[stw_animeangleX].d = 0;
			 stp->s[stw_animeangleZ].d = 0;
		}

	}

	s_stop_animeend();	/* wait anime */


}

/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/


#if 0
		s_set_camerainfo(execstp,BATTLE_KUPPA_JUMPEND);
		if ( obj_playerdist < 850 )	Mbitset(player1stp->s[stw_mail].d,PLAYERMAIL_KOPA_JUMPEND_NEAR);
		else 						Mbitset(player1stp->s[stw_mail].d,PLAYERMAIL_KOPA_JUMPEND_FAR);
#endif


/*=============================================================================*/
/*=============================================================================*/
/*=============================================================================*/
/*=============================================================================*/
/*=============================================================================*/
/*=============================================================================*/

/********************************************************************************
	################################
	#####	kopa main program ######
	################################
 ********************************************************************************/

static void *kopa_modejmp[] = {
  
   s_kopa_wait,
   s_kopa_swingstart,
   s_kopa_superjumpstart,
   s_kopa_punch,
   s_kopa_dead,
   s_kopa_demo_wait,
   s_kopa_demo_walk,
   s_kopa_dash,
   s_kopa_sky_fire,
   s_kopa_small_fire,
   s_kopa_cliff_dance,
   s_kopa_turn,
   s_kopa_safe_return,
   s_kopa_jump_atom,
   s_kopa_search_walk,
   s_kopa_normal_fire,
   s_kopa_erasemove,
   s_kopa_jump,
   s_kopa_normal_wait,
   s_kopa_bg_rotate
  
};

/********************************************************************************
		 kopa areaout check
 ********************************************************************************/

static int kopa_areaout_check(void)
{

	if ( obj_mode != mode_s_kopa_superjumpstart  && obj_mode != mode_s_kopa_bg_rotate ){

		if (  obj_worldY < obj_attY-KOPALIMIT )	return(1);
		if ( obj_movestatus & MOVESTAT_BGBOUND ){
			if ( obj_bgcode == BGCHECKCODE_DAMEDE_1   )	return(1);
			if ( obj_bgcode == BGCHECKCODE_SPECIAL_R2 )	return(1);
		}
	}

	return(0);

}
														  

/********************************************************************************
		--------------------
		 kopa main program
		--------------------
 ********************************************************************************/

static EnemySoundRecord kopa_sound[] = {
	{ 0,0,0,0 },	    				/* ANM_kopa_G_swing_down   		0		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_G_swing_down2  		1		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_G_swing_help   		2		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_G_swing_start  		3		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_body_tmp       		4		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_down           		5		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_fire           		6		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_jump           		7		*/ 
	{ 1,0,-1, NA_SE3_KUPAWALK },		/* ANM_kopa_jump_end       		8		*/ 
	{ 1,0,-1, NA_SE3_KUPAGAO  },	   	/* ANM_kopa_jump_start     		9		*/ 
	{ 1,0,-1, NA_SE3_KUPAGAO  },		/* ANM_kopa_punch          		10		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_scream         		11		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_wait           		12		*/ 
	{ 1,20,40, NA_SE3_KUPAWALK },		/* ANM_kopa_walk           		13		*/ 
	{ 1,20,-1, NA_SE3_KUPAWALK },   	/* ANM_kopa_walk_end       		14		*/ 
	{ 1,20,40, NA_SE3_KUPAWALK },	    /* ANM_kopa_walk_start     		15		*/ 
	{ 1,0,-1,  NA_SE3_KUPADAMAGE },	   	/* ANM_kopa_dead_start			16		*/ 
	{ 1,0,-1,  NA_SE3_KUPADOWN },	   	/* ANM_kopa_dead_end			17		*/ 
	{ 1,8, -1, NA_SE3_KUPAWALK },		/* ANM_kopa_dash_start			18		*/ 
	{ 1,8, 17, NA_SE3_KUPAWALK },	    /* ANM_kopa_dash				19		*/ 
	{ 1,8,-10, NA_SE3_KUPAWALK },	    /* ANM_kopa_dash_end			20		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_dash_slip			21		*/ 
	{ 1,5,-1,NA_SE3_KUPPA_F_SHOT },		/* ANM_kopa_small_fire			22		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_cliff_dance			23		*/ 
	{ 0,0,0,0 },	    				/* ANM_kopa_cliff_dance_end		24		*/ 
	{ 1,0,-1, NA_SE3_KUPADAMAGE   },	/* ANM_kopa_safe_down_start		25		*/ 
	{ 1,0,-1, NA_SE3_KUPAGAO 	  },	/* ANM_kopa_safe_down_end		26		*/ 
};


extern void kopa_main(void)
{
	BGCheckData		*bgcheck_data;
	StrategyRecord	*stp;
	float		 	bgY;

/*------------------------------------------------------*/
/*	BGcheck offset calc									*/
/*------------------------------------------------------*/

	if ( ( stp = execstp->ride_strat ) != NULL ){
	 	matrix_offset(0,stp);
	//	rmonpf(( "hellow\n" ));
	}

/*------------------------------------------------------*/
/*	kopa main Program 									*/
/*------------------------------------------------------*/

	kopa_throwflag = 0;
	s_enemybgcheck();
	s_modejmp(kopa_modejmp);
	s_enemymove(-78);

/*------------------------------------------------------*/
/*	kopa areaout check !!								*/
/*------------------------------------------------------*/

	if ( kopa_areaout_check() )	obj_mode = mode_s_kopa_superjumpstart;

/*------------------------------------------------------*/
/*	Check MoveBG										*/
/*------------------------------------------------------*/

	bgY = mcBGGroundCheck(obj_worldX,obj_worldY,obj_worldZ,&bgcheck_data);

	if ( ( bgcheck_data != NULL ) && ( bgcheck_data->stratp != NULL ) ){
	 	execstp->ride_strat = bgcheck_data->stratp;
	} else {
	 	execstp->ride_strat = NULL;
	}

/*------------------------------------------------------*/
/*	kopa sound											*/
/*------------------------------------------------------*/

	s_enemysound(kopa_sound);	/* bomking sound */

}

/********************************************************************************
	#####
	#####	kopa catch
	#####
********************************************************************************/

static void kopa_catch(void)
{
	float	POW;

	Mbitclr(kopa_status,KOPA_SKYFIRE);
	s_hitOFF();
	switch(kopa_throwflag){
	 	case	0:
			objsound(NA_SE3_KUPADAMAGE);
			s_mode_catch(ANM_kopa_G_swing_start,mode_s_kopa_swingstart);
			kopa_throwflag++;
			break;
		case	1:
			if ( s_check_animeend() ){
				s_set_skelanimeNo(ANM_kopa_G_swing_help);
				kopa_throwflag++;
			}
			break;
		case	2:
			break;
	}

	obj_movestatus = 0;		/* movestatus ALL CLEAR */
	kopa_throwangleX	  = player1stp->s[stw_angleX].d;
	kopa_throwangleYspeed = player1stp->s[stw_anglespeedY].d;
	obj_angleY 			  = player1stp->s[stw_angleY].d;

}

/********************************************************************************
	#####
	#####	kopa throw
	#####
********************************************************************************/

static void kopa_throw(void)
{
	float	POW;

	kopa_throwflag = 0;
	s_mode_throw(1,1,mode_s_kopa_swingstart);

	POW = ( kopa_throwangleYspeed / 3000.0 ) * KOPA_SWINGSPEED ;
	if ( POW < 0 )	POW = -POW;
	if ( POW > 90 ) POW = POW * (2.5);

	obj_speedF = POW *  cos(kopa_throwangleX);
	obj_speedY = POW * -sin(kopa_throwangleX);

	s_hitOFF();
										/*--- new mode ---*/
	execstp->childobj->s[stw_mode].d 	= mode_kopatail_wait;
	execstp->childobj->s[stw_timer].d	= 0;
	execstp->childobj->s[stw_process].d = 0;
	obj_timer 	= 0;
	obj_process = 0;


	// dbErrPrint("pw %d\n",(int)POW);

}

/********************************************************************************
	#####
	#####	kopa catch
	#####
********************************************************************************/
/*------------------------------------------------------------------------------*/
/*		kopa program															*/
/*------------------------------------------------------------------------------*/

extern void s_kopa(void)
{

	short	dangle;
	short	center_angle;

//	int		player_centerdist;

	kopa_centerdist	 = sqrtf(obj_worldX*obj_worldX+obj_worldZ*obj_worldZ);
	kopa_centerangle = atan(0-obj_worldZ,0-obj_worldX);
	dangle 			 = s_calc_dangle(obj_angleY,obj_targetangle);
	center_angle 	 = s_calc_dangle(obj_angleY,kopa_centerangle);

	Mbitclr(kopa_status,0xff);
	if ( dangle 	     < 0x2000 	) Mbitset(kopa_status,KOPA_LOOKPLAYER);
	if ( center_angle    < 0x3800 	) Mbitset(kopa_status,KOPA_LOOKCENTER);
	if ( kopa_centerdist < 1000 	) Mbitset(kopa_status,KOPA_NEARCENTER);
	if ( obj_playerdist  < 850    	) Mbitset(kopa_status,KOPA_NEARPLAYER);

	switch(execstp->s[stw_actionmode].d){
		case	CHILEDMODE_NO_CATCH:	kopa_main();			break;
		case	CHILEDMODE_CATCH:		kopa_catch();			break;
		case	CHILEDMODE_THROW:		kopa_throw();			break;
		case	CHILEDMODE_DROP:		kopa_throw();			break;
	}
	
	s_set_mtxmode();

	/*---- alpha control ----*/

	if ( obj_mode != mode_s_kopa_dead ){
		if ( kopa_alpha != obj_alpha ){
		 	if ( kopa_alpha > obj_alpha ){
				obj_alpha += 20;
				if ( obj_alpha > 255 ) obj_alpha = 255;
			} else {
				obj_alpha -= 20;
				if ( obj_alpha < 0   ) obj_alpha = 0;
			}
		}
	}

#ifdef yajima
//	player_centerdist	 = sqrtf(player_worldX*player_worldX+player_worldZ*player_worldZ);
//	dbErrPrint("cd %d",(int)player_centerdist);
//	dbErrPrint("am %d",execstp->s[stw_skelanimeNo].d);
//	dbErrPrint("fr %d",execstp->map.skelanim.frame);
//	dbErrPrint("tm %d",obj_timer);
//	dbErrPrint("md %d",obj_mode);
//	dbErrPrint("st %d",(int)kopa_status);
//	dbErrPrint("cd %d",(int)kopa_centerdist);
#endif


	


}

/*------------------------------------------------------------------------------*/
/*		kopa initialize															*/
/*------------------------------------------------------------------------------*/
static char	initkopa_light[] = { 0, 0, 1};
#ifdef yajima
static char	initkopa_hp[] 	 = { 1, 1, 2};
#else
static char	initkopa_hp[] 	 = { 1, 1, 3};
#endif

extern void s_kopa_init(void)
{

	int kopasel;

	kopa_ai_mode	= 1;	/* 	ai mode (0)		*/
	obj_alpha		= 255;	/* 	alpha			*/
	kopa_alpha		= 255;	

	if 		( activeStageNo == 33 ) kopasel = KOPA_YOGAN;
	else if ( activeStageNo == 34 ) kopasel = KOPA_LAST;
	else						    kopasel = KOPA_1GOU;

	obj_programselect 		= kopasel;
	kopa_lightmode(execstp) = initkopa_light[kopasel];
	obj_hp					= initkopa_hp[kopasel];



	s_set_camerainfo(execstp,BATTLE_KUPPA);
	obj_mode 				= mode_s_kopa_demo_wait;
	kopa_eyetimer(execstp)	= 0;
	kopa_eyemode(execstp)	= 0;

}

/********************************************************************************

		Kopa Eye Program

 ********************************************************************************/



/********************************************************************************
	========================
			hms Program
	========================
 ********************************************************************************/

extern unsigned long KopaProc1(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);
		}

	}

	return(0);

}

/********************************************************************************
		-------------
		 Eye Program
		-------------
 ********************************************************************************/
enum{
	kopaeye_0,
	kopaeye_1,
	kopaeye_2,
	kopaeye_R1,
	kopaeye_R2,
	kopaeye_L1,
	kopaeye_L2,
	kopaeye_damage,
	kopaeye_angry,
	kopaeye_3
};


/*===========================================================================================*/
static void kopaeye_normal(StrategyRecord *stp,MapSelect *select)
{
	int		mode; 
	short	dangle = s_calc_dangle(stp->s[stw_angleY].d,stp->s[stw_targetangle].d);

	switch(mode = select->selsw){
	 	case	kopaeye_0:
			if	( dangle > 0x2000 ){
				if 	( stp->s[stw_anglespeedY].d > 0 )	select->selsw = kopaeye_L1;
				if	( stp->s[stw_anglespeedY].d < 0 )	select->selsw = kopaeye_R1;
			}
			if  ( kopa_eyetimer(stp) > 50 )				select->selsw = kopaeye_1;
			break;
	 	case	kopaeye_1:
			if  ( kopa_eyetimer(stp) > 2 )				select->selsw = kopaeye_2;
			break;
	 	case	kopaeye_2:
			if  ( kopa_eyetimer(stp) > 2 )				select->selsw = kopaeye_3;
			break;
	 	case	kopaeye_3:
			if  ( kopa_eyetimer(stp) > 2 )				select->selsw = kopaeye_0;
			break;
		case	kopaeye_L1:
			if  ( kopa_eyetimer(stp) > 2 ){
				select->selsw = kopaeye_L2;
				if	( stp->s[stw_anglespeedY].d <= 0 )  select->selsw = kopaeye_0;
			}
			break;
		case	kopaeye_L2:
			if	( stp->s[stw_anglespeedY].d		<= 0 )	select->selsw = kopaeye_L1;
			break;
	 	case	kopaeye_R1:
			if  ( kopa_eyetimer(stp) > 2 ){
				select->selsw = kopaeye_R2;
				if	( stp->s[stw_anglespeedY].d >= 0 )  select->selsw = kopaeye_0;
			}
			break;
	 	case	kopaeye_R2:
			if	( stp->s[stw_anglespeedY].d 	>= 0 )	select->selsw = kopaeye_R1;
			break;
		default:
			select->selsw = kopaeye_0;
	}

	if ( mode != select->selsw ) kopa_eyetimer(stp) = -1;

}

/*===========================================================================================*/
extern unsigned CtrlKuppaEye(int code, MapNode *node, void *data)
{
	short			mode;
	short			eye;
	short			dangle;
	StrategyRecord	*stp	= (StrategyRecord *)hmsActiveShape;
	MapSelect 		*select = (MapSelect *)node;

	if (code == MAP_CBACK_EXEC) {

		if ( hmsActiveSucker != NULL )	stp = (StrategyRecord *)hmsActiveSucker->shape;
										 
		switch(mode = kopa_eyemode(stp)){
			case mode_kopaeye_normal: kopaeye_normal(stp,select); 	break;	/* kopa-eye normal */
			case mode_kopaeye_damage: select->selsw = kopaeye_2; 	break;	/* kopa-eye damage */
		}

		kopa_eyetimer(stp) += 1;

	}

	return(0);
}


/********************************************************************************/
/*																				*/
/*		Alpha Animation	(hms-proc)												*/
/*																				*/
/*				Alpha Parameter wo kirikaeru !!									*/
/*																				*/
/*																				*/
/********************************************************************************/

extern unsigned long KopaLightCtrl(int code, MapNode *node, void *data)
{

	Gfx	*gfxPtr = NULL;
	Gfx	*gfxTmp;

	if (code == MAP_CBACK_EXEC)	{

		StrategyRecord	 *stratp 	= (StrategyRecord *)hmsActiveShape;
		MapCProg		 *cprog		= (MapCProg *)node;

		if ( hmsActiveSucker != NULL )	stratp = (StrategyRecord *)hmsActiveSucker->shape;
		if ( stratp->s[stw_alpha].d == 255 )	MapSetRenderMode(cprog, RM_SURF);
		else									MapSetRenderMode(cprog, RM_XSURF);

		gfxPtr = (Gfx *)AllocDynamic(2*sizeof(Gfx));
		gfxTmp = gfxPtr ;

		if ( kopa_lightmode(stratp) != 0 )	gSPClearGeometryMode(gfxTmp++,G_LIGHTING);

		gSPEndDisplayList(gfxTmp);

	}

	return((ulong)gfxPtr);
}

/*################*/
#endif
/*################*/
/*===============================================================================
		end end end end end end end end 
===============================================================================*/


