PDA

View Full Version : Magic Drain



Mega Link
12-23-2007, 03:48 PM
I'm trying to make a script that will slowly drain Link's magic (as seen in Phantom Hourglass).

Here is the script:


// My First Script
// +----------------+
// Magic Drain

import "std.zh"
ffc script magicdrain {
void run()
{

if(Link->magic += 1) //If Link has magic,
{Link->magic = -1} //Slowly drain it.

else Link->HP = -1; //If not, slowly drain his Hearts.

}
}

What is the correct variable for Link's magic?

Joe123
12-23-2007, 04:12 PM
Nono, you have the check for whether Link has magic or not wrong.
What it says inside your if clause, where you can only run checks and not set things, is 'check the integer, Link->magic (which you haven't declared, Link->magic is not a zscript command, you want 'Link->MP'), and add 1 to it'.
So what you want to do is use a greater than sign, to check the field of it rather than trying to set it, more like:

if(Link->MP > 1)

Your command for removing magic from Link won't work properly either, what you told it to do is 'set Link's magic to -1', not 'check Link's magic, then remove one from it', you need to put:

Link->MP -= 1
Where the '-=' command checks Link's MP, then removes the value after it from what his MP is.

All functions have to end in a semi colon, so:

{Link->MP -= 1;}

The script also doesn't loop, and is missing the last left brace.
Oh no you didn't it's just outside the code box =P


Let's have a look at how to make it work:

// Mega Link's First Script ;)
// +----------------+
// Magic Drain

import "std.zh"

ffc script magicdrain{
void run(int speed){
int framedelay; //I have declared two integers here that we're going to use later, to make the script not occur every single frame; otherwise Link would die at an alarming rate.
if(speed == 0){speed = 15;} //this line checks whether the integer 'speed', which is 'DO' in the ffc's arguments is == 0. if it is, then it sets it to 15.

while(true){ //this clause is a loop, causing the script to continue checking, rather than just once.
framedelay ++; //this line increases framedelay by one each frame. We do this so that the script doesn't remove Link's MP so fast.

if(framedelay == speed){ //if the integer 'framedelay' is equal to the value that you give to 'speed' in D0, continue with the script. If you leave speed as 0, this will happen every quarter of a second.
if(Link->MP > 0){ //if Link's MP is greater than 0
Link->MP -=8; //remove 8 MP from Link (8 MP is half a block I think, 1 isn't very much)

}else{ //so, if Link's MP is equal to 0
Link->HP -=8; //remove half a heart from Link (once again, one heart is 16 HP)
}

framedelay = 0; //this resets the framedelay counter
}
Waitframe(); //we need this, otherwise the script will continually loop and freeze the system. Also helps with how long you want to wait for things to happen
}
}
}

Russ
12-23-2007, 04:13 PM
Link->MP is the correct way to acess Link's magic power. So it looks like you are trying to create a level like PH Temple of the Ocean King. Good luck with that.

Edit: Never mind. Joe beat me to answering. Again.

Joe123
12-23-2007, 04:14 PM
Betcha to it!

Again! =P

Russ
12-23-2007, 04:15 PM
Why is it you always beat me to answering people's questions? It's not fair!

Mega Link
12-23-2007, 04:40 PM
I works!

Thanks Joe123 I added you to the credit list:

// My First Script
// Magic Drain
//
// Made Possible by Joe123
//
import "std.zh"

