C-Dawg
11-06-2006, 12:13 PM
I'm having a really frustrating time getting this script to work right.
GOAL: Design a script for an ice slick. If Link does not have any Winter Boots, the ice slick will make him slide uncontrolably until he exits the slick or hits a solid combo. Then he can choose to slide in another direction, but can never change direction unless he's off of the slick or against a solid combo. If Link has Level 1 Winter Boots, then he can move normally on the ice slick, but he will slip and slide in any direction he has momentum. Level 2 Winter Boots allow him to move normally on the ice slick.
PROBLEM: I can't get any stage of this ice slick to work correctly. First, I tried to code up the ice slick's behavior when Link has no Winter Boots.
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip uncontrollably
// in that direction until he exits the rectangle or
// until he hits a solid object.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(int north, int south, int west, int east){
while(true){
if (state == 1){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y - 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else { state = 0; }
} // end of state = 1
if (state == 2){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y + 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else { state = 0; }
} // end of state = 2
if (state == 3){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X + 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->X = Link->X + 1;
}
else { state = 0; }
} // end of state = 3
if (state == 4){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X - 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->X = Link->X - 1;
}
else { state = 0; }
} // end of state = 4
if (state == 0){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west)){
if(Link->InputUp && canMove(Link->X, Link->Y-16))
{ state = 1; }
if(Link->InputDown && canMove(Link->X, Link->Y+16))
{ state = 2; }
if(Link->InputRight && canMove(Link->X+16, Link->Y))
{ state = 3; }
if(Link->InputLeft && canMove(Link->X-16, Link->Y))
{ state = 4; }
}
} // end of state 0
Waitframe();
} // end of while loop
} // end of run void
// Collision detection function
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[ComboAt(x,y)] == 0;
}
}
This works, sort of. It compiles fine, but at runtime, Link will slide across the ice, come to rest somewhere, and usually then gets stuck. He can still move if pushed (for instance, drop a bomb and it will push him away) but the directional input is turned off. Yet Link is immobile. This seems IMPOSSIBLE given the script, which only terminates input in the same if{} statement that forces Link to slide across the ice.
I tried to fix the code by changing how Link would slide as follows:
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip uncontrollably
// in that direction until he exits the rectangle or
// until he hits a solid object.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(int north, int south, int west, int east){
while(true){
if (state == 1){
Link->Y = Link->Y - 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y - 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 1
if (state == 2){
Link->Y = Link->Y + 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y + 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 2
if (state == 3){
Link->X = Link->X + 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X + 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 3
if (state == 4){
Link->X = Link->X - 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X - 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 4
if (state == 0){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west)){
if(Link->InputUp && canMove(Link->X, Link->Y-16))
{ state = 1; }
if(Link->InputDown && canMove(Link->X, Link->Y+16))
{ state = 2; }
if(Link->InputRight && canMove(Link->X+16, Link->Y))
{ state = 3; }
if(Link->InputLeft && canMove(Link->X-16, Link->Y))
{ state = 4; }
}
} // end of state 0
Waitframe();
} // end of while loop
} // end of run void
// Collision detection function
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[ComboAt(x,y)] == 0;
}
}
But alas, this had no effect on the bizzare behavior. Link would still become immobile and unable to move on the ice. Additionally, the collision detection is wonky; it will stop him two full combos away from solid blocks instead of right next to them, seemingly at random.
Since this didn't work, I tried to use secret flags. This would be, in theory, easier and more useful, since the ice slicks could be any shape at all. I came up with this:
// =============================================
// Ice_Slick: On a screen with this FFC, Link will
// slip on any tile that has Flag 16 (Secret Flag 0)
// on layer 0. When Link steps on such a tile, he
// will slip in that direction until he's next to
// a combo without that secret flag.
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(){
while(true){
if (state == 0){
if ((Link->InputUp) &&
(Screen->ComboF[ComboAt(Link->X,Link->Y-16)] == 16)){
state == 1;
}
if ((Link->InputDown) &&
(Screen->ComboF[ComboAt(Link->X,Link->Y+16)] == 16)){
state == 2;
}
if ((Link->InputRight) &&
(Screen->ComboF[ComboAt(Link->X+16,Link->Y)] == 16)){
state == 3;
}
if ((Link->InputLeft) &&
(Screen->ComboF[ComboAt(Link->X-16,Link->Y)] == 16)){
state == 4;
}
} // end of state = 0
if (state == 1){
if (Screen->ComboF[ComboAt(Link->X,Link->Y-16)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else{ state = 0;}
} // end of state = 1
if (state == 2){
if (Screen->ComboF[ComboAt(Link->X,Link->Y+16)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else{ state = 0;}
} // end of state = 2
if (state == 3){
if (Screen->ComboF[ComboAt(Link->X+16,Link->Y)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else{ state = 0;}
} // end of state = 3
if (state == 4){
if (Screen->ComboF[ComboAt(Link->X-16,Link->Y)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else{ state = 0;}
} // end of state = 4
Waitframe();
} // end of while loop
} // end of void main
} // end of FFC Script
This script didn't do ANYTHING. It was as if the secret flags weren't being detected. I tested both innate secret flags (assigned in the combo editor) and placed secret flags (assigned in the screen editor). Neither triggered any behavior.
So, last, I tried the second-level behavior of the ice slick. That is, giving Link momentum when he moves in a direction and making him slip in that direction. I came up with this:
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip on the ice. The slipping
// is controlled by momentum variables that increase
// in the direction Link steps, and decrease in the direction
// he steps away from, as long as that direction is held.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
int slip_x; // Link's slipping factor
int slip_y;
void run(int north, int south, int west, int east){
while(true){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) ){
if (Link->InputUp){slip_y = slip_y - 0.2;}
if (Link->InputDown){slip_y = slip_y + 0.2;}
if (Link->InputRight){slip_y = slip_x + 0.2;}
if (Link->InputLeft){slip_y = slip_x - 0.2;}
if(slip_y > 1) { slip_y = 1);
if(slip_y < -1) { slip_y = -1);
if(slip_x > 1) { slip_x = 1);
if(slip_x < -1) { slip_x = -1);
if(slip_y < 1 && !Link->InputUp){ Link->Y = Link->Y + slip_y); }
if(slip_y > 1 && !Link->InputDown){ Link->Y = Link->Y + slip_y); }
if(slip_x > 1 && !Link->InputRight){ Link->X = Link->X + slip_x); }
if(slip_x < 1 && !Link->InputLeft){ Link->X = Link->X + slip_x); }
Waitframe();
} // end of while loop
} // end of void run
} // end of ffc script
Which, as far as I can tell, also does NOTHING.
I'm going nuts here. Is this a compiler error, or are my algorithms missing something?
GOAL: Design a script for an ice slick. If Link does not have any Winter Boots, the ice slick will make him slide uncontrolably until he exits the slick or hits a solid combo. Then he can choose to slide in another direction, but can never change direction unless he's off of the slick or against a solid combo. If Link has Level 1 Winter Boots, then he can move normally on the ice slick, but he will slip and slide in any direction he has momentum. Level 2 Winter Boots allow him to move normally on the ice slick.
PROBLEM: I can't get any stage of this ice slick to work correctly. First, I tried to code up the ice slick's behavior when Link has no Winter Boots.
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip uncontrollably
// in that direction until he exits the rectangle or
// until he hits a solid object.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(int north, int south, int west, int east){
while(true){
if (state == 1){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y - 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else { state = 0; }
} // end of state = 1
if (state == 2){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y + 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else { state = 0; }
} // end of state = 2
if (state == 3){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X + 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->X = Link->X + 1;
}
else { state = 0; }
} // end of state = 3
if (state == 4){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X - 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->X = Link->X - 1;
}
else { state = 0; }
} // end of state = 4
if (state == 0){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west)){
if(Link->InputUp && canMove(Link->X, Link->Y-16))
{ state = 1; }
if(Link->InputDown && canMove(Link->X, Link->Y+16))
{ state = 2; }
if(Link->InputRight && canMove(Link->X+16, Link->Y))
{ state = 3; }
if(Link->InputLeft && canMove(Link->X-16, Link->Y))
{ state = 4; }
}
} // end of state 0
Waitframe();
} // end of while loop
} // end of run void
// Collision detection function
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[ComboAt(x,y)] == 0;
}
}
This works, sort of. It compiles fine, but at runtime, Link will slide across the ice, come to rest somewhere, and usually then gets stuck. He can still move if pushed (for instance, drop a bomb and it will push him away) but the directional input is turned off. Yet Link is immobile. This seems IMPOSSIBLE given the script, which only terminates input in the same if{} statement that forces Link to slide across the ice.
I tried to fix the code by changing how Link would slide as follows:
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip uncontrollably
// in that direction until he exits the rectangle or
// until he hits a solid object.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(int north, int south, int west, int east){
while(true){
if (state == 1){
Link->Y = Link->Y - 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y - 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 1
if (state == 2){
Link->Y = Link->Y + 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X, Link->Y + 16)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 2
if (state == 3){
Link->X = Link->X + 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X + 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 3
if (state == 4){
Link->X = Link->X - 1;
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) &&
(canMove(Link->X - 16, Link->Y)) ){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
}
else { state = 0; }
} // end of state = 4
if (state == 0){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west)){
if(Link->InputUp && canMove(Link->X, Link->Y-16))
{ state = 1; }
if(Link->InputDown && canMove(Link->X, Link->Y+16))
{ state = 2; }
if(Link->InputRight && canMove(Link->X+16, Link->Y))
{ state = 3; }
if(Link->InputLeft && canMove(Link->X-16, Link->Y))
{ state = 4; }
}
} // end of state 0
Waitframe();
} // end of while loop
} // end of run void
// Collision detection function
bool canMove(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
return false;
return Screen->ComboS[ComboAt(x,y)] == 0;
}
}
But alas, this had no effect on the bizzare behavior. Link would still become immobile and unable to move on the ice. Additionally, the collision detection is wonky; it will stop him two full combos away from solid blocks instead of right next to them, seemingly at random.
Since this didn't work, I tried to use secret flags. This would be, in theory, easier and more useful, since the ice slicks could be any shape at all. I came up with this:
// =============================================
// Ice_Slick: On a screen with this FFC, Link will
// slip on any tile that has Flag 16 (Secret Flag 0)
// on layer 0. When Link steps on such a tile, he
// will slip in that direction until he's next to
// a combo without that secret flag.
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
void run(){
while(true){
if (state == 0){
if ((Link->InputUp) &&
(Screen->ComboF[ComboAt(Link->X,Link->Y-16)] == 16)){
state == 1;
}
if ((Link->InputDown) &&
(Screen->ComboF[ComboAt(Link->X,Link->Y+16)] == 16)){
state == 2;
}
if ((Link->InputRight) &&
(Screen->ComboF[ComboAt(Link->X+16,Link->Y)] == 16)){
state == 3;
}
if ((Link->InputLeft) &&
(Screen->ComboF[ComboAt(Link->X-16,Link->Y)] == 16)){
state == 4;
}
} // end of state = 0
if (state == 1){
if (Screen->ComboF[ComboAt(Link->X,Link->Y-16)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else{ state = 0;}
} // end of state = 1
if (state == 2){
if (Screen->ComboF[ComboAt(Link->X,Link->Y+16)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else{ state = 0;}
} // end of state = 2
if (state == 3){
if (Screen->ComboF[ComboAt(Link->X+16,Link->Y)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y + 1;
}
else{ state = 0;}
} // end of state = 3
if (state == 4){
if (Screen->ComboF[ComboAt(Link->X-16,Link->Y)] == 16){
Link->InputUp = false;
Link->InputDown = false;
Link->InputRight = false;
Link->InputLeft = false;
Link->Y = Link->Y - 1;
}
else{ state = 0;}
} // end of state = 4
Waitframe();
} // end of while loop
} // end of void main
} // end of FFC Script
This script didn't do ANYTHING. It was as if the secret flags weren't being detected. I tested both innate secret flags (assigned in the combo editor) and placed secret flags (assigned in the screen editor). Neither triggered any behavior.
So, last, I tried the second-level behavior of the ice slick. That is, giving Link momentum when he moves in a direction and making him slip in that direction. I came up with this:
// =============================================
// Ice_Slick: On a screen with this FFC, when Link
// steps inside of a rectangle defined by the four
// data coordinates, he will slip on the ice. The slipping
// is controlled by momentum variables that increase
// in the direction Link steps, and decrease in the direction
// he steps away from, as long as that direction is held.
// Data is set up as follows:
// D0 - The north X coordinate of the ice slick
// D1 - The south X coordinate of the ice slick
// D2 - The west y coordinate of the ice slick
// D3 - The east y coordinate of the ice slick
// =============================================
ffc script ice_slick{
// VARIABLES
int state = 0; // Whether or not Link is slipping.
// 0 = Not slipping
// 1 = Slipping north
// 2 = Slipping south
// 3 = slipping east
// 4 = slipping west
int slip_x; // Link's slipping factor
int slip_y;
void run(int north, int south, int west, int east){
while(true){
if( (Link->X < south) && (Link->X > north) &&
(Link->Y < east) && (Link->Y > west) ){
if (Link->InputUp){slip_y = slip_y - 0.2;}
if (Link->InputDown){slip_y = slip_y + 0.2;}
if (Link->InputRight){slip_y = slip_x + 0.2;}
if (Link->InputLeft){slip_y = slip_x - 0.2;}
if(slip_y > 1) { slip_y = 1);
if(slip_y < -1) { slip_y = -1);
if(slip_x > 1) { slip_x = 1);
if(slip_x < -1) { slip_x = -1);
if(slip_y < 1 && !Link->InputUp){ Link->Y = Link->Y + slip_y); }
if(slip_y > 1 && !Link->InputDown){ Link->Y = Link->Y + slip_y); }
if(slip_x > 1 && !Link->InputRight){ Link->X = Link->X + slip_x); }
if(slip_x < 1 && !Link->InputLeft){ Link->X = Link->X + slip_x); }
Waitframe();
} // end of while loop
} // end of void run
} // end of ffc script
Which, as far as I can tell, also does NOTHING.
I'm going nuts here. Is this a compiler error, or are my algorithms missing something?