...I'm confident that my approach wasn't the best, and I'm sure there are all sorts of limitations to it, but I felt it was interesting none-the-less --- and it's my first FFC script, so I'm compelled to post it even if it totally sucks --- so here's one possible way to have a push block puzzle where certain blocks have to be on certain triggers to solve the puzzle. (What an introduction...:eyebrow:)


Figure 1: On this screen, the secret is only triggered when the red block is on the red rug and green block is on the green rug.

My scripts are shown below. The basic approach is that you create various Push Block combos. Each one is of type Push (Heavy), and each one has an Inherent Flag set to one of the General Purpose flags (98 through 102). So hypothetically you could have 5 different block-trigger pairs.

The "triggers" are actually FFCs. So instead of placing the typical Block Trigger flags on the screen, you're going to create and place FFCs as your triggers. Each "trigger FFC" uses one of the "Block*Detect" scripts shown below. You pass in the Inherent Flag number that should trigger the secret. One additional FFC monitors global flags to detect when all the blocks are in the proper positions.


Figure 2: Flags for the puzzle.

To trigger the secret, once all the blocks are in the proper spot an enemy is killed. Since the screen has the Enemies -> Secret flag checked the secret is then revealed. This is why I had to use Push (Heavy) combos, versus Push (Wait) combos (man, I wish the ZC developers would just create a Push No-Wait combo...or did I miss it?).

At any rate, that's it in a nutshell. I've coded it for a two block puzzle (not much of a puzzle), but you can see that it would be very easy to add any number of blocks (remembering you only get 5 distinct "flavors" of block, but you could have several blocks with the same Inherent flag I suppose).

The main "pro" is that since the Push Blocks are real Push Blocks and not FFCs, you don't have to deal with walkability issues at all. A downside is that since I had to use Push (Heavy) combos, you have to give Link the power bracelet. Also, the way I coded it you have to use the typical 16x16, single-tile combos.

Here's the code listing:
Code:
import "std.zh"

//==============================================================================
// Global Variables
//==============================================================================
bool Block1Detected;
bool Block2Detected;
bool Block3Detected = true;  // DEBUG!
bool Block4Detected = true;  // DEBuG!

//==============================================================================
// FFC Scripts
//==============================================================================

//------------------------------------------------------------------------------
// Script   : CheckAllBlocks
// Purpose  : Checks the Block*Detected global
//            variables.  If they are all true,
//            the secrets on the screen
//            are triggered.
// Run Args : None.
// Use      : Assign this script to an invisible FFC on the screen.
//------------------------------------------------------------------------------
ffc script CheckAllBlocks{
  void run(){

    // This really only needs to run
    // until the secret is triggered.
    bool SecretTriggered = false;
    npc TriggerNPC;

    while(!SecretTriggered){
    
      SecretTriggered = Block1Detected && Block2Detected &&
                        Block3Detected && Block4Detected;

      if(SecretTriggered){
        // Show the secrets.
        TriggerNPC = Screen->LoadNPC(1);
        TriggerNPC->HP = 0;
        Trace(-1);
      }

      // Process other events.
      Waitframe();

    } // while !SecretTriggered
  } // run
} // CheckAllBlocks


//------------------------------------------------------------------------------
// Script   : Block1Detect
// Purpose  : Determines if a block with the specified inherent flag has been
//            pushed under this FFC.  If so, a global flag is set to notify
//            the CheckAllBlocks script.
// Run Args : LookForFlag - the inherent flag number to look for.  Typically
//            this will be one of the custom flags ranging from 98 and up.
// Use      : Assign this script to an FFC on the screen.  The FFC essentially
//            takes the place of the Block Trigger flag, so the FFC must be
//            located where the Push Block should trigger the secret.
//------------------------------------------------------------------------------
ffc script Block1Detect{
  void run(int LookForFlag){

    // Initialization.  This block detector
    // hasn't detected a block yet.  
    Block1Detected = false;

    // Now just loop and look for a pushblock that
    // has the specified inherent flag to be
    // pushed under this FFC.
    while(true){

      Block1Detected = (Screen->ComboI[ComboAt(this->X, this->Y)] == LookForFlag);

      // Process other events.
      Waitframe();

    } // while true

  } // run
} // Block1Detect


//------------------------------------------------------------------------------
// Script   : Block2Detect
// Purpose  : Determines if a block with the specified inherent flag has been
//            pushed under this FFC.  If so, a global flag is set to notify
//            the CheckAllBlocks script.
// Run Args : LookForFlag - the inherent flag number to look for.  Typically
//            this will be one of the custom flags ranging from 98 and up.
// Use      : Assign this script to an FFC on the screen.  The FFC essentially
//            takes the place of the Block Trigger flag, so the FFC must be
//            located where the Push Block should trigger the secret.
//------------------------------------------------------------------------------
ffc script Block2Detect{
  void run(int LookForFlag){

    // Initialization.  This block detector
    // hasn't detected a block yet.  
    Block2Detected = false;

    // Now just loop and look for a pushblock that
    // has the specified inherent flag to be
    // pushed under this FFC.
    while(true){

      Block2Detected = (Screen->ComboI[ComboAt(this->X, this->Y)] == LookForFlag);

      // Process other events.
      Waitframe();

    } // while true

  } // run
} // Block2Detect