ffc script magicdrain{
...

Now for the safe zone:

int magic=Link->MP //sets variable magic to Link->MP
if (Link->stands on flag 96) //If Link is standing on a "No Enemies" flag,
{magic=magic} //leave his magic alone.

Edit: This safe zone script is going to be added on to the Magic Drain script.

Joe123
12-23-2007, 05:32 PM
Why is it you always beat me to answering people's questions? It's not fair!

Sorry ^_^



Well, why do you want to set Link's MP to a variable?
So that you can have the script run, then add a clause that says to undo what you just told it to do?

Wouldn't it be better to just tell the script not to up the frame delay whilst Link is on said flag?

It's also not as easy as that to check where Link is, and what flags are at that position.
You have to say 'check for the combo at Link's X position and Link's Y position to see whether that flag is placed on it'.

Something like:

Screen->ComboF[ComboAt(Link->X+8,Link->Y+8)] != 98
I'll run through that a bit better:
Firstly, the command is 'int ComboF[i];'.
This means that ZC checks for what flag is at the position 'i', and then sends it back through the integer.

This is a 'Screen' Variable, so it has to have the 'Screen->' pointer before it.

Now, checking for the flag at 'i', where ZC counts along each row of pixels, then when it gets to the end, starts again at the next row, isn't all too helpful.
This is where 'ComboAt(x,y)' comes into play.
It's a utility routine from std.zh, which allows you to convert a single number pixel reference into geometric coordinates.

Then, within ComboAt, we have 'Link->X' and 'Link->Y'. 'X' and 'Y' are (reasonably obvious) generic integers, and with the 'Link->' pointer, we tell ZC that we're referencing Link's coordinates.

I've added 8 onto both of them, because passing '(Link->X, Link->Y)' through a parameter brings up the coordinates of his top-left pixel, and that's not where he 'is' to you, so by adding on those 8 pixels, we make it reference the centre of Link instead.

'!=' means 'is not equal to', so this just makes sure Link is not standing on a safe zone.

And finally, why make it 96?
We have script specific flags nowadays, might as well use'em y'know?
I've put it to 98.
Unless you wanted it to be 96 for some specific reason? :confused:



Anyway, enough of that; let's put it into the script.

import "std.zh" // I've put this on the first line, just to emphasize that it's not attributed just to your script. It's generic, and only needs to be (well, only can be) in the script file once. Put all your scripts in the same file, otherwise your impending doom awaits.

// My First Script
// Magic Drain
//
// Made Possible by Joe123
//


ffc script magicdrain{
void run(int speed){
int framedelay; //I have declared two integers here that we're going to use later, to make the script not occur every single frame; otherwise Link would die at an alarming rate.
if(speed == 0){speed = 15;} //this line checks whether the integer 'speed', which is 'DO' in the ffc's arguments is == 0. if it is, then it sets it to 15.

while(true){ //this clause is a loop, causing the script to continue checking, rather than just once.

if(Screen->ComboF[ComboAt(Link->X+8, Link->Y+8)] != 98){ // so here we check that Link is not on a safe zone
framedelay ++; //this line increases framedelay by one each frame. We do this so that the script doesn't remove Link's MP so fast.
}
//what this first 'if' clause does then, is make sure Link is not on a safe zone before adding one to the framedelay counter. If he is on a safezone, the counter will not increase, and therefore the script's effects will not be applied.

if(framedelay == speed){ //if the integer 'framedelay' is equal to the value that you give to 'speed' in D0, continue with the script. If you leave speed as 0, this will happen every quarter of a second.
if(Link->MP > 0){ //if Link's MP is greater than 0
Link->MP -=8; //remove 8 MP from Link (8 MP is half a block I think, 1 isn't very much)

}else{ //so, if Link's MP is equal to 0
Link->HP -=8; //remove half a heart from Link (once again, one heart is 16 HP)
}

framedelay = 0; //this resets the framedelay counter
}
Waitframe(); //we need this, otherwise the script will continually loop and freeze the system. Also helps with how long you want to wait for things to happen
}
}
}

EDIT: Oh yeah, and if you ever need to know anything like how to access Link's HP or whatever, you need to check 'zscript.txt'.
It has all of the information you need, and saves you from making things up :)

Just on a side note to that, all of the functions are in sections. The header for the section is the pointer needed to access the array, ie.
'PlaySound(i);' is in the 'Game' section, therefore you use it via 'Game->PlaySound(i);'
That had me confused for months. Well, possibly a month. I haven't been at this too many months come to think of it.
Anyway.

EDIT2: Oh no, I had a semicolon instead of an L brace in there somewhere.
I've changed it, better copy it over again.
Apologies.


I'm getting quite good at posting novels here :eek:

Mega Link
12-23-2007, 05:57 PM
Thanks.. again!

And finally, why make it 96?
We have script specific flags nowadays, might as well use'em y'know?
I've put it to 98.
Unless you wanted it to be 96 for some specific reason? :confused:
Safe Zones are areas where enemies can't enter, and Link's magic won't decrease.

Last part of the script: Clock

What I want is the script to display how much time is left, to the right of the FFC which is at coordinates: (0,0).

Is all that possible? :confused:

Joe123
12-23-2007, 06:04 PM
Oh sorry yeah, didn't think of that =P


import "std.zh" // I've put this on the first line, just to emphasize that it's not attributed just to your script. It's generic, and only needs to be (well, only can be) in the script file once. Put all your scripts in the same file, otherwise your impending doom awaits.

// My First Script
// Magic Drain
//
// Made Possible by Joe123
//


ffc script magicdrain{
void run(int speed){
int framedelay; //I have declared two integers here that we're going to use later, to make the script not occur every single frame; otherwise Link would die at an alarming rate.
if(speed == 0){speed = 15;} //this line checks whether the integer 'speed', which is 'DO' in the ffc's arguments is == 0. if it is, then it sets it to 15.

while(true){ //this clause is a loop, causing the script to continue checking, rather than just once.

if(Screen->ComboF[ComboAt(Link->X+8, Link->Y+8)] != 96){ // so here we check that Link is not on a safe zone
framedelay ++; //this line increases framedelay by one each frame. We do this so that the script doesn't remove Link's MP so fast.
}else{framedelay = 0;}// just added this line to reset the counter if Link is on a safe zone
//what this first 'if' clause does then, is make sure Link is not on a safe zone before adding one to the framedelay counter. If he is on a safezone, the counter will not increase, and therefore the script's effects will not be applied.

if(framedelay == speed){ //if the integer 'framedelay' is equal to the value that you give to 'speed' in D0, continue with the script. If you leave speed as 0, this will happen every quarter of a second.
if(Link->MP > 0){ //if Link's MP is greater than 0
Link->MP -=8; //remove 8 MP from Link (8 MP is half a block I think, 1 isn't very much)

}else{ //so, if Link's MP is equal to 0
Link->HP -=8; //remove half a heart from Link (once again, one heart is 16 HP)
}

framedelay = 0; //this resets the framedelay counter
}
Waitframe(); //we need this, otherwise the script will continually loop and freeze the system. Also helps with how long you want to wait for things to happen
}
}
}

