Spin Check
In some Zelda games, there are puzzles where you must use the Spin Attack to hit a number of switches all at once. If you don't hit them at once, then they'll just reset a split-second later. This script allows you to do that too.
Basically, you just have to set up your switches as Singular, and pop this script in the middle, and it will do the rest.
Script
import "std.zh"
ffc script spincheck {
void run(int dirs, int timer, int sfx) {
//by the way, plz petition a dev for arrays
//?u = up, ?ur = up-right, etc.
//these hold the data for the 8 possible tiles link may need to spin attack
int du; //"data" == combo
int cu; //cset
int fu; //flag
int pu; //position (ComboAt())
int iu; //inherent flag
int tu; //type
int dur;int cur;int fur;int pur;int iur;int tur;
int dr; int cr; int fr; int pr; int ir; int tr;
int ddr;int cdr;int fdr;int pdr;int idr;int tdr;
int dd; int cd; int fd; int pd; int id; int td;
int ddl;int cdl;int fdl;int pdl;int idl;int tdl;
int dl; int cl; int fl; int pl; int il; int tl;
int dul;int cul;int ful;int pul;int iul;int tul;
//48 variables for this? Madness!
int tmp;
//gather the data required
if(((dirs >> DIR_UP) & 1)==1){
pu = ComboAt(this->X, this->Y - 16);
du = Screen->ComboD[pu];
cu = Screen->ComboC[pu];
fu = Screen->ComboF[pu];
iu = Screen->ComboI[pu];
tu = Screen->ComboT[pu];
}
if(((dirs >> DIR_DOWN) & 1)==1){
pd = ComboAt(this->X, this->Y + 16);
dd = Screen->ComboD[pd];
cd = Screen->ComboC[pd];
fd = Screen->ComboF[pd];
id = Screen->ComboI[pd];
td = Screen->ComboT[pd];
}
if(((dirs >> DIR_LEFT) & 1)==1){
pl = ComboAt(this->X - 16, this->Y);
dl = Screen->ComboD[pl];
cl = Screen->ComboC[pl];
fl = Screen->ComboF[pl];
il = Screen->ComboI[pl];
tl = Screen->ComboT[pl];
}
if(((dirs >> DIR_RIGHT) & 1)==1){
pr = ComboAt(this->X + 16, this->Y);
dr = Screen->ComboD[pr];
cr = Screen->ComboC[pr];
fr = Screen->ComboF[pr];
ir = Screen->ComboI[pr];
tr = Screen->ComboT[pr];
}
if(((dirs >> DIR_LEFTUP) & 1)==1){
pul = ComboAt(this->X - 16, this->Y - 16);
dul = Screen->ComboD[pul];
cul = Screen->ComboC[pul];
ful = Screen->ComboF[pul];
iul = Screen->ComboI[pul];
tul = Screen->ComboT[pul];
}
if(((dirs >> DIR_RIGHTUP) & 1)==1){
pur = ComboAt(this->X + 16, this->Y - 16);
dur = Screen->ComboD[pur];
cur = Screen->ComboC[pur];
fur = Screen->ComboF[pur];
iur = Screen->ComboI[pur];
tur = Screen->ComboT[pur];
}
if(((dirs >> DIR_RIGHTDOWN) & 1)==1){
pdr = ComboAt(this->X + 16, this->Y + 16);
ddr = Screen->ComboD[pdr];
cdr = Screen->ComboC[pdr];
fdr = Screen->ComboF[pdr];
idr = Screen->ComboI[pdr];
tdr = Screen->ComboT[pdr];
}
if(((dirs >> DIR_LEFTDOWN) & 1)==1){
pdl = ComboAt(this->X - 16, this->Y + 16);
ddl = Screen->ComboD[pdl];
cdl = Screen->ComboC[pdl];
fdl = Screen->ComboF[pdl];
idl = Screen->ComboI[pdl];
tdl = Screen->ComboT[pdl];
}
//ok, now we can check stuff
while(true) {
//the outer loop is the main loop.
while(true) {
//we need to wait for Link to attack
if(
(pu != 0 && Screen->ComboD[pu] != du) ||
(pl != 0 && Screen->ComboD[pl] != dl) ||
(pd != 0 && Screen->ComboD[pd] != dd) ||
(pr != 0 && Screen->ComboD[pr] != dr) ||
(pul != 0 && Screen->ComboD[pul] != dul) ||
(pur != 0 && Screen->ComboD[pur] != dur) ||
(pdl != 0 && Screen->ComboD[pdl] != ddl) ||
(pdr != 0 && Screen->ComboD[pdr] != ddr)
) {
break; //Link is attacking, march!
}
Waitframe(); //Link is doing squat, try again next frame.
}
int i;
//now we need to count down the timer. If at any point ALL the combos
//have been changed, abort, as Link is successful. Otherwise, reset them.
for(i = 0; i < timer; i++) {
if(
(pu == 0 || Screen->ComboD[pu] != du) &&
(pl == 0 || Screen->ComboD[pl] != dl) &&
(pd == 0 || Screen->ComboD[pd] != dd) &&
(pr == 0 || Screen->ComboD[pr] != dr) &&
(pul == 0 || Screen->ComboD[pul] != dul) &&
(pur == 0 || Screen->ComboD[pur] != dur) &&
(pdl == 0 || Screen->ComboD[pdl] != ddl) &&
(pdr == 0 || Screen->ComboD[pdr] != ddr)
) {
if(sfx!=0) Game->PlaySound(sfx);
Quit(); //Link won, oh noes!
}
Waitframe();
}
//Oops, time's up
if(du != 0) {
Screen->ComboD[pu] = du;
Screen->ComboC[pu] = cu;
Screen->ComboF[pu] = fu;
Screen->ComboI[pu] = iu;
Screen->ComboT[pu] = tu;
}
if(dl != 0) {
Screen->ComboD[pl] = dl;
Screen->ComboC[pl] = cl;
Screen->ComboF[pl] = fl;
Screen->ComboI[pl] = il;
Screen->ComboT[pl] = tl;
}
if(dd != 0) {
Screen->ComboD[pd] = dd;
Screen->ComboC[pd] = cd;
Screen->ComboF[pd] = fd;
Screen->ComboI[pd] = id;
Screen->ComboT[pd] = td;
}
if(dr != 0) {
Screen->ComboD[pr] = dr;
Screen->ComboC[pr] = cr;
Screen->ComboF[pr] = fr;
Screen->ComboI[pr] = ir;
Screen->ComboT[pr] = tr;
}
if(dur != 0) {
Screen->ComboD[pur] = dur;
Screen->ComboC[pur] = cur;
Screen->ComboF[pur] = fur;
Screen->ComboI[pur] = iur;
Screen->ComboT[pur] = tur;
}
if(dul != 0) {
Screen->ComboD[pul] = dul;
Screen->ComboC[pul] = cul;
Screen->ComboF[pul] = ful;
Screen->ComboI[pul] = iul;
Screen->ComboT[pul] = tul;
}
if(ddr != 0) {
Screen->ComboD[pdr] = ddr;
Screen->ComboC[pdr] = cdr;
Screen->ComboF[pdr] = fdr;
Screen->ComboI[pdr] = idr;
Screen->ComboT[pdr] = tdr;
}
if(ddl != 0) {
Screen->ComboD[pdl] = ddl;
Screen->ComboC[pdl] = cdl;
Screen->ComboF[pdl] = fdl;
Screen->ComboI[pdl] = idl;
Screen->ComboT[pdl] = tdl;
}
}
}
}
Arguments
- Which directions to care about (see the notes)
- How long before reseting the switches, when Link fails to trip them all. Measured in frames
- The sound to play when all switches are triggered. 0 is "play no sound"
Notes
- The direction argument is actually a bitfield, with each bit representing a direction. Just add the following numbers together to get the value:
- 1 - Up
- 2 - Down
- 4 - Left
- 8 - Right
- 16 - Up-Left
- 32 - Up-Right
- 64 - Down-Left
- 128 - Down-Right
So, 7 would mean "Up + Down + Left", and 240 would be all four diagonal corners.
- Avoid using the diagonal directions unless you give Link the slash!
- 20 frames is a good value for the reset time.
- Place the FFC on the square in the middle of your circle of switches.
- If you want just one sound to play, set the "No secret sounds" screen flag, and set argument #3 (27 is the default secret sound)
- Make sure you put the Singular flags like in the tutorial!
Screen shots



