Creation/Dev/Excalibur's scripting guide: Difference between revisions

From Graal Bible
No edit summary
No edit summary
 
(5 intermediate revisions by 4 users not shown)
Line 1: Line 1:
'''http://www.antiunixmad.com/
[[Category:Scripting Tutorials]]
== '''Excalibur's Scripting Guide''' ==
I'm hoping this allows people to learn how to script a bit easier, I believe all staff should know some scripting basics, and I find other GS2 guides hard to follow. This should help you get started out. I'm afraid it isn't complete and there are a few typos in it. I'm working on it.  


Viper's Graal Issues.
Starting:


Hello everyone, as of late, many people have been attacking me on the issues and matters, trying to lie about things, bend the truth, and downright spin to make me and others of my cause look bad, in this text document i will discuss and lay to rest the issues that matter.
Level NPCs:


I have been involved graal for over three years now, and i used to really like Graal and its admins alot, then slowly after about a year Graal and its admins went in a bad downward spiral, i still stuck with graal in hopes graal would pull itself out of this hole and unixmad would go back to the right path, this however did not happen, instead unixmad and even stefan went fouler and lower than i could have imageined, First with fireing Pachuka and Fuitad, two of the BEST graal admins ever in my view for no other reason than disagreeing with his future plans, then if just fireing them was not bad enough, he threatend to sue them and kill they're families, this was so wrong and bad Fuitad even said he would punch unixmad in the face for saying that if he met him in real life, but that was just the beginning of the downward spiral unixmad foolishly invoked onto graal, he then blatantly STOLE a domain name graal.net from Owl Shimy which costed over 30$ US Dollars, and never gave it back to him and never paid him for the cost of the domain, he also threatend to sue Owl Shimy and kill his family although it was Unixmad which stole the domain from Owl Shimy, then around Graal1.3.1 he blocked off Gservers officially and threatend to sue anyone that ran the former Gservers, although they were released as "Freeware" and actually used to encourage people to use the Gservers, this was a blatant attempt to monopolise , threaten, and intemidate that players that actually helped graal and supported him, he then made claims he copyrighted "Graal" and would contact so called "Lawres" about anyone that used the name "Graal" or had "Graal Files" on there websites, although graal was distributed as "Freeware" or "Shareware" and had no official software copyrights related to it, and that the name "Graal" was actually the name of a holy sacred golden cup used in some religion, and in that he has commited blasphemy against whatever religion has the so called "Holy Graal", then later on Unixmad fired SuperNick, because of his country and his origion and called him an American Asian slut, this was the first sign of racism on the part of Unixmad, towards Graal1.4.1 Unixmad was secretly unwrapping his sadistic plans, he then started claiming credit and claiming to own the copyrights to graal, although unixmad has done nothing but host some stupid weak as servers, and yet Stefan Knorr has done all the real work for Graal, and was the one to make ZeldaOnline , GraalOnline in the first place and has written every bit of codeing for the Graal Client , Gserver, RC, ect, yet unixmad the worthless pile of trash that he is steals all credit for Graal, then in February 2001, Unixmad and Antago release Graal2001 and the start of the "Pay to Play" system, now i have no problem with the fact that it is pay to play, the issue is when you PAY for something you actually expect to get the worth while of your money in this product, but instead they got a shittily made level generated land that was 99% empty, the NPCs were and are laggy as hell, and there were no quests, and there is only two shitty things today for hearts that suck so much i refuse to even call them quests, and to add to that about 40% of everyone that paid and gave unixmad there credit card number NEVER got the accounts they paid 27$ or more for, and those that did clearly got chumped out by a cheap peice of crap that aint worth paying for, it sucked so badly that most people played on Graal Classic still, even those that foolishly paid for pay to play accounts, and in an attempt to "FORCE" people to pay for a shitty product they do not want against they're will Unixmad hired "Tyhm" to deface and ruin GraalClassic in an attempt to make it buggier and less fun than even Graal2001, about this time i was disgusted with unixmad and most of the other admins and decided to downright turn against Graal and for the most part stop playing the peice of crap in general. People starting getting angry, complaining, asking for help, and asking for refunds, of coarse unixmad gave noone a cash refund, and simply deleted and banned "PAID ACCOUNTS" of those who complained, asked for help, or asked for a refund these are PAYING CUSTOMERS, they have the rights of basic service that they PAID for, unixmad promises pay to play players a quality product and customer service, but instead gives them a grade F product and ripps off his customers and delete they're accounts that they PAID HIM money for, his excuse? Credit card fraud, when infact at least 90% of the people he bans for credit card fraud pay legitamately with there OWN credit cards or pay via paypal by check, and yet Unixmad has stolen and used others credit card numbers to buy things for himself on several occassions, he also claims he needs pay to play money to keep graal alive and running, yet there has been evidence that he makes at least 90% profit out of the monies he gets, and that he uses illegal porn ad banners and illegal cookie style web tracking and giveing email adresses of the players and even phone numbers of every player to spam and telemarketting companies without there permission, he even keeps personal player info, includeing email, adress, and phone number on unsecure servers which have already been leaked out, such info about people should not be on a public webserver accessable to the internet in anyway, then after all that Unixmad starts banning african american people, asians, koreans, and or people with images of people of that race from the Graal2001 forums and graal itself, yet again they are paying customers and this is another sickening act of racism on the part of Unixmad and GraalOnline, and then even more disgusting is what Stefan posts on the Graal2001 forums, he makes several anti american, racist, pro terrorist, pro nazi, and pro taliban comments on that post and goes on and on several pages bashing americans, this post was offense, obcene, and disgusting to many people includeing myself . If all that does not make you sick to your stomache or dislike unixmad yet, i am far from done, then Unixmad proceeds to illegally DDOS webservers of mafukie and make threats to him over the phone, and has phone assaulted me over 40 times a day between midnight and 5am, and has made threats to sue dozens of people, kill there families, and shut down innocent websites and servers, while hosting illegal stuff and doing illegal things himself with the use of his own wanadoo.fr servers, stuff which includes child porn, bestiality porn, DVD Piracy, DDOS Attacks, theft of copyrighted materials from gameing companies such as nintendo, Credit Card fraud, theft, spamming, phone harrassment, useage of illegal pirated corperate softwares, all this just to start the list of what Unixmad, Stefan, and they're servers are doing 24/7 for nearly 4 years now , anyone that likes unixmad or thinks he is a good person even after all this is clearly a fool, everything in this document is the truth and why i hate unixmad so much, if you like unixmad after all these sickening things he does, then you are no better than a KKK or Neo Nazi member and should go kill yourselfs, i do not tolerate facists, racists, or nazis, they are all bad people, and unixmad is one of the worst of the worst, and no person with any morales could tolerate or support such a person like Stephane Portha or Stefan Knorr. The people that spin, lie and bend the truth in support of unixmad will always exist, but i will always reveal the truth about unixmad, and EVERYTHING said in this document is true, despite what any assclowns try and say about this, and this supriseingly enough is only 1% of the bad things Unixmad has done, how some people even tolerate, none the less support such a bad person is beyond me... I fight against bad people like unixmad, why? Because unlike many others in this world i actually care about other people, and i will do everything in my power to stop unixmad from hurting graal or its innocent players, many say i want to destroy and kill graal, this is NOT true, i used to love graal, i only wish to stop unixmad's evil sadistic illegal actions and restore graal to the great game it used to be when it was "for the players, by the players" , but if i have to destroy GraalOnline in exchange to stop unixmad's tyranny, it will be regreteable, but sometimes some sacrifices have to be made for the greater good, lets just hope that unixmad drops dead and that sacrifice never has to be made... I love graal and lots of its players, and i wish to someday restore it to the grandness it once had, but bad people like unixmad must be gotten rid of if that is to be achieved...'''
A level NPC is an npc that functions in a specific level. These are the most common on most servers. They are also a very important part of developement.
 
A script:
<pre>
//this is a note
/*
 
this is also a note, these help make scripts more clear
this type of note can go on as longe as it's inclosed
*/
//#CLIENTSIDE
//This tells the computer that the following
//script will be on the players client,
//as opposed to the server, this is very important.
function onPlayerTouchsMe()
//this checks if the player has touched the NPC
{ // starting bracket
  this.chat = "Hey!"; //displays a message above the NPC
}//closing bracket
</pre>
The above script checks to see if the event, playertouchsme is true, then acts on what is in the bracket. It is important to include this clientside, because too many serverside scripts can cause problems for an NPC server, however they are more secure. If you wanted to do the last script serverside, you would omit the //#CLIENTSIDE , and add the shape to the NPC:
<pre>
function onCreated()
{
  setshape(1,32,32);
  setimg("block.png");
//img can also be done in the box above the script
}
function onPlayertouchsme()
{
  this.chat = "You made a serverside script!";
}
</pre>
This takes a bit longer than clientside commands, and it takes up serverside script time, however, for secure actions, it may be necessary.
A secure script example:
<pre>
function onCreated()
{
  this.account="Excaliber7388";
  setshape(1,32,32);
  this.chat="Excaliber's Chest";
}
function onPlayertouchsme()
{
  if(player.account==this.account)
  {
    this.chat="This is a secure message!";
  }
}
</pre>
First, I would like to quickly point out the 'if' statement. Some guides go into this a lot, but it's actually quite simple. The if statement is a very important part of scripting. It's what allows the NPC to make choices. The code withing the brackets of an if statement will only execute if the statement is true. Also, there is a catchall statement you can use, else. If the if statement is not true, the else will exectue it's script, other wise it is ignored.
Example:
<pre>
//#CLIENTSIDE
function onCreated()
{
  this.a=1;
}
if(this.a==1)
//always use '==' for comparasons, NEVER just '=' as '=' is for assignments
{
  this.b=2;
}
else if(this.a==2) //will only execute if first is false, AND this.a==2
{
  this.b=3;
}
else //catch all if above 2 statements are false
{
  this.b=4;
}
</pre>
Now, in the above example, this.b will always be 2, however, it's the format that's important.
<pre>
if(statement)
else if(statement)
else if(statement //may be used many times
else //catch all
</pre>
Now, back to serverside and clientside scripts:
By putting the checks on serverside, you disable a hackers ability to send an action from their client. So, this script is much more secure, and can only be accessed by the specified account (Excaliber7388 in this case). Most playerworlds and classic servers do these checks serverside as well, but we also apply a different method, to avoid having too much serverside script time:
<pre>
function onCreated()
{
  this.account="Excaliber7388";
  setshape 1,32,32;
  this.chat="Excaliber's Chest";
}
function onActiontouched()
{
  if(player.account==this.account)
  {
    this.chat="Yup, this is still secure, yay!";
  }
}
//#CLIENTSIDE
function onPlayertouchsme()
{
  triggeraction(x,y,"Touched","Touched");//no params needed
}
</pre>
This script will take up more time, but the playertouchsme check is clientside. Would this help much? Probably not, in fact, sending the action in this case would probably create more lag than having the script serverside. However, if a large portion of the script is serverside, and can be moved to clientside without risking security, it may be a good idea.
Serverisde timeouts=bad idea.
You shouldn't send to many actions to serverside, especially if you do so quickly. You should always limit the serverside timeouts, and the amount of time between actions to the server from client should be spaced out. Also, you should never have a timeout shorter than .05 on serverside, though it is possible, please do not do it. Many playerworlds have expierenced problems from serverside timeouts which can lead to NPC server crashing or lagging.
 
Here are two examples of serverside scripts, the first is [b]VERY[/b] bad, the second is more productive:
<pre>
function onCreated()
{
  setshape 1,32,32;
}
function onActiontime()
{
  for(server.i=0;server.i<5;server.i++)
//WHY use server for this???
//for loops, use this. it works only for this NPC
  {
    sleep(.01);
//WAY to short of a sleep time for the server
  } 
    server.time+=.1;
}
//#CLIENTSIDE
function onCreated()
{
  settimer(.05); //minimum clientside timeout
}
function onTimeout()
{
  triggeraction(x,y,"time","time");
  settimer(.05);
//Will cause a loop through the timeout, sending action
//to serverside TOO quickly, AND while the server is
//still working on the last action. This WILL cause the  
//server to crash.
}
</pre>
If you put the above script on a server, say goodbye to your NPC server, because it will crach pretty quickly!
A better version:
<pre>function onCreated()
{
  setshape 1,32,32;
  //setshape is needed for all level NPCs triggeractions
  //this sets it to a square of tiles 32x32 pixels.
}
function onActiontime()
{
  server.time++;
  //no need for incredible accuracy
}
//#CLIENTSIDE
function onCreated()
{
  settimer(1);
}
function onTimeout()
{
  triggeraction(x,y,"time","time");
  settimer(1);
}
</pre>
This will execute the script less often, however, it still is an unlimited loop. Don't have too many of these NPCs, or you could have problems!
 
Now, you may have noticed this line in the bad script:
<pre>
  for(server.i=0;server.i<5;server.i++)
</pre>
This is a 'for' loop. There are many types of loops, however the for loop isn't the easiest to learn first. Therefore, I will show you the 'while loop' first.
The while loop executes whatever is held within it's brackets as long as the statement within it is true. The while loop is just like an if statement, but you cannot use else with a with statement.
format:
<pre>
while(statments)
{
  //commands
}
//if statment is still true, it will loop
</pre>
here's a script example:
<pre>
//#CLIENTSIDE
function onCreated()
{
  this.size=10;
}
while(this.size<=20) //while this.size is less than or equal to 20
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  //as the story is retold....
  sleep(.5);
  this.size=this.size+1;
  //increment the size
}
</pre>
The above script will run through the loop until this.size is equal or greater than 20.
Some important things to know:
<pre>
if(a==b) means if a is equal to b
if(a<b) means if a is less than b
if(a>b) means if a is greater than b
if(a<=b) means if a is less than or equal to be
if(a>=b) means if a is greater than or equal to be
a++      is the same as a=a+1
a--      is the same as a=a-1
a+=b    means a=a+b
a-=b    means a=a-b
a*=b    means a=a*b (multiplied by b)
a/=b    means a=a/b
++a    is just like a, but it will add to a before anything else in the line,  
        this is not important to know now
--a    just like ++a, but with subtraction
a%b    Modulus, basically, its a/b and th remainder is the output
        for example 10%3=1
</pre>
These may be helpfull in loops, or in any other rational expressions you may use. (Well, it's important for all scripting!)
Now, recall this line:
<pre>
  this.chat="The fish was " @this.size@ " centimeters long!";
</pre>
The output for this is: The fish was (size here) centimeters long!
The script NEEDS to know where a variable is, so if you want to put it in between a string you surround it with the '@' symbol. Or if it's at the end, you only put the '@' at the beggining of the variable. The variable and the '@' do NOT go in the quotes. Example:
<pre>
//#CLIENTSIDE
function onPlayertouchsme()
{
  this.chat="Well hi there, " @player.account@ " I like your sword, " @player.swordimg;
}
</pre>
This would display the player's account, and sword image.
 
Now, back to the 'for' loop.
This a very interesting loop it's format is as follows:
<pre>
for(command;expression;command)
{
}
</pre>
Here's an example:
<pre>
//#CLIENTSIDE
function onPlayertouchsme()
{
  for(this.i=0;this.i<10;this.i++)
  {
    this.chat="Loops: " @this.i;
    sleep(.5);
  }
}
</pre>
This loop would be activated when the player touchs it.
It would go through 10 loops, displaying the count, and taking .5 seconds for each loop (due to the sleep() command)
Now remember this while loop?
<pre>
function onCreated()
{
  this.size=10;
}
while(this.size<=20)
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  //as the story is retold....
  sleep(.5);
  this.size=this.size+1;
  //increment the size
}
</pre>
There's an easier way of doing it with a for loop, in fact all loops done with while can be replaced by for.
<pre>
for(this.size=10;this.size<=20;this.size++)
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  sleep(.5);
}
</pre>
See? Much shorter and easier to use!
Once you know the format of a for loop, you can make longer and more complex loops as well, and they'll take less time to script, which is always a bonus.
 
Some more detail on actions:
An action is an effective way to use a portion of script more than once, have one script act on another script, more script to serverside from clientside (and the other way) and more.
So how do you use them? Here's the format:
<pre>
triggeraction(x,y,"params[0]","params[1]");
</pre>
You must have two parameters, but you can have as many as you want a quick example:
<pre>
function onCreated()
{
  setshape 1,32,32;
}
function onActiontrigger()
{
  player.chat="Account: " @params[1]@ " Sword " @params[2]@ " head: " @params[3];
}
//#CLIENTSIDE
function onPlayerchats()
{
  if(player.chat=="Who am I?") //amnesia? multiple identities?
  {
    triggeraction(x,y,"trigger",player.account,player.swordimg,player.headimg);
  }
}
</pre>
See? You can make more than one parameter.
Now, there are a few differences between a level NPC with a triggeraction, and a weapon with a triggeraction. Weapons need their location (serverside or clientside) as the first parameter, params[0] is the one after it. Here, you can have just one parameter, and the x and y is always 0 (because the npc server is at 0,0), and you need to include the name of the weapon in the action.
here's an example:
<pre>
//weapon script with a triggeraction
//Weapon name: Fire Ball
function onActionserverside()
{
  if(params[0]=="mp")
  {
    playermp-=10
  }
}
//#CLIENTSIDE
function onWeaponfired()
{
  if(playermp>=10)
  {
    shootfireball(playerdir);
    triggeraction(0,0,"serverside","Fireball","mp");
  }
  else
  {
    player.chat="Not enough mp!";
  }
}
</pre>
This nifty little weapon will cost 10 mp per use, and fires a fireball in the direction the player is facing. Hopefully, you can learn to make many weapons of your own!
Triggeractions can be used in shops as well (and these are the scripts people ask for the most).
<pre>
//a shop script, yay!
function onCreated()
{
  setshape 1,32,32;
}
function onActionbuy()
{
  if(playerrupees>=100)
  {
    addweapon Fire Ball;
    playerrupees-=100;
  }
}
//#CLIENTSIDE
function onPlayerchats()
{
  if(player.chat=="buy fire ball")
  {
    triggeraction(x,y,"buy","buy");
    //the level npc triggeraction type
  }
}
</pre>
There, now you can make a little shop that sells a Fire Ball weapon. Have fun with it, search the commands, there's plenty of easy weapons you can make, and the weapon script is easy to follow and modify as well. Hopefully, you know enough about parameters to make more than one weapon for sale in the same NPC, just make the weapon name part of the action, then check for that parameter before they can buy.
Now there are other types of loops. One I commonly see is a timeout loop. You should understand why. Back with GS1, it was a bit easier to tell what was happening in the script. In GS1 the script for function onTimeout() would be displayed as if(timeout). It was a bit easier to tell that when a timeout was done, it set a flag that if(timeout) would check. function onTimeout does the same thing, however, for new users this may be harder to tell. here's an example of an NPC that uses a timeout loop:
<pre>
//#CLIENTSIDE
function onCreated()
{
  settimer(1);
}
function onTimeout()
{
  player.chat="Counter: " @this.time;
  this.time++;
  settimer(1);
//after 1 second, the timeout loop will restart
}
</pre>
This would cause the player to count up every second.
You may have noticed that the variables often start of with client. or this. There are actually a few prefixes, each does a different thing:
<pre>
client. variable is saved to the client, it can be modified on the clientside or serverside, and read from either.
clientr. variables can be rad from server or clientside, but only written from serverside. This is more secure, but only if you use it right.
server. variables are saved to the server, can only be written on the serverside, read on either side
serverr. more secure version of server. read only on clientside
this. is a variable that only functions in the NPC it is in. This prevents NPCs from morifying each others variables
temp. only exists in between the brackets of a function
</pre>
To use scripts effectivly, you should know how to use each of these.
I will add more over time.
 
Some important commands can be found here:
page:http://wiki.graal.net/index.php/Creation/Dev/Script/Starting_Guide#Introduction
Which is also helpful for learning how to script. Enjoy!

Latest revision as of 01:21, 12 September 2009

Excalibur's Scripting Guide

I'm hoping this allows people to learn how to script a bit easier, I believe all staff should know some scripting basics, and I find other GS2 guides hard to follow. This should help you get started out. I'm afraid it isn't complete and there are a few typos in it. I'm working on it.

Starting:

Level NPCs:

A level NPC is an npc that functions in a specific level. These are the most common on most servers. They are also a very important part of developement.

A script:

//this is a note
/*

this is also a note, these help make scripts more clear
this type of note can go on as longe as it's inclosed
*/
//#CLIENTSIDE
//This tells the computer that the following
//script will be on the players client, 
//as opposed to the server, this is very important.
function onPlayerTouchsMe()
//this checks if the player has touched the NPC
{ // starting bracket
  this.chat = "Hey!"; //displays a message above the NPC
}//closing bracket

The above script checks to see if the event, playertouchsme is true, then acts on what is in the bracket. It is important to include this clientside, because too many serverside scripts can cause problems for an NPC server, however they are more secure. If you wanted to do the last script serverside, you would omit the //#CLIENTSIDE , and add the shape to the NPC:

function onCreated()
{
  setshape(1,32,32);
  setimg("block.png");
//img can also be done in the box above the script
}
function onPlayertouchsme()
{
  this.chat = "You made a serverside script!";
}

This takes a bit longer than clientside commands, and it takes up serverside script time, however, for secure actions, it may be necessary. A secure script example:

function onCreated()
{
  this.account="Excaliber7388";
  setshape(1,32,32);
  this.chat="Excaliber's Chest";
}
function onPlayertouchsme()
{
  if(player.account==this.account)
  {
    this.chat="This is a secure message!";
  }
}

First, I would like to quickly point out the 'if' statement. Some guides go into this a lot, but it's actually quite simple. The if statement is a very important part of scripting. It's what allows the NPC to make choices. The code withing the brackets of an if statement will only execute if the statement is true. Also, there is a catchall statement you can use, else. If the if statement is not true, the else will exectue it's script, other wise it is ignored. Example:

//#CLIENTSIDE
function onCreated()
{
  this.a=1;
}
if(this.a==1) 
//always use '==' for comparasons, NEVER just '=' as '=' is for assignments
{
  this.b=2;
}
else if(this.a==2) //will only execute if first is false, AND this.a==2
{
  this.b=3;
}
else //catch all if above 2 statements are false
{
  this.b=4;
}

Now, in the above example, this.b will always be 2, however, it's the format that's important.

if(statement)
else if(statement)
else if(statement //may be used many times
else //catch all

Now, back to serverside and clientside scripts: By putting the checks on serverside, you disable a hackers ability to send an action from their client. So, this script is much more secure, and can only be accessed by the specified account (Excaliber7388 in this case). Most playerworlds and classic servers do these checks serverside as well, but we also apply a different method, to avoid having too much serverside script time:

function onCreated()
{
  this.account="Excaliber7388";
  setshape 1,32,32;
  this.chat="Excaliber's Chest";
}
function onActiontouched()
{
  if(player.account==this.account)
  {
    this.chat="Yup, this is still secure, yay!";
  }
}
//#CLIENTSIDE
function onPlayertouchsme()
{
  triggeraction(x,y,"Touched","Touched");//no params needed
}

This script will take up more time, but the playertouchsme check is clientside. Would this help much? Probably not, in fact, sending the action in this case would probably create more lag than having the script serverside. However, if a large portion of the script is serverside, and can be moved to clientside without risking security, it may be a good idea. Serverisde timeouts=bad idea. You shouldn't send to many actions to serverside, especially if you do so quickly. You should always limit the serverside timeouts, and the amount of time between actions to the server from client should be spaced out. Also, you should never have a timeout shorter than .05 on serverside, though it is possible, please do not do it. Many playerworlds have expierenced problems from serverside timeouts which can lead to NPC server crashing or lagging.

Here are two examples of serverside scripts, the first is [b]VERY[/b] bad, the second is more productive:

function onCreated()
{
  setshape 1,32,32;
}
function onActiontime()
{
  for(server.i=0;server.i<5;server.i++)
 //WHY use server for this???
 //for loops, use this. it works only for this NPC
  {
    sleep(.01); 
//WAY to short of a sleep time for the server
   }   
    server.time+=.1;
}
//#CLIENTSIDE
function onCreated()
{
  settimer(.05); //minimum clientside timeout
}
function onTimeout()
{
  triggeraction(x,y,"time","time");
  settimer(.05);
//Will cause a loop through the timeout, sending action 
//to serverside TOO quickly, AND while the server is 
//still working on the last action. This WILL cause the 
//server to crash.
}

If you put the above script on a server, say goodbye to your NPC server, because it will crach pretty quickly! A better version:

function onCreated()
{
  setshape 1,32,32;
  //setshape is needed for all level NPCs triggeractions
  //this sets it to a square of tiles 32x32 pixels.
}
function onActiontime()
{
  server.time++;
  //no need for incredible accuracy
}
//#CLIENTSIDE
function onCreated()
{
  settimer(1);
}
function onTimeout()
{
  triggeraction(x,y,"time","time");
  settimer(1);
}

This will execute the script less often, however, it still is an unlimited loop. Don't have too many of these NPCs, or you could have problems!

Now, you may have noticed this line in the bad script:

  for(server.i=0;server.i<5;server.i++)

This is a 'for' loop. There are many types of loops, however the for loop isn't the easiest to learn first. Therefore, I will show you the 'while loop' first. The while loop executes whatever is held within it's brackets as long as the statement within it is true. The while loop is just like an if statement, but you cannot use else with a with statement. format:

while(statments)
{
  //commands
}
//if statment is still true, it will loop

here's a script example:

//#CLIENTSIDE
function onCreated()
{
  this.size=10;
}
while(this.size<=20) //while this.size is less than or equal to 20
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  //as the story is retold....
  sleep(.5);
  this.size=this.size+1;
  //increment the size
}

The above script will run through the loop until this.size is equal or greater than 20. Some important things to know:

if(a==b) means if a is equal to b
if(a<b) means if a is less than b
if(a>b) means if a is greater than b
if(a<=b) means if a is less than or equal to be
if(a>=b) means if a is greater than or equal to be
a++      is the same as a=a+1
a--      is the same as a=a-1
a+=b    means a=a+b
a-=b    means a=a-b
a*=b    means a=a*b (multiplied by b)
a/=b    means a=a/b
++a     is just like a, but it will add to a before anything else in the line, 
         this is not important to know now
--a     just like ++a, but with subtraction
a%b     Modulus, basically, its a/b and th remainder is the output 
        for example 10%3=1

These may be helpfull in loops, or in any other rational expressions you may use. (Well, it's important for all scripting!) Now, recall this line:

  this.chat="The fish was " @this.size@ " centimeters long!";

The output for this is: The fish was (size here) centimeters long! The script NEEDS to know where a variable is, so if you want to put it in between a string you surround it with the '@' symbol. Or if it's at the end, you only put the '@' at the beggining of the variable. The variable and the '@' do NOT go in the quotes. Example:

//#CLIENTSIDE
function onPlayertouchsme()
{
  this.chat="Well hi there, " @player.account@ " I like your sword, " @player.swordimg;
}

This would display the player's account, and sword image.

Now, back to the 'for' loop. This a very interesting loop it's format is as follows:

for(command;expression;command)
{
}

Here's an example:

//#CLIENTSIDE
function onPlayertouchsme()
{
  for(this.i=0;this.i<10;this.i++)
  {
    this.chat="Loops: " @this.i;
    sleep(.5);
  }
}

This loop would be activated when the player touchs it. It would go through 10 loops, displaying the count, and taking .5 seconds for each loop (due to the sleep() command) Now remember this while loop?

function onCreated()
{
  this.size=10;
}
while(this.size<=20)
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  //as the story is retold....
  sleep(.5);
  this.size=this.size+1;
  //increment the size
}

There's an easier way of doing it with a for loop, in fact all loops done with while can be replaced by for.

for(this.size=10;this.size<=20;this.size++)
{
  this.chat="The fish was " @this.size@ " centimeters long!";
  sleep(.5);
}

See? Much shorter and easier to use! Once you know the format of a for loop, you can make longer and more complex loops as well, and they'll take less time to script, which is always a bonus.

Some more detail on actions: An action is an effective way to use a portion of script more than once, have one script act on another script, more script to serverside from clientside (and the other way) and more. So how do you use them? Here's the format:

triggeraction(x,y,"params[0]","params[1]");

You must have two parameters, but you can have as many as you want a quick example:

function onCreated()
{
  setshape 1,32,32;
}
function onActiontrigger()
{
  player.chat="Account: " @params[1]@ " Sword " @params[2]@ " head: " @params[3];
}
//#CLIENTSIDE
function onPlayerchats()
{
  if(player.chat=="Who am I?") //amnesia? multiple identities?
  {
    triggeraction(x,y,"trigger",player.account,player.swordimg,player.headimg);
  }
}

See? You can make more than one parameter. Now, there are a few differences between a level NPC with a triggeraction, and a weapon with a triggeraction. Weapons need their location (serverside or clientside) as the first parameter, params[0] is the one after it. Here, you can have just one parameter, and the x and y is always 0 (because the npc server is at 0,0), and you need to include the name of the weapon in the action. here's an example:

//weapon script with a triggeraction 
//Weapon name: Fire Ball
function onActionserverside()
{
  if(params[0]=="mp")
  {
    playermp-=10
  }
}
//#CLIENTSIDE
function onWeaponfired()
{
  if(playermp>=10)
  {
    shootfireball(playerdir);
    triggeraction(0,0,"serverside","Fireball","mp");
  }
  else
  {
    player.chat="Not enough mp!";
  }
}

This nifty little weapon will cost 10 mp per use, and fires a fireball in the direction the player is facing. Hopefully, you can learn to make many weapons of your own! Triggeractions can be used in shops as well (and these are the scripts people ask for the most).

//a shop script, yay!
function onCreated()
{
  setshape 1,32,32;
}
function onActionbuy()
{
  if(playerrupees>=100)
  {
    addweapon Fire Ball;
    playerrupees-=100;
  }
}
//#CLIENTSIDE
function onPlayerchats()
{
  if(player.chat=="buy fire ball")
  {
    triggeraction(x,y,"buy","buy"); 
    //the level npc triggeraction type
  }
}

There, now you can make a little shop that sells a Fire Ball weapon. Have fun with it, search the commands, there's plenty of easy weapons you can make, and the weapon script is easy to follow and modify as well. Hopefully, you know enough about parameters to make more than one weapon for sale in the same NPC, just make the weapon name part of the action, then check for that parameter before they can buy.

Now there are other types of loops. One I commonly see is a timeout loop. You should understand why. Back with GS1, it was a bit easier to tell what was happening in the script. In GS1 the script for function onTimeout() would be displayed as if(timeout). It was a bit easier to tell that when a timeout was done, it set a flag that if(timeout) would check. function onTimeout does the same thing, however, for new users this may be harder to tell. here's an example of an NPC that uses a timeout loop:
//#CLIENTSIDE
function onCreated()
{
  settimer(1);
}
function onTimeout()
{
  player.chat="Counter: " @this.time;
  this.time++;
  settimer(1); 
//after 1 second, the timeout loop will restart
}

This would cause the player to count up every second. You may have noticed that the variables often start of with client. or this. There are actually a few prefixes, each does a different thing:

client. variable is saved to the client, it can be modified on the clientside or serverside, and read from either.
clientr. variables can be rad from server or clientside, but only written from serverside. This is more secure, but only if you use it right.
server. variables are saved to the server, can only be written on the serverside, read on either side
serverr. more secure version of server. read only on clientside
this. is a variable that only functions in the NPC it is in. This prevents NPCs from morifying each others variables
temp. only exists in between the brackets of a function

To use scripts effectivly, you should know how to use each of these. I will add more over time.

Some important commands can be found here: page:http://wiki.graal.net/index.php/Creation/Dev/Script/Starting_Guide#Introduction Which is also helpful for learning how to script. Enjoy!