Scripting guide

Scripts - where do I put them?

Each server/game has its own script project with the sub-folders scriptclasses (for server scripts) and clientclasses (to run on the phone/browser). Look there to also see some cool existing scripts.

But how do you use the scripts? In Tiled (the map editor we use) you can add following custom properties for each object. Don't forget to set type to "NPC" (note: not required anymore but still good to do)!

Another way is to type /addscriptnpc as admin, which is adding a "rock", which is actually a scriptable NPC. Click on the rock to change its look and add a script.

For other objects you need to define the scriptclasses in a configuration file:

Script events (functions)

When certain things happen, such as the player colliding (touching) with the NPC, then the script of the NPC is started and can react to the collision event. You can react to the event by writing a function "function onEventname" such as

function onPlayerSays(pl) {
}

Following events exist right now:

For all scripted objects:

For NPCs:

See more at NPC Reference

For players:

See more at Player Reference

For weapons / tools:

For items:

For projectiles:

Objects and global variables

Following objects and variables exist. Some of these are read-only. You can additionally set attributes of the objects and call functions.

Non-Player Character

The NPC object can be accessed by the identifier this. If you change a property (such as image or ani) and want it to be permanent, then call this.save(). Most attributes can also be changed by calling setATTRIBUTE(name) such as this.setchat(text). NPC functions are currently also available as global functions, so that you can call either "this.say(text)" or "say(text)", although the use of this.say is recommended. Object attributes defined in Tiled can also be accessed by script, such as this.npcclass.

See more at NPC Reference

Player

The player who was causing the event can be accessed with the identifier player. You can add custom variables to the player object (player.myvar = 123). These are kept until the player logouts, and are saved to the player object permanently when being configured in syncscriptvars.json.

See more at Player Reference

Maps

You can access the current map or the map of the player by this.map and player.map. The map itself has following attributes and functions. Also check out the Tiled-guide

See more at Map Reference

Server

See more at Server Reference

GUI

GUI Controls are used to pop up a window on the players screen, on client-side. The functions that are used are:

See a full list at GUI Reference

Database

Database tables must be created manually using the file browser. Following function exist to access the database:

See a full list at DB Reference and an Example: Database

Image functions

Load, change and save image data on server-side.

Misc

Simple Scripting Examples

You can find some more complex examples in Examples/ folder. Here some basic examples such as adding items and starting a timeout (there is also a this.sleep(seconds) function!).

Adding items

This adds a firework once you say three times "yes".

function onPlayerTouchsMe(pl) {
    this.say("Say 'yes' three times if you want to get a firework!");
}

function onPlayerSays(pl) {
    if (pl.chat == "yes") {
        pl.saycounter = (pl.saycounter? pl.saycounter+1 : 1);
        if (pl.saycounter < 3)
            this.say("Say 'yes' " + (3-pl.saycounter) + " more time(s)!");
        else {
            pl.saycounter = 0;
            if (pl.hasitem("firework1"))
                this.say("You already have that!");
            else if (pl.additem("firework1"))
                this.say("There it is!");
            else
                this.say("There was a problem adding the item!");
        }
    }
}  

Scheduling a timeout or a scheduled event

function onPlayerTouchsMe(pl) {
    if (!this.touched)
      this.touched = 0;
    this.touched++;
    this.say("check: " + pl.name + " - " + this.touched + " - " + pl.x);

    this.settimeout(2); //Start the timeout
    this.scheduleevent(1, "myevent", 123); //Or start a scheduled event
}

//After 2 seconds the timeout function is called
function onTimeout() {
    this.say("Timeout!");
}

//After 1 second the scheduled event is called
function onMyEvent(testvar) {
    this.say("MyEvent: " + testvar + "!");
}  

Copy and NPC Movement

//If the player says copy, the NPC will look exactly like the player
function onPlayerSays(pl) {
    switch (pl.chat) {
        case "copy": {
            this.setani("player_idle"); // pl.ani);
            this.sethead(pl.head);
            this.setbody(pl.body);
            this.sethat(pl.hat);
            this.setweapon(null); // pl.weapon);
            this.setmount(null); // pl.mount);
            this.setbow(pl.bow);
            this.save();
            this.say("Copied you!");
            break;
        }
        case "come": {  
            let time = 1;
            this.scheduleevent(time, "movefinished", this.ani); //Invoke the MoveFinished event once it arrives at the destination
            this.setani("player_walk"); //Act as though the object is moving
            this.move(time, player.x, player.y); //Move the object to the location of the player
            break;
        }
    }
}

//Created by the scheduleevent above and is called once the object has finished moving
function onMoveFinished(newani) {
    this.setani(newani);
}  

Music

Client-side juke-box, use commands play1, play2, play3, play radio and stop music

function onPlayerSays(pl) {
    switch (pl.chat) {
        case "play1": { this.setmusic("egyptmusic.mp3"); break; }
        case "play2": { this.setmusic("dungeon_music1.mp3"); break; }
        case "play3": { this.setmusic("diningmusic.mp3"); break; }
        case "play radio": { this.setmusic("http://streams.antennemv.de/antennemv-live/mp3-128/listenlive/play.m3u"); break; }
        case "stop music": { this.stopmusic(); break; }
    }
}