Jump to content

Photo

Only one lockblock??


  • Please log in to reply
50 replies to this topic

#16 Joe123

Joe123

    Retired

  • Members

Posted 21 January 2010 - 07:45 PM

It does work with perm == 0, where you using another script that accessed that D register on the same screen?
That's me using bit-wise operators so I can store a lot more information in that one integer.

Do you understand how a number can be expressed in binary?

#17 AgentLym

AgentLym

    • Zelda and Pokémon Master •

  • Members
  • Location:Skyloft

Posted 21 January 2010 - 07:49 PM

Like, how the number 1 is represented by something like '00101'? I get the concept, since computers have to read things as either 'true' or 'false', with '1's being 'true', and '0's 'false'.

And if you add something, it's like:

10011
01010 +
=
11001 (or is it 00110... I'm not sure)

Though, I'm still not sure what that line is doing. icon_razz.gif

#18 Joe123

Joe123

    Retired

  • Members

Posted 21 January 2010 - 08:01 PM

Oh right ok, just checking. There's no point trying to explain bitwise operators to someone who doesn't understand binary.

CODE
10011   (19)
01010+  (10)
=
11101   (29)

I'm afraid.


Anyway, so you can express an integer as a string of bits, our ZScript variables hold 18.
This means that you can (with the right operations), use them like an array of booleans (which is what I'm doing).
The bitwise operators are &, |, ^, ~, << and >>.
AND, OR, XOR, NOT, Left Shift and Right Shift.

&, | and ~ work the same was as &&, || and ! do with boolean operators except they compare each bit together in the two integers, ^ is like checking for 'A != B', and << and >> move the bits along the variable by the amount specified on the right.
Saffith's explanation of them here is better than any I'm about to write now, so go and have a look at that =)

#19 ShadowTiger

ShadowTiger

    The Doctor Is In

  • Members

Posted 21 January 2010 - 08:12 PM

You can technically get multiple Lock Blocks on the screen at the same time, but you can only trigger them in a set order. It's done via combo page layout.

[¯] = Lockblock
[¯] = Triggered Lockblock

-------------------------------
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯]
[]][]][]]


-------------------------------

If you lay them out like that on your combo page, the player will be able to trigger the lockblock placed down from the top row first, then the one in the second row, then the one in the third row, and then the one in the fourth row. I just tested it out, and it works just fine.

Of course, if you don't trigger them in the right order, it breaks the effect. You have to know what the combo page looks like and how lockblock combos work. All the Lockblock combos on the screen, no matter if they're different combos, will be triggered at once.


... I'll bet this has been mentioned in this thread already. icon_heh.gif

Yeah, it has been. At least I posted a diagram.

*Is somewhat helpful* icon_puppyeyes.gif

#20 Joe123

Joe123

    Retired

  • Members

Posted 21 January 2010 - 08:14 PM

QUOTE(Theryan @ Jan 21 2010, 03:32 AM) View Post
You could just make the 2nd lockblock a copycat with its "open" combo being another lockblock. The only problems with this are that you have to open the lockblocks a certain order and that you can only have a max of two that way.
Sorry ST =P

#21 Linkus

Linkus

    .

  • Members
  • Real Name:Adam

Posted 21 January 2010 - 08:24 PM

So, the reason you're telling me why there's only one lock block trigger is because it runs on a global Boolean, and there's no way to apply a similar Step->Next effect to the combo module nor have it run independently on its own local variables? Or to set up a copycat to check its perimeter for any lock blocks?

I have a feeling that when you start on the next version that you'll be using a more independent class system, and then make combos the objects themselves. It'll probably be more efficient and cleaner that way, but at this point i know I'm dreaming.

#22 Joe123

Joe123

    Retired

  • Members

Posted 21 January 2010 - 08:27 PM

Well, not global but there's only one per screen.
It wouldn't be hard to change it to work like you say, but that'd break all previous quests so no-one's about to do it.

Yeah, that'd be how I would want to make a future version of ZQuest at least. It's only a dream at the moment though, as you say.

