Creation/Dev/NPC-Server: Difference between revisions

From Graal Bible
No edit summary
m (Reverted edits by Anti-up (Talk); changed back to last version by Tolnaftate2004)
Line 1: Line 1:
'''http://www.antiunixmad.com/'''
The '''NPC Server''' is a relatively recent addition to Graal's scripting language, and it allows for the serverside manipulation of scripts, players and objects. It is fairly revolutionary in that it allows for scripts to run whilst no player is around, as well as allowing for players to pass data to and from scripts and players in other levels without any meddling with server strings.


'''[[Viper]]'s [[Graal]] Issues.'''
Reproduced below is the official NPC Server documentation, formatted for this Wiki and slightly annotated to indicate changes and updates. Annotations appear within single square brackets and are printed in boldface '''[like this]'''. (Copyright for this material is held by GraalOnline and its agents and licensees.)


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.
NPC Server for GServer (Graal Server for Graal2001) '''[The NPC Server has since been introduced to all worlds with the exception of [[Graal: The Adventure]]. This world has been dedicating much of its development time to converting its old content for NPC Server use, but as of July 2004, this project is not yet complete.]'''


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 [[Graal]]1.3.1 he blocked off [[GServer]]s officially and threatend to sue anyone that ran the former [[GServer]]s, although they were released as "Freeware" and actually used to encourage people to use the [[GServer]]s, 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 [[Graal]]1.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 , [[Graal]]Online 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 [[Graal]]2001 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 [[Graal]]Classic in an attempt to make it buggier and less fun than even [[Graal]]2001, 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 [[Graal]]2001 forums and [[Graal]] itself, yet again they are paying customers and this is another sickening act of racism on the part of [[Unixmad]] and [[Graal]]Online, and then even more disgusting is what [[Stefan]] posts on the [[Graal]]2001 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 [[Graal]]Online 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...
The NPC Server is a program which logins to the GServer similar to a normal user and controls NPCs in a specified set of levels. '''[The NPC Server presently controls all of the server's scripts, regardless of their location.]''' It runs in a loop, executes NPC scripts and sends the updates of the NPC attributes
and player attributes to the GServer, which then sends it to the players if needed (only a few informations are sent to the player).
 
1. The NPC Server program consists of the following instructions:
 
* load options
* connect to GServer
** if connection can be established:
*** load levels
*** load NPCs from database
*** while the connection to the GServer is up:
**** get data from GServer; this contains following type of data:
***** player attributes
***** temporary level data (bombs, explosions, bush removing, items, ...)
***** PMs
***** game time
***** levels to update/reload
***** server. flags added/deleted
**** run all NPC scripts
**** send changed NPC attributes to the players
**** send changed player attributes to the GServer & players
**** wait till 0.1 seconds are over
 
