You know what? I'll just post some baseline code for the song checker later.
EDIT: I haven't tested it, but here it is. I hope it works pretty well.
I don't know how to freeze all action though, which is REALLY important. I did forget a few other things, but I don't feel like adding them, so this code is in no way complete. I probably won't finish it myself, so I give everyone else permission to tweak it.
const int I_INVIS = 200; //Placeholder. This probably already exists somewhere else in your code.
const int FFC_SONGSECRETS = 31; //Placeholder
const int OC_A = 1;
const int OC_D = 2;
const int OC_R = 3;
const int OC_L = 4;
const int OC_U = 5;
const int SFX_OC_A = 100; //Placeholder
const int SFX_OC_D = 101; //Placeholder
const int SFX_OC_R = 102; //Placeholder
const int SFX_OC_L = 103; //Placeholder
const int SFX_OC_U = 104; //Placeholder
const int SFX_SONG_EPONA = 105; //Placeholder
const int SFXLEN_SONG_EPONA = 300; //Placeholder
const int SFX_SONG_SARIA = 106; //Placeholder
const int SFXLEN_SONG_SARIA = 300; //Placeholder
const int SFX_SONG_HEALING = 107; //Placeholder
const int SFXLEN_SONG_HEALING = 300; //Placeholder
const int SONGLEN_EPONA = 6;
const int SONG_EPONA_PLAYED = 1; //Placeholder
bool KnowEponaSong = true; //This is for testing purposes. Change it to false in your quest.
const int SONGLEN_SARIA = 6;
const int SONG_SARIA_PLAYED = 2; //Placeholder
bool KnowSariaSong = true; //This is for testing purposes. Change it to false in your quest.
const int SONGLEN_HEALING = 6;
const int SONG_HEALING_PLAYED = 3; //Placeholder
bool KnowSongOfHealing = true; //This is for testing purposes. Change it to false in your quest.
//Treat these like constants!
int SONG_EPONA[6] = {5, 4, 3, 5, 4, 3}; //Fixed that.
int SONG_SARIA[6] = {2, 3, 4, 2, 3, 4};
int SONG_HEALING[6] = {4, 3, 2, 4, 3, 2};
//This needs to be checked in the global script.
bool PlayingOcarina = false;
item script Ocarina {
void run() {
PlayingOcarina = true;
}
}
//This should be a method in your global script
void PlayOcarina() {
int notes[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //Remembers the last 8 notes you played.
int ptr = 0; //last note played. (It wraps around)
//Copied from Elmensajero.
while(Link->InputB) Waitframe(); //Wait until B is depressed so it doesn't quit right away
Link->Item[I_INVIS] = true; //Turn Link invisible
int upleftT = Screen->ComboT[0]; //Hey, it MIGHT be important.
Screen->ComboT[0] = CT_SCREENFREEZE; //Change that combo so that the screen freezes
while(true) {
if(Link->PressB) break;
if(Link->PressA) {
notes[ptr] = OC_A;
ptr = (ptr + 1) % 8; //The modulus is for wrap-around
Game->PlaySound(SFX_OC_A);
}
else if(Link->PressDown) {
notes[ptr] = OC_D;
ptr = (ptr + 1) % 8; //The modulus is for wrap-around
Game->PlaySound(SFX_OC_D);
}
else if(Link->PressRight) {
notes[ptr] = OC_R;
ptr = (ptr + 1) % 8; //The modulus is for wrap-around
Game->PlaySound(SFX_OC_R);
}
else if(Link->PressLeft) {
notes[ptr] = OC_L;
ptr = (ptr + 1) % 8; //The modulus is for wrap-around
Game->PlaySound(SFX_OC_L);
}
else if(Link->PressUp) {
notes[ptr] = OC_U;
ptr = (ptr + 1) % 8; //The modulus is for wrap-around
Game->PlaySound(SFX_OC_U);
}
//Here's the fun part. We get to check the notes against known songs! YAAAY! D:
//Yes, you have to check each song. ZScript can't pass arrays as parameters. :(
if(KnowEponaSong) {
//Work through the notes BACKWARDS starting with the last note that was played.
//If at any time, there is a mismatch, it's WRONG, so exit the loop.
bool correct = true;
for(int pos = 0; pos < SONGLEN_EPONA && correct; pos++) {
correct &&= (notes[(ptr - pos) % 8] == SONG_EPONA[SONGLEN_EPONA - pos - 1]);
if(!correct) break;
}
//If the song was right, play the song, then pass the song number onto ffc FFC_SONGSECRETS to process secrets...
if(correct) {
Game->PlaySound(SFX_SONG_EPONA);
Waitframes(SFXLEN_SONG_EPONA);
ffc activator = Screen->LoadFFC(FFC_SONGSECRETS);
activator->X = SONG_EPONA_PLAYED;
//Call Epona if possible.
break;
}
}
if(KnowSariaSong) {
//Work through the notes BACKWARDS starting with the last note that was played.
//If at any time, there is a mismatch, it's WRONG, so exit the loop.
bool correct = true;
for(int pos = 0; pos < SONGLEN_SARIA && correct; pos++) {
correct &&= (notes[(ptr - pos) % 8] == SONG_SARIA[SONGLEN_SARIA - pos - 1]);
if(!correct) break;
}
//If the song was right, play the song, then pass the song number onto ffc FFC_SONGSECRETS to process secrets...
if(correct) {
Game->PlaySound(SFX_SONG_SARIA);
Waitframes(SFXLEN_SONG_SARIA);
ffc activator = Screen->LoadFFC(FFC_SONGSECRETS);
activator->X = SONG_SARIA_PLAYED;
break;
}
}
if(KnowSongOfHealing) {
//Work through the notes BACKWARDS starting with the last note that was played.
//If at any time, there is a mismatch, it's WRONG, so exit the loop.
bool correct = true;
for(int pos = 0; pos < SONGLEN_HEALING && correct; pos++) {
correct &&= (notes[(ptr - pos) % 8] == SONG_HEALING[SONGLEN_HEALING - pos - 1]);
if(!correct) break;
}
//If the song was right, play the song, then pass the song number onto ffc FFC_SONGSECRETS to process secrets...
if(correct) {
Game->PlaySound(SFX_SONG_HEALING);
Waitframes(SFXLEN_SONG_HEALING);
ffc activator = Screen->LoadFFC(FFC_SONGSECRETS);
activator->X = SONG_HEALING_PLAYED;
break;
}
}
Waitframe();
}
PlayingOcarina = false;
Screen->ComboT[0] = upleftT;
}
//Song Secrets Activator
//D0: Song number
//D1: Flag to replace
//D2: Replacement combo number
//D3: Replacement cset
//D4: Replacement flag
//D5: Replacement inherent flag
//D6: Replacement type
//D7: Replacement walkability mask
//Notes: Set Y to nonzero to indicate that secrets are permanent,
//in which case you should mark the "run script on screen init." box.
//Place this script on your reserved ffc.
ffc script SongSecrets {
void run(int song_num, int rflag, int data, int cset, int flag, int inherent, int type, int solid) {
//If the secrets are permanent, switch out the combos right now!
if(this->Y != 0 && Screen->State[ST_SECRET]) {
for(int i = 0; i < 176; i++) {
//Check for the flag.
if(Screen->ComboF[i] == rflag ||
Screen->ComboI[i] == rflag) {
//Change the combo information.
Screen->ComboD[i] = data;
Screen->ComboC[i] = cset;
Screen->ComboF[i] = flag;
Screen->ComboI[i] = inherent;
Screen->ComboT[i] = type;
Screen->ComboS[i] = solid;
}
}
Quit(); //All done!
}
while(true) {
if(this->X == song_num) {
//Trigger activated! Sweep through the screen and replace the appropriate combos.
for(int i = 0; i < 176; i++) {
//Check for the flag.
if(Screen->ComboF[i] == rflag ||
Screen->ComboI[i] == rflag) {
//Change the combo information.
Screen->ComboD[i] = data;
Screen->ComboC[i] = cset;
Screen->ComboF[i] = flag;
Screen->ComboI[i] = inherent;
Screen->ComboT[i] = type;
Screen->ComboS[i] = solid;
}
}
//"Turn off" the song that was just played so that this isn't activated again
this->X = 0;
//Set the screen state if appropriate.
if(this->Y != 0) {
Screen->State[ST_SECRET] = true;
Quit(); //All done!
}
}
Waitframe();
}
}
}
Edited by Beefster, 28 June 2009 - 03:44 PM.