PDA

View Full Version : Wall following script



Dan Furst
05-30-2007, 02:21 PM
Hi guys,

This script allows a freeform combo to follow the contours of a wall, or any other solid construct. The movement pattern is the same as the Sparks in Mario 2, if know what I mean. The ff combos are capable of following dynamic walkability patterns, and have a variety of speeds. You can have as many combos on the screen as ZQuest allows.

In this example quest, I made the combos damage type and they look like traps. (The cheat is "4" if you are impatient or can't get through.) I developed and tested this quest under 311.

wallflower.qst (http://filer.case.edu/dpf4/wallflower.qst)

Note you must pass in the ffc number, the pattern, the attachment, and the speed.


ffc script wallflower {

// PATTERN: The direction that the ffc will move initially.

// Up = 1
// Down = 2
// Left = 3
// Right = 4


// ATTACHED: Specify the side of the ffc which is attached to the wall initially.

// Top = 1
// Bottom = 2
// Left = 3
// Right = 4
// TL corner = 5
// TR corner = 6
// BL corner = 7
// BR corner = 8


// SPEED: The speed must be one of the following values:
// 16, 8, 4, 2, 1, 0.5, 0.25, 0.125, 0.0625


void run(int this_ffc_num, int pattern, int attached, float speed)
{
// "this_ffc->" bug workaround
ffc this_ffc = Screen->LoadFFC(this_ffc_num);

//if I'm stuck or floating
if(!is_walkable(this_ffc->X, this_ffc->Y))
{
//I'm on a solid combo
Quit();
}
if(is_walkable(this_ffc->X, this_ffc->Y - 16) && is_walkable(this_ffc->X, this_ffc->Y + 16) &&
is_walkable(this_ffc->X - 16, this_ffc->Y) && is_walkable(this_ffc->X + 16, this_ffc->Y) &&
is_walkable(this_ffc->X - 16, this_ffc->Y - 16) && is_walkable(this_ffc->X + 16, this_ffc->Y - 16) &&
is_walkable(this_ffc->X - 16, this_ffc->Y + 16) && is_walkable(this_ffc->X + 16, this_ffc->Y + 16))
{
//I'm not near any wall
Quit();
}

//the first move
int dir = 0;
dir = first_move(this_ffc->X, this_ffc->Y, pattern, attached);

while(true) // main loop
{
if(dir == 1)
{
//up
this_ffc->Vx = 0;
this_ffc->Vy = -speed;
}
else if(dir == 2)
{
//down
this_ffc->Vx = 0;
this_ffc->Vy = speed;
}
else if(dir == 3)
{
//left
this_ffc->Vx = -speed;
this_ffc->Vy = 0;
}
else if(dir == 4)
{
//right
this_ffc->Vx = speed;
this_ffc->Vy = 0;
}
else
{
Quit();
}

// only do whole combos
for(int i=0; i<(16/speed); i++)
{
Waitframe();
}

// see if the direction needs to be changed
if(dir == 1) // was moving up
{
if(attached == 3) // L
{
if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 7; //BL
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 3; // L
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 1; // T
}
else // D
{
dir = 2; // D
attached = 4; // R
}
}
else if(attached == 4) // R
{
if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 8; //BR
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 4; // R
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 1; // T
}
else // D
{
dir = 2; // D
attached = 3; // L
}
}
else if(attached == 5) // TL
{
if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 3; // L
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 1; // T
}
else // D
{
dir = 2; // D
attached = 4; // R
}
}
else if(attached == 6) // TR
{
if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 4; // R
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 1; // T
}
else // D
{
dir = 2; // D
attached = 3; // L
}
}
else
{
Quit();
}
}
if(dir == 2) // was moving down
{
if(attached == 3) // L
{
if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 5; //TL
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 3; // L
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 2; // B
}
else // U
{
dir = 1; // U
attached = 4; // R
}
}
else if(attached == 4) // R
{
if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 6; //TR
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 4; // R
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 2; // B
}
else // U
{
dir = 1; // U
attached = 3; // L
}
}
else if(attached == 7) // BL
{
if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 3; // L
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 2; // B
}
else // U
{
dir = 1; // U
attached = 4; // R
}
}
else if(attached == 8) // BR
{
if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 4; // R
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 2; // B
}
else // U
{
dir = 1; // U
attached = 3; // L
}
}
else
{
Quit();
}
}
if(dir == 3) // was moving left
{
if(attached == 1) // T
{
if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 6; // TR
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 1; // T
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 3; // L
}
else
{
dir = 4; // R
attached = 2; // B
}
}
else if(attached == 2) // B
{
if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 8; // BR
}
else if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 2; // B
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 3; // L
}
else
{
dir = 4; // R
attached = 1; // T
}
}
else if(attached == 5) // TL
{
if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 1; // T
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 3; // L
}
else // R
{
dir = 4; // R
attached = 2; // B
}
}
else if(attached == 7) // BL
{
if(is_walkable(this_ffc->X - 16, this_ffc->Y)) // L
{
dir = 3; // L
attached = 2; // B
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 3; // L
}
else // R
{
dir = 4; // R
attached = 1; // T
}
}
else
{
Quit();
}
}
if(dir == 4) // was moving right
{
if(attached == 1) // T
{
if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 5; // TL
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 1; // T
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 4; // R
}
else
{
dir = 3; // L
attached = 2; // B
}
}
else if(attached == 2) // B
{
if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 7; // BL
}
else if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 2; // B
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 4; // R
}
else
{
dir = 3; // L
attached = 1; // T
}
}
else if(attached == 6) // TR
{
if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 1; // T
}
else if(is_walkable(this_ffc->X, this_ffc->Y + 16)) // D
{
dir = 2; // D
attached = 4; // R
}
else // L
{
dir = 3; // L
attached = 2; // B
}
}
else if(attached == 8) // BR
{
if(is_walkable(this_ffc->X + 16, this_ffc->Y)) // R
{
dir = 4; // R
attached = 2; // B
}
else if(is_walkable(this_ffc->X, this_ffc->Y - 16)) // U
{
dir = 1; // U
attached = 4; // R
}
else // L
{
dir = 3; // L
attached = 1; // T
}
}
else
{
Quit();
}
}
}// end while true
}

