const int SFX_BLOCK_HOLE_ORDER_ERROR = 3;//Sound to play, if wrong pushblock was dropped into hole.
const int SFX_BLOCK_HOLE_ORDER_FALL = 38;//Sound to play, wnen pushblock was dropped into hole, in general.
const int SPR_BLOCK_HOLE_FALL = 91;//Sprite to display, wnen pushblock was dropped into hole, in general.
const int BLOCK_HOLE_ORDER_NO_DROP_AFTER_SECRET = 1; //>0 - Blocks no longer fall into hole, if secrets are triggered.
//Ordered Pushblock dropping hole puzzle.
//Drop pushblocks into hole in specific order to solve this puzzle and open secrets.
//Works only with Tall/Large pushblocks.
//1.Set up multiple FFCs, all of the same size, with TallPushblock script. Make sure to place them on top of similar solid combos.
//2.Place invisible FFC on top of non-solid hole with the same size as push blocks. Better use Direct Warp to avoid 2.55 pitfall related glitches. Make sure it halso has Ethernal flag on, unless you make FFC look like weighted trapdoor. Assign this script to it.
// D0-D7 solution. Must be set to combos that are underneath pushblock FFCs.
ffc script OrderedBlockHole{
void run (int sol1, int sol2, int sol3, int sol4, int sol5, int sol6, int sol7, int sol8){
int solution[9] = {sol1,sol2,sol3,sol4,sol5,sol6,sol7,sol8,0};
int cursol=0;
int str1[]="LargeTallPushBlock";
int scr1 = Game->GetFFCScript(str1);
int pos = ComboAt(CenterX(this),CenterY(this));
int ucmb[16];
int ucset[16];
int uflag[16];
bool fail = false;
int dropcmb = 0;
if (Screen->State[ST_SECRET]){
if (BLOCK_HOLE_ORDER_NO_DROP_AFTER_SECRET==0)fail=true;
else Quit();
}
if (solution[0]==0) fail=true;
for (int i=0;i<16;i++){
if ((i%4)>=this->TileWidth) continue;
if (Floor(i/4)>=this->TileHeight) continue;
int x = this->X+(i%4)*16;
int y = this->Y+Floor(i/4)*16;
int curpos = ComboAt(x,y);
ucmb[i]=Screen->ComboD[curpos];
ucset[i]=Screen->ComboC[curpos];
uflag[i]=Screen->ComboF[curpos];
}
while(true){
if (Screen->ComboD[pos]!=ucmb[0]){
dropcmb = Screen->ComboD[pos];
//Drop FFC pushblock into hole
Game->PlaySound(SFX_BLOCK_HOLE_ORDER_FALL);
lweapon s = CreateLWeaponAt(LW_SPARKLE, ComboX(pos), ComboY(pos));
s->UseSprite(SPR_BLOCK_HOLE_FALL);
s->CollDetection=false;
for (int i=0;i<16;i++){
if ((i%4)>=this->TileWidth) continue;
if (Floor(i/4)>=this->TileHeight) continue;
int x = this->X+(i%4)*16;
int y = this->Y+Floor(i/4)*16;
int curpos = ComboAt(x,y);
Screen->ComboD[curpos]=ucmb[i];
Screen->ComboC[curpos]=ucset[i];
Screen->ComboF[curpos]=uflag[i];
}
for (int i=1; i<32; i++){
ffc f = Screen->LoadFFC(i);
if (f==this)continue;
if (f->Script!=scr1) continue;
if (f->X!= this->X) continue;
if (f->Y!= this->Y) continue;
f->Data=0;
}
if (!fail){
if (dropcmb!=solution[cursol]){ //wrong pushblock was dropped into hole
Game->PlaySound(SFX_BLOCK_HOLE_ORDER_ERROR);
fail=true;
}
else {//correct pushblock was dropped into hole
cursol++;
if (solution[cursol]==0){
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
if (BLOCK_HOLE_ORDER_NO_DROP_AFTER_SECRET>0) Quit();
fail=true;
}
}
}
}
Waitframe();
}
}
}