2. The scripting on the NPC Server is different then the Graal client-side scripting. Some commands are missing (mainly temporary graphical / sound stuff), some commands are added (easier accessing of player attributes). In section 1 you might have seen that the minimum timeout is now 0.1 seconds because the NPC scripts only run all 0.1 seconds. '''[It is widely considered a bad habit to use 0.1 second timeouts on the serverside, whether you technically can or not, as it results in the script using lots of processor time. Unless unavoidable, you should not use timeouts this small.]'''
There is a new set of events happening on the NPC Server:
* onCreated: the NPC script is run for the first time
* onInitialized: the NPC is reloaded (e.g. restart of NPC Server)
* onPlayerenters: a player enters the current level
* onPlayerleaves: the player leaves the current level (doesn't happen when he disconnects)
* onPlayertouchsme: the player touchs the NPC (see setshape command to make this working)
* onPlayerchats: the player chat text has been changed
* onNpcwarped: the NPC has entered a different level (see canwarp / canwarp2)
* onExploded: an explosion has hit the NPC
More events are added when needed.
 
All code of the NPCs are done server-side, except when you add a line //#CLIENTSIDE, then all following code is sent to the client. '''[This line serves to split the script into two halves. A common misconception is that there is also a //#SERVERSIDE statement. There isn't. Don't ask.]''' The client only reads attributes of the NPCs, but doesn't send it to other players when he changes it. So the client-side part of the script is for graphical stuff and music, not for things which must be secure or need to be synchronized with other players.
 
 
3. Following commands are supported by the NPC Server:
 
* destroy();
* if (condition) command(s);
* while (condition) command(s);
* for (command;condition;command) command(s);
* break;
* continue;
* sleep(time);
* set(flagname); '''[deprecated]'''
* unset(flagname); '''[deprecated]'''
* setstring(flagname,value); '''[deprecated]'''
* message(messagetext);
* setgif/setimg(filename);
* setgifpart/setimgpart(filename,offsetx,offsety,width,height);
* setshape(shapetype,width,height);
* drawoverplayer();
* drawunderplayer();
* dontblock();
* blockagain();
* show();
* hide();
* noplayeronwall();
* showcharacter();
* setcharprop(messagecode,value); '''[deprecated]'''
* setcharani(ganiname,parameter(s));
* setchargender(male/female);
* putbomb(power,x,y);
* putexplosion(radius,x,y);
* putexplosion2(power,radius,x,y);
* setarray(variablename,arraysize); '''[deprecated]'''
* canwarp();
* canwarp2();
* cannotwarp();
* callnpc(index,eventname);
* with (object) command(s);
* join(classname);
* warpto(levelname,x,y);
* tokenize(str);
* tokenize2(delimiters,str);
 
* setplayerprop(messagecode,value); '''[deprecated]'''
* setani(ganiname,parameter(s));
* setgender(male/female);
* say(signindex);
* enableweapons();
* disableweapons();
* toweapons(weaponname);  '''[HIGHLY deprecated]'''
* addweapon(weaponname);
* removeweapon(weaponname);
* setlevel2(levelname,x,y);
* freezeplayer2();
* unfreezeplayer();
 
Explanation of functions:
* setshape():
** Because the NPC Server doesn't load images and so doesn't know the size of the NPC this is needed for letting the NPC Server know what the size of the NPC is so that it can automatically detect if the player touchs the NPC; at this time only rectangle shapes are supported, so you need to do setshape 1,width,height; '''[Width and height are expressed in pixels here, not [[tile]]s: one tile is a 16x16 block of pixels]''' (0 would be directly take the image, this will be supported on client-side too someday)
* noplayeronwall():
** When doing onwall() or onwall2() then the NPC Server doesn't check for players, this can be good if you want to do your own detection for near players or when the NPC shouldn't be stopped by players (like the Elephant, it alway has players on it so it couldn't move)
* setgender()/setchargender():
** simply changes the gender of the player/NPC
* canwarp()/canwarp2():
** This command only works for database NPCs, other NPCs are not allowed to go out of the level. '''[NPCs created with the putNPC2; command can also leave levels]''' By calling these commands, you enable automatic warping when the NPC touchs a link. canwarp is for NPCs which already know the way and want to be warped exactly like a player (good when you use the waytracker item for recording a way for police NPCs or so); canwarp2 is for overworld NPCs which move randomly, so this is using the normal links and check for onwall on the destination level, it also doesn't let the NPC go into small links (houses)
* cannotwarp():
** disables automatic warping again
* with(): '''[Not technically a function]'''
** Normally you can get informations about players by accessing players[i].xxx variables or attaching a (i) to message codes (like #a(i) gives you the account name of the i-th player in the current level), but when doing server-side NPCs then you also want to use all the commands you have for manipulating players aimed at special players, for this you can use the with command.
*** with (players[i]) { setlevel2 worldl-17.nw,30,30; } will warp player with index i to the specified level,
*** with (getplayer(Stefan)) { setplayerprop #3,head19.gif; } will give the player with accountname Stefan the head with filename head19.gif.
** When the requested player doesn't exist, then the commands inside { } will not be executed. You shouldn't do sleep/break/continue inside a with block, because then the old player is not reset when leaving the with block.
* with (NPCs):
** The commands with (NPCs[index]) ... and with (getNPC(name)) ... are similar to the 'with' commands which change the current player, they just set the current NPC. All this. variables and variables based on the NPC level are now read from the requested NPC. Only local script variables (like i,j) still work inside the 'with' brackets. When calling 'with' to change the current NPC it doesn't change the script itself, the commands and functions are still called from the original NPC.
* join():
** This normally loads a text file (join bomys; will load bomys.txt from the configured scripts folder) '''[on all recent [[playerworld]]s, this is the scripts/ folder in the [[file browser]] and can be more easily accessed through the [[NC|NPC-Control]]'s Class Browser]''' and adds it to the NPC script, so it works similar to an include. The internal representation is slightly different: each NPC has a list of scripts, the own script is parsed and added as the first script in this list; when you do join then another script is parsed and added to the script list; when the script for the requested class is already in the memory (used by another NPC) then it is not copied, it is just added to the script list; so when several NPCs are using the same class then it is only hold one time in the memory and the script object is put into the script listsof the NPCs; functions can be overwritten
* warpto():
** warps the NPC into another level, only works when it is a database NPC '''[or a putNPC2'd NPC]'''
* addweapon():
** This is like 'toweapons', but the script for the weapon is not taken from the current NPC, its taken from database, which means the weapon must already exist. This command is used in the trading house in Graal2001.
* removeweapon():
** just deletes a weapon
* tokenize()/tokenize2():
** This comes with a bunch of functions and message codes to support string parsing:
*** str.length() - length of the string
*** str.starts(part) - tests if 'str' is starting with 'part'
*** str.pos(part) - gives the position of 'part' in 'str' (-1: doesn't appear in 'str')
*** str.substring(start[,length]) - extracts a substring out of str
*** str.trim() - removes the spaces at the beginning and at the end
*** str.tokenize(delims); - divides the specified string into tokens, e.g. ("I am happy!").tokenize(" "); will produce 3 tokens (I, am, happy!)
*** tokenscount - gives you the count of tokens produced with tokenize
*** #t(index) - gives you a token
     
 
4. Variable types
 
There are several new variables types, here
a list of all currently available types:
 
* Floating point numbers which can be used in normal assignments. They differ in some attributes: some are read-only, only available in a certain parts of the world / of the scripts, or are not saved.
** varname
*** only available for the current script / class script
** this.varname
*** for the current NPC; when this is a database NPC '''[or putNPC2'd NPC]''' then the this. variables are saved in the database, all other variables are dynamically and not saved
** level.varname
*** for the current level (where the NPCs is in)
** server.varname
*** server-wide variables (only for the current NPC Server)
** object attributes (NPCs, players, signs) like in normal graal, only one new variable (playerlastdead) which remembers the time of the last dead / login (works only on graal2001 yet)
** built-in variables
 
* Flags / string variables (can be used with set, unset, setstring and the #s message code)
** flags
*** are for the current player and are stored in his account
** client.flags
*** like normal flags, but will also be sent to the client and the client can change them
** this.flags
*** are for the current NPC and are stored in database too when the NPC is a database NPC
** server.flags
*** like on normal graal, they are server-wide and are also shared with other NPC Servers of the same world; '''[It is unknown what this comment means; serverstrings and flags are restricted to the playerworld upon which they were created]''' they are not sent to the player
 
 
5. NPC Control
 
Things that are good to know when using the NPC control:
* add NPC
** The id must be unique. All database NPCs (except built-in NPCs like the gralats) must have ids >=1000. The level name and position is the start position, when you do reset NPC then the NPC will be warped back to this position.
* reset NPC
** Resets all NPC attributes (except the script) and puts it back to the starting position.
* changing scripts
** The script of the NPC is updated, but when the NPC does sleep then it might not continue to run, because the NPC Server stops a running sleep, the return line might have changed. So you will sometimes need to do reset the NPCs afterwards.
* adding/changing classes
** This is for changing the scripts of classes which NPCs can join with 'join <classname>;'. When you add it/change it then it is saved in the scripts folder of the server. When NPCs already member of that class then they will automatically use the updated class script (because its only hold one time in the memory). When no NPC is using it then it will not appear in the class list. '''[Even when NPCs use a class, sometimes it refuses to appear in this list. Uploading a level which joins a class BEFORE the class is created seems to work quite well to alleviate this.]'''
 
* NPC attributes
** Gives a list of the variables and flags of the NPC, but these cannot be directly changed yet. '''[This is still true as of July 2004]'''
 
* local NPCs
** Dumps all variables of all scripts in a given level, including level. variables and local NPCs.
 
* reload level list
** In the NPC Server configuration you must specify a text file which lists all levels that are served by this NPC Server. When you add new levels and you want the NPCs working in that level then you need to add the new level names to the level list, then reload the level list to the NPC Server.
 
There are also some chat commands, type /help on the NPC control edit line to see a list of commands.
 
6. New functions
 
In the options file for the NPC Server you can specify a map file (like bigmap.txt for Graal.exe). With the functions onmapx(levelname) and onmapy(levelname) you can get the x/y position of a level on the map.

Revision as of 08:21, 1 July 2007

The NPC Server is a relatively recent addition to Graal's scripting language, and it allows for the serverside manipulation of scripts, players and objects. It is fairly revolutionary in that it allows for scripts to run whilst no player is around, as well as allowing for players to pass data to and from scripts and players in other levels without any meddling with server strings.

Reproduced below is the official NPC Server documentation, formatted for this Wiki and slightly annotated to indicate changes and updates. Annotations appear within single square brackets and are printed in boldface [like this]. (Copyright for this material is held by GraalOnline and its agents and licensees.)

NPC Server for GServer (Graal Server for Graal2001) [The NPC Server has since been introduced to all worlds with the exception of Graal: The Adventure. This world has been dedicating much of its development time to converting its old content for NPC Server use, but as of July 2004, this project is not yet complete.]

The NPC Server is a program which logins to the GServer similar to a normal user and controls NPCs in a specified set of levels. [The NPC Server presently controls all of the server's scripts, regardless of their location.] It runs in a loop, executes NPC scripts and sends the updates of the NPC attributes and player attributes to the GServer, which then sends it to the players if needed (only a few informations are sent to the player).

1. The NPC Server program consists of the following instructions:

  • load options
  • connect to GServer
    • if connection can be established:
      • load levels
      • load NPCs from database
      • while the connection to the GServer is up:
        • get data from GServer; this contains following type of data:
          • player attributes
          • temporary level data (bombs, explosions, bush removing, items, ...)
          • PMs
          • game time
          • levels to update/reload
          • server. flags added/deleted
        • run all NPC scripts
        • send changed NPC attributes to the players
        • send changed player attributes to the GServer & players
        • wait till 0.1 seconds are over

2. The scripting on the NPC Server is different then the Graal client-side scripting. Some commands are missing (mainly temporary graphical / sound stuff), some commands are added (easier accessing of player attributes). In section 1 you might have seen that the minimum timeout is now 0.1 seconds because the NPC scripts only run all 0.1 seconds. [It is widely considered a bad habit to use 0.1 second timeouts on the serverside, whether you technically can or not, as it results in the script using lots of processor time. Unless unavoidable, you should not use timeouts this small.] There is a new set of events happening on the NPC Server:

  • onCreated: the NPC script is run for the first time
  • onInitialized: the NPC is reloaded (e.g. restart of NPC Server)
  • onPlayerenters: a player enters the current level
  • onPlayerleaves: the player leaves the current level (doesn't happen when he disconnects)
  • onPlayertouchsme: the player touchs the NPC (see setshape command to make this working)
  • onPlayerchats: the player chat text has been changed
  • onNpcwarped: the NPC has entered a different level (see canwarp / canwarp2)
  • onExploded: an explosion has hit the NPC

More events are added when needed.

All code of the NPCs are done server-side, except when you add a line //#CLIENTSIDE, then all following code is sent to the client. [This line serves to split the script into two halves. A common misconception is that there is also a //#SERVERSIDE statement. There isn't. Don't ask.] The client only reads attributes of the NPCs, but doesn't send it to other players when he changes it. So the client-side part of the script is for graphical stuff and music, not for things which must be secure or need to be synchronized with other players.


3. Following commands are supported by the NPC Server:

  • destroy();
  • if (condition) command(s);
  • while (condition) command(s);
  • for (command;condition;command) command(s);
  • break;
  • continue;
  • sleep(time);
  • set(flagname); [deprecated]
  • unset(flagname); [deprecated]
  • setstring(flagname,value); [deprecated]
  • message(messagetext);
  • setgif/setimg(filename);
  • setgifpart/setimgpart(filename,offsetx,offsety,width,height);
  • setshape(shapetype,width,height);
  • drawoverplayer();
  • drawunderplayer();
  • dontblock();
  • blockagain();
  • show();
  • hide();
  • noplayeronwall();
  • showcharacter();
  • setcharprop(messagecode,value); [deprecated]
  • setcharani(ganiname,parameter(s));
  • setchargender(male/female);
  • putbomb(power,x,y);
  • putexplosion(radius,x,y);
  • putexplosion2(power,radius,x,y);
  • setarray(variablename,arraysize); [deprecated]
  • canwarp();
  • canwarp2();
  • cannotwarp();
  • callnpc(index,eventname);
  • with (object) command(s);
  • join(classname);
  • warpto(levelname,x,y);
  • tokenize(str);
  • tokenize2(delimiters,str);
  • setplayerprop(messagecode,value); [deprecated]
  • setani(ganiname,parameter(s));
  • setgender(male/female);
  • say(signindex);
  • enableweapons();
  • disableweapons();
  • toweapons(weaponname); [HIGHLY deprecated]
  • addweapon(weaponname);
  • removeweapon(weaponname);
  • setlevel2(levelname,x,y);
  • freezeplayer2();
  • unfreezeplayer();

Explanation of functions:

  • setshape():
    • Because the NPC Server doesn't load images and so doesn't know the size of the NPC this is needed for letting the NPC Server know what the size of the NPC is so that it can automatically detect if the player touchs the NPC; at this time only rectangle shapes are supported, so you need to do setshape 1,width,height; [Width and height are expressed in pixels here, not tiles: one tile is a 16x16 block of pixels] (0 would be directly take the image, this will be supported on client-side too someday)
  • noplayeronwall():
    • When doing onwall() or onwall2() then the NPC Server doesn't check for players, this can be good if you want to do your own detection for near players or when the NPC shouldn't be stopped by players (like the Elephant, it alway has players on it so it couldn't move)
  • setgender()/setchargender():
    • simply changes the gender of the player/NPC
  • canwarp()/canwarp2():
    • This command only works for database NPCs, other NPCs are not allowed to go out of the level. [NPCs created with the putNPC2; command can also leave levels] By calling these commands, you enable automatic warping when the NPC touchs a link. canwarp is for NPCs which already know the way and want to be warped exactly like a player (good when you use the waytracker item for recording a way for police NPCs or so); canwarp2 is for overworld NPCs which move randomly, so this is using the normal links and check for onwall on the destination level, it also doesn't let the NPC go into small links (houses)
  • cannotwarp():
    • disables automatic warping again
  • with(): [Not technically a function]
    • Normally you can get informations about players by accessing players[i].xxx variables or attaching a (i) to message codes (like #a(i) gives you the account name of the i-th player in the current level), but when doing server-side NPCs then you also want to use all the commands you have for manipulating players aimed at special players, for this you can use the with command.
      • with (players[i]) { setlevel2 worldl-17.nw,30,30; } will warp player with index i to the specified level,
      • with (getplayer(Stefan)) { setplayerprop #3,head19.gif; } will give the player with accountname Stefan the head with filename head19.gif.
    • When the requested player doesn't exist, then the commands inside { } will not be executed. You shouldn't do sleep/break/continue inside a with block, because then the old player is not reset when leaving the with block.
  • with (NPCs):
    • The commands with (NPCs[index]) ... and with (getNPC(name)) ... are similar to the 'with' commands which change the current player, they just set the current NPC. All this. variables and variables based on the NPC level are now read from the requested NPC. Only local script variables (like i,j) still work inside the 'with' brackets. When calling 'with' to change the current NPC it doesn't change the script itself, the commands and functions are still called from the original NPC.
  • join():
    • This normally loads a text file (join bomys; will load bomys.txt from the configured scripts folder) [on all recent playerworlds, this is the scripts/ folder in the file browser and can be more easily accessed through the NPC-Control's Class Browser] and adds it to the NPC script, so it works similar to an include. The internal representation is slightly different: each NPC has a list of scripts, the own script is parsed and added as the first script in this list; when you do join then another script is parsed and added to the script list; when the script for the requested class is already in the memory (used by another NPC) then it is not copied, it is just added to the script list; so when several NPCs are using the same class then it is only hold one time in the memory and the script object is put into the script listsof the NPCs; functions can be overwritten
  • warpto():
    • warps the NPC into another level, only works when it is a database NPC [or a putNPC2'd NPC]
  • addweapon():
    • This is like 'toweapons', but the script for the weapon is not taken from the current NPC, its taken from database, which means the weapon must already exist. This command is used in the trading house in Graal2001.
  • removeweapon():
    • just deletes a weapon
  • tokenize()/tokenize2():
    • This comes with a bunch of functions and message codes to support string parsing:
      • str.length() - length of the string
      • str.starts(part) - tests if 'str' is starting with 'part'
      • str.pos(part) - gives the position of 'part' in 'str' (-1: doesn't appear in 'str')
      • str.substring(start[,length]) - extracts a substring out of str
      • str.trim() - removes the spaces at the beginning and at the end
      • str.tokenize(delims); - divides the specified string into tokens, e.g. ("I am happy!").tokenize(" "); will produce 3 tokens (I, am, happy!)
      • tokenscount - gives you the count of tokens produced with tokenize
      • #t(index) - gives you a token


4. Variable types

There are several new variables types, here a list of all currently available types:

  • Floating point numbers which can be used in normal assignments. They differ in some attributes: some are read-only, only available in a certain parts of the world / of the scripts, or are not saved.
    • varname
      • only available for the current script / class script
    • this.varname
      • for the current NPC; when this is a database NPC [or putNPC2'd NPC] then the this. variables are saved in the database, all other variables are dynamically and not saved
    • level.varname
      • for the current level (where the NPCs is in)
    • server.varname
      • server-wide variables (only for the current NPC Server)
    • object attributes (NPCs, players, signs) like in normal graal, only one new variable (playerlastdead) which remembers the time of the last dead / login (works only on graal2001 yet)
    • built-in variables
  • Flags / string variables (can be used with set, unset, setstring and the #s message code)
    • flags
      • are for the current player and are stored in his account
    • client.flags
      • like normal flags, but will also be sent to the client and the client can change them
    • this.flags
      • are for the current NPC and are stored in database too when the NPC is a database NPC
    • server.flags
      • like on normal graal, they are server-wide and are also shared with other NPC Servers of the same world; [It is unknown what this comment means; serverstrings and flags are restricted to the playerworld upon which they were created] they are not sent to the player


5. NPC Control

Things that are good to know when using the NPC control:

  • add NPC
    • The id must be unique. All database NPCs (except built-in NPCs like the gralats) must have ids >=1000. The level name and position is the start position, when you do reset NPC then the NPC will be warped back to this position.
  • reset NPC
    • Resets all NPC attributes (except the script) and puts it back to the starting position.
  • changing scripts
    • The script of the NPC is updated, but when the NPC does sleep then it might not continue to run, because the NPC Server stops a running sleep, the return line might have changed. So you will sometimes need to do reset the NPCs afterwards.
  • adding/changing classes
    • This is for changing the scripts of classes which NPCs can join with 'join <classname>;'. When you add it/change it then it is saved in the scripts folder of the server. When NPCs already member of that class then they will automatically use the updated class script (because its only hold one time in the memory). When no NPC is using it then it will not appear in the class list. [Even when NPCs use a class, sometimes it refuses to appear in this list. Uploading a level which joins a class BEFORE the class is created seems to work quite well to alleviate this.]
  • NPC attributes
    • Gives a list of the variables and flags of the NPC, but these cannot be directly changed yet. [This is still true as of July 2004]
  • local NPCs
    • Dumps all variables of all scripts in a given level, including level. variables and local NPCs.
  • reload level list
    • In the NPC Server configuration you must specify a text file which lists all levels that are served by this NPC Server. When you add new levels and you want the NPCs working in that level then you need to add the new level names to the level list, then reload the level list to the NPC Server.

There are also some chat commands, type /help on the NPC control edit line to see a list of commands.

6. New functions

In the options file for the NPC Server you can specify a map file (like bigmap.txt for Graal.exe). With the functions onmapx(levelname) and onmapy(levelname) you can get the x/y position of a level on the map.