Copy to Clipboard Test

Simon Says Minigame Code

const int CF_SIMONGAME_BUTTON = 98;//Combo flag to define playable key combos.
const int CF_SIMONGAME_BUTTON_COPYCAT = 99;//Combo flag to define unpressable "copycats" key combos. They change to next combo in list for 2 frames, toghether with CF_SIMONGAME_BUTTON on the same column;

const int SPR_SIMONGAME_INPUT = 0;//Sprite to display, when key button is highlighted.

const int CSET_SIMONGAME_FAIL = 11;//CSet to turn keyboard combos on minigame failure. 
const int CSET_SIMONGAME_WIN = 5;//CSet to turn keyboard combos on minigame victory. 

const int SFX_SIMONGAME_ARR_INPUT = 62; // ID First sound in sequence for keys. 
const int SFX_SIMONGAME_FAIL = 26; //Sound to play on hitting wrong button, thus failing the minigame.
const int SFX_SIMONGAME_SUCCESS = 61; //Sound to play, when correct pattern is inputed
const int SFX_SIMONGAME_VICTORY = 27; //Sound to play, when all patterns are correctly reproduced.

const int SFX_SIMONGAME_LIGHTNING = 37; //Sound to play, when lightning strikes
const int TILE_SIMONGAME_LIGHTNING = 451; //Tile used for lightning bolt rendering
const int CSET_SIMONGAME_LIGHTNING = 2; //CSet used for rendering lightning strike.

const int C_SIMONGAME_FLASH_FAIL = 0x81;//Flash color for minigame failure.

//const int FLAG_SIMONGAME_REVERSE_INPUT = 1;//DON`T EDIT
//const int FLAG_SIMONGAME_RANDOMIZE_ENTIRE_SEQUENCE = 2;

const int MODE_SIMONGAME_INTRO = 0;//DON`T EDIT
const int MODE_SIMONGAME_DEMO = 1;
const int MODE_SIMONGAME_REPLAY = 2;
const int MODE_SIMONGAME_PIANO = 3;

//Simon Says minigame.
//You are given a piano keyboard. After certaain time, keys start playing in a sequence. Your objective is to memorize the pattern and reproduce it by
//snanding on keyboard keys and pressing Ex1. Then process repeats with longer and faster patterns until either wrong button is pressed, which may result in deadly
//lighning strike, or certain limit is reached, which is rewarded either by item or secret trigger.

//Set up sequence of sounds for key tones, max 16.
//Set SFX_SIMONGAME_ARR_INPUT constant to ID of 1st sound in sequence.
//Set up combos for keys - Unpressed, then pressed.
//Build keyboard, place CF_SIMONGAME_BUTTON flags on keys,one per column,  max 16.
//Place invisible FFC with script anywhere in the screen.
//D0 - number of keys in staerting sequence. 0 to turn into normal piano, to be used just for fun, or in other puzzles.
//D1 - number of keys in final sequence, one step away from reward. Max 16.
//D2 - Add together: 1 - memorized sequence must be replayed in reverse, 2 - randomize entire sequence, instead of adding one note at the end.
//D3 - Delay between notes playing in demonstration, in frames.
//D4 - Reduction of delay each round, making demonstration play fater with each round.
//D5 - Reward on victory: >0 - ID if prize item, -1 - secret trigger.
//D6 - Penalty for failure, in 1/4ths of heart in damage caused by lightning strike.

