Forgot? Join

Scripting

LSL Guide

Every script function this grid actually runs, read straight from the region software rather than copied from a wiki — including the wolf* functions that exist only here.

Functions · Constants

wolfCall

Wolf Territories
list wolfCall(string name, list args)

Calls the Wolf plugin function `name` with `args` and returns its answer as a list. Returns an empty list with wolfGetLastError saying why when there is no such plugin function on this region, the plugin refused, ran too long or failed. Defined on Wolf_Api.wolfCall / IWolfPluginCalls.

Calls a Wolf plugin function and returns its answer as a list. Plugins are pieces of region software the grid adds and updates while the region keeps running - no restart - so new features can arrive without waiting for one. Each plugin gives its functions names (for example "echo" or "greet"); wolfCall finds whichever plugin answers that name on this region now. The list you pass is handed to the plugin as it is (integers, floats, strings, keys, vectors and rotations keep their types) and its answer comes back the same way. A call takes a moment at most: the region stops a plugin that runs too long. If there is no such function on this region, the plugin refuses, fails or is busy, you get an empty list and wolfGetLastError says why. A function that needs time (one that asks the web, say) answers through wolfCallAsync instead, and says so if you use wolfCall. Which plugins a region has is up to the grid; the commands every Wolf Territories region answers are listed below.

Parameters

TypeName What it does
string name The plugin function to call, e.g. "echo".
list args What to give it: any list.

Example

// Ask the region's echo plugin something and say the answer.
touch_start(integer n)
{
    list answer = wolfCall("echo", [llDetectedName(0), 42, <1.0, 2.0, 3.0>]);
    if (llGetListLength(answer) == 0)
        llOwnerSay("No answer: " + wolfGetLastError());
    else
        llOwnerSay("The plugin answered " + llList2CSV(answer));
}

Wolf plugin commands on this grid

Every Wolf Territories region answers these names (the wolf-commands plugin). With them a script anywhere on the region - rezzed on your land or worn as a HUD - runs your own WolfNPCs. npc is the NPC's key (from npc.list, or its object's key).

wolf-commands: the names, what to give, what comes back, who may use them
NameGive itYou get backWho mayWhat it does
wolf.version[]["wolf-commands", version, 1]anyoneWhich version of these commands this region runs.
wolf.commands[]the command namesanyoneEvery command in this list that this region answers.
npc.list[] or ["all"][count, key, name, rights, ...]anyoneYour NPCs on this region, or with "all" every NPC here. Rights is "edit" (yours to run), "control" (you may stop it, send it home, animate it, make a dragon breathe) or "none". At most 80 are listed; count is all of them.
npc.info[npc] or [npc, "STATE" | "INTENT" | "EVENTS" | "CFG"][text]control; CFG: ownerSTATE is "intention|awake or asleep|alive or dead|health/max". INTENT is what it is doing, EVENTS its running events, CFG all its settings as JSON.
npc.say[npc, text]["ok"]ownerIt says the words (up to 1000 characters) in local chat. An NPC speaks at most 5 lines in ten seconds.
npc.goto[npc, <x, y, z>] or [npc, place]["ok"]ownerIt walks to that spot on this region, or to one of its own places (or tools) by name.
npc.follow[npc, key or name] or [npc, ""]["ok"]ownerIt follows an avatar or NPC on this region; "" stops following.
npc.stop[npc]["ok"]controlIt stops and stands. Its looped animations stop too.
npc.home[npc] or [npc, "here"]["ok"]control; "here": ownerIt goes home. With "here", where it stands now becomes its home.
npc.anim[npc, animation] or [npc, animation, "once" | "loop" | "stop"]["ok"]controlPlays one of the animations in its contents once (the default), keeps it looping, or stops it. [npc, "", "stop"] stops them all.
npc.breath[npc, "fire" | "ice" | "stop"] or [npc, "fire" | "ice", seconds]["ok"]controlA dragon breathes fire or ice for 0.5 to 20 seconds (0 or none = 3), the same breath as in its window.

Who may

  • owner: the NPC's owner, while they may still build where it lives - they own the region or are one of its estate managers, or they own the parcel under its home (a travelling pet: anywhere). The same rule as editing it in the NPC window.
  • control: the owner as above, or the region's owner or an estate manager - what the NPC window lets them do with anyone's NPC. They can never make someone else's NPC speak, walk, follow, move its home or read its settings.
  • The script must belong to the owner of the object it is in: someone else's script dropped into your object never acts for you. Only NPCs on the same region.

Answers and limits

  • Every command answers at least one value. An empty list (wolfCall) or NULL_KEY (wolfCallAsync) means it was refused, and wolfGetLastError() says why in plain words - for example "only its owner can do that".
  • ["ok"] means the NPC has been told; it does it straight away, even while it is asleep with nobody near.
  • With wolfCallAsync the answer comes in dataserver as one string, the values joined with "|".
  • At most 20 calls in ten seconds from one object, 60 from all of one resident's objects, and 600 from the whole region; an NPC says at most 5 lines in ten seconds. Over that, the call is refused with a message and works again a few seconds later.