I've spent the last few hours re-scripting a few different combotypes with ffcs which should allow us all a lot more freedom when it comes to lockblocks and chests and the like though, so hopefully everyone'll find them useful.

#23 AgentLym

AgentLym

    • Zelda and Pokémon Master •

  • Members
  • Location:Skyloft

Posted 21 January 2010 - 08:35 PM

QUOTE(Joe123)
Saffith's explanation of them here is better than any I'm about to write now, so go and have a look at that =)

... complicated. Though, I seem to get it a bit more now (no pun intended ^^' )

Though I still don't understand this line:
CODE
while((Screen->D[d] & (1<<perm)) == 0){


Under what circumstances would it be false? What is that while checking for, anyhow?
If d was 0 and perm was 0, then:
CODE
0 & 1 == 0 //true

//but what if d was 1?
1 & 1 == 1 //false


I'm confused. icon_razz.gif Wouldn't you want it to be true, even if d was 1? And if d was 7, for that matter. icon_razz.gif

QUOTE(Linkus)
So, the reason you're telling me why there's only one lock block trigger is because it runs on a global Boolean, and there's no way to apply a similar Step->Next effect to the combo module nor have it run independently on its own local variables? Or to set up a copycat to check its perimeter for any lock blocks?

I have a feeling that when you start on the next version that you'll be using a more independent class system, and then make combos the objects themselves. It'll probably be more efficient and cleaner that way, but at this point i know I'm dreaming.

Heh, I wouldn't be surprised if the devs took a 20 year reprieve from ZQ updating once 2.5 is released! ^^'

Edited by AgentLym, 21 January 2010 - 08:36 PM.


#24 Joe123

Joe123

    Retired

  • Members

Posted 21 January 2010 - 08:43 PM

Right, what (1<<perm) says is 'pick the bit perm bits along the string'.
CODE
00000000 //Here is a string of 8 bits, expressing 0
00000001 //Here is 1 expressed as an 8 bit integer, or '1 << 0'
00000010 //This is '1 << 1'
00000100 //This is '1<< 2'
10000000 //And this is '1 << 7'

So as you can see, 'perm' works out which bit of the string we want to use as our boolean.

Then we use & to check whether that bit has been set or not.
Let's say perm is 4, and the integer we're checking against looks like this already:
010110100
We're only interested in whether the 5th bit is 1 or not, so we use '&(1<<4)', and we get this calculation
CODE
010110100
000010000&
=
000010000

And it's not equal to 0, so the bit were checking for's been set.

'<<' finds the bit we want to compare, '|=' sets that bit that we want, and '&' checks it.

#25 AgentLym

AgentLym

    • Zelda and Pokémon Master •

  • Members
  • Location:Skyloft

Posted 21 January 2010 - 09:18 PM

Ok, I think I got it. So your script does:...
CODE
ffc script LockBlock{
    void run(int pushtime, int sfx, int perm, int d){                       //setup
        if(pushtime == 0) pushtime = 10;
        int loc = ComboAt(this->X,this->Y);

        int pushclk = 0;
        while((Screen->D[d] & (1<<perm)) == 0){          //checks to see if the specified bit along Screen->D[d] is already used or not
            if(PushingCombo(loc) && CheckKeys()) pushclk++;          //if it isn't, then run this part of the script
            else pushclk = 0;
            Waitframe();
            if(pushclk == pushtime) Unlock(sfx,perm,d);
        }
        Screen->ComboD[loc]++;
    }
   void Unlock(int sfx, int perm, int d){
        if(sfx == 0) Game->PlaySound(SFX_SHUTTER);
        else if(sfx > 0) Game->PlaySound(sfx);
        Screen->D[d] |= (1<<perm);                             //this sets... wait, how does this work?        <--------------------
        if(Game->LKeys[Game->GetCurLevel()] > 0) Game->LKeys[Game->GetCurLevel()]--;
        else Game->Counter[CR_KEYS]--;
    }
    bool CheckKeys(){
        return Game->Counter[CR_KEYS] > 0 || Game->LKeys[Game->GetCurLevel()] > 0;
    }
    bool PushingCombo(int loc){
        int y = ComboY(loc); int x = ComboX(loc);
        return (Link->Dir == DIR_UP && Link->InputUp && Link->Y == y+8 && Abs(Link->X-x) < 8)
            || (Link->Dir == DIR_DOWN && Link->InputDown && Link->Y == y-16 && Abs(Link->X-x) < 8)
            || (Link->Dir == DIR_LEFT && Link->InputLeft && Link->X == x+16 && Abs(Link->Y-y) < 8)
            || (Link->Dir == DIR_RIGHT && Link->InputRight && Link->X == x-16 && Abs(Link->Y-y) < 8);
    }
}

ffc script Copycat{
    void run(int perm, int d){
        while((Screen->D[d] & (1<<perm)) == 0) Waitframe();
        Screen->ComboD[ComboAt(this->X,this->Y)]++;
    }
}

Edited by AgentLym, 21 January 2010 - 09:22 PM.


#26 Theryan

Theryan

    Burrito

  • Members

Posted 21 January 2010 - 09:45 PM

QUOTE(ShadowTiger @ Jan 21 2010, 08:12 PM) View Post

You can technically get multiple Lock Blocks on the screen at the same time, but you can only trigger them in a set order. It's done via combo page layout.

[¯] = Lockblock
[¯] = Triggered Lockblock

-------------------------------
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯][¯][¯][¯]
[¯]
[]][]][]]


