/********************************************************************************
					-------------------------
				 	 Ultra 64 MARIO Brothers
					-------------------------

					File		: pathcoin.s
					Description	: 
					Date		: 1995.8.1
					Author		: H.yajima

 ********************************************************************************/


/*################*/
#ifdef ASSEMBLER
/*################*/


/********************************************************************************
		obake coin program
 ********************************************************************************/


/* ---------------------------------------- */
/*											*/
/*											*/
/*		initcoin_speedY = stw_work7			*/
/*											*/
/*											*/
/* ---------------------------------------- */

e_enemyset_bluecoin:
	p_initialize(item)
	p_setname(COIN)
	p_setbit( flag,stf_moveON )
	p_softspritemodeON
	p_hitON
	p_setf(work7,20)
	p_animereset
	p_setmovedata(30,-400,-70,1000,1000,200,0,0)
	p_program(s_player_coin_init)
	p_setd(ap,5)					/* attack point 5 	*/
	p_sethitbox(120,64)				/* hitcheck wide	*/
	p_while
		p_program(s_player_coin)
		p_animeinc
	p_loop



/********************************************************************************
		obake coin program
 ********************************************************************************/

e_obake_coin:
	p_initialize(item)
	p_sethitbox(100,64)
	p_setname(COIN)						/* player coincount ++ */
	p_setbit( flag,stf_moveON | stf_alldispON )
	p_setmovedata(30,-400,-70,1000,1000,200,0,0)
	p_softspritemodeON
	p_program(s_areastage_init)
	p_while
		p_program(s_obake_coin)
		p_animeinc
	p_loop


/********************************************************************************
		manycoin program
 ********************************************************************************/

e_manycoin_obj:
	p_initialize(item)
	p_setbit( flag,stf_moveON )
	p_softspritemodeON
	p_while
		p_program(s_manycoin_obj)
	p_loop

e_manycoin:
	p_initialize(control)
	p_setbit( flag,stf_moveON | stf_playerdistON )
	p_program(s_manycoin_init)
	p_while
		p_program(s_manycoin)
	p_loop


/********************************************************************************
		<< 1 >> coin
 ********************************************************************************/

e_coin_ground:
	p_initialize(item)
	p_setd(programselect,1)
	p_jmp(el_coin_common)

e_coin:
	p_initialize(item)
el_coin_common:
	p_softspritemodeON
	p_setbit( flag,stf_moveON | stf_playerdistON )
	p_program(s_coin_init)
	p_while
		p_program(s_coin)
	p_loop


e_coin_timeend:
	p_initialize(item)
	p_softspritemodeON
	p_setbit( flag,stf_moveON )
	p_program(s_coin_init)
	p_while
		p_program(s_coin_timeend)
	p_loop

/********************************************************************************
		player coin
 ********************************************************************************/

e_player_coin_3:
	p_initialize(option)
	p_setbit( flag,stf_moveON )
	p_do(3)
		p_makeshape(S_coin,e_player_coin)
	p_next
	p_killshape

e_player_coin_10:
	p_initialize(option)
	p_setbit( flag,stf_moveON )
	p_do(10)
		p_makeshape(S_coin,e_player_coin)
	p_next
	p_killshape

e_player_coin:
	p_initialize(item)
	p_setbit( flag,stf_moveON)
	p_softspritemodeON
	p_program(s_player_coin_init)
	p_setmovedata(30,-400,-70,1000,1000,200,0,0)
	p_while
		p_program(s_player_coin)
		p_animeinc
	p_loop


/*################*/
#else
/*################*/

/********************************************************************************/
/*																				*/
/*		coin hitcheck program													*/
/*																				*/
/********************************************************************************/

static HitCheckRecord coin_hit = {
	OBJNAME_COIN,
	0,1,0,0,	/* flag,ap,hp,coin 		 */
	100,64,		/* player attack hitarea */
	 0, 0,		/* player damage hitarea */
};

/*-------------------------------------------------------------------------------*/

static int coin_hitcheck(void)
{

	if( ( obj_mail & EMAIL_PLAYERHIT ) && ((obj_mail & EMAIL_BOMB) == 0 )){
		s_makeobj_nowpos(execstp,S_spark,e_coinspark);
		s_remove_obj(execstp);
		return(1);
	} 
	obj_mail = 0;
	return(0);

}

/********************************************************************************/
/*																				*/
/*		coin program															*/
/*																				*/
/********************************************************************************/