int first_move(int x, int y, int pattern, int attached)
{
if(pattern == 1)
{
//if up is walkable && not attached by B, BL, BR
if(is_walkable(x, y - 16) && attached != 2 && attached != 7 && attached != 8)
{
return 1;
}
return 0;
}
else if(pattern == 2)
{
//if down is walkable && not attached by T, TL, TR
if(is_walkable(x, y + 16) && attached != 1 && attached != 5 && attached != 6)
{
return 2;
}
return 0;
}
else if(pattern == 3)
{
//if left is walkable && not attached by R, TR, BR
if(is_walkable(x - 16, y) && attached != 4 && attached != 6 && attached != 8)
{
return 3;
}
return 0;
}
else if(pattern == 4)
{
//if right is walkable && not attached by L, TL, BL
if(is_walkable(x + 16, y) && attached != 3 && attached != 5 && attached != 7)
{
return 4;
}
return 0;
}
else
{
//you entered an invalid pattern
Quit();
}
}

bool is_walkable(int x, int y)
{
if(x<0 || x>240 || y<0 || y>160)
{
return false;
}

return Screen->ComboS[y+(x>>4)]==0;
}

}//end


So how do you like my first script?

C-Dawg
05-30-2007, 04:39 PM
Here comes a new challanger!

Excellent work. This script, and your ice block script, are both behaviors I tried to get scripted up a few months back and wasn't able to complete. Awesome job on creating a working script! I hope this isn't the last we'll see from ya.

Dan Furst
05-30-2007, 04:48 PM
I owe (at least a little) credit to you C-Dawg. I saw your attempted wall hugger script and got inspiration. I also stole your is_walkable function; hope you don't mind. ;)


Wouldn't this script be cool to use in sideview, with jumping?

C-Dawg
05-30-2007, 04:59 PM
Yep. I've already been using spark enemies, but so far they've been hard-coded using FFC changers. This will make them easier to apply to strangely shaped surfaces.

Oh, and no credit to me for the is_walkable function. That came from... whatshisface... the fellow with Sonic the Hedgehog holding a gun as his avatar...

Pheonix
06-02-2007, 10:14 AM
Problem: when I try to import the script, it says (this is directly from the error box) "Unable to parse instruction 1 from script wallflower.t The error was: invalid intstruction. The command was (script)(wallflower,()"
Can someone help me?

Dan Furst
06-02-2007, 04:13 PM
First, the file should have a .z extension.

You went to Tools -> Scripts -> Import ASM FFC Script, right? You don't want to do that. This is not ZASM, it's a ZScript. You want Tools -> Scripts -> Compile ZScript. Then import wallflower.z, compile it, and put it in a script slot.

Then make a ffc on the screen you want it on, and pass in the parameters with D0-4.

Pheonix
06-02-2007, 05:19 PM
I see the problem. Thanks.

Hot Water Music
06-04-2007, 03:12 AM
Like those bubbles in Link's Awakening that move along the wall.
You should make it so if you hit it with a boomarange, it spawns a fairy.

C-Dawg
06-04-2007, 09:53 AM
And you can, Hot Water Music. Thanks for volunteering.

1. Set up a custom "fire" enemy with no attacks, invisible, vulnerable only to the boomerang.
2. Add the enemy_ghosting script to this script, or make a second FFC that runs that script.
3. Add a bit to the script that spawns a fairy and moves the FFC to -16,-16 when the invisible fire enemy loses hit points.
4. Profit.