Well, I changed that (which undoubtedly you could've done yourself, don't worry I'm not trying to insult your intellegence =P) but I also added a line to reset the framedelay counter if Link is on a safezone, otherwise you might get situations where Link goes onto a safezone, then comes out and gets damaged straight away.


Last part of the script: Clock

What I want is the script to display how much time is left, to the right of the FFC which is at coordinates: (0,0).

Is all that possible? :confused:
Well, what are you counting on the timer?
Are you actually just converting the magic bar into the sand of hours?
So you want to check how much MP Link has left, and convert that to a counter that references a time he can last outside of a safezone without taking damage, correct?

That is... possible?
But perhaps not easy.
I might have a look at it later if it's what you want.
(http://www.purezc.com/index.php?page=tiles&id=145)

Oh, and did you catch the edits on my last post?
Just making sure.

Mega Link
12-23-2007, 06:20 PM
Well, I changed that (which undoubtedly you could've done yourself, don't worry I'm not trying to insult your intellegence =P) but I also added a line to reset the framedelay counter if Link is on a safezone, otherwise you might get situations where Link goes onto a safezone, then comes out and gets damaged straight away.Actually, I did. (It is just a matter of changing 98 to 96... right? Or is there more to it?


Well, what are you counting on the timer?
Are you actually just converting the magic bar into the sand of hours?
So you want to check how much MP Link has left, and convert that to a counter that references a time he can last outside of a safezone without taking damage, correct?

That is... possible?
But perhaps not easy.
I might have a look at it later if it's what you want.
(http://www.purezc.com/index.php?page=tiles&id=145)You don't have to use magic for sand of hours if you don't want to.

I just want a timer that will restart when Link exits the dmap and comes back.

The reason why choose to use magic is so Link can get more "Sand of Hours" without having the full thing be a script.

...

This is much harder than I thought it would be.

Joe123
12-23-2007, 06:28 PM
Actually, I did. (It is just a matter of changing 98 to 96... right? Or is there more to it?
Nope, that'll do it.


You don't have to use magic for sand of hours if you don't want to.

I just want a timer that will restart when Link exits the dmap and comes back.

The reason why choose to use magic is so Link can get more "Sand of Hours" without having the full thing be a script.

...

This is much harder than I thought it would be.

Well, it's not what I want to do, it's what you want to do =P
Are you planning on doing a complete conversion, and not using the magic bar, or keeping the magic bar and just having it double up for that function?

Mega Link
12-23-2007, 06:38 PM
Both. Where this script is used, you won't see the magic bar.

Joe123
12-23-2007, 06:43 PM
Ohhhh!
DMap specific Passive Subscreens!

>_<

How did I miss that.

Anyway.
So you need a script that set's Link's MP to full in the entrance room, and preferably one that sets it back to what it was when he leaves, plus that timer script.

Right then, about that timer.
I need to know the exact amounts that you're going to be using for various things.
So I need to know the value you have for 'speed', as in, does the script occur ever 15 frames, like I set to be default, or have you changed that?
How much MP are you removing from Link with the script? Is that still 8?

What is the max MP you're going to give Link in the game?
A full 8 blocks?
So 256 magic?
(32 is one block, not 16, I got that bit wrong)

How often do you want the timer to be updated?
Once a frame, once a second?

What's the maximum time limit you'll be able to have?
Can you tell me exactly what tiles you're going to be using?

EDIT: Are you going to disable magic using items in the dungeon or something?
You do realise it'll take time off the timer if you use magic items whilst in the dungeon, correct?

Mega Link
12-23-2007, 07:12 PM
So I need to know the value you have for 'speed', as in, does the script occur ever 15 frames, like I set to be default, or have you changed that?
How much MP are you removing from Link with the script? Is that still 8?No, it is 2.

What is the max MP you're going to give Link in the game?
A full 8 blocks?
So 256 magic?
(32 is one block, not 16, I got that bit wrong)He starts with 64 magic (10:00), and gets 12.8 magic (2:00) every time he defeats a boss.

Are you going to disable magic using items in the dungeon or something?No.

You do realise it'll take time off the timer if you use magic items whilst in the dungeon, correct?Yes.