PDA

View Full Version : Lttp style 'pickup rock' script



ShadowMancer
08-09-2007, 05:18 PM
Now you can pickup rocks (or any other object of your choice) and use them as weapons just like in Lttp.
it requires some settup to use.
I choose combo page 25 to use for 'liftable objects' you can change that if you want, but to use this script as is, just setup the first 120 combos on page 25 as follows:

combo 6400 - 6419 - Light objects
combo 6420 - 6439 - Held Light objects
combo 6440 - 6459 - Heavy objects
combo 6460 - 6479 - Held Heavy objects
combo 6480 - 6499 - Very Heavy objects
combo 6500 - 6519 - Held Very Heavy objects

Arguments:
D0: the combo ID of the under combo you want to use after a rock is lifted
D1: the damage of Light objects
D2: the damage of Heavy objects
D3: the damage of Very Heavy objects

Just put this script in a FFC in each room you have something liftable.

This script is setup to use the R button for lifting and throwing objects

The only thing missing is to change Link's graphics to actually look like he is holding the object, I am thinking of giveing Link an invisible Item that does nothing execpt use the Link tile modifier to switch his graphics while holding the rock, and take the Item away once he has thrown it. Hopefully someone will make some graphics for this (as I am not useing Link as my main character I am working on other graphics)

Enjoy, and please report any bugs! :)