ffc script SimonSaysMinigame{
	void run (int startseq, int endseq, int flags, int speed, int incr, int reward, int penalty){
		int seq[16];
		//int sfx[16];
		int list[16];
		int arr = 0;
		int mode=MODE_SIMONGAME_INTRO;
		if (startseq==0||endseq==0)mode=MODE_SIMONGAME_PIANO;
		for (int i=0;i<176;i++){
			if (ComboFI(i,CF_SIMONGAME_BUTTON)){
				list[arr]=i;
				//sfx[i]=arr;
				arr++;
				if (arr>=16)break;
			}
		}
		for (int i=arr;i<16;i++){
			if (i==16)break;
			//sfx[i]=0;
			list[i]=-1;
		}
		arr=0;
		for (int i=0;i<16;i++){
			seq[i]=-1;
			while(seq[i]<0){
				seq[i] = RandFromArray(list);				
			}
			//sfx[i]=ArrayMatch(list, seq[i]);
		}
		// TraceNL();
		// for (int i=0;i<16;i++){
		// Trace(seq[i]);
		// }
		arr=0;
		int animcounter=60;
		while(true){
			if (mode==MODE_SIMONGAME_INTRO){
				animcounter--;
				if (animcounter==0){
					animcounter=speed;
					mode = MODE_SIMONGAME_DEMO;
				}
			}
			if (mode==MODE_SIMONGAME_DEMO){
				animcounter--;
				if (animcounter==0){
					int cmb=seq[arr];
					if (SPR_SIMONGAME_INPUT>0){
						lweapon s = CreateLWeaponAt(LW_SPARKLE, ComboX(cmb), ComboY(cmb));
						s->UseSprite(SPR_SIMONGAME_INPUT);
						s->CollDetection=false;
						s->Y+=2;
					}
					int sound = ArrayMatch(list, seq[arr]);
					Game->PlaySound(SFX_SIMONGAME_ARR_INPUT+sound);
					arr++;
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]++;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]++;
					}
					Waitframes(4);
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]--;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]--;
					}
					if (arr>=startseq){
						mode = MODE_SIMONGAME_REPLAY;
						arr--;
						if ((flags&1)==0)arr=0;
					}
					else animcounter=speed;
				}
			}
			if (mode==MODE_SIMONGAME_REPLAY){
				int cmb = ComboAt (CenterLinkX(), CenterLinkY());
				if (ComboFI(cmb,CF_SIMONGAME_BUTTON) && Link->PressEx1){
					int sound = ArrayMatch(list, cmb);
					if (sound>=0) Game->PlaySound(SFX_SIMONGAME_ARR_INPUT+sound);
					if (SPR_SIMONGAME_INPUT>0){
						lweapon s = CreateLWeaponAt(LW_SPARKLE, ComboX(cmb), ComboY(cmb));
						s->UseSprite(SPR_SIMONGAME_INPUT);
						s->CollDetection=false;
						s->Y+=2;
					}
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]++;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]++;
					}
					Waitframes(4);
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]--;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]--;
					}
					if (cmb!=seq[arr]){
						Game->PlaySound(SFX_SIMONGAME_FAIL);
						if(penalty>0){
							Game->PlaySound(SFX_SIMONGAME_LIGHTNING);
							int ly=Link->Y;
							while(ly>=-16){
								Screen->FastTile(7, Link->X, ly, TILE_SIMONGAME_LIGHTNING, CSET_SIMONGAME_LIGHTNING, OP_OPAQUE);
								ly-=16;
							}
							eweapon e = FireEWeapon(EW_SCRIPT10, Link->X+InFrontX(Link->Dir, 12), Link->Y+InFrontY(Link->Dir, 12), 0, 0, penalty, -1, -1, EWF_UNBLOCKABLE);
							e->Dir = Link->Dir;
							e->DrawYOffset = -1000;
							SetEWeaponLifespan(e, EWL_TIMER, 1);
							SetEWeaponDeathEffect(e, EWD_VANISH, 0);
							
						}	
						for (int i=1; i<176; i++){
							if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboC[i]=CSET_SIMONGAME_FAIL;
							else if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboC[i]=CSET_SIMONGAME_FAIL;
						}
						Screen->Rectangle(6, 0, 0, 256, 172, C_SIMONGAME_FLASH_FAIL, -1, 0, 0, 0, true, OP_OPAQUE);
						Quit();
					}
					else{
						if ((flags&1)>0)arr--;
						else arr++;
						int endarr = startseq;
						if ((flags&1)>0)endarr=-1;
						if (arr==endarr){
							if (startseq==endseq){
								if (reward<0 && !Screen->State[ST_SECRET]){
									Game->PlaySound(SFX_SIMONGAME_VICTORY);
									Screen->TriggerSecrets();
									Screen->State[ST_SECRET]=true;
								}
								if (reward>0 && !Screen->State[ST_SPECIALITEM]){
									Game->PlaySound(SFX_SIMONGAME_VICTORY);
									item it = CreateItemAt(reward, Link->X, Link->Y);
									it->Pickup = 0x802;
									it->Z=128;
									WaitNoAction(30);
								}
								for (int i=1; i<176; i++){
									if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboC[i]=CSET_SIMONGAME_WIN;
									else if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboC[i]=CSET_SIMONGAME_WIN;
								}
								Quit();
							}
							else{
								Game->PlaySound(SFX_SIMONGAME_SUCCESS);
								startseq++;
								if ((flags&2)>0){
									for (int i=0; i<16; i++){
										seq[i]=-1;
										while(seq[i]<0){
											seq[i] = RandFromArray(list);				
										}
									}
								}
								arr=0;
								speed-=incr;
								if (speed<=0)speed=1;
								animcounter=60;
								mode=MODE_SIMONGAME_INTRO;
							}
						}
					}
				}
			}
			if (mode==MODE_SIMONGAME_PIANO){
				int cmb = ComboAt (CenterLinkX(), CenterLinkY());
				if (ComboFI(cmb,CF_SIMONGAME_BUTTON) && Link->PressEx1){
					int sound = ArrayMatch(list, cmb);
					if (sound>=0) Game->PlaySound(SFX_SIMONGAME_ARR_INPUT+sound);
					if (SPR_SIMONGAME_INPUT>0){
						lweapon s = CreateLWeaponAt(LW_SPARKLE, ComboX(cmb), ComboY(cmb));
						s->UseSprite(SPR_SIMONGAME_INPUT);
						s->CollDetection=false;
						s->Y+=2;
					}
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]++;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]++;
					}
					Waitframes(4);
					for (int i=1; i<176; i++){
						if (ComboX(i)!=ComboX(cmb))continue;
						if (ComboFI(i, CF_SIMONGAME_BUTTON)) Screen->ComboD[i]--;
						if (ComboFI(i, CF_SIMONGAME_BUTTON_COPYCAT)) Screen->ComboD[i]--;
					}
				}
			}
			Waitframe();
		}
	}
}

//Picks random elemnemt from given array and returns it
int RandFromArray(int arr){
	int size = SizeOfArray(arr);
	int rnd = Rand(size-1);
	return arr[rnd];
}	

//Returns index of the given element that exists in the given array or -1, if it does not exist.
int ArrayMatch(int arr, int value){
	for (int i=0; i<SizeOfArray(arr); i++){
		if (arr[i] == value) return i;
	}
	return -1;
}