C-Dawg
11-01-2006, 04:05 PM
Here's another script that I did on lunch break at work. Havn't tested it yet. Still, every time I post one of these, Saffith comes and explains my misconceptions about ZScript. To continue the education for me and for anyone reading these threads, I present: the Rolling Block script.
What I think I'll do is modify my Multiblock_trigger script to detect either walkability OR the presense of another FFC. That way, you can make puzzles that require you to push a rolling block into position, ala Brainlord. I also recall OoT having some of these puzzles in the ice levels.
// ===============================================
// rolling_block = When pushed, this block will
// continue rolling until it hits another solid
// combo. Link needs to stand next to it and push
// for several tics to make it roll.
// Uses two combos, one for stationary, and
// a second for rolling. Use the FFC data to set
// whether Link needs the Bracelet #1 or #2 to
// roll the block.
// 0 = No bracelet needed
// 1 = Need #1 bracelet
// 2 = Need #2 bracelet
// ===============================================
ffc script rolling_block{
// CONSTANTS - use to change behavior
int speed = 2; // The speed at which the
// FFC rolls.
int delay = 5; // How many tics Link must
// push against the ffc
// before it moves.
// VARIABLES - Do not change!
int state = 0; // Current state of the FFC.
// 0 = stationary
// 1 = rolling
int roll_x =0; // Used to determine the direction
int roll_y =0; // of the roll.
int push_counter = delay;
void run (int heavy){
while(true){
if(state == 0){
// First, check if Link has the appropriate bracelet. Then,
// check for Link pushing this combo. If he's been
// pushing it constantly for push_counter tics,
// start it in motion in the appropriate direction.
if( (heavy == 0) || ((heavy == 1) && (Link->Item[19])) || ((heavy == 2) && (Link->Item[56])) ){
if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y)){
if (push_counter = 0){
state = 0;
roll_x = 0;
roll_y = -1;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y)){
if (push_counter = 0){
state = 0;
roll_x = 0;
roll_y = 1;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X)){
if (push_counter = 0){
state = 0;
roll_x = -1;
roll_y = 0;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X)){
if (push_counter = 0){
state = 0;
roll_x = -1;
roll_y = 0;
this->Data++;
}
else { push_counter--;}
}
else{push_counter = delay;}
}
}
}
}
// Simulate unwalkability
if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y) && (Abs(Link->X - this->X) < 16)){
{Link->InputUp = false;}
if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y) && (Abs(Link->X - this->X) < 16)){
Link->InputDown = false;}
if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X) && (Abs(Link->Y - this->Y) < 16)){
Link->InputLeft = false;}
if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X) && (Abs(Link->Y - this->Y) < 16)){
Link->InputRight = false;}
} // end of state = 0
if (state = 1){
if( ((roll_y > 0) && canMove(this->X, this->Y + 16)) ||
((roll_y < 0) && canMove(this->X, this->Y - 16)) ||
((roll_x > 0) && canMove(this->X + 16, this->Y)) ||
((roll_x < 0) && canMove(this->X - 16, this->Y)) ){
this->Vx = speed * roll_x;
this->Vy = speed * roll_y;
}
else{
state = 0;
push_counter = delay;
this->Data--;
}
} // end of state = 1
Waitframe();
} // end of while loop
} // end of void run
// Collision detection function.
// Returns true if the tile on layer 0 is within the
// range of the screen and no part of it is solid.
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[y+(x>>4)]==0;
}
} // end of ffc script
What I think I'll do is modify my Multiblock_trigger script to detect either walkability OR the presense of another FFC. That way, you can make puzzles that require you to push a rolling block into position, ala Brainlord. I also recall OoT having some of these puzzles in the ice levels.
// ===============================================
// rolling_block = When pushed, this block will
// continue rolling until it hits another solid
// combo. Link needs to stand next to it and push
// for several tics to make it roll.
// Uses two combos, one for stationary, and
// a second for rolling. Use the FFC data to set
// whether Link needs the Bracelet #1 or #2 to
// roll the block.
// 0 = No bracelet needed
// 1 = Need #1 bracelet
// 2 = Need #2 bracelet
// ===============================================
ffc script rolling_block{
// CONSTANTS - use to change behavior
int speed = 2; // The speed at which the
// FFC rolls.
int delay = 5; // How many tics Link must
// push against the ffc
// before it moves.
// VARIABLES - Do not change!
int state = 0; // Current state of the FFC.
// 0 = stationary
// 1 = rolling
int roll_x =0; // Used to determine the direction
int roll_y =0; // of the roll.
int push_counter = delay;
void run (int heavy){
while(true){
if(state == 0){
// First, check if Link has the appropriate bracelet. Then,
// check for Link pushing this combo. If he's been
// pushing it constantly for push_counter tics,
// start it in motion in the appropriate direction.
if( (heavy == 0) || ((heavy == 1) && (Link->Item[19])) || ((heavy == 2) && (Link->Item[56])) ){
if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y)){
if (push_counter = 0){
state = 0;
roll_x = 0;
roll_y = -1;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y)){
if (push_counter = 0){
state = 0;
roll_x = 0;
roll_y = 1;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X)){
if (push_counter = 0){
state = 0;
roll_x = -1;
roll_y = 0;
this->Data++;
}
else { push_counter--;}
}
else{
if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X)){
if (push_counter = 0){
state = 0;
roll_x = -1;
roll_y = 0;
this->Data++;
}
else { push_counter--;}
}
else{push_counter = delay;}
}
}
}
}
// Simulate unwalkability
if( (Link->InputUp) && (Link->Y << this->Y + 16) &&
(Link-Y >> this->Y) && (Abs(Link->X - this->X) < 16)){
{Link->InputUp = false;}
if( (Link->InputDown) && (Link->Y >> this->Y - 16) &&
(Link-Y << this->Y) && (Abs(Link->X - this->X) < 16)){
Link->InputDown = false;}
if( (Link->InputLeft) && (Link->X << this->X + 16) &&
(Link-X >> this->X) && (Abs(Link->Y - this->Y) < 16)){
Link->InputLeft = false;}
if( (Link->InputRight) && (Link->X >> this->X - 16) &&
(Link-X << this->X) && (Abs(Link->Y - this->Y) < 16)){
Link->InputRight = false;}
} // end of state = 0
if (state = 1){
if( ((roll_y > 0) && canMove(this->X, this->Y + 16)) ||
((roll_y < 0) && canMove(this->X, this->Y - 16)) ||
((roll_x > 0) && canMove(this->X + 16, this->Y)) ||
((roll_x < 0) && canMove(this->X - 16, this->Y)) ){
this->Vx = speed * roll_x;
this->Vy = speed * roll_y;
}
else{
state = 0;
push_counter = delay;
this->Data--;
}
} // end of state = 1
Waitframe();
} // end of while loop
} // end of void run
// Collision detection function.
// Returns true if the tile on layer 0 is within the
// range of the screen and no part of it is solid.
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[y+(x>>4)]==0;
}
} // end of ffc script