Dan Furst made one a while back. I modified one or two lines to allow it to work in the newer builds. The big downside is every single square of ice floor has to be a separate combo that can only be used once per quest. HUGE downside, but it's still a pretty useful script.
CODE
// The ice blocks must start at ffc #1 and then use 2, 3, etc.... You may have up to eight ice blocks.
// Each square of ice on the screen must be a new combo. These combos can be used only once each (in the entire quest).
// To have ice blocks stop sliding at the "edge" of ice, make the surrounding combos inherently "No Push Block" (flag 67).
// The "ice trigger" freeform combo should be any completely transparent tile (other than combo 0).
// Starting with the third argument (D2), pass in all of the locations you want triggers. Use them in order.
// Pass them in as the ith combo on the screen, starting with 0 as the top left. Combos are counted left to right, top to bottom.
ffc script ice_push{
void run(int this_ffc_num)
{
ffc this_ffc = Screen->LoadFFC(this_ffc_num);
// make the combos at the saved positions walkable
Screen->ComboS[(Screen->D[this_ffc_num-1])] = 0;
while(true)
{
//make where I am unwalkable
Screen->ComboS[this_ffc->Y + (this_ffc->X >> 4)] = 15; // 15d = 1111b
//if Link is trying to push it Right
if(Link->X == this_ffc->X - 16 && (Link->Y < this_ffc->Y + 1 && Link->Y > this_ffc->Y - 12) && Link->InputRight)
{
while(Screen->ComboI[this_ffc->Y + ((this_ffc->X + 16) >> 4)] != 67 && // not "No Push Block"
Screen->ComboS[this_ffc->Y + ((this_ffc->X + 16) >> 4)] == 0) // and is walkable
{
Screen->ComboS[this_ffc->Y + (this_ffc->X >> 4)] = 0;
this_ffc->Vx = 1;
for(int j=0; j<16; j++)
{
Link->Dir = DIR_RIGHT;
Link->InputUp = false;
Link->InputDown = false;
Link->InputLeft = false;
Link->InputRight = false;
Waitframe();
}
}
this_ffc->Vx = 0;
// save the position
Screen->D[this_ffc_num-1] = this_ffc->Y + (this_ffc->X >> 4);
Waitframe();
}
//if Link is trying to push it Left
else if(Link->X == this_ffc->X + 16 && (Link->Y < this_ffc->Y + 1 && Link->Y > this_ffc->Y - 12) && Link->InputLeft)
{
while(Screen->ComboI[this_ffc->Y + ((this_ffc->X - 16) >> 4)] != 67 && // not "No Push Block"
Screen->ComboS[this_ffc->Y + ((this_ffc->X - 16) >> 4)] == 0) // and is walkable
{
Screen->ComboS[this_ffc->Y + (this_ffc->X >> 4)] = 0;
this_ffc->Vx = -1;
for(int j=0; j<16; j++)
{
Link->Dir = DIR_LEFT;
Link->InputUp = false;
Link->InputDown = false;
Link->InputLeft = false;
Link->InputRight = false;
Waitframe();
}
}
this_ffc->Vx = 0;
// save the position
Screen->D[this_ffc_num-1] = this_ffc->Y + (this_ffc->X >> 4);
Waitframe();
}
//if Link is trying to push it Down
else if(Link->Y == this_ffc->Y - 16 && (Link->X < this_ffc->X + 4 && Link->X > this_ffc->X - 4) && Link->InputDown)
{
while(Screen->ComboI[(this_ffc->Y + 16) + (this_ffc->X >> 4)] != 67 && // not "No Push Block"
Screen->ComboS[(this_ffc->Y + 16) + (this_ffc->X >> 4)] == 0) // and is walkable
{
Screen->ComboS[this_ffc->Y + (this_ffc->X >> 4)] = 0;
this_ffc->Vy = 1;
for(int j=0; j<16; j++)
{
Link->Dir = DIR_DOWN;
Link->InputUp = false;
Link->InputDown = false;
Link->InputLeft = false;
Link->InputRight = false;
Waitframe();
}
}
this_ffc->Vy = 0;
// save the position
Screen->D[this_ffc_num-1] = this_ffc->Y + (this_ffc->X >> 4);
Waitframe();
}
//if Link is trying to push it Up
else if(Link->Y == this_ffc->Y + 8 && (Link->X < this_ffc->X + 4 && Link->X > this_ffc->X - 4) && Link->InputUp)
{
while(Screen->ComboI[(this_ffc->Y - 16) + (this_ffc->X >> 4)] != 67 && // not "No Push Block"
Screen->ComboS[(this_ffc->Y - 16) + (this_ffc->X >> 4)] == 0) // and is walkable
{
Screen->ComboS[this_ffc->Y + (this_ffc->X >> 4)] = 0;
this_ffc->Vy = -1;
for(int j=0; j<16; j++)
{
Link->Dir = DIR_UP;
Link->InputUp = false;
Link->InputDown = false;
Link->InputLeft = false;
Link->InputRight = false;
Waitframe();
}
}
this_ffc->Vy = 0;
// save the position
Screen->D[this_ffc_num-1] = this_ffc->Y + (this_ffc->X >> 4);
Waitframe();
}
else
{
Waitframe();
}
}
}
}//end
ffc script ice_trigger{
void run(int this_ffc_num, int num_of_ice_blocks, int loc_1, int loc_2, int loc_3, int loc_4, int loc_5, int loc_6)
{
ffc this_ffc = Screen->LoadFFC(this_ffc_num);
int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int y1;
int y2;
int y3;
int y4;
int y5;
int y6;
int num_triggers = 0;
int good_counter = 0;
bool once = true;
if(loc_1 != 0)
{
x1 = (loc_1 % 16) * 16;
y1 = Floor(loc_1 / 16) * 16;
num_triggers++;
}
else
{
Quit();
}
if(loc_2 != 0)
{
x2 = (loc_2 % 16) * 16;
y2 = Floor(loc_2 / 16) * 16;
num_triggers++;
}
if(loc_3 != 0)
{
x3 = (loc_3 % 16) * 16;
y3 = Floor(loc_3 / 16) * 16;
num_triggers++;
}
if(loc_4 != 0)
{
x4 = (loc_4 % 16) * 16;
y4 = Floor(loc_4 / 16) * 16;
num_triggers++;
}
if(loc_5 != 0)
{
x5 = (loc_5 % 16) * 16;
y5 = Floor(loc_5 / 16) * 16;
num_triggers++;
}
if(loc_6 != 0)
{
x6 = (loc_6 % 16) * 16;
y6 = Floor(loc_6 / 16) * 16;
num_triggers++;
}
while(true)
{
for(int i=1; i<num_of_ice_blocks+1; i++)
{
ffc block_ffc = Screen->LoadFFC(i);
//if a block is on #1 and not moving
if(x1 == block_ffc->X && y1 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
if(x2 == block_ffc->X && y2 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
if(x3 == block_ffc->X && y3 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
if(x4 == block_ffc->X && y4 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
if(x5 == block_ffc->X && y5 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
if(x6 == block_ffc->X && y6 == block_ffc->Y && block_ffc->Vx == 0 && block_ffc->Vy == 0)
{
good_counter++;
}
}
if(good_counter == num_triggers && once == true)
{
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET] = true;
once = false;
}
good_counter = 0;
Waitframe();
}
}
}//end