//Chest Minigame FFC
//By: ZoriaRPG
//v0.3.4

//!The initial combo for this ffc should be a rupee icon with a numeric cost. The next combo in the list, should be blank. 

const int CMB_CHEST_GAME_CLOSED = 0;
const int CMB_CHEST_GAME_OPEN = 0;

const int CHEST_GAME_NO_CHEST = 0;
const int CHEST_GAME_CHEST_CLOSED = 1;
const int CHEST_GAME_CHEST_OPEN = 2;

const int TIME_INPUT_UP_OPEN_CHEST = 100; //100 frames of inputting up will open a closed chest. 

const int MSG_CHEST_GAME_OVER = 0;
const int SFX_OPEN_CHEST = 63;

const int MSG_CHEST_GAME_OVER = 0;
const int MSG_CHEST_GAME_RULES = 0;

const int CHEST_GAME_LAYER = 2;
const int CHEST_GAME_SCREEN_D_REGISTER = 5; 
const int CHEST_GAME_HOLDUP_TYPE = LA_HOLD1LAND;

const int CHEST_GAME_ALLOW_REPLAY = 0; 

const int SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE = 64; 




//D0: Number of chests to allow the player to open, per play.
//D1: ID of special prize to award.
//D2: Percentage chance of awarding special prize.
//D3: Backup prize, if special prize already awarded (e.g. 100 rupees, instead of a heart piece). Set to '0' to not offer a backup prize. 
//D4: Cost per play.
//D5: String for game rules.
//D6: String to play at end of game. 


