PDA

View Full Version : Placement of Waitframes in this script...



ShadowTiger
12-02-2006, 07:47 PM
I had the concept of an invulnerability script a few minutes ago. It would check for your health when you enter the screen, set it to a variable, then constantly set your health to that variable every two to four frames. (Has to be quick, but shouldn't overdo it.) So the script would go something like this, right?


ffc script invulnerability_script_001;

{ // <-- 1

void run(); // <-- No idea what this does; it's simply a tradition to me.

{ // <-- 2

float D[1] = int HP; // <-- "float D[1] is the right syntax, right? Otherwise, the line sets the value of the variable D[1] to whatever Link's HP is at the moment. It then goes into a while loop in a bit and won't leave.

float D[2] = 1; // <-- Setting a switch. Purely for paranoia reasons.

while(D[2] = 1); // <-- The while statement; while D[2] (still) equals 1. .. Hopefully it still will.

{ // <-- 3

int HP = D[1]; // <-- Sets the value of Link's HP to the value of D[1].

Waitframe(); // <-- The infamous Waitframe.

} // <-- 3

} // <-- 2

} // <-- 1

This is pretty much the first ZScript I've ever written. I'm more than willing to bet that it's rife with technical inaccuracies and other horrific oversights.

So do I need another Waitframe() outside of the while loop? Thanks for your comments. :)

Saffith
12-02-2006, 09:23 PM
I've tried something similar myself, and I'm sorry to say it doesn't quite work. If Link's health hits 0, he dies instantly, and no script can save him. As long as he has some life left, though, it'll work fine.



ffc script invulnerability_script_001;
...
void run();
...
while(D[2] = 1);Those semicolons shouldn't be there. Anything that's followed by curly braces shouldn't have a semicolon.

The worst part is that that isn't always invalid. Putting a semicolon after a while statement is perfectly acceptable, but it's equivalent to while(...) { }. In other words, if the condition is true, it'll do nothing forever, causing the game to hang.



void run(); // <-- No idea what this does; it's simply a tradition to me.The statement void run() marks the beginning of the run() function (if you don't know how to interpret function headers, I'll be glad to explain). When a scripted FFC appears, the game automatically calls this function. So, in effect, this simply tells the game where to start running the script. It's comparable to main() in C.



float D[1] = int HP; // <-- "float D[1] is the right syntax, right? Otherwise, the line sets the value of the variable D[1] to whatever Link's HP is at the moment. It then goes into a while loop in a bit and won't leave.

float D[2] = 1; // <-- Setting a switch. Purely for paranoia reasons.Hm... Okay, lemme go over variables and pointers real fast...

A variable, as I think you know, is basically a place to store data. There are three types of variables in ZScript: ints/floats (numbers - never mind why there are two names for the moment), bools (true or false), and void (nothing - again, never mind that for now).

There are also several pointer types; a pointer is similar to a variable, in that they're both places to store data. Pointer types include link, screen, game, ffc, and others. In many cases, there's just one pointer of each type; for example, the only link pointer is Link, and the only game pointer is Game.

The difference between a pointer and a variable is that pointers indicate complex data types that have their own personal sets of data, called data members. These are accessed using the arrow operator; for example, Link's HP is accessed via Link->HP. Similarly, screen variables are accessed using Screen->D[x].

With few exceptions (screen and global variables are the only ones, I think), changing the value of a pointer's data member directly affects the game in some way, while changing a regular variable's value does not.

Now, you also have to know about declaring variables. The built-in pointers, like Link, this, Screen, and so forth don't have to be declared, and neither do their data members. Any other pointers or variables must be declared before they're used, and must only be declared once. Variables and pointers are declared by preceding their names by their types, like so:

int x; // Declare a variable named x of type int
x = 5; // Set x's value to 5
int y = x; // Declare a variable named y of type int and set its value to x's value
int y; // Error: y was already declared.
So... Where were we?


float D[1] = int HP; // <-- "float D[1] is the right syntax, right? Otherwise, the line sets the value of the variable D[1] to whatever Link's HP is at the moment. It then goes into a while loop in a bit and won't leave.

float D[2] = 1; // <-- Setting a switch. Purely for paranoia reasons.Ah, right. Well, it appears you mean to store Link's HP into D[1]. D[1] and Link's HP are data members of Screen and Link, respectively, so the necessary code is this:

Screen->D[1] = Link->HP;
You could also avoid the screen variables altogether and simply declare your own variable:

int storedHP = Link->HP;
That's safer if you're using this along with other scripts, since the others might change D[1] themselves.
One thing to mention about that, though: in previous betas, that variable might not have been local, as it should be. I think it's been fixed, but watch for problems if you change it.

As for the 1 in D[2], you don't need that, for reasons I'll get to shortly.

By the way, the variables are numbered 0-7, not 1-8, so the first of the screen variables is Screen->D[0].



while(D[2] = 1);The semicolon I already covered.
Also important is the equals sign. You need one equals sign for assignment and two for comparison. That is, you should write Screen->D[2] == 1 for this comparison.
However, you don't need to do this at all. The simplest expression that'll always evaluate to true:

while(true)



int HP = D[1]; // <-- Sets the value of Link's HP to the value of D[1].

Waitframe(); // <-- The infamous Waitframe.Not much to say here; already went over variables, and the Waitframe() is there. Basically, this just needs to be:

Link->HP=Screen->D[1];
Waitframe();



So, in short, the completely rewritten version of this script (minus comments):

ffc script invulnerability_script_001
{
void run()
{
Screen->D[0] = Link->HP;

while(true)
{
Link->HP = Screen->D[0];
Waitframe();
}
}
}
And the alternate version, avoiding the screen variable:

ffc script invulnerability_script_001
{
void run()
{
int storedHP = Link->HP;

while(true)
{
Link->HP = storedHP;
Waitframe();
}
}
}

ShadowTiger
12-02-2006, 11:09 PM
I've tried something similar myself, and I'm sorry to say it doesn't quite work. If Link's health hits 0, he dies instantly, and no script can save him. As long as he has some life left, though, it'll work fine.Frankly, you'd be hardpressed to find Link entering a room with zero health. :p It's sort of like "If your parents didn't have children, you more than likely won't have any either" sort of thing. If you've managed to enter a room with zero health, you'd be dead. I'm also hoping that the script will indeed trigger instantaneously as I enter the room, (As having told it to do so would dictate...) so hopefully he'll have enough health that the infrequencies of the checks won't leave big enough gaps to get his health lowered.

Thank you very, very much, Saffith. :) It's greatly appreciated. ;) :thumbsup: (As the overabundance of emoticons may imply. :p )

Okay. I've got the structure down pat; The concept of the -> looks fairly straightforward, and things seem to be falling into place. :) Thanks very much. ^^.

Saffith
12-02-2006, 11:29 PM
Frankly, you'd be hardpressed to find Link entering a room with zero health. :p It's sort of like "If your parents didn't have children, you more than likely won't have any either" sort of thing. If you've managed to enter a room with zero health, you'd be dead. I'm also hoping that the script will indeed trigger instantaneously as I enter the room, (As having told it to do so would dictate...) so hopefully he'll have enough health that the infrequencies of the checks won't leave big enough gaps to get his health lowered.I'm not referring to his life when he enters the room. Keep in mind, the script won't actually keep his HP fixed at its original amount; rather, it simply resets it every frame. If Link gets hit, his life will still be reduced for the fraction of a frame before the script is run again, and that's plenty of time for him to die.