const int SPR_TRIFORCE_SCENE_EX_DISAPPEAR = 22;//Sprite to display, when floating triforce pieces disappear after end of cutscene.
const int SFX_TRIFORCE_SCENE_INIT_ANIM = 3;//sound to play for each triforce piece appearing during cutscene initialization.
const int CF_TRIFORCE_SCENE_TRIGGER = 98;//Combo flag Link nees to step on to trigger Triforce Entrance script.
//Link`s Awakening Triforce Entrance unlocking cutscene.
//If steps on trigger flag fith full Triforce (or full set of custom McGuffins), all it`s pieces appear in curcle, 1 by 1, then circle around specific spot for certain period of time, then secrets open.
//1. Set up as many combos in sequence, as you have Triforce Pieces in quest.
//2. If you want to use custom items, instead of Triforce pieces, set up array of consecutive empty passive items in Editor, so they render in subscreen when collected.
//2. Flag all trigger spots in triforce-locked entrance screen via CF_TRIFORCE_SCENE_TRIGGER combp flag.
//3. Place invisible FFC with 1st combo from step 1 at locked dungeon entrance.
// D0 - number of Triforce pieces (items) needed to unlock secret.
// D1 - String to display if not enough.
// D2 - MIDI to play during cutscene.
// D3 - circling radius for Triforce pieces.
// D4 - circling speed for Triforce pieces. negative for reverse direction.
// D5 - duration of cutscene in frames.
// D6 - >0 - use array of D0 consecutive custom items in leu of Triforce pieces, starting from D6 as ID.
// D7 - delay between triforce piece appearing during cutscene initialization, in frames.
ffc script TriforceSecretEX{
void run(int numpieces, int message, int midi, int radius, int aspeed, int duration, int itemsreq, int initspeed){
if (Screen->State[ST_SECRET]) Quit();
int count = 0;
int drawxpos=0;
int drawypos=0;
int angle=270;
int linkcmb=-1;
int timer =initspeed;
int numitems=0;
int curitem = 0;
while(true){
linkcmb = ComboAt (CenterLinkX(), CenterLinkY());
if (ComboFI(linkcmb, CF_TRIFORCE_SCENE_TRIGGER)){
numitems=0;
if (itemsreq>0){
for (int i=0; i<numpieces;i++){
curitem = itemsreq+i;
if (Link->Item[curitem]) numitems++;
}
}
else numitems = NumTriforcePieces();
if (numitems>=numpieces){
Game->PlayMIDI(0);
while(count<numpieces){
timer--;
if (timer<=0){
Game->PlaySound(SFX_TRIFORCE_SCENE_INIT_ANIM);
count++;
timer=initspeed;
}
DrawTriforceCombos(count, numpieces, this->Data, this->X, this->Y, angle, radius, 6, this->CSet);
NoAction();
Waitframe();
}
Game->PlayMIDI(midi);
timer=duration;
while(timer>0){
angle+=aspeed;
timer--;
DrawTriforceCombos(count, numpieces, this->Data, this->X, this->Y, angle, radius, 6, this->CSet);
NoAction();
Waitframe();
}
if (SPR_TRIFORCE_SCENE_EX_DISAPPEAR>0){
for (int i=0; i<count; i++){
drawxpos=this->X+radius*Cos(angle+360*i/numpieces);
drawypos=this->Y+radius*Sin(angle+360*i/numpieces);
lweapon s = CreateLWeaponAt(LW_SPARKLE, drawxpos, drawypos);
s->UseSprite(SPR_TRIFORCE_SCENE_EX_DISAPPEAR);
s->CollDetection=false;
}
}
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET] = true;
Game->PlayMIDI(0);
Quit();
}
else{
Screen->Message(message);
Quit();
}
}
Waitframe();
}
}
//Draws a circle of animated combos around given position.
void DrawTriforceCombos(int count, int number, int cmb, int xpos, int ypos, int angle, int radius, int layer, int cset){
if (count==0)return;
int drawx=0;
int drawy=0;
for (int i=0; i<count; i++){
angle+= (360/number);
drawx = xpos+radius*Cos(angle);
drawy = ypos+radius*Sin(angle);
Screen->FastCombo (layer, drawx, drawy,cmb+i, cset, OP_OPAQUE);
}
}
}
//FF_whistle trigger.
//Like normal whistle trigger, but needs higher whistle level to work. Also can be triggered anywhere in the screen.
//Place invisible FFC anywhere in the screen.
//D0 - minimum whistle level needed.
//D1 - Combo flag for trigger position Link needs to stand on to trigger secrets. 0 for anywhere in the screen.
ffc script FF_WhistleTrigger{
void run (int level, int flag){
if (Screen->State[ST_SECRET]) Quit();
int cmb=-1;
lweapon l;
int itm = 0;
while(true){
cmb = ComboAt (CenterLinkX(), CenterLinkY());
if (ComboFI(cmb,flag)||flag==0){
for (int i=1;i<=Screen->NumLWeapons();i++){
l=Screen->LoadLWeapon(i);
if (l->ID!=LW_WHISTLE) continue;
itm = GetCurrentItem(IC_WHISTLE);
if (itm<0)continue;
itemdata it = Game->LoadItemData(itm);
int lvl = it->Level;
if (lvl>=level){
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET] = true;
Quit();
}
else break;
}
}
Waitframe();
}
}
}
//Triggers screen secrets immediately, if Link has counters high enough or has needed items to afford cost.
//Place invisible FFC anywhere in the screen.
//D0 to D5 - #####.____ - counters to check. <0 - Item ID to check.
// _____.#### - costs to apply.
// D6 - 2->Drain subtraction, 1->Instant subtraction, 0->Only validate cost. If >0 - items checked will be removed from Link`s inventory.
// D7- #####.____ - String to display on counter fail.
// _____.#### - String to display on secret trigger.
ffc script InstantCounterTrigger{
void run (int cr1, int cr2, int cr3, int cr4, int cr5, int cr6, int subtract, int str){
if (Screen->State[ST_SECRET]) Quit();
int counters[6];
int costs[6];
for (int i=0;i<6;i++){
counters[i] = GetHighFloat(this->InitD[i]);
costs[i] = GetLowFloat(this->InitD[i]);
}
int str1 = GetHighFloat(str);
int str2 = GetLowFloat(str);
if (!CanAffordCounters(counters, costs))Screen->Message(str1);
while (!CanAffordCounters(counters, costs))Waitframe();
if (subtract>0){
for (int i=0; i<SizeOfArray(counters);i++){
int cr = counters[i];
if (cr<0){
cr = Abs(cr);
Link->Item[cr]=false;
}
else{
if (subtract>1) Game->DCounter[cr]-=costs[i];
else Game->DCounter[cr]-=costs[i];
}
}
}
Screen->Message(str2);
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET] = true;
Quit();
}
bool CanAffordCounters(int counters, int costs){
for (int i=0; i<SizeOfArray(counters);i++){
int cr = counters[i];
if (cr<0){
cr = Abs(cr);
if (!Link->Item[cr]) return false;
}
else if (Game->Counter[cr]<costs[i]) return false;
}
return true;
}
}