ffc script ChestMiniGame{	//layer for combos, number of plays, big prize, hold up animation, Screen->D register, percentage chance of main prize, backup prize if big prize already awarded, and rolled again. cost per play, message to play when game is over. 
	void run(int max_chests_Link_can_open, int specialPrize, int percentMainprize, int backupPrize, int costPerPlay, int msgRules, int msgEnd,){
		//!We need to decide which args to keep. 
		
		//! chestLayer, and reg can easily be constants.
			//the sfx should only be a constant
		
		
		//Populate with the IDs of prizes to award. Each index is a 1% chance. 
		int chestPrizes[]= { 	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0; 	}

		int initialData = this->Data; //Store the initial combo, to revert, if replay is enabled. 
		int chestComboSpots[176];
		int check;
		
		int mainprize;
		int input_up_timer = TIME_INPUT_UP_OPEN_CHEST; 
		bool openchest;
		int has_opened_number_of_chests;
		bool award_main_prize;
		bool gameRunning;
		bool gameOver;
		
		//Populate chestComboSpots with the coordinates of each closed chest. 
		for ( int q = 0; q < 176; q++ ) {
			int cmb = GetLayerComboD(CHEST_GAME_LAYER,q);
			if ( cmb == CMB_CHEST_GAME_CLOSED ) chestComboSpots[q] = CHEST_GAME_CHEST_CLOSED;
		}
		
		int spotsUnderChests[192]; //Populate with the combo positions under closed chests.
		
		for ( int q = 0; q < 176; q++ ) { //Each combo under a chest is 16 combos higher in number than the actual chest. 
			 spotsUnderChests[q+16] = chestComboSpots[q];
		}
		
		if ( msgRules ) Screen->Message(msgRules);
		else Screen->Message(MSG_CHEST_GAME_RULES);	//Show the string for the chest game rules. 
		
		while(true) {
			
			if ( gameOver && !CHEST_GAME_ALLOW_REPLAY ) break;
			
			if ( gameOver && CHEST_GAME_ALLOW_REPLAY ) {
				gameRunning = false;
				this->Data = initialData;
			}
			
			if ( LinkCollision(this) && Game->Counter[CR_RUPEES] > costPerPlay && Xor(Link->PressA,Link->PressB) && !gameRunning ) {	
					//If Link collides with the ffc, which should show the cost, and presses a button, start the game. 
				gameRunning = true;
				Game->DCounter[CR_RUPEES] -= costPerPlay;
				this->Data++; //increase to the next combo, removing the cost icon. 
			}
				
			
			
			if ( gameRunning ) {
			
				if ( input_up_timer <= 0 ) {
					openchest = true;
					input_up_timer = TIME_INPUT_UP_OPEN_CHEST;
				}
				
				//Check to see if the combo above Link is a chest.
			
				if ( spotsUnderChests[ ComboAt( CenterLinkX(), CenterLinkY() ) ] == CHEST_GAME_CHEST_CLOSED && Link->Dir == DIR_UP && has_opened_number_of_chests <= max_chests_Link_can_open) {
				
					//if Link is under a closed chest, and is facing up. 
					//if Link is pressing up
					if ( Link->InputUP && !openchest ) input_up_timer--;

					//if Link stops pressing up, reset the timer instantly. 
					if ( !Link->InputUp ) input_up_timer = TIME_INPUT_UP_OPEN_CHEST;
					
					//If the timer expires, and Link is still pressing up...
					if ( ( Link->InputUp && openchest ) || ( Xor(Link->PressA,Link->PressB) ) ) { //The timer is over, and Link is still pressing up, so open the chest.
						has_opened_number_of_chests++; //Update out counter, so that Link can only open as many chests as specified by arg 'max_chests_Link_can_open'.
						int combo_under_link = ComboAt( CenterLinkX(), CenterLinkY() ); //Store the position of Link's undercombo.
						int cmb_chest_to_open = ComboAt( CenterLinkX(), CenterLinkY() ) - 16; //and the position of the chest combo.
						
						
						
						item i; //make an item pointer.
						SetLayerComboD(CHEST_GAME_LAYER,cmb_chest_to_open,CMB_CHEST_GAME_OPEN); //Change the chest to an open chest combo.
						
						spotsUnderChests[combo_under_link] = CHEST_GAME_CHEST_OPEN; //Mark the array indices as being open.
						chestComboSpots[cmb_chest_to_open] = CHEST_GAME_CHEST_OPEN; //in both arrays.
						
						check = Rand(1,100);  //Make a check, to use for determining if the main prize should e awarded.
						if ( check <= percentMainPrize ) award_main_prize = true; //If that check passes, then we will award the main prize.
						
						if ( check > percentMainPrize ) check = Rand(0,SizeOfArray(chestPrizes); //Otherwise, reuse that var, and make a new check to determine
															//the prize to award from the table. 
						
		
						int itm;
			
						if ( award_main_prize && !Screen->D[CHEST_GAME_SCREEN_D_REGISTER] ) { //The main prize has not been awarded, and has been randomly chosen. 
							Screen->D[CHEST_GAME_SCREEN_D_REGISTER] = 1; 	//Set the register so that Link cannot collect the special prize again. 
							Game->PlaySound(SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE); //Play the fanfare...
							i = Screen->CreateItem(specialPrize);	//Assign the pointer, and make the item.
							itm = specialPrize;	//Set the value of the item ID to a var so that we can use it for holding it up. 
						}
						if ( award_main_prize && Screen->D[CHEST_GAME_SCREEN_D_REGISTER] ) { 	//The main prize has already been awarded, so recheck. 
							check = Rand(0,SizeOfArray(chestPrizes)); //Make the new check, to determine what prize to award. 
							if ( backupPrize ) {	//if a backup prize is set in the script args...
								Game->PlaySound(SFX_CHEST_GAME_SPECIAL_PRIZE_FANFARE);	//Play the special award fanfare...
								i = Screen->CreateItem(backupPrize);	//Assign the pointer, and make the item.
								itm = backupPrize;	//Set the value of the item ID to a var so that we can use it for holding it up. 
							}
							
							if ( !backupPrize && check ) {	//If the array index is not zero...
								//if ( sfx ) Game->PlaySound(sfx); //if the sfx arg is set, play that SFX file.
								Game->PlaySound(SFX_OPEN_CHEST); //otherwise, play the default.
								i = Screen->CreateItem(chestPrizes[check]); //Assign the pointer, and make the item.
								itm = chestPrizes[check];	//Set the value of the item ID to a var so that we can use it for holding it up. 
							}
						}
						else { 	//Otherwise, if the check to award a special prize did not pass..
							if ( check ) { //if the array index is not zero...
								//if ( sfx ) Game->PlaySound(sfx); //if the sfx arg is set, play that SFX file.
								Game->PlaySound(SFX_OPEN_CHEST); //otherwise, play the default.
								i = Screen->CreateItem(chestPrizes[check]); //Award a normal prize, from the list. 
								itm = chestPrizes[check]; //Set the value of the item ID to a var so that we can use it for holding it up. 
							}
						}
						if ( check ) {	//if we're awarding a prize...
							i -> X = Link->X;
							i -> Y = Link->Y;
							if ( CHEST_GAME_HOLDUP_TYPE ) {  //If the setting to hold the item overhead is enabled...
								Link->Action = CHEST_GAME_HOLDUP_TYPE; //Hold the item overhead, using the value of that setting. 
								Link->HeldItem =  itm;
							}
						}
						else Remove(i);	//if check is zero, remove the item pointer. 
								//This allows chances of getting nothing at all. 
					}
				
					if ( has_opened_number_of_chests > max_chests_Link_can_open ) {
						gameOver = true;
						gameRunning = false;
						if ( msgEnd ) Screen->Message(msgEnd);
						else Screen->Message(MSG_CHEST_GAME_OVER);
						
					}
				
					Waitframe();

					//if ComboAt( ( GridX( CenterLinkX()  ) ), GridX( CenterLinkY() -8 ) ) 
				}
				Waitframe();
			}
		
			Waitframe();
		}
		//If we reach here, then the chest game is over. 
		this->Data = 0;
		this->Script = 0;
		Quit();
	}
}

		
		