ffc script liftRock{
void run(int under, int dam_1, int dam_2, int dam_3) {
int xx = 0;
int yy = 0;
int this_dam = 0;
bool is_hit = false;
bool is_hold = false;
while (true) {
is_hit = false;
if (Link->Dir == 0) {
xx = Link->X;
yy = Link->Y-8;
}
if (Link->Dir == 1) {
xx = Link->X;
yy = Link->Y+16;
}
if (Link->Dir == 2) {
xx = Link->X-16;
yy = Link->Y;
}
if (Link->Dir == 3) {
xx = Link->X+16;
yy = Link->Y;
}
if (Link->InputR && can_lift(xx,yy) > 0 && is_hold == false)
{
//Main Action Loop
if (can_lift(xx,yy) == 1) {this_dam = dam_1;}
if (can_lift(xx,yy) == 2) {this_dam = dam_2;}
if (can_lift(xx,yy) == 3) {this_dam = dam_3;)
//assumes the shape of the rock
this->Data = Screen->ComboD[ComboAt(xx,yy)] + 20;
this->CSet = Screen->ComboC[ComboAt(xx,yy)];
//Changes Rock to undercombo
Screen->ComboD[ComboAt(xx,yy)] = under;
//moves ffc to position of rock
this->X = xx;
this->Y = yy;
//Sets flag to tell Link is holding rock
is_hold = true;

while(Link->InputR) { Waitframe(); }
}


if (is_hold == true)
{
//moves rock to above Link's head
this->X = Link->X;
this->Y = Link->Y-12;
}

if (Link->InputR && is_hold == true)
{
//Throwing routine
is_hold = false;
if (Link->Dir == 0)
{
while (is_hit == false)
{
this->Y-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 1)
{
while (is_hit == false)
{
this->Y+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 2)
{
while (is_hit == false)
{
this->X-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 3)
{
while (is_hit == false)
{
this->X+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
}




//}
Waitframe();
}
}
}



int can_lift(int xn, int yn)
{
int result = 0;
if(xn<0 || xn>240 || yn<0 || yn>160)
{
return 0;
}

if (Link->Item[107] && Screen->ComboD[ComboAt(xn,yn)] >= 6400 && Screen->ComboD[ComboAt(xn,yn)] <= 6419) { result = 1;}
if (Link->Item[19] && Screen->ComboD[ComboAt(xn,yn)] >= 6440 && Screen->ComboD[ComboAt(xn,yn)] <= 6459) { result = 2 ;}
if (Link->Item[56] && Screen->ComboD[ComboAt(xn,yn)] >= 6480 && Screen->ComboD[ComboAt(xn,yn)] <= 6499) { result = 3;}

return result;
}

bool ene_damage(int damage,int xn, int yn) {
int ene_chk = 1;
bool result = false;
if (xn<0 || xn>240 || yn<0 || yn>160) {result = true;}
while (ene_chk <= Screen->NumNPCs()) {
npc trg_ene = Screen->LoadNPC(ene_chk);
if (trg_ene->X+8 >= xn-8 && trg_ene->X+8 <= xn+24 && trg_ene->Y+8 >= yn-8 && trg_ene->Y+8 <= yn+24) {
//Enemy is Hit
result = true;
int timer = 10;
trg_ene->HP -= damage;
while(timer > 0) {
//Flash CSet
int def_cset = trg_ene->CSet;
if (trg_ene->CSet == def_cset) {
trg_ene->CSet = 5;}
else {
trg_ene->CSet = def_cset;}
//Push enemy back
//0,1,2,3, - Up,Dn,Lt,Rt
if (trg_ene->Dir == 0) {
if (is_walkable(trg_ene->X,trg_ene->Y+4)) {trg_ene->Y+=4;}
}
if (trg_ene->Dir == 1) {
if (is_walkable(trg_ene->X,trg_ene->Y-4)) {trg_ene->Y-=4;}
}
if (trg_ene->Dir == 2) {
if (is_walkable(trg_ene->X+4,trg_ene->Y)) {trg_ene->X+=4;}
}
if (trg_ene->Dir == 3) {
if (is_walkable(trg_ene->X-4,trg_ene->Y)) {trg_ene->X-=4;}
}
timer -= 1;
}
}
ene_chk += 1;
Waitframe();

}
return result;
}

Din
08-10-2007, 10:30 AM
Cool. Thanks dude!

Beta Link
08-10-2007, 01:12 PM
Very interesting. Just make it change Link's tiles, and you've got a perfect LA Power Bracelet. ;)

Edit: I don't know much about scripting, but can't you change this into an item script and let that item change Link's tiles? That way, there's less setup involved. But whatever. Whatever'll work.

C-Dawg
08-10-2007, 03:15 PM
I am thinking of giveing Link an invisible Item that does nothing execpt use the Link tile modifier to switch his graphics while holding the rock, and take the Item away once he has thrown it. Hopefully someone will make some graphics for this (as I am not useing Link as my main character I am working on other graphics)


Thats the way to do it. In Zodiac, I used the Bait to change the player's graphics when they're clinging to a wall ala Ninja Gaiden. Because, fuck, who uses the Bait anyway? Useless item.

I'd use the z255 blank items, but despite my pleas, no one has fixed them so they can be reliably equipped or offered decent explaination on subscreen setup. So Bait it is.


You might also want to think about making this into an item script hybrid. The item would just set a global variable telling the FFC script that the player is using the appropriate item. That way, you save a button. You could even use the Glove. I dont think there's anything stopping you from using an item with a mere possession effect like the Glove pushing blocks also as a useable item, is there?

beefster09
08-11-2007, 12:26 AM
Nah! Use the Cane of Byrna! It's not even implemented anyway! :P

Good job though.

shadowfall1976
01-03-2008, 02:12 PM
I am getting a fatal error P00: can't open or parse input file

EDIT: it says now that LINE XXX (last line) has an unexpected $end on token

pkmnfrk
01-03-2008, 05:40 PM
You must be missing the ending }. Check to make sure you've copied that too. If it's not that, then it's up to Shadowmancer to help you...

lucas92
01-03-2008, 06:16 PM
It shows this to me when I try to import the script.

Unable to parse instruction 1 from script script_liftrock
the error was : invalid instruction
the command was (script)(liftrock{,)

Anyone have an idea?

pkmnfrk
01-03-2008, 06:23 PM
Ah. You're importing it wrong. This is a ZScript, not a ZASM script. You need to put it in a text file, like this:


import "std.zh"

//insert ShadowMancer's script here

Save it as "rock.z" (not rock.txt or anything, rock.z) in your Zelda Classic folder, and then, in ZQuest, go Tools->Scripts->Compile ZScript...

Then, click on Import. If it asks if you want to overwrite the buffer, click Yes. Now, choose rock.z, and click OK. Now, click on Compile, and see if that works.

lucas92
01-03-2008, 06:35 PM
Well, now it shows up:

Line 33: syntax error, unexpected RPAREN, on token )
Fatal error P00: can't open or parse input file

pkmnfrk
01-03-2008, 07:15 PM
I see a bug in his script. Find this line:


if (can_lift(xx,yy) == 3) {this_dam = dam_3;)

and replace it with this one:


if (can_lift(xx,yy) == 3) {this_dam = dam_3;}

(the brace at the end wasn't curly)

You need to re-import it to re-compile it.

lucas92
01-03-2008, 07:24 PM
Now it says:

line 117: syntax error, unexpected RBrace
expecting $ end, on token }

Is this script working or not?

pkmnfrk
01-03-2008, 09:04 PM
I don't know, I didn't write it, nor have I tried to use it.

I just tried to, though, and it's severely broken. It's missing a whole function! So, I'll say no.

Tips to ShadowMancer:

- Pick one style of indenting and braces, and use it.
- Try to compile your own scripts before posting them

shadowfall1976
01-03-2008, 09:19 PM
thanks for trying, I was hoping ShadowMancer would view this and fix it
I never expected anyone else to step in to try. I know nothing of code, so
I tried fixing a few things, but my problem is in the end and I have copied
all the code right down to the last } as well as added the "import std.zh",
and still get errors. I did all this first before posting, which is why I got stumped.

so hopefully Shadow will respond, as there is no other way to make contact
with him.

Joe123
01-03-2008, 09:21 PM
I haven't seen him around for ages :(

You could try PM'ing him, if he has the 'get email about PM' thing on, he might notice it.

Shame really, he used to help out a lot around here.

pkmnfrk
01-03-2008, 09:34 PM
In case anyone wants to pick it up in his absence, here's the script, as cleaned up by me:


import "std.zh"

ffc script liftRock{
void run(int under, int dam_1, int dam_2, int dam_3) {
int xx = 0;
int yy = 0;
int this_dam = 0;
bool is_hit = false;
bool is_hold = false;
while (true) {
is_hit = false;
if (Link->Dir == 0) {
xx = Link->X;
yy = Link->Y-8;
}
if (Link->Dir == 1) {
xx = Link->X;
yy = Link->Y+16;
}
if (Link->Dir == 2) {
xx = Link->X-16;
yy = Link->Y;
}
if (Link->Dir == 3) {
xx = Link->X+16;
yy = Link->Y;
}
if (Link->InputR && can_lift(xx,yy) > 0 && is_hold == false) {
//Main Action Loop
if (can_lift(xx,yy) == 1) {this_dam = dam_1;}
if (can_lift(xx,yy) == 2) {this_dam = dam_2;}
if (can_lift(xx,yy) == 3) {this_dam = dam_3;}
//assumes the shape of the rock
this->Data = Screen->ComboD[ComboAt(xx,yy)] + 20;
this->CSet = Screen->ComboC[ComboAt(xx,yy)];
//Changes Rock to undercombo
Screen->ComboD[ComboAt(xx,yy)] = under;
//moves ffc to position of rock
this->X = xx;
this->Y = yy;
//Sets flag to tell Link is holding rock
is_hold = true;

while(Link->InputR) { Waitframe(); }
}


if (is_hold == true) {
//moves rock to above Link's head
this->X = Link->X;
this->Y = Link->Y-12;
}

if (Link->InputR && is_hold == true) {
//Throwing routine
is_hold = false;
if (Link->Dir == 0) {
while (is_hit == false)
{
this->Y-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 1) {
while (is_hit == false) {
this->Y+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 2) {
while (is_hit == false) {
this->X-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 3) {
while (is_hit == false) {
this->X+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
}
Waitframe();
}
}
}



int can_lift(int xn, int yn) {
int result = 0;
if(xn<0 || xn>240 || yn<0 || yn>160){
return 0;
}

if (Link->Item[107] && Screen->ComboD[ComboAt(xn,yn)] >= 6400 && Screen->ComboD[ComboAt(xn,yn)] <= 6419) { result = 1;}
if (Link->Item[19] && Screen->ComboD[ComboAt(xn,yn)] >= 6440 && Screen->ComboD[ComboAt(xn,yn)] <= 6459) { result = 2 ;}
if (Link->Item[56] && Screen->ComboD[ComboAt(xn,yn)] >= 6480 && Screen->ComboD[ComboAt(xn,yn)] <= 6499) { result = 3;}

return result;
}

bool ene_damage(int damage,int xn, int yn) {
int ene_chk = 1;
bool result = false;
if (xn<0 || xn>240 || yn<0 || yn>160) result = true;
while (ene_chk <= Screen->NumNPCs()) {
npc trg_ene = Screen->LoadNPC(ene_chk);
if (trg_ene->X+8 >= xn-8 && trg_ene->X+8 <= xn+24 && trg_ene->Y+8 >= yn-8 && trg_ene->Y+8 <= yn+24) {
//Enemy is Hit
result = true;
int timer = 10;
trg_ene->HP -= damage;
while(timer > 0) {
//Flash CSet
int def_cset = trg_ene->CSet;
if (trg_ene->CSet == def_cset) {
trg_ene->CSet = 5;}
else {
trg_ene->CSet = def_cset;}
//Push enemy back
//0,1,2,3, - Up,Dn,Lt,Rt
if (trg_ene->Dir == 0) {
if (is_walkable(trg_ene->X,trg_ene->Y+4)) trg_ene->Y+=4;
}
if (trg_ene->Dir == 1) {
if (is_walkable(trg_ene->X,trg_ene->Y-4)) trg_ene->Y-=4;
}
if (trg_ene->Dir == 2) {
if (is_walkable(trg_ene->X+4,trg_ene->Y)) trg_ene->X+=4;
}
if (trg_ene->Dir == 3) {
if (is_walkable(trg_ene->X-4,trg_ene->Y)) trg_ene->X-=4;
}
timer -= 1;
}
}
ene_chk += 1;
Waitframe();

}
return result;
}

lucas92
01-03-2008, 09:56 PM
It gives me this:

pass 1 : parsing
pass 2 : preprocessing
pass 3 : building symbol tables
TMP , line140 : error S10 : Function is_walkable is undeclared
TMP , line143 : error S10 : Function is_walkable is undeclared
TMP , line146 : error S10 : Function is_walkable is undeclared
TMP , line149 : error S10 : Function is_walkable is undeclared

pkmnfrk
01-03-2008, 10:26 PM
Right, as I previously discussed, the script is broken. If I knew exactly what "is_walkable" does, then I could probably fix it. For all I know, it could add health to Link, since it can be named anything >_>

Yes, yes, I know that it probable checks to see if that spot is solid or not. Fine, here you go. I added "is_walkable", based on the "isSolid" function found in my Ladder script (http://zctut.com/ladder.php):


import "std.zh"

ffc script liftRock{
void run(int under, int dam_1, int dam_2, int dam_3) {
int xx = 0;
int yy = 0;
int this_dam = 0;
bool is_hit = false;
bool is_hold = false;
while (true) {
is_hit = false;
if (Link->Dir == 0) {
xx = Link->X;
yy = Link->Y-8;
}
if (Link->Dir == 1) {
xx = Link->X;
yy = Link->Y+16;
}
if (Link->Dir == 2) {
xx = Link->X-16;
yy = Link->Y;
}
if (Link->Dir == 3) {
xx = Link->X+16;
yy = Link->Y;
}
if (Link->InputR && can_lift(xx,yy) > 0 && is_hold == false) {
//Main Action Loop
if (can_lift(xx,yy) == 1) {this_dam = dam_1;}
if (can_lift(xx,yy) == 2) {this_dam = dam_2;}
if (can_lift(xx,yy) == 3) {this_dam = dam_3;}
//assumes the shape of the rock
this->Data = Screen->ComboD[ComboAt(xx,yy)] + 20;
this->CSet = Screen->ComboC[ComboAt(xx,yy)];
//Changes Rock to undercombo
Screen->ComboD[ComboAt(xx,yy)] = under;
//moves ffc to position of rock
this->X = xx;
this->Y = yy;
//Sets flag to tell Link is holding rock
is_hold = true;

while(Link->InputR) { Waitframe(); }
}


if (is_hold == true) {
//moves rock to above Link's head
this->X = Link->X;
this->Y = Link->Y-12;
}

if (Link->InputR && is_hold == true) {
//Throwing routine
is_hold = false;
if (Link->Dir == 0) {
while (is_hit == false)
{
this->Y-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 1) {
while (is_hit == false) {
this->Y+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 2) {
while (is_hit == false) {
this->X-=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
if (Link->Dir == 3) {
while (is_hit == false) {
this->X+=12;
if (ene_damage(this_dam,this->X,this->Y) == true) { is_hit = true; }
Waitframe();
}
this->Data = 0;
this->X = 0;
this->Y = 0;
}
}
Waitframe();
}
}

int can_lift(int xn, int yn) {
int result = 0;
if(xn<0 || xn>240 || yn<0 || yn>160){
return 0;
}

if (Link->Item[107] && Screen->ComboD[ComboAt(xn,yn)] >= 6400 && Screen->ComboD[ComboAt(xn,yn)] <= 6419) { result = 1;}
if (Link->Item[19] && Screen->ComboD[ComboAt(xn,yn)] >= 6440 && Screen->ComboD[ComboAt(xn,yn)] <= 6459) { result = 2 ;}
if (Link->Item[56] && Screen->ComboD[ComboAt(xn,yn)] >= 6480 && Screen->ComboD[ComboAt(xn,yn)] <= 6499) { result = 3;}

return result;
}

bool ene_damage(int damage,int xn, int yn) {
int ene_chk = 1;
bool result = false;
if (xn<0 || xn>240 || yn<0 || yn>160) result = true;
while (ene_chk <= Screen->NumNPCs()) {
npc trg_ene = Screen->LoadNPC(ene_chk);
if (trg_ene->X+8 >= xn-8 && trg_ene->X+8 <= xn+24 && trg_ene->Y+8 >= yn-8 && trg_ene->Y+8 <= yn+24) {
//Enemy is Hit
result = true;
int timer = 10;
trg_ene->HP -= damage;
while(timer > 0) {
//Flash CSet
int def_cset = trg_ene->CSet;
if (trg_ene->CSet == def_cset) {
trg_ene->CSet = 5;}
else {
trg_ene->CSet = def_cset;}
//Push enemy back
//0,1,2,3, - Up,Dn,Lt,Rt
if (trg_ene->Dir == 0) {
if (is_walkable(trg_ene->X,trg_ene->Y+4)) trg_ene->Y+=4;
}
if (trg_ene->Dir == 1) {
if (is_walkable(trg_ene->X,trg_ene->Y-4)) trg_ene->Y-=4;
}
if (trg_ene->Dir == 2) {
if (is_walkable(trg_ene->X+4,trg_ene->Y)) trg_ene->X+=4;
}
if (trg_ene->Dir == 3) {
if (is_walkable(trg_ene->X-4,trg_ene->Y)) trg_ene->X-=4;
}
timer -= 1;
}
}
ene_chk += 1;
Waitframe();

}
return result;
}

bool is_walkable(int x, int y) {

if(x<0 || x>255 || y<0 || y>175) return false;

int mask=1111b;

if(x &#37; 16 < 8)
mask &= 0011b;
else
mask &= 1100b;

if(y % 16 < 8)
mask &= 0101b;
else
mask &= 1010b;

int ret = Screen->ComboS[ComboAt(x, y)] & mask;

return (ret==0);
}
}

lucas92
01-03-2008, 10:33 PM
Yup, it works. Nice work! :)

Can't wait to try it. :)

pkmnfrk
01-03-2008, 10:39 PM
I must point out that I have not actually tried it, and have no idea if it actually does what i promises, etc etc. No refunds, as is, caveat scriptor, etc.

lucas92
01-03-2008, 11:17 PM
Nah, not working... :(

It just does nothing...

pkmnfrk
01-03-2008, 11:25 PM
That, I am afraid, I can do nothing about. Sorry.

shadowfall1976
01-04-2008, 01:42 AM
good show pkmnfrk, but I can understand from your POV, you know not what
was in his head. no it doesn't work but I have just tried another code from him
and get the same errors, me not know why, but whatever....
maybe he'll respond to the inquiries.