Creation/Dev/Script/Starting Guide: Difference between revisions
No edit summary |
m (→Events) |
||
(9 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Scripting Tutorials]][[Category:Scripting Reference]] | |||
== Introduction == | |||
=== Why scripts === | |||
Scripts bring life into objects and make it easy to | |||
customize the game. Instead of just placing a stone | |||
into your world, you can make it so that the stone | |||
can be lifted or kicked. Instead of being limited to | |||
some fixed player movement you can rescript it | |||
to let the player jump, strafe and duck. To let the | |||
player inspect and organize his/her items you can | |||
create some dialogs and display those by script, | |||
e.g. when the player presses a special key. | |||
In Graal the scripting is done in 'Graal Script', | |||
it's looking like Java/C++, but brings some | |||
additional features for making things easier | |||
for game creators, while on the other hand | |||
running in a sandbox and limiting access to | |||
game-related stuff only. | |||
Graal Script is almost fully compatible to | |||
the 'old' Graal script used in Graal v1.0 - 3.0, | |||
and is partially compatible to Torque script. | |||
=== NPCs and 'weapons' === | |||
There are generally two types of objects in Graal | |||
which have scripts: The first type are the | |||
non-player-characters (NPCs). The name 'NPC' is | |||
actually used for all visible objects in the game: | |||
monsters, stones, bushes, houses, ships, plants etc. | |||
Scripts for npcs are most of the time containing | |||
code for moving the npc or for reacting to | |||
activities of the player, e.g. giving money to | |||
the player when he/she grabs the npc. | |||
The other type of script-holding objects are the | |||
'weapons'. Those are items in the inventory of | |||
the player, not necessary being weapons. Most of | |||
the time they are actually just scripts which | |||
control the movement of the player, display weapon | |||
graphics, or display menus. | |||
So there are objects in the game which have | |||
their own script, and players which have a set | |||
of scripts in their invisible backpack. | |||
=== Server-side and client-side === | |||
Graal is an online game, and there are differences | |||
to standard scripting in offline games. | |||
In offline programs you have access to everything, | |||
anytime. In online games everything is divided | |||
into two parts: the server-side which controls | |||
most things in the game, and the client-side which | |||
displays the game to the player. | |||
Since the client only displays things, it is not | |||
possible to cheat by hacking the client. On client-side | |||
you mainly have code for displaying special effects, | |||
for displaying the GUI (windows, status bars, item menus), | |||
playing sound effects and music. Also the player | |||
movement is done on client-side. | |||
On the server-side scripts are used to do the more | |||
secure parts of the game engine, | |||
and things that are the same for all players - | |||
npcs are added, moved, npcs interact with players, | |||
the stats of the players are calculated, the | |||
communication between players is handled. | |||
All scripts for npcs and weapons can contain | |||
server-side code and client-side code. The server-side | |||
code is executed directly on the server, the | |||
client-side code is sent to the client when he/she | |||
logins and executed separately for each player on | |||
their own computer. Usually the two parts of the script | |||
are divided by a line that only contains "//#CLIENTSIDE", | |||
like this: | |||
<pre>// Server-side part which is setting the image | |||
// of the npc when it is created | |||
function onCreated() { | |||
setimg("door.png"); | |||
} | |||
//#CLIENTSIDE | |||
// Here follows the client-side part, | |||
// which plays a sound effect when the player | |||
// touchs the npc | |||
function onPlayerTouchsme() { | |||
play("chest.wav"); | |||
}</pre> | |||
Also see [[clientside]] and [[serverside]]. | |||
=== Events === | |||
In general scripts are made for reacting to | |||
events - when the npc is created then the script | |||
initializes the attributes of the npc, | |||
when the player says something then the npc is | |||
moving to the player, when the player grabs the | |||
npc then the npc is giving the player some money etc. | |||
So the script is basicly a collection of actions | |||
that are done when special events are happening. | |||
Events can e.g. be the "created" event when the npc | |||
is created, the "playertouchsme" event when the | |||
player touchs the npc, or the "playerchats" event | |||
when the player says something. To write code that reacts | |||
to one of those event, you define an event | |||
function like this: | |||
<pre>function onEVENTNAME() { | |||
// actions | |||
}</pre> | |||
When the event is happening, then Graal executes | |||
that scripting function and all commands you | |||
have added there. | |||
Sometimes the event gives some parameters to the | |||
event function, then change your function to: | |||
<pre>function onEVENTNAME(parameter1, parameter2, ...) { | |||
// actions | |||
}</pre> | |||
By accessing 'parameter1' etc. (you can name | |||
them differently) you can react to the event more | |||
exactly. | |||
Instead of reacting to events, the npcs and | |||
weapons can also invoke new events. That way | |||
you can let other npcs doing things. You also | |||
need that if you want to coninuously doing things - | |||
use timeout events for that. | |||
<pre>function onCreated() { | |||
setTimer(1); | |||
} | |||
function onTimeout() { | |||
// actions | |||
setTimer(1); | |||
}</pre> | |||
In the onCreated event function the script is | |||
setting the timer to 1 second. When that second is | |||
over, then the "timeout" event is invoked on the | |||
npc and the onTimeout event function is executed. | |||
Because it is setting the timer to 1 second | |||
again, the onTimeout event will occur again after | |||
one second, and so on. | |||
Compatibility note: | |||
In older Graal scripts you will also find the | |||
deprecated way of receiving events: | |||
<pre>if (EVENTNAME) { | |||
// actions | |||
}</pre> | |||
That is an if-command outside of any brackets. If | |||
Graal sees that you use such an if-command, then | |||
it will execute the whole script so that the actions | |||
you have written inside the if-command will be | |||
executed too. | |||
The events for GUI controls are listed in the description of the different object types: | |||
[[Creation/Dev/Script/Client#Classes_.2F_Object_Types|Object types]] | |||
== Basics == | |||
=== Accessing variables === | |||
Graal Script variables are 'variant', that means they are objects | |||
that hold values of different types. | |||
When you assign a value to the variable then it automatically | |||
switches to the right type: | |||
Numeric (floating point): | |||
var = 1; | |||
String (text): | |||
var = "hello"; | |||
Object link: | |||
var = player; | |||
Array (list of objects): | |||
var = {1,2,3}; | |||
You can check the current type with the | |||
type()-function - obj.type() returns | |||
0,1,2,3 for numeric, string, object or array. | |||
=== Operators === | |||
<pre> | |||
Addition a + b | |||
Substraction a - b | |||
Mulitplication a * b | |||
Division a / b | |||
Modulus a % b | |||
Power a ^ b | |||
String Concationation a @ b | |||
with space a SPC b | |||
with newline a NL b | |||
with tabulator a TAB b | |||
Bool-And a && b | |||
Bool-Or a || b | |||
Bool-Not !a | |||
Negative -a | |||
Equal a == b | |||
Not-Equal a != b | |||
Less a < b | |||
Greater a > b | |||
Less-Equal a <= b, a =< b | |||
Greater-Equal a >= b, a => b | |||
In-Range a in <b,c>, a in |b,c>, a in <b,c|, a in |b,c| | |||
In-Array a in {b,c,...}, {a,b,...} in {c,d,...} | |||
Bitwise-Or a | b | |||
Bitwise-And a & b | |||
Bitwise-Shift left a << b | |||
Bitwise-Shift right a >> b | |||
Bitwise-Invert ~a | |||
Bitwise-Xor a xor b (operator ^ already used for power) | |||
Array-Constructor {a,b,...} | |||
Empty Array new [count], new[countdim1][countdim2]... | |||
Array Member a[index] | |||
Function call a(), a(b,c,...) | |||
Object Attribute a.b, a.(b) | |||
Post Increment a++ | |||
Post Decrement a-- | |||
Pre Increment ++a | |||
Pre Decrement --a | |||
Old String Function #a | |||
Conditional a? b : c | |||
Assignment a = b, a := b | |||
Additive Assignment a += b | |||
Substractive Assignment a -= b | |||
Multiplicative Assignment a *= b | |||
Division Assignment a /= b | |||
Modulus Assignment a %= b | |||
Power Assignment a ^= b | |||
Bitwise-Or Assignment a |= b | |||
Bitwise-And Assignment a &= b | |||
Shift Left Assignment a <<= b | |||
Shift Right Assignment a >>= b | |||
String Append a @= b | |||
</pre> | |||
=== Standard object functions === | |||
Here only some of the built-in functions: | |||
<pre> | |||
obj.type() - gets the type of the var (float 0, string 1, object 2, array 3) | |||
obj.length() - string length | |||
obj.trim() - removes spaces from the front and back of a string | |||
obj.lower() - converts a string to lower case | |||
obj.upper() - converts a string to upper case | |||
obj.tokenize([delimiters]) - splits the string into an array wherever the delimiters occur | |||
obj.charat(pos) - character at specified position | |||
obj.pos(substring) - first position of the substring in the string | |||
obj.positions(substring) - array of positions of the substring in the string | |||
obj.starts(string) - does the string start with the specified string? | |||
obj.ends(string) - does the string end with the specified string? | |||
obj.substring(index[,length]) - returns the string starting at the index and ending after the length specified | |||
obj.size() - array length | |||
obj.add(obj2) - adds an object to an array | |||
obj.delete(index) - deletes the object from an array at the specified index | |||
obj.remove(obj2) - removes the first instance of the specified object from the array | |||
obj.replace(index,obj2) - replace the object at the specified index | |||
obj.insert(index,obj2) - insert the object at the index without replacing other indexes | |||
obj.clear() - clear the array | |||
obj.subarray(index[,length]) | |||
obj.addarray(obj2) | |||
obj.insertarray(index,obj2) | |||
obj.index(obj2) - position of obj2 in the array | |||
obj.indices(obj2) - positions of obj2 in the array | |||
obj.link() - used to pass an array to a function which | |||
can modify the array, also prevents copying of huge arrays | |||
</pre> | |||
Also see [[Creation/Dev/Script/Client/TGraalVar|TGraalVar]] for more functions for objects. | |||
=== Standard functions === | |||
<pre> | |||
_(string) - translates a text on serverside | |||
to the language of the current player, | |||
if translations are enabled | |||
abs(float) - returns absolute value of the float | |||
arctan(float) - arcus tangens | |||
char(ascii) - gets the character for an ascii code (char(65) returns 'A') | |||
cos(angle) - cosinus of a radiant angle | |||
exp(float) | |||
float(string) - for explicitely converting a string | |||
to number (normally done automatically though | |||
when accessing a string with numeric operators) | |||
format(format,parameters,...) - formats a "%s %d" string, | |||
inserts the parameters, and returns a string | |||
getangle(delta x,delta y) - [http://en.wikipedia.org/wiki/Atan2 atan2] | |||
getdir(delta x,delta y) - returns the direction for the delta x and y | |||
int(a) - gets the integer part of a floating point number (truncates at the decimal) | |||
log(base,a) | |||
max(a,b) - returns the highest value between the two given | |||
min(a,b) - returns the lowest value between the two given | |||
printf(format,parameters,...) - same as | |||
echo(format(format,parameters,...)) | |||
random(rangestart,rangeend) - returns a random float between rangestart and rangeend | |||
sin(angle) - sinus of a radiant angle | |||
sleep(time) - suspends the current script for the time | |||
vecx(direction 0..3) - direction to move x if dir is the specified direction | |||
vecy(direction 0..3) - direction to move y if dir is the specified direction | |||
waitfor(objectname,event[,timeout]) - suspends the current script | |||
and waits until an event is invoked on the specified object, | |||
returns false when the parameters are wrong or the event | |||
was not received before the timeout; | |||
only available in the latest versions of npcserver | |||
</pre> | |||
Also see [[Creation/Dev/Script/Client#Functions|Client Functions]] for more functions. | |||
== Old script compatibility == | |||
=== Removed functionality === | |||
<pre> | |||
- toinventory | |||
- followplayer | |||
- playersays() | |||
- setbackpal | |||
</pre> | |||
=== Supported old scripting commands and their mapping to new script === | |||
<pre> | |||
addstring oldstring, oldstring; | |||
list.add(string); | |||
addtiledef oldstring, oldstring, float; | |||
addtiledef(string,string,float); | |||
addtiledef2 oldstring, oldstring, float, float; | |||
addtiledef2(string,string,float,float); | |||
attachplayertoobj float, float; | |||
attachplayertoobj(float,float); | |||
blockagain; | |||
blockagain(); | |||
blockagainlocal; | |||
blockagainlocal(); | |||
callnpc float, oldstring; | |||
callnpc(float,string); | |||
callweapon float, oldstring; | |||
callweapon(float,string); | |||
canbecarried; | |||
canbecarried(); | |||
canbepulled; | |||
canbepulled(); | |||
canbepushed; | |||
canbepushed(); | |||
cannotbecarried; | |||
cannotbecarried(); | |||
cannotbepulled; | |||
cannotbepulled(); | |||
cannotbepushed; | |||
cannotbepushed(); | |||
canwarp; | |||
canwarp(); | |||
canwarp2; | |||
canwarp2(); | |||
carryobject oldstring; | |||
carryobject(string); | |||
changeimgcolors float, float, float, float, float; | |||
changeimgcolors(float,float,float,float,float); | |||
changeimgmode float, float; | |||
changeimgmode(float,float); | |||
changeimgpart float, float, float, float, float; | |||
changeimgpart(float,float,float,float,float); | |||
changeimgvis float, float; | |||
changeimgvis(float,float); | |||
changeimgzoom float, float; | |||
changeimgzoom(float,float); | |||
deletestring oldstring, float; | |||
deletestring(string,float); | |||
destroy; | |||
destroy(); | |||
detachplayer; | |||
detachplayer(); | |||
disabledefmovement; | |||
disabledefmovement(); | |||
disablemap; | |||
disablemap(); | |||
disablepause; | |||
disablepause(); | |||
disableselectweapons; | |||
disableselectweapons(); | |||
disableweapons; | |||
disableweapons(); | |||
dontblock; | |||
dontblock(); | |||
dontblocklocal; | |||
dontblocklocal(); | |||
drawaslight; | |||
drawaslight(); | |||
drawoverplayer; | |||
drawoverplayer(); | |||
drawunderplayer; | |||
drawunderplayer(); | |||
enabledefmovement; | |||
enabledefmovement(); | |||
enablefeatures float; | |||
enablefeatures(float); | |||
enablemap; | |||
enablemap(); | |||
enablepause; | |||
enablepause(); | |||
enableselectweapons; | |||
enableselectweapons(); | |||
enableweapons; | |||
enableweapons(); | |||
explodebomb float; | |||
explodebomb(float); | |||
followplayer; | |||
followplayer(); | |||
freezeplayer float; | |||
freezeplayer(float); | |||
freezeplayer2; | |||
freezeplayer2(); | |||
hide; | |||
hide(); | |||
hideimg float; | |||
hideimg(float); | |||
hideimgs float, float; | |||
hideimgs(float,float); | |||
hidelocal; | |||
hidelocal(); | |||
hitcompu float, float, float, float; | |||
hitcompu(float,float,float,float); | |||
hitnpc float, float, float, float; | |||
hitnpc(float,float,float,float); | |||
hitobjects float, float, float; | |||
hitobjects(float,float,float); | |||
hideplayer float; | |||
hideplayer(float); | |||
hidesword float; | |||
hidesword(float); | |||
hitplayer float, float, float, float; | |||
hitplayer(float,float,float,float); | |||
hurt float; | |||
hurt(float); | |||
insertstring oldstring, float, oldstring; | |||
insertstring(string,float,string); | |||
join oldstring; | |||
join(string); | |||
lay oldstring; | |||
lay(string); | |||
lay2 oldstring, float, float; | |||
lay2(string,float,float); | |||
loadmap oldstring; | |||
loadmap(string); | |||
message oldstring; | |||
message(string); | |||
move float, float, float, float; | |||
move(float,float,float,float); | |||
noplayerkilling; | |||
noplayerkilling(); | |||
openurl oldstring; | |||
openurl(string); | |||
openurl2 oldstring, float, float; | |||
openurl2(string,float,float); | |||
play oldstring; | |||
play(string); | |||
play2 oldstring, float, float, float; | |||
play2(string,float,float,float); | |||
playlooped oldstring; | |||
playlooped(string); | |||
putbomb float, float, float; | |||
putbomb(float,float,float); | |||
putcomp oldstring, float, float; | |||
putcomp(string,float,float); | |||
putexplosion float, float, float; | |||
putexplosion(float,float,float); | |||
putexplosion2 float, float, float, float; | |||
putexplosion2(float,float,float,float); | |||
puthorse oldstring, float, float; | |||
puthorse(string,float,float); | |||
putleaps float, float, float; | |||
putleaps(float,float,float); | |||
putnewcomp oldstring, float, float, oldstring, float; | |||
putnewcomp(string,float,float,string,float); | |||
putnpc oldstring, oldstring, float, float; | |||
putnpc(string,string,float,float); | |||
putnpc2 float, float, oldstring; | |||
putnpc2(float,float,string); | |||
reflectarrow float; | |||
reflectarrow(float); | |||
removearrow float; | |||
removearrow(float); | |||
removebomb float; | |||
removebomb(float); | |||
removecompus; | |||
removecompus(); | |||
removeexplo float; | |||
removeexplo(float); | |||
removehorse float; | |||
removehorse(float); | |||
rmeoveitem float; | |||
removeitem(float) | |||
removestring oldstring, oldstring; | |||
removestring(string,string); | |||
removetiledefs oldstring; | |||
removetiledefs(string); | |||
replaceani oldstring, oldstring; | |||
replaceani(string,string); | |||
replacestring oldstring, float, oldstring; | |||
replacestring(string,float,string); | |||
resetfocus; | |||
resetfocus(); | |||
savelog oldstring; | |||
savelog(string); | |||
savelog2 oldstring, oldstring; | |||
savelog2(string,string); | |||
say float; | |||
say(float); | |||
say2 oldstring; | |||
say2(string); | |||
sendrpgmessage oldstring; | |||
sendrpgmessage(string); | |||
sendpm oldstring; | |||
sendpm(string); | |||
sendtonc oldstring; | |||
sendtonc(string); | |||
sendtorc oldstring; | |||
sendtorc(string); | |||
serverwarp oldstring; | |||
serverwarp(string); | |||
set oldstring; | |||
set(string); | |||
setani oldstring, oldstring; | |||
setani(string,string); | |||
setarray float, float; | |||
setarray(var,float); | |||
setbeltcolor oldstring; | |||
setbeltcolor(string); | |||
setbow oldstring; | |||
setbow(string); | |||
setcharani oldstring, oldstring; | |||
setcharani(string,string); | |||
setchargender oldstring; | |||
setchargender(string); | |||
setcharprop oldstring, oldstring; | |||
string = string; | |||
setcoatcolor oldstring; | |||
setcoatcolor(string); | |||
setcoloreffect float, float, float, float; | |||
setcoloreffect(float,float,float,float); | |||
setcursor float; | |||
setcursor(float); | |||
setcurcor2 oldstring; | |||
setcursor2(string); | |||
seteffect float, float, float, float; | |||
seteffect(float,float,float,float); | |||
seteffectmode float; | |||
seteffectmode(float); | |||
setfocus float, float; | |||
setfocus(float,float); | |||
setgender oldstring; | |||
setgender(string); | |||
sethead oldstring; | |||
sethead(string); | |||
setlevel oldstring; | |||
setlevel(string); | |||
setlevel2 oldstring, float, float; | |||
setlevel2(string,float,float); | |||
setmap oldstring, oldstring, float, float; | |||
setmap(string,string,float,float); | |||
setminimap oldstring, oldstring, float, float; | |||
setminimap(string,string,float,float); | |||
setmusicvolume float, float; | |||
setmusicvolume(float,float); | |||
setimg oldstring; | |||
setimg(string); | |||
setimgpart oldstring, float, float, float, float; | |||
setimgpart(string,float,float,float,float); | |||
setletters oldstring; | |||
setletters(string); | |||
setplayerdir oldstring; | |||
setplayerdir(string); | |||
setplayerprop oldstring, oldstring; | |||
string = string; | |||
setpm oldstring; | |||
setpm(string); | |||
setshape float, float, float; | |||
setshape(float,float,float); | |||
setshape2 float, float, float; | |||
setshape2(float,float,float); | |||
setshield oldstring, float; | |||
setshield(string,float); | |||
setshoecolor oldstring; | |||
setshoecolor(string); | |||
setshootparams oldstring; | |||
setshootparams(string); | |||
setskincolor oldstring; | |||
setskincolor(string); | |||
setsleevecolor oldstring; | |||
setsleevecolor(string); | |||
setstring oldstring, oldstring; | |||
setstring(string,string); | |||
setsword oldstring, float; | |||
setsword(string,float); | |||
seturllevel oldstring; | |||
seturllevel(string); | |||
setz float, float, float, float, float, float, float, float; | |||
setz(float,float,float,float,float,float,float,float); | |||
setzoomeffect float; | |||
setzoomeffect(float); | |||
shoot float, float, float, float, float, float, oldstring, oldstring; | |||
shoot(float,float,float,float,float,float,string,string); | |||
shootarrow float; | |||
shootarrow(float); | |||
shootball; | |||
shootball(); | |||
shootfireball float; | |||
shootfireball(float); | |||
shootfireblast float; | |||
shootfireblast(float); | |||
shootnuke float; | |||
shootnuke(float); | |||
show; | |||
show(); | |||
showani float, float, float, float, oldstring; | |||
showani(float,float,float,float,string); | |||
showani2 float, float, float, float, float, oldstring; | |||
showani2(float,float,float,float,float,string); | |||
showcharacter; | |||
showcharacter(); | |||
showfile oldstring; | |||
showfile(string); | |||
showimg float, oldstring, float, float; | |||
showimg(float,string,float,float); | |||
showimg2 float, oldstring, float, float, float; | |||
showimg2(float,string,float,float,float); | |||
showlocal; | |||
showlocal(); | |||
showpoly float, float; | |||
showpoly(float,array); | |||
showpoly2 float, float; | |||
showpoly2(float,array); | |||
showstats float; | |||
showstats(float); | |||
showtext float, float, float, oldstring, oldstring, oldstring; | |||
showtext(float,float,float,string,string,string); | |||
showtext2 float, float, float, float, oldstring, oldstring, oldstring; | |||
showtext2(float,float,float,float,string,string,string); | |||
sleep float; | |||
sleep(float); | |||
spyfire float, float; | |||
spyfire(float,float); | |||
stopmidi; | |||
stopmidi(); | |||
stopsound oldstring; | |||
stopsound(string); | |||
take oldstring; | |||
take(string); | |||
take2 float; | |||
take2(float); | |||
takehorse float; | |||
takehorse(float); | |||
takeplayercarry; | |||
takeplayercarry(); | |||
takeplayerhorse; | |||
takeplayerhorse(); | |||
throwcarry; | |||
throwcarry(); | |||
timereverywhere; | |||
timereverywhere(); | |||
timershow; | |||
timershow(); | |||
toinventory oldstring; | |||
toinventory(string); | |||
tokenize oldstring; | |||
tokens = string.tokenize(); | |||
tokenize2 oldstring, oldstring; | |||
tokens = string.tokenize(" ," @ string); | |||
toweapons oldstring; | |||
toweapons(string); | |||
triggeraction float, float, oldstring, oldstring; | |||
triggeraction(float,float,string,string); | |||
unfreezeplayer; | |||
unfreezeplayer(); | |||
unset oldstring; | |||
unset(string); | |||
updateboard float, float, float, float; | |||
updateboard(float,float,float,float); | |||
updateterrain; | |||
updateterrain(); | |||
wraptext float, oldstring, oldstring; | |||
tokens = wraptext(float," ," @ string,string); | |||
wraptext2 float, float, oldstring, oldstring; | |||
tokens = wraptext2(float,float," ," @ string,string); | |||
</pre> | |||
=== Supported old string operations === | |||
These old string operators can be used in string parameters | |||
for the old commands, also you can use them directly as operators, e.g. | |||
#c = "hello" | |||
is actually doing | |||
player.chat = "hello" | |||
It is recommended to use the new scripting style though. | |||
<pre> | |||
#a player.account | |||
#a(float) players[float].account | |||
#m player.ani | |||
ani | |||
#m(float) players[float].ani | |||
#K(float) char(float) | |||
#8 player.bodyimg | |||
bodyimg | |||
#8(float) players[float].bodyimg | |||
#c player.chat | |||
chat | |||
#c(float) players[float].chat | |||
#C0 player.colors[0] | |||
colors[0] | |||
#C0(float) players[float].colors[0] | |||
#C1 player.colors[1] | |||
colors[1] | |||
#C1(float) players[float].colors[1] | |||
#C2 player.colors[2] | |||
colors[2] | |||
#C2(float) players[float].colors[2] | |||
#C3 player.colors[3] | |||
colors[3] | |||
#C3(float) players[float].colors[3] | |||
#C4 player.colors[4] | |||
colors[4] | |||
#C4(float) players[float].colors[4] | |||
#C5 player.colors[5] | |||
colors[5] | |||
#C5(float) players[float].colors[5] | |||
#D downloadfile() | |||
#E emoticonchar() | |||
#e(float,float,oldstring) | |||
string.substring(float,float) | |||
#g player.guild | |||
guild | |||
#g(float) players[float].guild | |||
#3 player.headimg | |||
headimg | |||
#3(float) players[float].headimg | |||
#5 player.horseimg | |||
horseimg | |||
#5(float) players[float].horseimg | |||
#k(float) keyname(float) | |||
#L player.level | |||
#I(oldstring,float) | |||
getstring(string)[float] | |||
#n player.nick | |||
nick | |||
#n(float) players[float].nick | |||
#f image | |||
#f(float) npcs[float].image | |||
#F level | |||
#p(float) params[float] | |||
#P(float) player.attr[float] | |||
attr[float] | |||
#P(float_1,float_2) | |||
players[float_2].attr[float_1] | |||
#P1 player.attr[1] | |||
attr[1] | |||
#P1(float) players[float].attr[1] | |||
#P2 player.attr[2] | |||
attr[2] | |||
#P2(float) players[float].attr[2] | |||
#P3 player.attr[3] | |||
attr[3] | |||
#P3(float) players[float].attr[3] | |||
#P4 player.attr[4] | |||
attr[4] | |||
#P4(float) players[float].attr[4] | |||
#P5 player.attr[5] | |||
attr[5] | |||
#P5(float) players[float].attr[5] | |||
#P6 player.attr[6] | |||
attr[6] | |||
#P6(float) players[float].attr[6] | |||
#P7 player.attr[7] | |||
attr[7] | |||
#P7(float) players[float].attr[7] | |||
#P8 player.attr[8] | |||
attr[8] | |||
#P8(float) players[float].attr[8] | |||
#P9 player.attr[9] | |||
attr[9] | |||
#P9(float) players[float].attr[9] | |||
#R(oldstring) string.random() | |||
#2 player.shieldimg | |||
shieldimg | |||
#2(float) players[float].shieldimg | |||
#s(oldstring) getstring(string) | |||
#1 player.swordimg | |||
swordimg | |||
#1(float) players[float].swordimg | |||
#S player.sword.script | |||
#t(float) tokens[float] | |||
#T(oldstring) string.trim() | |||
#v(float) float | |||
#W player.weapon.image | |||
#W(float) weapons[float].image | |||
#w player.weapon.name | |||
#w(float) weapons[float].name | |||
</pre> | |||
Compatibility note: | |||
When you use the command setcharprop then the first parameter | |||
is handled differently: instead of changing 'player.chat' it | |||
is changing 'chat', the chat text of the npc. So 'setcharprop #c,hello' | |||
would be translated into | |||
chat = "hello" | |||
while 'setplayerprop #c,hello' is translated into | |||
player.chat = "hello" | |||
In the list above both possibilities are listed. |
Latest revision as of 10:48, 16 April 2010
Introduction
Why scripts
Scripts bring life into objects and make it easy to customize the game. Instead of just placing a stone into your world, you can make it so that the stone can be lifted or kicked. Instead of being limited to some fixed player movement you can rescript it to let the player jump, strafe and duck. To let the player inspect and organize his/her items you can create some dialogs and display those by script, e.g. when the player presses a special key.
In Graal the scripting is done in 'Graal Script', it's looking like Java/C++, but brings some additional features for making things easier for game creators, while on the other hand running in a sandbox and limiting access to game-related stuff only.
Graal Script is almost fully compatible to the 'old' Graal script used in Graal v1.0 - 3.0, and is partially compatible to Torque script.
NPCs and 'weapons'
There are generally two types of objects in Graal which have scripts: The first type are the non-player-characters (NPCs). The name 'NPC' is actually used for all visible objects in the game: monsters, stones, bushes, houses, ships, plants etc. Scripts for npcs are most of the time containing code for moving the npc or for reacting to activities of the player, e.g. giving money to the player when he/she grabs the npc. The other type of script-holding objects are the 'weapons'. Those are items in the inventory of the player, not necessary being weapons. Most of the time they are actually just scripts which control the movement of the player, display weapon graphics, or display menus.
So there are objects in the game which have their own script, and players which have a set of scripts in their invisible backpack.
Server-side and client-side
Graal is an online game, and there are differences to standard scripting in offline games. In offline programs you have access to everything, anytime. In online games everything is divided into two parts: the server-side which controls most things in the game, and the client-side which displays the game to the player. Since the client only displays things, it is not possible to cheat by hacking the client. On client-side you mainly have code for displaying special effects, for displaying the GUI (windows, status bars, item menus), playing sound effects and music. Also the player movement is done on client-side. On the server-side scripts are used to do the more secure parts of the game engine, and things that are the same for all players - npcs are added, moved, npcs interact with players, the stats of the players are calculated, the communication between players is handled.
All scripts for npcs and weapons can contain server-side code and client-side code. The server-side code is executed directly on the server, the client-side code is sent to the client when he/she logins and executed separately for each player on their own computer. Usually the two parts of the script are divided by a line that only contains "//#CLIENTSIDE", like this:
// Server-side part which is setting the image // of the npc when it is created function onCreated() { setimg("door.png"); } //#CLIENTSIDE // Here follows the client-side part, // which plays a sound effect when the player // touchs the npc function onPlayerTouchsme() { play("chest.wav"); }
Also see clientside and serverside.
Events
In general scripts are made for reacting to events - when the npc is created then the script initializes the attributes of the npc, when the player says something then the npc is moving to the player, when the player grabs the npc then the npc is giving the player some money etc. So the script is basicly a collection of actions that are done when special events are happening. Events can e.g. be the "created" event when the npc is created, the "playertouchsme" event when the player touchs the npc, or the "playerchats" event when the player says something. To write code that reacts to one of those event, you define an event function like this:
function onEVENTNAME() { // actions }
When the event is happening, then Graal executes that scripting function and all commands you have added there. Sometimes the event gives some parameters to the event function, then change your function to:
function onEVENTNAME(parameter1, parameter2, ...) { // actions }
By accessing 'parameter1' etc. (you can name them differently) you can react to the event more exactly.
Instead of reacting to events, the npcs and weapons can also invoke new events. That way you can let other npcs doing things. You also need that if you want to coninuously doing things - use timeout events for that.
function onCreated() { setTimer(1); } function onTimeout() { // actions setTimer(1); }
In the onCreated event function the script is setting the timer to 1 second. When that second is over, then the "timeout" event is invoked on the npc and the onTimeout event function is executed. Because it is setting the timer to 1 second again, the onTimeout event will occur again after one second, and so on.
Compatibility note: In older Graal scripts you will also find the deprecated way of receiving events:
if (EVENTNAME) { // actions }
That is an if-command outside of any brackets. If Graal sees that you use such an if-command, then it will execute the whole script so that the actions you have written inside the if-command will be executed too.
The events for GUI controls are listed in the description of the different object types: Object types
Basics
Accessing variables
Graal Script variables are 'variant', that means they are objects that hold values of different types. When you assign a value to the variable then it automatically switches to the right type:
Numeric (floating point):
var = 1;
String (text):
var = "hello";
Object link:
var = player;
Array (list of objects):
var = {1,2,3};
You can check the current type with the type()-function - obj.type() returns 0,1,2,3 for numeric, string, object or array.
Operators
Addition a + b Substraction a - b Mulitplication a * b Division a / b Modulus a % b Power a ^ b String Concationation a @ b with space a SPC b with newline a NL b with tabulator a TAB b Bool-And a && b Bool-Or a || b Bool-Not !a Negative -a Equal a == b Not-Equal a != b Less a < b Greater a > b Less-Equal a <= b, a =< b Greater-Equal a >= b, a => b In-Range a in <b,c>, a in |b,c>, a in <b,c|, a in |b,c| In-Array a in {b,c,...}, {a,b,...} in {c,d,...} Bitwise-Or a | b Bitwise-And a & b Bitwise-Shift left a << b Bitwise-Shift right a >> b Bitwise-Invert ~a Bitwise-Xor a xor b (operator ^ already used for power) Array-Constructor {a,b,...} Empty Array new [count], new[countdim1][countdim2]... Array Member a[index] Function call a(), a(b,c,...) Object Attribute a.b, a.(b) Post Increment a++ Post Decrement a-- Pre Increment ++a Pre Decrement --a Old String Function #a Conditional a? b : c Assignment a = b, a := b Additive Assignment a += b Substractive Assignment a -= b Multiplicative Assignment a *= b Division Assignment a /= b Modulus Assignment a %= b Power Assignment a ^= b Bitwise-Or Assignment a |= b Bitwise-And Assignment a &= b Shift Left Assignment a <<= b Shift Right Assignment a >>= b String Append a @= b
Standard object functions
Here only some of the built-in functions:
obj.type() - gets the type of the var (float 0, string 1, object 2, array 3) obj.length() - string length obj.trim() - removes spaces from the front and back of a string obj.lower() - converts a string to lower case obj.upper() - converts a string to upper case obj.tokenize([delimiters]) - splits the string into an array wherever the delimiters occur obj.charat(pos) - character at specified position obj.pos(substring) - first position of the substring in the string obj.positions(substring) - array of positions of the substring in the string obj.starts(string) - does the string start with the specified string? obj.ends(string) - does the string end with the specified string? obj.substring(index[,length]) - returns the string starting at the index and ending after the length specified obj.size() - array length obj.add(obj2) - adds an object to an array obj.delete(index) - deletes the object from an array at the specified index obj.remove(obj2) - removes the first instance of the specified object from the array obj.replace(index,obj2) - replace the object at the specified index obj.insert(index,obj2) - insert the object at the index without replacing other indexes obj.clear() - clear the array obj.subarray(index[,length]) obj.addarray(obj2) obj.insertarray(index,obj2) obj.index(obj2) - position of obj2 in the array obj.indices(obj2) - positions of obj2 in the array obj.link() - used to pass an array to a function which can modify the array, also prevents copying of huge arrays
Also see TGraalVar for more functions for objects.
Standard functions
_(string) - translates a text on serverside to the language of the current player, if translations are enabled abs(float) - returns absolute value of the float arctan(float) - arcus tangens char(ascii) - gets the character for an ascii code (char(65) returns 'A') cos(angle) - cosinus of a radiant angle exp(float) float(string) - for explicitely converting a string to number (normally done automatically though when accessing a string with numeric operators) format(format,parameters,...) - formats a "%s %d" string, inserts the parameters, and returns a string getangle(delta x,delta y) - [http://en.wikipedia.org/wiki/Atan2 atan2] getdir(delta x,delta y) - returns the direction for the delta x and y int(a) - gets the integer part of a floating point number (truncates at the decimal) log(base,a) max(a,b) - returns the highest value between the two given min(a,b) - returns the lowest value between the two given printf(format,parameters,...) - same as echo(format(format,parameters,...)) random(rangestart,rangeend) - returns a random float between rangestart and rangeend sin(angle) - sinus of a radiant angle sleep(time) - suspends the current script for the time vecx(direction 0..3) - direction to move x if dir is the specified direction vecy(direction 0..3) - direction to move y if dir is the specified direction waitfor(objectname,event[,timeout]) - suspends the current script and waits until an event is invoked on the specified object, returns false when the parameters are wrong or the event was not received before the timeout; only available in the latest versions of npcserver
Also see Client Functions for more functions.
Old script compatibility
Removed functionality
- toinventory - followplayer - playersays() - setbackpal
Supported old scripting commands and their mapping to new script
addstring oldstring, oldstring; list.add(string); addtiledef oldstring, oldstring, float; addtiledef(string,string,float); addtiledef2 oldstring, oldstring, float, float; addtiledef2(string,string,float,float); attachplayertoobj float, float; attachplayertoobj(float,float); blockagain; blockagain(); blockagainlocal; blockagainlocal(); callnpc float, oldstring; callnpc(float,string); callweapon float, oldstring; callweapon(float,string); canbecarried; canbecarried(); canbepulled; canbepulled(); canbepushed; canbepushed(); cannotbecarried; cannotbecarried(); cannotbepulled; cannotbepulled(); cannotbepushed; cannotbepushed(); canwarp; canwarp(); canwarp2; canwarp2(); carryobject oldstring; carryobject(string); changeimgcolors float, float, float, float, float; changeimgcolors(float,float,float,float,float); changeimgmode float, float; changeimgmode(float,float); changeimgpart float, float, float, float, float; changeimgpart(float,float,float,float,float); changeimgvis float, float; changeimgvis(float,float); changeimgzoom float, float; changeimgzoom(float,float); deletestring oldstring, float; deletestring(string,float); destroy; destroy(); detachplayer; detachplayer(); disabledefmovement; disabledefmovement(); disablemap; disablemap(); disablepause; disablepause(); disableselectweapons; disableselectweapons(); disableweapons; disableweapons(); dontblock; dontblock(); dontblocklocal; dontblocklocal(); drawaslight; drawaslight(); drawoverplayer; drawoverplayer(); drawunderplayer; drawunderplayer(); enabledefmovement; enabledefmovement(); enablefeatures float; enablefeatures(float); enablemap; enablemap(); enablepause; enablepause(); enableselectweapons; enableselectweapons(); enableweapons; enableweapons(); explodebomb float; explodebomb(float); followplayer; followplayer(); freezeplayer float; freezeplayer(float); freezeplayer2; freezeplayer2(); hide; hide(); hideimg float; hideimg(float); hideimgs float, float; hideimgs(float,float); hidelocal; hidelocal(); hitcompu float, float, float, float; hitcompu(float,float,float,float); hitnpc float, float, float, float; hitnpc(float,float,float,float); hitobjects float, float, float; hitobjects(float,float,float); hideplayer float; hideplayer(float); hidesword float; hidesword(float); hitplayer float, float, float, float; hitplayer(float,float,float,float); hurt float; hurt(float); insertstring oldstring, float, oldstring; insertstring(string,float,string); join oldstring; join(string); lay oldstring; lay(string); lay2 oldstring, float, float; lay2(string,float,float); loadmap oldstring; loadmap(string); message oldstring; message(string); move float, float, float, float; move(float,float,float,float); noplayerkilling; noplayerkilling(); openurl oldstring; openurl(string); openurl2 oldstring, float, float; openurl2(string,float,float); play oldstring; play(string); play2 oldstring, float, float, float; play2(string,float,float,float); playlooped oldstring; playlooped(string); putbomb float, float, float; putbomb(float,float,float); putcomp oldstring, float, float; putcomp(string,float,float); putexplosion float, float, float; putexplosion(float,float,float); putexplosion2 float, float, float, float; putexplosion2(float,float,float,float); puthorse oldstring, float, float; puthorse(string,float,float); putleaps float, float, float; putleaps(float,float,float); putnewcomp oldstring, float, float, oldstring, float; putnewcomp(string,float,float,string,float); putnpc oldstring, oldstring, float, float; putnpc(string,string,float,float); putnpc2 float, float, oldstring; putnpc2(float,float,string); reflectarrow float; reflectarrow(float); removearrow float; removearrow(float); removebomb float; removebomb(float); removecompus; removecompus(); removeexplo float; removeexplo(float); removehorse float; removehorse(float); rmeoveitem float; removeitem(float) removestring oldstring, oldstring; removestring(string,string); removetiledefs oldstring; removetiledefs(string); replaceani oldstring, oldstring; replaceani(string,string); replacestring oldstring, float, oldstring; replacestring(string,float,string); resetfocus; resetfocus(); savelog oldstring; savelog(string); savelog2 oldstring, oldstring; savelog2(string,string); say float; say(float); say2 oldstring; say2(string); sendrpgmessage oldstring; sendrpgmessage(string); sendpm oldstring; sendpm(string); sendtonc oldstring; sendtonc(string); sendtorc oldstring; sendtorc(string); serverwarp oldstring; serverwarp(string); set oldstring; set(string); setani oldstring, oldstring; setani(string,string); setarray float, float; setarray(var,float); setbeltcolor oldstring; setbeltcolor(string); setbow oldstring; setbow(string); setcharani oldstring, oldstring; setcharani(string,string); setchargender oldstring; setchargender(string); setcharprop oldstring, oldstring; string = string; setcoatcolor oldstring; setcoatcolor(string); setcoloreffect float, float, float, float; setcoloreffect(float,float,float,float); setcursor float; setcursor(float); setcurcor2 oldstring; setcursor2(string); seteffect float, float, float, float; seteffect(float,float,float,float); seteffectmode float; seteffectmode(float); setfocus float, float; setfocus(float,float); setgender oldstring; setgender(string); sethead oldstring; sethead(string); setlevel oldstring; setlevel(string); setlevel2 oldstring, float, float; setlevel2(string,float,float); setmap oldstring, oldstring, float, float; setmap(string,string,float,float); setminimap oldstring, oldstring, float, float; setminimap(string,string,float,float); setmusicvolume float, float; setmusicvolume(float,float); setimg oldstring; setimg(string); setimgpart oldstring, float, float, float, float; setimgpart(string,float,float,float,float); setletters oldstring; setletters(string); setplayerdir oldstring; setplayerdir(string); setplayerprop oldstring, oldstring; string = string; setpm oldstring; setpm(string); setshape float, float, float; setshape(float,float,float); setshape2 float, float, float; setshape2(float,float,float); setshield oldstring, float; setshield(string,float); setshoecolor oldstring; setshoecolor(string); setshootparams oldstring; setshootparams(string); setskincolor oldstring; setskincolor(string); setsleevecolor oldstring; setsleevecolor(string); setstring oldstring, oldstring; setstring(string,string); setsword oldstring, float; setsword(string,float); seturllevel oldstring; seturllevel(string); setz float, float, float, float, float, float, float, float; setz(float,float,float,float,float,float,float,float); setzoomeffect float; setzoomeffect(float); shoot float, float, float, float, float, float, oldstring, oldstring; shoot(float,float,float,float,float,float,string,string); shootarrow float; shootarrow(float); shootball; shootball(); shootfireball float; shootfireball(float); shootfireblast float; shootfireblast(float); shootnuke float; shootnuke(float); show; show(); showani float, float, float, float, oldstring; showani(float,float,float,float,string); showani2 float, float, float, float, float, oldstring; showani2(float,float,float,float,float,string); showcharacter; showcharacter(); showfile oldstring; showfile(string); showimg float, oldstring, float, float; showimg(float,string,float,float); showimg2 float, oldstring, float, float, float; showimg2(float,string,float,float,float); showlocal; showlocal(); showpoly float, float; showpoly(float,array); showpoly2 float, float; showpoly2(float,array); showstats float; showstats(float); showtext float, float, float, oldstring, oldstring, oldstring; showtext(float,float,float,string,string,string); showtext2 float, float, float, float, oldstring, oldstring, oldstring; showtext2(float,float,float,float,string,string,string); sleep float; sleep(float); spyfire float, float; spyfire(float,float); stopmidi; stopmidi(); stopsound oldstring; stopsound(string); take oldstring; take(string); take2 float; take2(float); takehorse float; takehorse(float); takeplayercarry; takeplayercarry(); takeplayerhorse; takeplayerhorse(); throwcarry; throwcarry(); timereverywhere; timereverywhere(); timershow; timershow(); toinventory oldstring; toinventory(string); tokenize oldstring; tokens = string.tokenize(); tokenize2 oldstring, oldstring; tokens = string.tokenize(" ," @ string); toweapons oldstring; toweapons(string); triggeraction float, float, oldstring, oldstring; triggeraction(float,float,string,string); unfreezeplayer; unfreezeplayer(); unset oldstring; unset(string); updateboard float, float, float, float; updateboard(float,float,float,float); updateterrain; updateterrain(); wraptext float, oldstring, oldstring; tokens = wraptext(float," ," @ string,string); wraptext2 float, float, oldstring, oldstring; tokens = wraptext2(float,float," ," @ string,string);
Supported old string operations
These old string operators can be used in string parameters for the old commands, also you can use them directly as operators, e.g.
#c = "hello"
is actually doing
player.chat = "hello"
It is recommended to use the new scripting style though.
#a player.account #a(float) players[float].account #m player.ani ani #m(float) players[float].ani #K(float) char(float) #8 player.bodyimg bodyimg #8(float) players[float].bodyimg #c player.chat chat #c(float) players[float].chat #C0 player.colors[0] colors[0] #C0(float) players[float].colors[0] #C1 player.colors[1] colors[1] #C1(float) players[float].colors[1] #C2 player.colors[2] colors[2] #C2(float) players[float].colors[2] #C3 player.colors[3] colors[3] #C3(float) players[float].colors[3] #C4 player.colors[4] colors[4] #C4(float) players[float].colors[4] #C5 player.colors[5] colors[5] #C5(float) players[float].colors[5] #D downloadfile() #E emoticonchar() #e(float,float,oldstring) string.substring(float,float) #g player.guild guild #g(float) players[float].guild #3 player.headimg headimg #3(float) players[float].headimg #5 player.horseimg horseimg #5(float) players[float].horseimg #k(float) keyname(float) #L player.level #I(oldstring,float) getstring(string)[float] #n player.nick nick #n(float) players[float].nick #f image #f(float) npcs[float].image #F level #p(float) params[float] #P(float) player.attr[float] attr[float] #P(float_1,float_2) players[float_2].attr[float_1] #P1 player.attr[1] attr[1] #P1(float) players[float].attr[1] #P2 player.attr[2] attr[2] #P2(float) players[float].attr[2] #P3 player.attr[3] attr[3] #P3(float) players[float].attr[3] #P4 player.attr[4] attr[4] #P4(float) players[float].attr[4] #P5 player.attr[5] attr[5] #P5(float) players[float].attr[5] #P6 player.attr[6] attr[6] #P6(float) players[float].attr[6] #P7 player.attr[7] attr[7] #P7(float) players[float].attr[7] #P8 player.attr[8] attr[8] #P8(float) players[float].attr[8] #P9 player.attr[9] attr[9] #P9(float) players[float].attr[9] #R(oldstring) string.random() #2 player.shieldimg shieldimg #2(float) players[float].shieldimg #s(oldstring) getstring(string) #1 player.swordimg swordimg #1(float) players[float].swordimg #S player.sword.script #t(float) tokens[float] #T(oldstring) string.trim() #v(float) float #W player.weapon.image #W(float) weapons[float].image #w player.weapon.name #w(float) weapons[float].name
Compatibility note: When you use the command setcharprop then the first parameter is handled differently: instead of changing 'player.chat' it is changing 'chat', the chat text of the npc. So 'setcharprop #c,hello' would be translated into chat = "hello" while 'setplayerprop #c,hello' is translated into player.chat = "hello" In the list above both possibilities are listed.