/*------------------------------------------------------------------------------*/
extern void s_coin_init(void)
{
	s_change_pathname(e_coin);	
	s_set_hitparam(execstp,&coin_hit);
	s_areastage_init();

	s_groundcheck();
	if ( s_abs_f(obj_worldY - obj_groundY) > 500 ) s_change_shape(S_coin_noshadow);
	if ( obj_groundY < -10000 )					   s_remove_obj(execstp);

}

/*------------------------------------------------------------------------------*/
extern void s_coin(void)
{
	coin_hitcheck();
	obj_animecounter++;
}

/*------------------------------------------------------------------------------*/
extern void s_coin_timeend(void)
{
	obj_animecounter++;
	if ( s_flash_shape(200,20) )	s_remove_obj(execstp);
	coin_hitcheck();

}


/********************************************************************************/
/*	player coin																	*/
/*																				*/
/*		initcoin_speedY = stw_work7												*/
/*																				*/
/********************************************************************************/

extern void s_player_coin_init(void)
{

	obj_speedY = Randomf()*10+30 + execstp->initcoin_speedY;
	obj_speedF = Randomf()*10;
	obj_angleY = Randomd();

	s_change_pathname(e_coin);				/* change pathname		*/
	s_set_hitparam(execstp,&coin_hit);
	s_hitOFF();

}

/*--------------------------------------------------*/
/*		player coin program							*/
/*--------------------------------------------------*/

#define		coin_soundcheck		execstp->s[stw_work9].d


extern void s_player_coin(void)
{

	BGCheckData *bgdata;
	short angle;

	s_enemybgcheck();	/* BG check 	*/
	s_wallreverse();   	/* Wall Reverse */
	s_enemymove(-62);  	/* Enemy Move	*/

	if ( (bgdata = obj_bgpointer) != NULL ){
		if ( obj_movestatus & MOVESTAT_BGTOUCH ) obj_process = 1;
		if ( obj_process == 1 ){
			obj_bound_e = 0;
			if ( bgdata->b < 0.9  ){
				angle = atan(bgdata->c,bgdata->a);
				s_chase_angleY(angle,0x400);
			}
		}
	}




	if ( obj_timer == 0 )	objsound(NA_SE2_COINFLY);
	if ( obj_speedY < 0 )	s_hitON();

	if ( obj_movestatus & MOVESTAT_BGBOUND ){
		if ( obj_movestatus & (MOVESTAT_FIRE + MOVESTAT_DEATHCODE) ) s_remove_obj(execstp);
	}

	if ( obj_movestatus & MOVESTAT_BIGBOUND ){
		if ( coin_soundcheck < 5 )	objsound(NA_SE2_COINBOUND);
	 	coin_soundcheck++;
	}
	if ( s_flash_shape(400,20) )	s_remove_obj(execstp);
	coin_hitcheck();

}

/********************************************************************************/
/*																				*/
/*		many coin program														*/
/*																				*/
/********************************************************************************/

#define		manycoin_flag		s[stw_work0].d
#define		manycoin_bgcheck	s[stw_work1].d


/*------------------------------------------------------------------------------*/
extern void s_manycoin_obj(void)
{

	if (obj_timer == 0 ){
		s_change_pathname(e_coin);	
		s_set_hitparam(execstp,&coin_hit);
		s_areastage_init();
		if ( execstp->manycoin_bgcheck ){
			obj_worldY += 300;
			s_groundcheck();
			if ( obj_worldY < obj_groundY || obj_groundY < -10000 ) s_remove_obj(execstp);
			else  obj_worldY = obj_groundY;
		} else {
			s_groundcheck();
			if ( s_abs_f(obj_worldY - obj_groundY) > 250 ) s_change_shape(S_coin_noshadow);
		}
	} else {
		if ( coin_hitcheck() )	execstp->motherobj->manycoin_flag |= s_index_bit(obj_programselect);
		obj_animecounter++;
	}

	if ( (execstp->motherobj->s[stw_mode].d) == 2 ) s_remove_obj(execstp);

}

/*------------------------------------------------------------------------------*/

typedef struct {
	short	Xpos;
	short	Zpos;
} ManyCoinRecord;

static ManyCoinRecord allow_data[] = {
	{ 0, -150 	},
	{ 0,  -50 	},
	{ 0,   50 	},
	{ 0,  150 	},
	{ -50,  100 },
	{ -100,  50 },
	{ 50,   100 },
	{ 100,   50 },
};

