const int CF_DOMINO = 99;//Combo Flag (INHERENT!) to label combos as domino parts
const int CF_IGNORE_MATCH = 66;//Combo flag (PLACED!) to place positions for domino parts that cannot be matched.
//Dominoes
//You have some pushable dominoes. You need to push those dominoes, so all sides are either located on specific combos, or adjaced to same numbered side of other dominoes. like 1-1, 1-0, 0-6, 6-5 etc.
//1. You need MatrixPushBlock script. Set it up.
//2. Set up combos for domino sides. Each number is represented by 4 sides of dominoe, top, bottom, left and right. All rows must be consecutive. All combos must be fully solid and have CF_DOMINO inherent flag.
//3. Import and compile the script. 2 FFC script slots used.
//4. Set up final puzzle solution using combos from step 1. Mark all combos in that setup that have no same number adjacent on different dominoe, like ends of snake, with CF_IGNORE_MATCH combo flag.
//5. Place aside all resulted dominoes in the same screen. Place 1x2 or 2x1 invisible FFC with MatrixPushBlock script. No arguments needed, unless you want to restrict push directions, icrease push weight, or make dominoes icy…
//6. Erase all dominoes from initial solution. Mark all combos with CF_IGNORE_MATCH to a different-looking non-solid combo (for indication).
//7. Place invisible FFC with Domino Match script and Combo as 1st combo from setup in step 2. No arguments needed.
//8. Place invisible FFC with MatrixBlockController script (included in script source code). It`s needed so secrets don`t trigger prematurely, when domino is being pushed.
// D0 - Script slot used by DominoMatch script.
// D1 - Script slot used by MatrixPushBlock script.
// D2 - 0.
// D3 - 7.
ffc script DominoMatch{
void run(){
if (Screen->State[ST_SECRET])Quit();
int origdata = this->Data;
int match=0;
int dir=0;
int number=0;
int cmb = 0;
while(true){
for (int i=0; i<=176; i++){
if (this->InitD[0]>0)break;
if (i==176){
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
Quit();
}
if (Screen->ComboI[i]!=CF_DOMINO) continue;
if (Screen->ComboF[i]==CF_IGNORE_MATCH) continue;
match=0;
number = Floor((Screen->ComboD[i]-origdata)/4);
//Screen->DrawInteger(3, ComboX(i), ComboY(i),0, 1,0 , -1, -1, number, 0, OP_OPAQUE);
for (int d=0;d<4;d++){
cmb = AdjacentComboFix(i,d);
if (Screen->ComboI[cmb]!=CF_DOMINO) continue;
dir = (Screen->ComboD[cmb]-origdata)%4;
if (dir==d)continue;
//Screen->FastCombo(1, ComboX(cmb), ComboY(cmb), origdata+d+28, 2,OP_OPAQUE);
if (Floor((Screen->ComboD[cmb]-origdata)/4)==number){
//Screen->Rectangle(3, ComboX(cmb), ComboY(cmb), ComboX(cmb)+15, ComboY(cmb)+15, 1, -1,0, 0, 0,false, OP_OPAQUE);
match++;
}
}
//Screen->DrawInteger(3, ComboX(i), ComboY(i)+8,0, 1,0 , -1, -1, match, 0, OP_OPAQUE);
if (match==0)break;
}
Waitframe();
}
}
//Fixed variant of AdjacentCombo function from std_extension.zh
int AdjacentComboFix(int cmb, int dir)
{
int combooffsets[13]={-0x10, 0x10, -1, 1, -0x11, -0x0F, 0x0F, 0x11};
if ( cmb % 16 == 0 ) combooffsets[9] = -1;//if it's the left edge
if ( (cmb % 16) == 15 ) combooffsets[10] = -1; //if it's the right edge
if ( cmb < 0x10 ) combooffsets[11] = -1; //if it's the top row
if ( cmb > 0x9F ) combooffsets[12] = -1; //if it's on the bottom row
if ( combooffsets[9]==-1 && ( dir == DIR_LEFT || dir == DIR_LEFTUP || dir == DIR_LEFTDOWN ) ) return -1; //if the left columb
if ( combooffsets[10]==-1 && ( dir == DIR_RIGHT || dir == DIR_RIGHTUP || dir == DIR_RIGHTDOWN ) ) return -1; //if the right column
if ( combooffsets[11]==-1 && ( dir == DIR_UP || dir == DIR_RIGHTUP || dir == DIR_LEFTUP ) ) return -1; //if the top row
if ( combooffsets[12]==-1 && ( dir == DIR_DOWN || dir == DIR_RIGHTDOWN || dir == DIR_LEFTDOWN ) ) return -1; //if the bottom row
if ( cmb >= 0 && cmb < 176 ) return cmb + combooffsets[dir];
else return -1;
}
}
ffc script MatrixBlockController{
void run(int scr1, int scr2, int InitD1, int initD2){
ffc f1;
ffc f2;
for (int i=1;i<=32;i++){
f1 = Screen->LoadFFC(i);
if (f1->Script==scr1)break;
}
while(true){
f1->InitD[InitD1]=0;
for (int i=1;i<=32;i++){
f2 = Screen->LoadFFC(i);
if (f2->Script!=scr2)continue;
if (f2->InitD[initD2]>=0){
f1->InitD[InitD1]=1;
break;
}
}
Waitframe();
}
}
}