-------------------------------

If you lay them out like that on your combo page, the player will be able to trigger the lockblock placed down from the top row first, then the one in the second row, then the one in the third row, and then the one in the fourth row. I just tested it out, and it works just fine.

Of course, if you don't trigger them in the right order, it breaks the effect. You have to know what the combo page looks like and how lockblock combos work. All the Lockblock combos on the screen, no matter if they're different combos, will be triggered at once.
... I'll bet this has been mentioned in this thread already. icon_heh.gif

Yeah, it has been. At least I posted a diagram.

*Is somewhat helpful* icon_puppyeyes.gif

You can only have 2 lockblocks through this method, however, because anything beyond that will reset upon entry into the room. If I remember correctly, not even perm. triggers solve this. icon_frown.gif Oh well... a man can dream.

#27 AgentLym

AgentLym

    • Zelda and Pokémon Master •

  • Members
  • Location:Skyloft

Posted 21 January 2010 - 09:50 PM

Hey, that's why we made this script!

Btw, Joe, is it okay if I release it? (or did you want to icon_razz.gif) I'm sure it'll come in mighty handy!

#28 ShadowTiger

ShadowTiger

    The Doctor Is In

  • Members

Posted 21 January 2010 - 09:50 PM

@Theryan:
Oh yeah, forgot about that. >.< It's why I tend to resort to making the tile warps instead, warping to identical screens. THAT way, they stay.

Of course, if you're having four lockblocks on the same screen where any can be triggered at any time, is that really good dungeon design? (much less screen design... sheesh.) Sure, it depends on what you want, but think of other methods too, to bypass any technical limitations barring you.

#29 AgentLym

AgentLym

    • Zelda and Pokémon Master •

  • Members
  • Location:Skyloft

Posted 21 January 2010 - 09:54 PM

I mean, sure I could make a duplicate room for each of my rooms that has two locked doors in it, but that'd require much more work than needed. Plus, wouldn't I then have to duplicate the entire dungeon behind that door so that I wouldn't enter into the room with the lock block intact? icon_heh.gif

I'm just not a big fan of duplicate dungeons (or overworlds, for that matter). Plus, I've always been prone to leaving out one little step or something, and it screws the whole thing up!

And, I just wanted to feel helpful. ^^

Edited by AgentLym, 21 January 2010 - 09:55 PM.


#30 Joe123

Joe123

    Retired

  • Members

Posted 22 January 2010 - 07:41 AM

QUOTE(AgentLym @ Jan 22 2010, 02:18 AM) View Post
Ok, I think I got it. So your script does:...