static void	manycoin_makepattern(int i,int flag )
{

	StrategyRecord *stp;
	int	pos[3];

	int makesw 		 = 1;
	int bgcheck_flag = 1;

	pos[0] = pos[1] = pos[2] = 0;

	switch(flag&0x7){
	 	case 0:				/* normal coin */
			pos[2] = -320+ i * 160;
			if ( i > 4 ) makesw = 0;
			break;
	 	case 1:				/* normal coin tate */
			bgcheck_flag = 0;
			pos[1] = i * 160 * 0.8;
			if ( i > 4 ) makesw = 0;
			break;
		case 2:				/* circle yoko */
			pos[0] = sin(i*0x2000)*300;
			pos[2] = cos(i*0x2000)*300;
			break;
		case 3:             /* circle tate */
			bgcheck_flag = 0;
			pos[0] = cos(i*0x2000)*200;
			pos[1] = sin(i*0x2000)*200+200;
			break;
		case 4:				/* allow       */
			pos[0] = allow_data[i].Xpos;
			pos[2] = allow_data[i].Zpos;
			break;
	}

	if ( flag&0x10 )	bgcheck_flag = 0;

	if (makesw){
		stp = s_makeobj_chain(i,pos[0],pos[1],pos[2],execstp,S_coin,e_manycoin_obj);
		stp->manycoin_bgcheck = bgcheck_flag;
	}

}


/*------------------------------------------------------------------------------*/
extern void s_manycoin_init(void)
{
	execstp->manycoin_flag = ( ( execstp->s[stw_actorcode].d >> 8 ) & 0xff );
}


extern void s_manycoin(void)
{

	int	i;

	switch(obj_mode){

		case	0:
			if ( obj_playerdist < 2000 ){
				for(i=0;i<8;i++){
					if ( (( execstp->manycoin_flag ) & (1<<i) ) == 0 ){
						manycoin_makepattern(i,obj_programselect);
					}
				}
				obj_mode++;
			}
			break;
		case	1:
			if ( obj_playerdist > 2100 ) obj_mode++;
			break;
		case	2:
			obj_mode = 0;
			break;

	}

	st_ramsave(execstp,(execstp->manycoin_flag)&0xff );

}






/********************************************************************************
	---------------------
	 obake coin program
	---------------------
 ********************************************************************************/

#define		obake_flag			s[stw_work7].d

/*------------------------------------------------------------------------------*/
/*		obake bound coin														*/
/*------------------------------------------------------------------------------*/
static void obakecoin_bound(void)
{

	s_enemybgcheck();	/* BG check 	*/
	s_wallreverse();

	if ( obj_movestatus & MOVESTAT_BIGBOUND ) objsound(NA_SE2_COINBOUND);
	if ( ( obj_timer > 90 ) || (( obj_movestatus & MOVESTAT_BGBOUND )!= 0)  ){
		s_set_hitparam(execstp,&coin_hit);
		s_hitON();
		s_change_pathname(e_coin);
	}
	s_enemymove(-30);
	coin_hitcheck();
	if ( s_check_shapename(S_bluecoin) ) obj_ap = 5;

	if ( s_flash_shape(400,20) )	s_remove_obj(execstp);

}


/*------------------------------------------------------------------------------*/
/*		obake take coin															*/
/*------------------------------------------------------------------------------*/

static void obakecoin_take(void)
{

	short 			playerY;
	float			playerspeed;
	StrategyRecord *mother = execstp->motherobj;	/* coin */

	s_hitOFF();

	/*----------------------------------------------------*/
	if ( ( obj_timer == 0 ) && ( activeStageNo == 4 ) ){
		s_change_shape(S_bluecoin);
		s_set_scale(0.7);
	}
	/*----------------------------------------------------*/

	s_copy_worldXYZ(execstp,mother);
	if ( mother->s[stw_imm].d == 1 ){
		obj_mode = mode_obakecoin_bound;
		playerY 	= (short)(player1stp->s[stw_angleY].d);
		playerspeed = 3;
		obj_speedX 	= playerspeed * sin(playerY);
		obj_speedZ 	= playerspeed * cos(playerY);
		obj_speedY 	= 35;
	}

}

/*------------------------------------------------------------------------------*/
/*		obake coin 																*/
/*------------------------------------------------------------------------------*/

static void *obakecoin_modejmp[] = {
	
	 obakecoin_take,
	 obakecoin_bound
	
};

extern void s_obake_coin(void)
{

	s_modejmp(obakecoin_modejmp);

}
/*################*/
#endif
/*################*/
/*===============================================================================
		end end end end end end end end 
===============================================================================*/