Example: make your NPC come to you and say hello

// Touch: your first NPC on this region walks to you and greets you.
touch_start(integer n)
{
    if (llDetectedKey(0) != llGetOwner()) return;
    list mine = wolfCall("npc.list", []);          // [count, key, name, rights, ...]
    if (llList2Integer(mine, 0) == 0)
    {
        llOwnerSay("No NPCs of yours here. " + wolfGetLastError());
        return;
    }
    key npc = llList2Key(mine, 1);
    if (wolfCall("npc.goto", [npc, llDetectedPos(0)]) == [])
        llOwnerSay("It will not come: " + wolfGetLastError());
    else
        wolfCall("npc.say", [npc, "Hello, " + llDetectedName(0) + "!"]);
}
A whole NPC remote to wear as a HUD (wolf_npc_remote.lsl, 113 lines: show or hide)

Download wolf_npc_remote.lsl

// Wolf NPC remote - wear it as a HUD (or rez it on your land) and control your own WolfNPCs on this region.
// Uses the wolf-commands plugin through wolfCall: no region restart is ever needed for these commands.
// Touch: pick one of your NPCs, then what it should do. Only NPCs you own (and may still run here) obey you.
// Wolf Territories, 2026. Copy, change and share freely.

integer CHANNEL;
integer listener;
list npcKeys;
list npcNames;
key chosen;
string chosenName;

// Every wolf-commands call answers with a list; an empty list means "refused", and wolfGetLastError() says why.
integer tell(string what, list answer)
{
    if (llGetListLength(answer) == 0)
    {
        llOwnerSay(what + ": " + wolfGetLastError());
        return FALSE;
    }
    return TRUE;
}

listenFor(float seconds)
{
    llListenRemove(listener);
    listener = llListen(CHANNEL, "", llGetOwner(), "");
    llSetTimerEvent(seconds);
}

pickNpc()
{
    // [count, key, name, rights, key, name, rights, ...] - rights is "edit", "control" or "none".
    list r = wolfCall("npc.list", []);
    if (!tell("Your NPCs", r)) return;
    npcKeys = [];
    npcNames = [];
    integer i;
    for (i = 1; i + 2 < llGetListLength(r) && llGetListLength(npcNames) < 12; i += 3)
    {
        if (llList2String(r, i + 2) != "none")
        {
            npcKeys += llList2Key(r, i);
            npcNames += llGetSubString(llList2String(r, i + 1), 0, 23);
        }
    }
    if (npcNames == [])
    {
        llOwnerSay("You have no NPCs you can control on this region.");
        return;
    }
    listenFor(60.0);
    llDialog(llGetOwner(), "Which NPC?", npcNames, CHANNEL);
}

pickAction()
{
    listenFor(60.0);
    llDialog(llGetOwner(), chosenName + " - what should it do?",
        ["Come here", "Follow me", "Stop", "Go home", "Say hello", "Status", "Fire", "Ice"], CHANNEL);
}

default
{
    state_entry()
    {
        CHANNEL = -1 - (integer)("0x" + llGetSubString((string)llGetKey(), 0, 6));
        chosen = NULL_KEY;
    }

    touch_start(integer n)
    {
        if (llDetectedKey(0) == llGetOwner()) pickNpc();
    }

    listen(integer ch, string name, key id, string msg)
    {
        integer i = llListFindList(npcNames, [msg]);
        if (chosen == NULL_KEY || i != -1)
        {
            if (i == -1) return;
            chosen = llList2Key(npcKeys, i);
            chosenName = msg;
            pickAction();
            return;
        }
        list r;
        if (msg == "Come here") r = wolfCall("npc.goto", [chosen, llList2Vector(llGetObjectDetails(llGetOwner(), [OBJECT_POS]), 0)]);
        else if (msg == "Follow me") r = wolfCall("npc.follow", [chosen, llGetOwner()]);
        else if (msg == "Stop") r = wolfCall("npc.stop", [chosen]);
        else if (msg == "Go home") r = wolfCall("npc.home", [chosen]);
        else if (msg == "Say hello") r = wolfCall("npc.say", [chosen, "Hello, " + llKey2Name(llGetOwner()) + "!"]);
        else if (msg == "Fire" || msg == "Ice") r = wolfCall("npc.breath", [chosen, llToLower(msg), 3.0]);   // dragons only
        else if (msg == "Status")
        {
            // "intention|awake or asleep|alive or dead|health/max"
            r = wolfCall("npc.info", [chosen]);
            if (tell(chosenName, r)) llOwnerSay(chosenName + ": " + llList2String(r, 0));
        }
        if (msg != "Status") tell(chosenName, r);
        chosen = NULL_KEY;
        llListenRemove(listener);
        llSetTimerEvent(0.0);
    }

    timer()
    {
        llListenRemove(listener);
        llSetTimerEvent(0.0);
        chosen = NULL_KEY;
    }
}
Energy 10

Ours alone. Grid features you will not find on any other OpenSimulator grid.

More in Wolf Territories