CODE
ffc script LockBlock{
    void run(int pushtime, int sfx, int perm, int d){
        if(pushtime == 0) pushtime = 10; //Set default value for pushtime, so it doesn't have to be set every time you use the script
        int loc = ComboAt(this->X,this->Y); //This saves calculating ComboAt everytime we want to use it

        int pushclk = 0;
        while((Screen->D[d] & (1<<perm)) == 0){ //checks to see if the specified bit along Screen->D[d] is already used or not
            //If it isn't, the block hasn't been unlocked. If it is, we don't want to unlock it again
            if(PushingCombo(loc) && CheckKeys()) pushclk++; //If Link is pressing against the combo, and he has the right keys increment the 'pushclk', which counts how many frames he's been pressing against it for
            else pushclk = 0; //If he stops pressing, don't allow the lockblok to unlock
            Waitframe(); //duh
            if(pushclk == pushtime) Unlock(sfx,perm,d); //If pushclk reaches pushtime, the block needs to be unlocked
        }
        Screen->ComboD[loc]++; //This changes the block's graphic
    }
   void Unlock(int sfx, int perm, int d){
        if(sfx == 0) Game->PlaySound(SFX_SHUTTER); //If the sound effect is zero, use the default sound
        else if(sfx > 0) Game->PlaySound(sfx); //Else use any sound the player wants
        Screen->D[d] |= (1<<perm); //I'll explain this further down
        if(Game->LKeys[Game->GetCurLevel()] > 0) Game->LKeys[Game->GetCurLevel()]--; //If Link has any level keys, use those instead of normal keys
        else Game->Counter[CR_KEYS]--; //Otherwise take away a normal key
    }
    bool CheckKeys(){
        return Game->Counter[CR_KEYS] > 0 || Game->LKeys[Game->GetCurLevel()] > 0; //Check for the different key types. I just realised I need to also allow for boss-key lockblocks
    }
    bool PushingCombo(int loc){
        int y = ComboY(loc); int x = ComboX(loc); //Slightly quicker with variables
        return (Link->Dir == DIR_UP && Link->InputUp && Link->Y == y+8 && Abs(Link->X-x) < 8)  //If Link's pushing against the block from the bottom
            || (Link->Dir == DIR_DOWN && Link->InputDown && Link->Y == y-16 && Abs(Link->X-x) < 8) //Top
            || (Link->Dir == DIR_LEFT && Link->InputLeft && Link->X == x+16 && Abs(Link->Y-y) < 8) //Right
            || (Link->Dir == DIR_RIGHT && Link->InputRight && Link->X == x-16 && Abs(Link->Y-y) < 8); //Left
    }
}

ffc script Copycat{
    void run(int perm, int d){
        while((Screen->D[d] & (1<<perm)) == 0) Waitframe();
        Screen->ComboD[ComboAt(this->X,this->Y)]++;
    }
}


Right,
CODE
Screen->D[d] |= (1<<perm)
. If '&' checks for a bit, '|' sets it. So say perm is '5'. let's look at what this line does, in two different cases.
CODE
case 1:
Screen->D[d] == 10010100
10010100
00100000|
=
10110100
case 2:
Screen->D[d] == 10110100
10110100
00100000|
=
10110100

As you can see, if we OR a single bit agaisnt a bit string, it sets that bit to '1' regardles of what it was in the original bit string. So basically we're setting that one to true.

QUOTE(AgentLym @ Jan 22 2010, 02:50 AM) View Post
Btw, Joe, is it okay if I release it? (or did you want to icon_razz.gif) I'm sure it'll come in mighty handy!
I'll get to it, don't worry.

QUOTE(ShadowTiger @ Jan 22 2010, 02:50 AM) View Post
Of course, if you're having four lockblocks on the same screen where any can be triggered at any time, is that really good dungeon design? (much less screen design... sheesh.) Sure, it depends on what you want, but think of other methods too, to bypass any technical limitations barring you.

Yes, if you're using an interior map so you can't use the Door Combo Sets, and you want to have more than one locked door. You might even want 4 locked doors on a single screen, if you enter from a stairway or something.


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users