Jump to content

Photo

Slippery Push Blocks


  • Please log in to reply
5 replies to this topic

#1 Mitchfork

Mitchfork

    no fun. not ever.

  • Members
  • Real Name:Mitch
  • Location:Alabama

Posted 15 May 2011 - 03:19 AM

So, in several games where ice is used as a dungeon element, it's common to see block puzzles where the blocks slide uncontrollably after being pushed, typically moving in a straight line until they hit something that stops them from moving. Here's a video of the concept from Alundra, but it was also done in Twilight Princess. Basically, I want a script that replicates this behavior.

To be clear:
  • When one of these "slippery blocks" is pushed, it will continue sliding until it hits an object that a push block would normally not be able to be pushed into (including other slippery blocks).
  • Slippery blocks should be able to trigger everything that a normal push block can.
  • Slippery blocks are room-dependent and should reset when the room is left and reentered (unless of course they triggered a permanent secret that would cause them to remain solved, as per regular push blocks).
  • Optional, but nice: assign a sound whenever the slippery block is pushed.

I realize that standard push block behavior is probably hard-coded into ZC, so it may be more tricky than simply modifying that behavior, but it would be really awesome if somebody could do this for me. Thanks. icon_smile.gif

#2 Russ

Russ

    Caelan, the Encouraging

  • Administrators
  • Location:Washington

Posted 15 May 2011 - 04:17 AM

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


#3 Mitchfork

Mitchfork

    no fun. not ever.

  • Members
  • Real Name:Mitch
  • Location:Alabama

Posted 15 May 2011 - 12:46 PM

That's way too big of a downside to be practical with the tiles I'm using.. If I was going to use this once in a quest, that'd be okay, but I don't want to devote what will probably end up being hundreds of duplicate combos to the ice graphics.

Is there any way that this can be modified so that it doesn't rely on ice "combos"? That is, that it will slide anywhere it can? I can use flags and such to prevent the block from sliding off the ice myself... if it'll get rid of the one-time-use combo limitation.

#4 Colossal

Colossal

    Illustrious

  • Members
  • Location:Canada

Posted 15 May 2011 - 03:30 PM

I rewrote that script so it doesn't rely on each combo only being used once. I've been thinking about submitting it to the database, though I would make a few minor tweaks first.


#5 Mitchfork

Mitchfork

    no fun. not ever.

  • Members
  • Real Name:Mitch
  • Location:Alabama

Posted 15 May 2011 - 04:05 PM

That sounds great. icon_smile.gif I'd love to use it, if you'll submit it, but feel free to fix it up as you see fit; I don't need this script immediately.

#6 Colossal

Colossal

    Illustrious

  • Members
  • Location:Canada

Posted 15 May 2011 - 06:16 PM

The script is submitted. It only requires layer 1 or 2 to look right (more info in the submission), which should be much easier than one-time-use combos. EDIT: I updated the script so that a layer screen is not required to make it look right.

Edited by Colossal, 18 May 2011 - 05:58 PM.



1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users