Jump to content

Photo

Reset Switches if Not Hit in Order


  • Please log in to reply
15 replies to this topic

#1 ywkls

ywkls

    Master

  • Members

Posted 15 March 2015 - 08:23 PM

I'm working in the latest version of Zquest with the Dance of Remembrance (Hybrid) tileset. I came up with this idea based upon two other scripts. The first is the authentic dungeon barriers script which I've included below.

 

Spoiler

 

The second is from this topic.

 

http://www.purezc.ne...= switch order

 

The idea I have seems like it would be a simple one, but so far my efforts to code it myself have hit against a giant wall. Namely, I can tell the script how to set up the dummy enemys, count the number of switches on screen and even reset the switches if you get the order wrong. But I'm a little hung up on telling the script what the right order is supposed to be.

 

My instincts tell me that this would probably have to either have an FFC which could have the right order placed as its arguments, or one FFC per switch. If it was the former, then I imagine doing something like this.

ffc script SwitchOrder {
 void run(int SwitchPos1, int SwitchPos2, int SwitchPos3, int SwitchPos4){//Etc up to 8 switches.

The code in the topic above is sufficiently different from what I'm after that I don't think it would work. Anyways, theoretically the ffc would detect which switch you just tried to hit (using the dummy enemy's location) and if it wasn't the right one; any switches that you had already correctly hit would be returned to normal. Sort of like a reset room combo, except where you have to hit it with a weapon to activate it.

 

My own code does nothing and I even know why... the FFC has no clue what the order is supposed to be. By using this, I could set up puzzles where you couldn't just randomly hit switches in the hope of figuring it out but had to read clues to get past. (I'd post what I came up with, but it isn't that different from the authentic barriers script; just changing names of variables and eliminating stuff that I don't need.)

 

Thanks in advance to anyone who can help! 



#2 justin

justin

    Adept

  • Members

Posted 15 March 2015 - 08:36 PM

You could use the ffc number as the order. So gotta hit ffc1 first, then ffc2, etc.

Each ffc when hit checks if the previous one has been hit (use the misc array, or check the combo under it to see if it is the triggered version), if it hasn't been hit then it cycles through all and resets them. If the previous has been triggered then trigger this one.

Instead of using the dummy enemy, I would just use a standard strike-> next combo, and watch for it to change.

Edited by justin, 15 March 2015 - 08:42 PM.


#3 ywkls

ywkls

    Master

  • Members

Posted 15 March 2015 - 09:00 PM

I knew that there was something that I forgot to mention whenever I created this thread. The reason I'm trying to reset the room is because it is a tiered secret. By having it where hitting the wrong switch resets the room, that keeps the player from just randomly hitting switches until one works.

 

Plus, that means I can't check for the combo changing. (I even tried that.) Since the combo won't change until the switches are hit in order, that means that it has to be active before the combo changes. I don't know of anything else I might be forgetting, but I'll post it if I think of it.



#4 justin

justin

    Adept

  • Members

Posted 15 March 2015 - 09:11 PM

i don't get exactly what you mean about it being a tiered secret.

 

you can still have the combo change, just change it into a combo that looks exactly like the first one.  the combo# is different for the scripting purpose, but the player sees the same tile.



#5 ywkls

ywkls

    Master

  • Members

Posted 15 March 2015 - 11:24 PM

Perhaps a screenshot might be of some assistance.

 

7elaE2H.png

 

On the screen in question, only one of the switches is marked with a flag that triggers a secret, changing it to a blue switch and activating one of the other three switches, which then activates the next. The way that the barrier script works is by detecting how many of the switch combos are on screen, assigning an unkillable dummy enemy to it and then detecting whether that enemy has been hit.

 

My intention was to create a script that would do that, then you could tell it what order the switches were supposed to be in and if you hit the wrong one all of the switches would reset to normal. (Basically, warping you back to the same screen in the same spot without any secrets triggered.) 

 

I think I know how to use the FFC Misc Array as you mentioned. As for each FFC detecting the previous, I can't really make heads or tails of the code from the crystal switches. (At least the barriers one makes sense to me, even if it works differently than what I want.)  I'll probably look over both codes more thoroughly tomorrow and see if I can work something out. If you happen to come solution or any other tips, I'd appreciate them.



#6 ywkls

ywkls

    Master

  • Members

Posted 16 March 2015 - 09:58 AM

I think that it might be possible to combine this script with the barriers script I posted above.

 

http://www.purezc.ne...tch#entry934664

 

This was designed to let you step on switches in a certain order, so hitting them in order shouldn't be that different.

The main problem I have comes with resetting the room.

 

There are several different methods I can think of to warp you back to the same room in the same spot. One I've tried and failed to get working is the one used by the Hole/Lava script. Just for reference, here's the script I'm talking about.

 

Spoiler

 

The easiest way I can think of to combine these is to use a second FFC script that is activated by the first. So, I worked up my own script to accomplish this. Instead of doing what I intended, it warps you to the top right corner and causes you to be invisible and visible every frame. I can even determine why it is doing this. Here's the script.

 

Spoiler

 

My instincts tell me that the Screen->D variable starts at zero, which then activates the while loop. Then the next if is being activated, even though it shouldn't be unless the enemy's HP isn't at max. (Maybe because there is more than one of them?) And since there are multiple switches, the number variable is never right, so the bool WrongSwitch is being activated constantly.

 

It may also be that the placement of commands is incorrect somehow. I know that WrongSwitch needs to be set to false, but I'm not sure where to put that. It is also possible that I need to place the if that detects its condition inside the while loop for ResetRoom, perhaps only activating the Reset() if WrongSwitch is true. I'm going to continue to work with it, but if anyone can point me in the right direction or suggest an alternative; I'd appreciate it.



#7 justin

justin

    Adept

  • Members

Posted 16 March 2015 - 11:05 AM

I think you're making this too complicated. I'm going to write the script when I get to a computer later today.

try this, uncompiled untested. setup three combos. the first two should look exactly the same. the first one has a strike->next or step->next or whatever on it. so when hit it turns into the next combo which looks exactly the same (so the player has no idea anything has happened). create a third combo that is the version that looks triggered. put those combo#s into the constants in the script.

place your combos onscreen and place the ffc script over each one. for the first ffc running the script set D0 to 1. have the ffcs in subsequent consecutive order, the order that they should be hit. on the last ffc of the puzzle set D0 to 2.

the script looks for the combo to have changed to the 2nd combo (the triggered but look-alike). if changed it checks whether the combo before it is triggered. if not, all the combos get reset to the 1st combo. if the previous one is triggered then we know all the ones before were triggered in correct order. once the last gets triggered, and the one before is triggered then we trigger secrets.
import "std.zh"
 
const int FFC_MISC_PUZZLEORDER = 0;  // set to an unused FFC->Misc[] array position
 
const int PUZZLEORDER_COMBO_UNSET = 0; // combo of the unhit trigger
const int PUZZLEORDER_COMBO_ISSET = 0; // combo of a hit trigger, should look the exact same as above
const int PUZZLEORDER_COMBO_ALLSET = 0; // combo of the hit trigger showing the puzzle is complete
 
// D0:  1 = is the first ffc in the puzzle, 2 = the last ffc in the puzzle.
//      only the first and last need this set, the others don't
 
ffc script PuzzleOrder
{
 void run(int isFirstorLast)
 {
  int loc = ComboAt(this->X,this->Y);
  int thisNum = FFCNum(this);
  ffc f;
 
  while(true)
  {
   if( Screen->ComboD[loc] == PUZZLEORDER_COMBO_ISSET && this->Misc[FFC_MISC_PUZZLEORDER] == 0)
   {
    if(isFirstorLast == 1) // first
    {
     this->Misc[FFC_MISC_PUZZLEORDER] = 1;
    }
    else
    {
     f = Screen->LoadFFC(thisNum-1);
     if( f->Misc[FFC_MISC_PUZZLEORDER] == 1 )
     {
      this->Misc[FFC_MISC_PUZZLEORDER] = 1;
      if(isFirstorLast == 2) // last
      {
       PuzzleOrderSetAll(this->Script);
       Screen->TriggerSecrets();
       Screen->State[ST_SECRET] = true;
      }
     }
     else
     {
      PuzzleOrderUnset(this->Script);
     }
    }
   }
 
   Waitframe();
  }
 }
 
 void PuzzleOrderSetAll(int scriptNum)
 {
  ffc f;
  for(int i = 1; i <= 32; i++)
  {
   f = Screen->LoadFFC(i);
   if(f->Script != scriptNum) continue;
   Screen->ComboD[ ComboAt(f->X,f->Y) ] = PUZZLEORDER_COMBO_ALLSET;
  }
 }
 
 void PuzzleOrderUnset(int scriptNum)
 {
  ffc f;
  for(int i = 1; i <= 32; i++)
  {
   f = Screen->LoadFFC(i);
   if(f->Script != scriptNum) continue;
   if(f->Misc[FFC_MISC_PUZZLEORDER] == 1)
   {
    Screen->ComboD[ ComboAt(f->X,f->Y) ] = PUZZLEORDER_COMBO_UNSET;
    f->Misc[FFC_MISC_PUZZLEORDER] = 0;
   }
  }
 }
}

Edited by justin, 16 March 2015 - 03:00 PM.


#8 justin

justin

    Adept

  • Members

Posted 16 March 2015 - 01:20 PM

see above



#9 ywkls

ywkls

    Master

  • Members

Posted 16 March 2015 - 02:44 PM

Okay, I'm not sure if I'm doing something wrong with the setup or if the code isn't working properly. I set up the FFCs that run the code on this screen.

 

7elaE2H.png

 

FFC one is at bottom left, with D0 set to one. Top right is FFC 2, Top left is FFC 3 and bottom right is FFC 4 which has D0 at 2. The three combo idea is similar to something I had thought of, using the Hamiltonian Path script as a model; so I'd already created Slash-Next Combos, along with one to the right that was identical and type none and one right of that which had the graphics of the hit switch and type none. So, i changed the constants at the top of the script to their combo numbers.

Also, I made the combos for a switch that was hit but not solved different so I could tell that it was doing something.

 

If hit in the right order, the secrets are triggered like they are supposed to. I can use Screen->D to make that permanent so you never have to solve the puzzle again. The problem is that now they can be hit in the wrong order too. For example, if I hit the first switch; then the third switch; the first switch changes back to normal. Then if I hit the second switch, it doesn't reset the puzzle. If I then hit the 4th switch, it acts as if the puzzle has been solved correctly.

 

I'm sure that there is a perfectly logical reason why this is happening, but sadly it eludes me.



#10 justin

justin

    Adept

  • Members

Posted 16 March 2015 - 03:03 PM

Oops, my bad, forgot to reset the misc value. The script above has been modified. Should work now

Oh, and I set secrets as permanent so you shouldn't need use a screen d register.

Edited by justin, 16 March 2015 - 03:08 PM.


#11 ywkls

ywkls

    Master

  • Members

Posted 16 March 2015 - 03:49 PM

Still doesn't seem to be working.... I've tested the following methods.

 

Hit the switches in the right order- almost perfect. Secrets are triggered, switches change to right combo. However, if you solve the puzzle again (which since the secrets stay triggered it isn't logical to do, but lets say somebody did) the secrets are untriggered. Best solution I can think of is saving to the Screen->D variable when solved and make the script not run and the combo's change to their hit status if that variable has been set.

 

Hit all the switches in any order- still solves the puzzle, strangely. Not only that, but the only trigger that is reset to its unhit state is the one covered by FFC one. If I start at any other switch, no triggers are reset and all I must do is hit all the switches to solve the puzzle. Whereas, if I start at the correct first switch, then hit a wrong switch; the first one resets but the puzzle can still be solved if I hit all of the other switches in any order.

 

One reason this might be is that script is checking for the value of FFC_MISC_PUZZLEORDER == 1 to reset them and that's only being set for the first switch. I can think of a few ways to modify it to check each FFC, but working it all out will probably take me a while. (Based on my past efforts.) Thanks for everything you've done so far.



#12 justin

justin

    Adept

  • Members

Posted 16 March 2015 - 08:47 PM

ok, this worked for me.  could only hit them in the correct order.  by using permanent secrets they are set as soon as you return to the room (don't use nes dungeon dmap).

 

import "std.zh"
 
const int FFC_MISC_PUZZLEORDER = 0;  // set to an unused FFC->Misc[] array position
 
const int PUZZLEORDER_COMBO_UNSET = 896; // combo of the unhit trigger
const int PUZZLEORDER_COMBO_ISSET = 897; // combo of a hit trigger, should look the exact same as above
const int PUZZLEORDER_COMBO_ALLSET = 898; // combo of the hit trigger showing the puzzle is complete
 
// D0:  1 = is the first ffc in the puzzle, 2 = the last ffc in the puzzle.
//      only the first and last need this set, the others don't
 
ffc script PuzzleOrder
{
 void run(int isFirstorLast)
 {
  if(Screen->State[ST_SECRET])
  {
   PuzzleOrderSetAll(this->Script);
   Quit();   
  }
 
  int loc = ComboAt(this->X,this->Y);
  int thisNum = FFCNum(this);
  ffc f;
 
  while(true)
  {
   if(Screen->State[ST_SECRET]) Quit();
 
   if( Screen->ComboD[loc] == PUZZLEORDER_COMBO_ISSET && this->Misc[FFC_MISC_PUZZLEORDER] != 1)
   {
    if(isFirstorLast == 1) // first
    {
     this->Misc[FFC_MISC_PUZZLEORDER] = 1;
    }
    else
    {
     f = Screen->LoadFFC(thisNum-1);
     if( f->Misc[FFC_MISC_PUZZLEORDER] != 1 ) PuzzleOrderUnset(this->Script);
     else
     {
      this->Misc[FFC_MISC_PUZZLEORDER] = 1;
      if(isFirstorLast == 2) // last
      {
       PuzzleOrderSetAll(this->Script);
       Screen->TriggerSecrets();
       Screen->State[ST_SECRET] = true;
      }
     }
    }
   }
 
   Waitframe();
  }
 }
 
 void PuzzleOrderSetAll(int scriptNum)
 {
  ffc f;
  for(int i = 1; i <= 32; i++)
  {
   f = Screen->LoadFFC(i);
   if(f->Script != scriptNum) continue;
   Screen->ComboD[ ComboAt(f->X,f->Y) ] = PUZZLEORDER_COMBO_ALLSET;
  }
 }
 
 void PuzzleOrderUnset(int scriptNum)
 {
  ffc f;
  for(int i = 1; i <= 32; i++)
  {
   f = Screen->LoadFFC(i);
   if(f->Script != scriptNum) continue;
   Screen->ComboD[ ComboAt(f->X,f->Y) ] = PUZZLEORDER_COMBO_UNSET;
   f->Misc[FFC_MISC_PUZZLEORDER] = 0;
  }
 }
 
}


#13 ywkls

ywkls

    Master

  • Members

Posted 16 March 2015 - 10:51 PM

The setup for this one is the same as the old one, right? That is, place the FFCs over the PUZZLEORDER_COMBO_UNSET combos, starting with the first and ending with the last. (First switch is FFC one, second is FFC two, etc.) Because when I loaded this version, if hit in the wrong order no switch is unset. And when hit in the right order, the puzzle isn't solved. FFC one's D0 is set to one and FFC 4's D0 is set to two, as per the instructions in the script. There are no other FFC's on the screen.



#14 justin

justin

    Adept

  • Members

Posted 17 March 2015 - 07:10 AM

ya the exact same setup.  did you change the constants?

 

i tested this, and it worked exactly as intended.  i can send you my test quest, or you can send me yours.



#15 ywkls

ywkls

    Master

  • Members

Posted 17 March 2015 - 08:57 AM

ya the exact same setup.  did you change the constants?

 

i tested this, and it worked exactly as intended.  i can send you my test quest, or you can send me yours.

Silly me... I forgot to set the constants. (I actually wondered about this before you suggested it, but didn't have a chance to test it until now.) The script works perfectly, keeping the switches and secrets triggered once all of them are hit in order and resetting if not hit in order. This puzzle is an interesting variation on the Lights Out Script I've seen in the database, so there's a chance that some other people might want to use it.

 

One way this could be done is by using the following code.

Spoiler

 

I haven't tested this idea myself, but the Hamiltonian Path Script uses a similar method so that you can make the combo's any number you want rather than hard coding them.

 

Thanks for the script! I plan to use it extensively in my current project.




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users