← Incoprea Workshop

Incoprea · Virtual world workshop

Small scripts.
Worlds of possibility.

Second Life & OpenSim Script Library — practical LSL examples, plain-language how-tos, and a few strange little inventions.

1211 original examples to explore and adapt. These have not been compiled or tested in-world. OpenSim / OSgrid compatibility needs checking on your region. Test on a spare object and read the setup and stopping instructions.

Imagined scripting workbench with a shark orbiting a wireframe world, building blocks, and a miniature doorway.
Build a little motion into your world. AI-generated concept illustration, not an in-world screenshot.

Find something to build

1211 original scripts in 18 expandable categories. Open a category, then a script for its code and setup. Search also looks inside the code.

1211 scripts

Build & animate 2 categories
MovementRotation, linked parts, and small moving builds.69 scripts

Download this category (.zip)

Movement · Intermediate

Actual child orbit around root

Orbit one child around the root while the root remains stationary.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place the moving child offset horizontally from the root. Put the script in that child; owner-touch starts.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. The initial root-local Z is retained. The child orientation turns with the path, preserving its starting tangential alignment. One revolution takes about 63 seconds.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            float angle=llGetTime()*0.1;
            rotation turn=llEuler2Rot(<0.0,0.0,angle>);
            vector p=home*turn;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,rest*turn]);
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float angle=llGetTime()*0.1;
        rotation turn=llEuler2Rot(<0.0,0.0,angle>);
        vector p=home*turn;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,rest*turn]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Align child to root axes

Temporarily align a child’s axes with the root while keeping its position unchanged.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child. Owner-touch sets its local rotation to identity; touch again restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Useful for inspecting modeled axes and preparing aligned displays. A mesh’s apparent forward may not match its local axes.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
rotation home;
default
{
    state_entry()
    {
        home=llGetLocalRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,ZERO_ROTATION]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Align child top to root plane

Place a child bounding-box top at a specified root-local height.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set TOP_HEIGHT. Use a nonphysical child with meaningful bounding-box dimensions. Owner-touch applies/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Useful for aligning shelf undersides or ceiling details. It uses projected bounding-box height, not exact mesh geometry.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
float TOP_HEIGHT=1.0;
vector home;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            vector size=llGetScale();
            rotation r=llGetLocalRot();
            vector x=<1.0,0.0,0.0>*r;
            vector y=<0.0,1.0,0.0>*r;
            vector z=<0.0,0.0,1.0>*r;
            float half=(llFabs(x.z)*size.x+llFabs(y.z)*size.y+llFabs(z.z)*size.z)*0.5;
            vector p=home;
            p.z=TOP_HEIGHT-half;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Allocate keyframe time by segment length

Assign times to polyline points for an approximately constant linear speed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set POINTS and positive SPEED. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Each segment is linear with instantaneous corner direction changes; smooth turning requires additional planning.

// Original Incoprea. MIT. Motion planning only.
list POINTS=[<0.0,0.0,0.0>,<3.0,0.0,0.0>,<3.0,4.0,0.0>];
float SPEED=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPEED<=0.0||llGetListLength(POINTS)<2)
        {
            llOwnerSay("Positive speed and two points required.");
            return;
        }
        float time;
        llOwnerSay("Frame0 time0");
        integer i;
        for(i=1;i<llGetListLength(POINTS);++i)
        {
            time+=llVecDist(llList2Vector(POINTS,i-1),llList2Vector(POINTS,i))/SPEED;
            llOwnerSay("Frame "+(string)i+" time="+(string)time);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Analog hour hand

Set an hour hand continuously between hour marks using the UTC hour and minute.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a hinge-centered child hand pointing +X in a root-local XY clock face. Owner-touch starts one-minute updates.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. A complete clock combines this with the separate minute-hand script. This uses UTC rather than local daylight-saving rules.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            string stamp=llGetTimestamp();
            integer hour=(integer)llGetSubString(stamp,11,12)%12;
            integer minute=(integer)llGetSubString(stamp,14,15);
            float angle=PI_BY_TWO-TWO_PI*(hour+minute/60.0)/12.0;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,angle>)]);
            llSetTimerEvent(60);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        string stamp=llGetTimestamp();
        integer hour=(integer)llGetSubString(stamp,11,12)%12;
        integer minute=(integer)llGetSubString(stamp,14,15);
        float angle=PI_BY_TWO-TWO_PI*(hour+minute/60.0)/12.0;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,angle>)]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Analog minute hand

Set a child hand to the current UTC minute around its local Z pivot.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a hinge-centered clock hand with +X pointing to the right at startup. Root-local clock face should be in XY; put the script in the child.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. The hand points to +Y at minute zero and rotates clockwise. It sets the actual angle, not an accumulating timer approximation.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            string stamp=llGetTimestamp();
            integer minute=(integer)llGetSubString(stamp,14,15);
            integer second=(integer)llGetSubString(stamp,17,18);
            float angle=PI_BY_TWO-TWO_PI*(minute+second/60.0)/60.0;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,angle>)]);
            llSetTimerEvent(1);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        string stamp=llGetTimestamp();
        integer minute=(integer)llGetSubString(stamp,14,15);
        integer second=(integer)llGetSubString(stamp,17,18);
        float angle=PI_BY_TWO-TWO_PI*(minute+second/60.0)/60.0;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,angle>)]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Bobbing exhibit on a pedestal

Owner touch starts or stops a small vertical bob of one child exhibit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child prim of a nonphysical stationary pedestal. The initial child position is the resting pose. Uses the root’s local Z direction.

Stop / restore: Touch to stop and restore the starting position before removing or resetting.

Actual child position changes, unlike visual target-omega. Keep the amplitude small and do not relink while running.

// Original Incoprea example. MIT. Not compiled or tested in-world.
vector home;
integer active;
default
{
    state_entry()
    {
        home = llGetLocalPos();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() < 2) return;
        if (llGetStatus(STATUS_PHYSICS)) return;
        active = !active;
        if (active)
        {
            llResetTime();
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POS_LOCAL, home]);
        }
    }
    timer()
    {
        if (llGetLinkNumber() < 2 || llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active = FALSE;
            return;
        }
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POS_LOCAL, home + <0.0, 0.0, 0.12 * llSin(llGetTime())>]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Bottom-anchored telescoping display

Double a child’s height while moving its center to keep the lower end in place.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a small nonphysical child aligned along its local Z axis. Owner-touch extends and retracts.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. Designed for an ordinary centered prim or centered mesh with matching bounds.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_SIZE, PRIM_POS_LOCAL, PRIM_ROT_LOCAL]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview = !preview;
        if (preview)
        {
            vector size=llList2Vector(saved,0);
            vector pos=llList2Vector(saved,1);
            rotation rot=llList2Rot(saved,2);
            vector offset=<0.0,0.0,size.z*0.5>*rot;
            size.z*=2.0;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SIZE,size,PRIM_POS_LOCAL,pos+offset]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SIZE,llList2Vector(saved,0),PRIM_POS_LOCAL,llList2Vector(saved,1)]);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Bounded angular sweep study

Sweep a child through a chosen angular range once and return to its resting orientation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a hinge-centered child. Owner-touch starts a ten-second sweep from 0 to 60 degrees and back.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. An angular inspection sweep is useful for clearance review. It does not sense collisions; observe the build on a copy.

// Original Incoprea. MIT. Not compiled or tested in-world.
rotation home;
integer active;
default
{
    state_entry()
    {
        home=llGetLocalRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        if(active)
        {
            active=FALSE;
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,home]);
            return;
        }
        active=TRUE;
        llResetTime();
        llSetTimerEvent(0.2);
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float t=llGetTime();
        if(t>=10.0)
        {
            active=FALSE;
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,home]);
            return;
        }
        float f=t/5.0;
        if(f>1.0)f=2.0-f;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,60.0*DEG_TO_RAD*f>)*home]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            home=llGetLocalRot();
            llOwnerSay("Links changed; current pose is the new Home.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Calculate a non-oscillating return

Evaluate a critically damped scalar return from initial displacement and velocity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive OMEGA, initial OFFSET/VELOCITY and nonnegative TIME. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Analytical unit-mass model. Large parameter products may underflow harmlessly toward zero.

// Original Incoprea. MIT. Motion planning only.
float OMEGA=3.0;
float OFFSET=1.0;
float VELOCITY=0.0;
float TIME=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OMEGA<=0.0||TIME<0.0)
        {
            llOwnerSay("Invalid frequency/time.");
            return;
        }
        float b=VELOCITY+OMEGA*OFFSET;
        float decay=llPow(2.718281828,-OMEGA*TIME);
        float x=(OFFSET+b*TIME)*decay;
        float v=(b-OMEGA*(OFFSET+b*TIME))*decay;
        llOwnerSay("Offset="+(string)x+" velocity="+(string)v);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Cap catch-up simulation work

Calculate bounded fixed updates and leftover accumulator after a long frame.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set nonnegative ACCUMULATOR/ELAPSED, positive STEP, and MAX_STEPS1..100. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Explicitly reports discarded backlog to avoid a spiral of excessive catch-up work. This is a planning demonstration.

// Original Incoprea. MIT. Motion planning only.
float ACCUMULATOR=0.02;
float ELAPSED=0.4;
float STEP=0.05;
integer MAX_STEPS=4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ACCUMULATOR<0.0||ELAPSED<0.0||STEP<=0.0||MAX_STEPS<1||MAX_STEPS>100)
        {
            llOwnerSay("Invalid step configuration.");
            return;
        }
        float available=ACCUMULATOR+ELAPSED;
        integer count=llFloor(available/STEP);
        integer run=count;
        if(run>MAX_STEPS)run=MAX_STEPS;
        float leftover=available-count*STEP;
        llOwnerSay("Run steps="+(string)run+" discarded seconds="+(string)((count-run)*STEP)+" remainder="+(string)leftover);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Child face-away pose

Orient a child’s local X axis radially away from its root for a display arrangement.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a nonphysical child with some offset from root. The object’s modeled front must be local +X.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. Roll is determined by the shortest-arc alignment from +X. It does not search for a mesh nose.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_ROT_LOCAL]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||llVecMag(llGetLocalPos())<0.01)return;
        preview = !preview;
        if (preview)
        {
            rotation aim=llRotBetween(<1.0,0.0,0.0>,llVecNorm(llGetLocalPos()));
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,aim]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Child sun pointer

Aim a child’s local +X axis toward the simulator sun.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a small arrow child. Owner-touch starts five-second updates.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Tracks parcel environment, which can differ from a viewer override. The script aims an indicator and does not modify the sky.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            vector local=llGetSunDirection()/llGetRootRotation();
            if(llVecMag(local)>0.01)llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,llVecNorm(local))]);
            llSetTimerEvent(5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        vector local=llGetSunDirection()/llGetRootRotation();
        if(llVecMag(local)>0.01)llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,llVecNorm(local))]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Child transform bookmarks

Capture and recall two local child poses including position and rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child. Home stores the startup pose; capture A/B after manual edits.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Does not save size or shape. Keep link topology unchanged; recalling a pose uses root-local coordinates.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list home;
list a;
list b;
list capture()
{
    return llGetLinkPrimitiveParams(LINK_THIS,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
}
apply(list pose)
{
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,llList2Vector(pose,0),PRIM_ROT_LOCAL,llList2Rot(pose,1)]);
}
init()
{
    home=capture();
    a=home;
    b=home;
}
show()
{
    menu("Child pose bookmarks",["Capture A","Capture B","Recall A","Recall B","Home"]);
}
choose(string s)
{
    if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
    if(s=="Capture A")a=capture();
    else if(s=="Capture B")b=capture();
    else if(s=="Recall A")apply(a);
    else if(s=="Recall B")apply(b);
    else if(s=="Home")apply(home);
    else return;
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Child wind vane

Turn a child arrow so local +X points with the simulator wind.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a child arrow whose front is local +X. Owner-touch starts wind tracking once per two seconds.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Converts a world direction into the root-local frame. Calm wind keeps the last meaningful orientation; the root never rotates.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            vector wind=llWind(ZERO_VECTOR);
            wind.z=0.0;
            if(llVecMag(wind)>0.01)
            {
                vector local=llVecNorm(wind)/llGetRootRotation();
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]);
            }
            llSetTimerEvent(2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        vector wind=llWind(ZERO_VECTOR);
        wind.z=0.0;
        if(llVecMag(wind)>0.01)
        {
            vector local=llVecNorm(wind)/llGetRootRotation();
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Choose a look-ahead steering point

Find a point a fixed distance ahead from a known segment and local segment fraction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set POINTS, SEGMENT, FRACTION0..1 and nonnegative LOOKAHEAD. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Assumes the caller already knows its current path segment; does not locate an object in the scene.

// Original Incoprea. MIT. Motion planning only.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<4.0,5.0,0.0>];
integer SEGMENT=0;
float FRACTION=0.5;
float LOOKAHEAD=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(SEGMENT<0||SEGMENT>=n-1||FRACTION<0.0||FRACTION>1.0||LOOKAHEAD<0.0)
        {
            llOwnerSay("Invalid route location.");
            return;
        }
        vector a=llList2Vector(POINTS,SEGMENT);
        vector b=llList2Vector(POINTS,SEGMENT+1);
        vector current=a+(b-a)*FRACTION;
        float remaining=LOOKAHEAD;
        integer i;
        for(i=SEGMENT+1;i<n;++i)
        {
            vector target=llList2Vector(POINTS,i);
            float length=llVecDist(current,target);
            if(length>0.0&&remaining<=length)
            {
                llOwnerSay("Lookahead="+(string)(current+(target-current)*(remaining/length)));
                return;
            }
            remaining-=length;
            current=target;
        }
        llOwnerSay("Lookahead clamped="+(string)current);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Compare spatial error from eased timing

Compare a linear and eased position along the same segment at a selected time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set A/B and normalized T. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Shows why easing changes speed while preserving endpoints. No scene object is changed.

// Original Incoprea. MIT. Motion planning only.
vector A=ZERO_VECTOR;
vector B=<10.0,0.0,0.0>;
float T=0.25;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(T<0.0||T>1.0)
        {
            llOwnerSay("T must be0..1.");
            return;
        }
        float eased=T*T*(3.0-2.0*T);
        vector linear=A+(B-A)*T;
        vector smooth=A+(B-A)*eased;
        llOwnerSay("Linear="+(string)linear+" smooth="+(string)smooth+" separation="+(string)llVecDist(linear,smooth));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Convert orbital speed into target omega

Translate a desired tangential speed and radius into radians per second and revolution time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive RADIUS and SPEED. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Useful when choosing llTargetOmega rate; visual nonphysical orbit still does not move collision geometry.

// Original Incoprea. MIT. Motion planning only.
float RADIUS=5.0;
float SPEED=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||SPEED<=0.0)
        {
            llOwnerSay("Positive radius/speed required.");
            return;
        }
        float omega=SPEED/RADIUS;
        llOwnerSay("Radians/sec="+(string)omega+" degrees/sec="+(string)(omega*RAD_TO_DEG)+" seconds/revolution="+(string)(TWO_PI/omega));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Count crossed cycle boundaries after a delay

Calculate how many periodic actions became due between two elapsed-time samples.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set PREVIOUS<=NOW and positive PERIOD. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

The interval is open at PREVIOUS and closed at NOW. A caller can cap catch-up work rather than running unbounded missed events.

// Original Incoprea. MIT. Motion planning only.
float PREVIOUS=2.4;
float NOW=9.2;
float PERIOD=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PERIOD<=0.0||NOW<PREVIOUS)
        {
            llOwnerSay("Invalid interval.");
            return;
        }
        integer first=llFloor(PREVIOUS/PERIOD)+1;
        integer last=llFloor(NOW/PERIOD);
        integer due=last-first+1;
        if(due<0)due=0;
        llOwnerSay("Boundaries due="+(string)due+" next deadline="+(string)((last+1)*PERIOD));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Counter-rotating gear demonstration

Rotate two named child gears in opposite directions with a 2:1 angular ratio.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root with uniquely named gear_small and gear_large children, pivots at their centers and axes local Z. Owner-touch toggles.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. This is geometric animation, not a gear simulation. Place compatible teeth manually; script cannot infer tooth count or mesh clearances.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer small;
integer large;
rotation a;
rotation b;
integer active;
default
{
    state_entry()
    {
        integer i;
        integer hits;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)
        {
            string name=llGetLinkName(i);
            if(name=="gear_small")
            {
                small=i;
                ++hits;
            }
            if(name=="gear_large")
            {
                large=i;
                ++hits;
            }
        }
        if(hits!=2||!small||!large)
        {
            small=0;
            large=0;
            return;
        }
        a=llList2Rot(llGetLinkPrimitiveParams(small,[PRIM_ROT_LOCAL]),0);
        b=llList2Rot(llGetLinkPrimitiveParams(large,[PRIM_ROT_LOCAL]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetStatus(STATUS_PHYSICS)||!small||!large)return;
        active=!active;
        if(active)
        {
            llResetTime();
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(small,[PRIM_ROT_LOCAL,a]);
            llSetLinkPrimitiveParamsFast(large,[PRIM_ROT_LOCAL,b]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float t=llGetTime()*0.3;
        llSetLinkPrimitiveParamsFast(small,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,t>)*a]);
        llSetLinkPrimitiveParamsFast(large,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,-t*0.5>)*b]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            small=0;
            large=0;
            llOwnerSay("Links changed; reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Crank and piston study

Animate a crank marker and a sliding piston as a simple mechanical exhibit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root with exactly one child named crank_marker and one piston. The illustration uses root-local XY; both should be small. Owner-touch starts/stops.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Uses a slider-crank relation with crank radius 0.2 m and connecting-rod length 0.6 m. No physics constraints or collisions are simulated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer crank;
integer piston;
list home;
integer active;
default
{
    state_entry()
    {
        integer i;
        integer hits;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)
        {
            string name=llGetLinkName(i);
            if(name=="crank_marker")
            {
                crank=i;
                ++hits;
            }
            if(name=="piston")
            {
                piston=i;
                ++hits;
            }
        }
        if(hits!=2||!crank||!piston)
        {
            crank=0;
            piston=0;
            return;
        }
        home=llGetLinkPrimitiveParams(crank,[PRIM_POS_LOCAL])+llGetLinkPrimitiveParams(piston,[PRIM_POS_LOCAL]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!crank||!piston)return;
        active=!active;
        if(active)
        {
            llResetTime();
            llSetTimerEvent(0.15);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(crank,[PRIM_POS_LOCAL,llList2Vector(home,0)]);
            llSetLinkPrimitiveParamsFast(piston,[PRIM_POS_LOCAL,llList2Vector(home,1)]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float a=llGetTime()*0.5;
        float y=0.2*llSin(a);
        float x=0.2*llCos(a);
        float slider=x+llSqrt(0.36-y*y);
        llSetLinkPrimitiveParamsFast(crank,[PRIM_POS_LOCAL,<x,y,0.5>]);
        llSetLinkPrimitiveParamsFast(piston,[PRIM_POS_LOCAL,<slider,0.0,0.5>]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            crank=0;
            piston=0;
            llOwnerSay("Links changed; reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Cycle through dwell, travel, dwell and return

Map elapsed time to an explicit four-phase shuttle timeline.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive TRAVEL, nonnegative HOLD and ELAPSED. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

The duration of a whole cycle is2*(travel+hold). Endpoints remain stationary during dwell phases.

// Original Incoprea. MIT. Motion planning only.
float TRAVEL=2.0;
float HOLD=1.0;
float ELAPSED=4.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TRAVEL<=0.0||HOLD<0.0)
        {
            llOwnerSay("Invalid timing.");
            return;
        }
        float period=2.0*(TRAVEL+HOLD);
        float t=ELAPSED-period*llFloor(ELAPSED/period);
        float p;
        string phase;
        if(t<HOLD)
        {
            phase="hold A";
            p=0.0;
        }
        else if(t<HOLD+TRAVEL)
        {
            phase="A to B";
            p=(t-HOLD)/TRAVEL;
        }
        else if(t<2.0*HOLD+TRAVEL)
        {
            phase="hold B";
            p=1.0;
        }
        else
        {
            phase="B to A";
            p=1.0-(t-2.0*HOLD-TRAVEL)/TRAVEL;
        }
        llOwnerSay("Phase="+phase+" progress="+(string)p);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Distribute oscillator phases around a ring

Compute phase offsets and simultaneous sinusoidal samples for eight coordinated parts.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set ELAPSED, positive PERIOD and WAVE_CYCLES around the ring. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

WAVE_CYCLES controls spatial repetition, not the number of objects. No texture or motion changes occur.

// Original Incoprea. MIT. Motion planning only.
float ELAPSED=0.5;
float PERIOD=4.0;
integer WAVE_CYCLES=2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PERIOD<=0.0)
        {
            llOwnerSay("Positive period required.");
            return;
        }
        integer i;
        for(i=0;i<8;++i)
        {
            float phase=TWO_PI*(ELAPSED/PERIOD+(float)(i*WAVE_CYCLES)/8.0);
            llOwnerSay("Part "+(string)i+" value="+(string)llSin(phase));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Eased child inspection reveal

Open and close a child offset with a smooth cubic ease instead of an abrupt jump.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child at its closed pose. Owner-touch toggles a half-meter root-Z reveal; each leg lasts two seconds.

Stop / restore: Owner-touch to close, then wait two seconds for Home restoration before removing or resetting.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Touching during a transition reverses from its current fraction. Home is restored only after the closing transition finishes.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
float value;
float from;
float target;
integer opened;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        opened=!opened;
        from=value;
        target=0.0;
        if(opened)target=1.0;
        llResetTime();
        llSetTimerEvent(0.1);
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            return;
        }
        float t=llGetTime()/2.0;
        if(t>=1.0)
        {
            t=1.0;
            llSetTimerEvent(0.0);
        }
        float ease=t*t*(3.0-2.0*t);
        value=from+(target-from)*ease;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home+<0.0,0.0,value*0.5>]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Edge-hinged ordinary cube door

Swing a standard centered child prim around its left edge by changing both position and rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a child cube with width along local Y, height Z and thickness X. Put in its closed pose. Owner-touch opens/closes 90 degrees.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Unlike a hinge-centered mesh, a centered cube needs its center translated around the hinge. The left edge is negative local Y; use a copy and verify orientation first.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
vector hinge;
integer opened;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
        vector size=llGetScale();
        hinge=home+<0.0,-size.y*0.5,0.0>*rest;
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        opened=!opened;
        vector p=home;
        rotation r=rest;
        if(opened)
        {
            rotation localTurn=llEuler2Rot(<0.0,0.0,PI_BY_TWO>);
            r=localTurn*rest;
            vector offset=(home-hinge)/rest;
            p=hinge+offset*r;
        }
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Figure-eight exhibit path

Move a small child through a horizontal figure-eight path around its resting point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a small child with at least half a meter of clear space in root X/Y.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Orientation stays fixed; this is a path study rather than automatic nose alignment. The path starts at its crossing center.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            float t=llGetTime()*0.4;
            vector p=home+<0.4*llSin(t),0.2*llSin(2.0*t),0.0>;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float t=llGetTime()*0.4;
        vector p=home+<0.4*llSin(t),0.2*llSin(2.0*t),0.0>;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Find the active keyframe interval

Locate the pair of keyframes surrounding an elapsed time and report local progress.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set increasing TIMES and QUERY. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Clamps before the first and after the last frame. Real keyframed motion has additional object and parcel constraints.

// Original Incoprea. MIT. Motion planning only.
list TIMES=[0.0,1.0,3.5,5.0];
float QUERY=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(TIMES);
        if(n<2)
        {
            llOwnerSay("Need two timestamps.");
            return;
        }
        integer i;
        for(i=1;i<n;++i)if(llList2Float(TIMES,i)<=llList2Float(TIMES,i-1))
        {
            llOwnerSay("Times must increase.");
            return;
        }
        if(QUERY<=llList2Float(TIMES,0))
        {
            llOwnerSay("At first frame.");
            return;
        }
        for(i=1;i<n;++i)
        {
            float end=llList2Float(TIMES,i);
            if(QUERY<=end)
            {
                float start=llList2Float(TIMES,i-1);
                llOwnerSay("Frames "+(string)(i-1)+" -> "+(string)i+" local t="+(string)((QUERY-start)/(end-start)));
                return;
            }
        }
        llOwnerSay("At last frame.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Fold a hinged display flat

Fold a child display 90 degrees around its local X axis for a two-pose presentation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a child whose modeled pivot is at the fold edge. Put the script in its unfolded resting pose.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. Pivot placement is required: a centered cube rotates around its middle.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_ROT_LOCAL]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview = !preview;
        if (preview)
        {
            rotation home=llList2Rot(saved,0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<PI_BY_TWO,0.0,0.0>)*home]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Fold elapsed time into a back-and-forth cycle

Calculate continuous0..1..0 progress without an extra direction state variable.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive PERIOD for a full out-and-back cycle and sample TIMES. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Uses floor-based wrapping so negative input times remain well-defined.

// Original Incoprea. MIT. Motion planning only.
float PERIOD=4.0;
list TIMES=[0.0,1.0,2.0,3.0,4.0,5.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PERIOD<=0.0)
        {
            llOwnerSay("Positive period required.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(TIMES);++i)
        {
            float t=llList2Float(TIMES,i);
            float phase=t/PERIOD;
            phase-=llFloor(phase);
            float progress=1.0-llFabs(2.0*phase-1.0);
            llOwnerSay("t="+(string)t+" progress="+(string)progress);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Gentle pendulum exhibit

Swing a hinge-centered child back and forth through a modest angle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical build with a child whose pivot is at its suspension point. Put the script in that child at rest, then owner-touch to start. Swing axis is the child’s local Y.

Stop / restore: Owner-touch to restore the resting rotation before deleting or resetting.

This is a driven display, not a physics simulation. A centered prim swings around its center.

// Original Incoprea example. MIT. Not compiled or tested in-world.
rotation home;
integer active;
default
{
    state_entry()
    {
        home = llGetLocalRot();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() < 2) return;
        if (llGetStatus(STATUS_PHYSICS)) return;
        active = !active;
        if (active)
        {
            llResetTime();
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, home]);
        }
    }
    timer()
    {
        if (llGetLinkNumber() < 2 || llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active = FALSE;
            return;
        }
        rotation swing = llEuler2Rot(<0.0, 0.3 * llSin(llGetTime()), 0.0>);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, swing * home]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Hinge-centered child door

Owner touch turns a child door 90 degrees and returns it to its saved rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical linked build. The door must be a child whose actual pivot is at the hinge (for example, a mesh with a hinge-centered origin). Put this script in that door while closed. A normal centered cube will spin around its middle.

Stop / restore: Touch once more to close before disabling or removing. Reset only while closed; the saved pose is held in script memory.

Rotation is about the door’s local Z axis. Does not change physics or provide access security. Do not relink while open.

// Original Incoprea example. MIT. Not compiled or tested in-world.
rotation closed;
integer opened;
default
{
    state_entry()
    {
        closed = llGetLocalRot();
        if (llGetLinkNumber() < 2) llOwnerSay("Put this in a child door prim.");
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() < 2) return;
        if (llGetStatus(STATUS_PHYSICS))
        {
            llOwnerSay("Use a nonphysical build.");
            return;
        }
        opened = !opened;
        rotation target = closed;
        if (opened) target = llEuler2Rot(<0.0, 0.0, PI_BY_TWO>) * closed;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROT_LOCAL, target]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Keyframed dwell stage

Move a whole stage up, wait, then return once using explicit keyframes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a small nonphysical unattached root already compatible with KFM. Owner-touch starts a 0.5-meter lift, two-second dwell and return.

Stop / restore: Owner-touch while active clears motion in place. A normal completed cycle returns to its starting height.

Do not change link topology, attachment state or physics while running. Selection can pause simulator motion. One-shot examples keep their armed flag until the next owner touch clears it, even after the path finishes; they do not infer completion from wall-clock timers. Not a passenger elevator or safety device. KFM can affect physical objects; keep the test clear. No shape/physics settings are changed.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        if(active)
        {
            llSetKeyframedMotion([],[]);
            active=FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        active=TRUE;
        llSetKeyframedMotion([<0.0,0.0,0.5>,3.0,ZERO_VECTOR,2.0,<0.0,0.0,-0.5>,3.0],[KFM_DATA,KFM_TRANSLATION,KFM_MODE,KFM_FORWARD]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetKeyframedMotion([],[]);
            active=FALSE;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Keyframed pause and resume console

Pause, resume or clear keyframed motion set by another script on this object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the nonphysical unattached root whose KFM motion you intend to control. Owner-touch opens a menu.

Stop / restore: Choose Clear to remove the motion. Pause retains the path for a later Resume; it does not clear or restore position.

Do not change link topology, attachment state or physics while running. Selection can pause simulator motion. One-shot examples keep their armed flag until the next owner touch clears it, even after the path finishes; they do not infer completion from wall-clock timers. KFM is an object property shared by scripts. This console does not know the original route; disable controllers that automatically restart it.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llDialog(llGetOwner(),"Control existing keyframed motion",["Pause","Resume","Clear"],channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        close();
        if(llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        if(s=="Pause")llSetKeyframedMotion([],[KFM_COMMAND,KFM_CMD_PAUSE]);
        else if(s=="Resume")llSetKeyframedMotion([],[KFM_COMMAND,KFM_CMD_PLAY]);
        else if(s=="Clear")llSetKeyframedMotion([],[]);
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Level a root while preserving heading

Remove root pitch and roll while keeping its horizontal forward bearing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in an unattached nonphysical root whose forward axis is local +X. Owner-touch levels; touch again restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Near-vertical forward directions have no stable heading and are rejected. Whole linkset geometry rotates; use clear space.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
rotation home;
default
{
    state_entry()
    {
        home=llGetRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        vector forward=llRot2Fwd(home);
        forward.z=0.0;
        if(llVecMag(forward)<0.01)return;
        preview=!preview;
        if(preview)
        {
            vector headingForward=llRot2Fwd(home);
            float heading=llAtan2(headingForward.y,headingForward.x);
            llSetRot(llEuler2Rot(<0.0,0.0,heading>));
        }
        else
        {
            llSetRot(home);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Limit a heading change by turn speed

Clamp the shortest heading change by an angular-speed budget for one elapsed step.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set headings, nonnegative TURN_SPEED and DT. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Uses degrees and a negative180-degree tie convention. This calculates yaw only, not full orientation.

// Original Incoprea. MIT. Motion planning only.
float CURRENT=350.0;
float TARGET=40.0;
float TURN_SPEED=30.0;
float DT=0.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TURN_SPEED<0.0||DT<0.0)
        {
            llOwnerSay("Invalid rate/time.");
            return;
        }
        float delta=TARGET-CURRENT+180.0;
        delta-=360.0*llFloor(delta/360.0);
        delta-=180.0;
        float limit=TURN_SPEED*DT;
        if(delta>limit)delta=limit;
        if(delta< -limit)delta=-limit;
        float result=CURRENT+delta;
        result-=360.0*llFloor(result/360.0);
        llOwnerSay("Next heading="+(string)result+" step="+(string)delta);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Linked contact-sheet layout

Arrange named display children into a compact three-column contact sheet.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in nonphysical root. Name up to 12 small child panels sheet_item. Grid uses root X/Z with 0.5-meter center spacing; Restore recovers positions.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Rotation is preserved, so orient the panels first. A grid can overlap large panels; use copies of your build.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list links;
list positions;
init()
{
    integer i;
    for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<12;++i)if(llGetLinkName(i)=="sheet_item")
    {
        links+=[i];
        positions+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
    }
}
show()
{
    menu("Contact-sheet layout",["Grid","Restore"]);
}
choose(string s)
{
    if(llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1||(s!="Grid"&&s!="Restore"))return;
    integer i;
    for(i=0;i<llGetListLength(links);++i)
    {
        vector p=llList2Vector(positions,i);
        if(s=="Grid")p=<(i%3-1)*0.5,0.0,1.0-(i/3)*0.5>;
        llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,p]);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Linked radial display layout

Place small exhibit children around a ring and aim their local X axes outward.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in nonphysical root. Name up to 12 children radial_item. Ring radius is one meter; Restore recovers both local positions and rotations.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Use small items and clear space. Real prim transforms change; seated avatars are not targeted.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list links;
list poses;
init()
{
    integer i;
    for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<12;++i)if(llGetLinkName(i)=="radial_item")
    {
        links+=[i];
        poses+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
    }
}
show()
{
    menu("Radial exhibit layout",["Ring","Restore"]);
}
choose(string s)
{
    if(llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1||(s!="Ring"&&s!="Restore"))return;
    integer i;
    integer n=llGetListLength(links);
    for(i=0;i<n;++i)
    {
        vector p=llList2Vector(poses,i*2);
        rotation r=llList2Rot(poses,i*2+1);
        if(s=="Ring")
        {
            float a=TWO_PI*i/n;
            p=<llCos(a),llSin(a),0.5>;
            r=llEuler2Rot(<0.0,0.0,a>);
        }
        llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r]);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Linked row alignment tool

Arrange named children in an evenly spaced horizontal row while preserving their original positions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in nonphysical root; name up to 12 children layout_item. Row spaces their centers by 0.4 m along root X; Restore recovers every position.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. This is a real layout operation, not a point calculator. It does not scale items to prevent overlap; choose small samples.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list links;
list positions;
init()
{
    integer i;
    for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<12;++i)if(llGetLinkName(i)=="layout_item")
    {
        links+=[i];
        positions+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
    }
}
show()
{
    menu("Arrange layout_item children",["Row","Restore"]);
}
choose(string s)
{
    if(llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1||(s!="Row"&&s!="Restore"))return;
    integer n=llGetListLength(links);
    integer i;
    for(i=0;i<n;++i)
    {
        vector p=llList2Vector(positions,i);
        if(s=="Row")p=<(i-(n-1)*0.5)*0.4,0.0,0.5>;
        llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,p]);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Linked wave sculpture

Animate a traveling height wave across a bounded set of child bars.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name up to 12 nonphysical children wave_bar. Their link order defines wave phase. Owner-touch starts/stops.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Only local Z changes by up to 0.15 meters. Start with enough separation and never relink while active.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list home;
integer active;
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<12;++i)if(llGetLinkName(i)=="wave_bar")
        {
            links+=[i];
            home+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            integer i;
            for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,llList2Vector(home,i)]);
        }
    }
    timer()
    {
        if(llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(links);++i)
        {
            vector p=llList2Vector(home,i)+<0.0,0.0,0.15*llSin(llGetTime()+i*0.5)>;
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,p]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Match position and velocity on an oscillation

Calculate displacement and velocity from the same sinusoidal phase.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set amplitude, positive period and time. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Velocity units are coordinate-units per second. No prim is moved.

// Original Incoprea. MIT. Motion planning only.
float AMPLITUDE=2.0;
float PERIOD=5.0;
float TIME=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PERIOD<=0.0)
        {
            llOwnerSay("Positive period required.");
            return;
        }
        float omega=TWO_PI/PERIOD;
        llOwnerSay("Displacement="+(string)(AMPLITUDE*llSin(omega*TIME))+" velocity="+(string)(AMPLITUDE*omega*llCos(omega*TIME)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

North-locked child arrow

Keep a child arrow pointing to world north even when its root is rotated.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a child whose modeled front is +X. Owner-touch starts; rotate the root manually to test.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. World north is +Y. The child’s roll uses the shortest-arc alignment and may not match a flat dashboard’s preferred roll.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            vector north=<0.0,1.0,0.0>/llGetRootRotation();
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,north)]);
            llSetTimerEvent(0.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        vector north=<0.0,1.0,0.0>/llGetRootRotation();
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,north)]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Beginner

One measured quarter-turn

Toggle a root object between its starting orientation and a 90-degree local turn.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical unlinked object or linkset root at the intended resting rotation. Owner-touch to toggle.

Stop / restore: Touch again to restore the captured orientation before removal or reset.

Moves the actual orientation in one step; no timer or persistent target-omega. Child prims follow the root.

// Original Incoprea example. MIT. Not compiled or tested in-world.
rotation home;
integer turned;
default
{
    state_entry()
    {
        home = llGetRot();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() > 1) return;
        if (llGetStatus(STATUS_PHYSICS)) return;
        turned = !turned;
        if (turned) llSetRot(llEuler2Rot(<0.0, 0.0, PI_BY_TWO>) * home);
        else llSetRot(home);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

One-shot keyframed presentation turn

Smoothly turn a whole object through one quarter-turn over four seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use an unattached nonphysical root already configured for KFM-compatible accounting. Owner-touch starts; touching while running cancels.

Stop / restore: At completion the new orientation remains. A touch while running clears motion in place; manually restore any desired previous orientation.

Do not change link topology, attachment state or physics while running. Selection can pause simulator motion. One-shot examples keep their armed flag until the next owner touch clears it, even after the path finishes; they do not infer completion from wall-clock timers. Use a small object with clear surroundings. This is real geometry motion, not target-omega. No automatic physics-shape changes; grid support varies.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        if(active)
        {
            llSetKeyframedMotion([],[]);
            active=FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        active=TRUE;
        llSetKeyframedMotion([llEuler2Rot(<0.0,0.0,PI_BY_TWO>),4.0],[KFM_DATA,KFM_ROTATION,KFM_MODE,KFM_FORWARD]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetKeyframedMotion([],[]);
            active=FALSE;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Orientation instrument

Show the prim’s world Euler angles as a simple builder’s instrument.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim to inspect. Owner-touch starts and stops updates; rotate the prim to observe the changing values.

Stop / restore: Touch to restore the original text before removal.

Euler angles have equivalent representations and can jump near singularities. The object’s modeled nose need not align with local X; this is not a flight-grade instrument.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
list original;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active) llSetTimerEvent(0.5);
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
        }
    }
    timer()
    {
        vector angles = llRot2Euler(llGetRot()) * RAD_TO_DEG;
        llSetText("World Euler degrees\nX " + (string)llRound(angles.x)
        + "  Y " + (string)llRound(angles.y) + "  Z " + (string)llRound(angles.z), <0.8, 0.9, 1.0>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Paired sliding panels

Move two named child panels apart and back with one owner-controlled switch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical root with exactly one child named panel_left and one panel_right. Put this script in root; travel is along root-local X.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. Names must be unique. Relinking or renaming while open can invalidate targets.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer left;
integer right;
vector a;
vector b;
integer opened;
default
{
    state_entry()
    {
        integer i;
        integer n=llGetObjectPrimCount(llGetKey());
        integer hits;
        for(i=2;i<=n;++i)
        {
            string name=llGetLinkName(i);
            if(name=="panel_left")
            {
                left=i;
                ++hits;
            }
            if(name=="panel_right")
            {
                right=i;
                ++hits;
            }
        }
        if(hits!=2||!left||!right)
        {
            left=0;
            right=0;
            llOwnerSay("Need uniquely named panel_left and panel_right children.");
            return;
        }
        a=llList2Vector(llGetLinkPrimitiveParams(left,[PRIM_POS_LOCAL]),0);
        b=llList2Vector(llGetLinkPrimitiveParams(right,[PRIM_POS_LOCAL]),0);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!left||!right)return;
        opened=!opened;
        vector x=a;
        vector y=b;
        if(opened)
        {
            x+=<-0.5,0.0,0.0>;
            y+=<0.5,0.0,0.0>;
        }
        llSetLinkPrimitiveParamsFast(left,[PRIM_POS_LOCAL,x]);
        llSetLinkPrimitiveParamsFast(right,[PRIM_POS_LOCAL,y]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Plan a wave radiating from an origin

Delay an identical envelope at each point according to propagation distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set POINTS, ORIGIN, positive WAVE_SPEED/DURATION and ELAPSED. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Uses a compact sine envelope after arrival; output is zero before and after the pulse.

// Original Incoprea. MIT. Motion planning only.
list POINTS=[<1.0,0.0,0.0>,<2.0,2.0,0.0>,<4.0,0.0,0.0>];
vector ORIGIN=ZERO_VECTOR;
float WAVE_SPEED=2.0;
float DURATION=1.0;
float ELAPSED=1.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WAVE_SPEED<=0.0||DURATION<=0.0)
        {
            llOwnerSay("Invalid timing.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(POINTS);++i)
        {
            float arrival=llVecDist(ORIGIN,llList2Vector(POINTS,i))/WAVE_SPEED;
            float t=(ELAPSED-arrival)/DURATION;
            float value=0.0;
            if(t>=0.0&&t<=1.0)value=llSin(PI*t);
            llOwnerSay("Part "+(string)i+" arrival="+(string)arrival+" envelope="+(string)value);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Plan a zero-acceleration start and finish

Calculate position, velocity and acceleration along a quintic rest-to-rest motion.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive DURATION, DISTANCE and TIME in the interval. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

The polynomial has zero velocity and acceleration at both endpoints; it does not automatically respect a speed limit.

// Original Incoprea. MIT. Motion planning only.
float DURATION=4.0;
float DISTANCE=6.0;
float TIME=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DURATION<=0.0||TIME<0.0||TIME>DURATION)
        {
            llOwnerSay("Time must be within a positive duration.");
            return;
        }
        float t=TIME/DURATION;
        float t2=t*t;
        float t3=t2*t;
        float t4=t3*t;
        float t5=t4*t;
        float p=10.0*t3-15.0*t4+6.0*t5;
        float v=(30.0*t2-60.0*t3+30.0*t4)/DURATION;
        float a=(60.0*t-180.0*t2+120.0*t3)/(DURATION*DURATION);
        llOwnerSay("Position="+(string)(DISTANCE*p)+" velocity="+(string)(DISTANCE*v)+" acceleration="+(string)(DISTANCE*a));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Plan an on/off cycle with soft edges

Calculate a pulse with independent on-time and fade time inside a repeating cycle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive PERIOD, ON_TIME within the period, and FADE no greater than half ON_TIME. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

The pulse has linear fade edges. It reports intensity only and does not flicker a light.

// Original Incoprea. MIT. Motion planning only.
float PERIOD=5.0;
float ON_TIME=2.0;
float FADE=0.4;
float ELAPSED=1.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PERIOD<=0.0||ON_TIME<=0.0||ON_TIME>PERIOD||FADE<=0.0||2.0*FADE>ON_TIME)
        {
            llOwnerSay("Invalid envelope timing.");
            return;
        }
        float t=ELAPSED-PERIOD*llFloor(ELAPSED/PERIOD);
        float value=0.0;
        if(t<ON_TIME)
        {
            value=1.0;
            if(t<FADE)value=t/FADE;
            else if(t>ON_TIME-FADE)value=(ON_TIME-t)/FADE;
        }
        llOwnerSay("Pulse intensity="+(string)value);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Plan attack, decay, sustain and release

Evaluate a four-stage one-shot envelope at a chosen elapsed time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive attack/decay/release, nonnegative hold and sustain0..1. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

This models an animation envelope; it does not synthesize or play sound.

// Original Incoprea. MIT. Motion planning only.
float ATTACK=0.3;
float DECAY=0.4;
float HOLD=1.0;
float RELEASE=0.8;
float SUSTAIN=0.6;
float ELAPSED=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ATTACK<=0.0||DECAY<=0.0||HOLD<0.0||RELEASE<=0.0||SUSTAIN<0.0||SUSTAIN>1.0)
        {
            llOwnerSay("Invalid ADSR values.");
            return;
        }
        float t=ELAPSED;
        float value=0.0;
        if(t>=0.0)
        {
            if(t<ATTACK)value=t/ATTACK;
            else if(t<ATTACK+DECAY)value=1.0+(SUSTAIN-1.0)*(t-ATTACK)/DECAY;
            else if(t<ATTACK+DECAY+HOLD)value=SUSTAIN;
            else if(t<ATTACK+DECAY+HOLD+RELEASE)value=SUSTAIN*(1.0-(t-ATTACK-DECAY-HOLD)/RELEASE);
        }
        llOwnerSay("Envelope value="+(string)value);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Radial assembly expansion

Expand a group’s root-local positions uniformly while keeping child size and orientation unchanged.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name up to 16 children expand_part. Owner-touch expands their center offsets by 25 percent, then restores.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Useful for an exploded assembly view. It scales offsets including height, not the children themselves; keep the root near the assembly center.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list home;
integer expanded;
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<16;++i)if(llGetLinkName(i)=="expand_part")
        {
            links+=[i];
            home+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))return;
        expanded=!expanded;
        integer i;
        for(i=0;i<llGetListLength(links);++i)
        {
            vector p=llList2Vector(home,i);
            if(expanded)p*=1.25;
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POS_LOCAL,p]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Record a short child-position path

Capture up to twenty manually positioned child locations, then replay the path once.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child. Owner short touch records a position; holding a touch for at least two seconds starts replay. The first recorded point is the return location.

Stop / restore: Owner-touch during replay stops and returns to the first recorded point, which may differ from the startup pose. The final replay step also returns there. A topology or physical-state change halts without moving.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Records the object’s own local positions only, never avatars. Replay uses one-second steps; stop by owner-touch during playback.

// Original Incoprea. MIT. Not compiled or tested in-world.
list points;
integer index;
integer playing;
float pressed;
integer skipEnd;
stop()
{
    playing=FALSE;
    llSetTimerEvent(0.0);
    if(llGetListLength(points))llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,llList2Vector(points,0)]);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        pressed=llGetTime();
        skipEnd=FALSE;
        if(playing)
        {
            stop();
            skipEnd=TRUE;
        }
    }
    touch_end(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        if(skipEnd)
        {
            skipEnd=FALSE;
            return;
        }
        if(llGetTime()-pressed>=2.0)
        {
            if(llGetListLength(points)>1)
            {
                index=0;
                playing=TRUE;
                llSetTimerEvent(1.0);
            }
            return;
        }
        if(llGetListLength(points)<20)
        {
            points+=[llGetLocalPos()];
            llOwnerSay("Recorded point "+(string)llGetListLength(points));
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            playing=FALSE;
            return;
        }
        if(index>=llGetListLength(points))
        {
            stop();
            return;
        }
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,llList2Vector(points,index++)]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetTimerEvent(0.0);
            playing=FALSE;
            points=[];
            llOwnerSay("Links changed; path cleared without moving.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Rest a child bounding box on root plane

Place a child’s bounding-box bottom on the root-local Z=0 plane.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical ordinary child box or a mesh with representative bounds. Owner-touch applies/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Computes projected box half-height from local scale and rotation. This is bounding-box placement, not mesh collision analysis.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector home;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            vector size=llGetScale();
            rotation r=llGetLocalRot();
            vector x=<1.0,0.0,0.0>*r;
            vector y=<0.0,1.0,0.0>*r;
            vector z=<0.0,0.0,1.0>*r;
            float half=(llFabs(x.z)*size.x+llFabs(y.z)*size.y+llFabs(z.z)*size.z)*0.5;
            vector p=home;
            p.z=half;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Reversible child nudge

Temporarily offset a child by a configurable root-local vector for clearance checks.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child. Edit OFFSET; owner-touch applies and restores. Keep within link distance limits.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
vector OFFSET=<0.0,0.0,0.25>;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_POS_LOCAL]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,llList2Vector(saved,0)+OFFSET]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Root cardinal orientation cycle

Cycle a nonphysical root through north, east, south and west, then restore its original orientation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare root whose modeled front is +X. Five owner touches visit four level cardinal orientations and restore.

Stop / restore: Cycle through four cardinal poses; the fifth owner touch restores Home. Restore before removing or resetting.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. This levels the root while previewing, so it intentionally removes pitch and roll until restored. Children follow the root.

// Original Incoprea. MIT. Not compiled or tested in-world.
rotation home;
integer step;
default
{
    state_entry()
    {
        home=llGetRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))return;
        if(step==4)
        {
            llSetRot(home);
            step=0;
            llOwnerSay("Home restored.");
            return;
        }
        float angle=PI_BY_TWO-step*PI_BY_TWO;
        llSetRot(llEuler2Rot(<0.0,0.0,angle>));
        ++step;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Root orientation bookmarks

Capture two root orientations and switch between them while retaining a startup Home pose.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical root. Rotate manually, choose Capture A/B, then recall either bookmark. Home restores startup orientation.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Bookmarks are rotations only; position and child-local transforms are not captured. Do not use on physical objects.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
rotation home;
rotation a;
rotation b;
init()
{
    home=llGetRot();
    a=home;
    b=home;
}
show()
{
    menu("Root orientation bookmarks",["Capture A","Capture B","Recall A","Recall B","Home"]);
}
choose(string s)
{
    if(llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS))return;
    if(s=="Capture A")a=llGetRot();
    else if(s=="Capture B")b=llGetRot();
    else if(s=="Recall A")llSetRot(a);
    else if(s=="Recall B")llSetRot(b);
    else if(s=="Home")llSetRot(home);
    else return;
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Schedule a staggered reveal across a row

Compute normalized progress for six items starting at regular delays.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set ELAPSED, positive DURATION and nonnegative STAGGER. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Values are clamped0..1; this calculates a frame of an animation rather than setting visibility.

// Original Incoprea. MIT. Motion planning only.
float ELAPSED=1.2;
float DURATION=1.0;
float STAGGER=0.25;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DURATION<=0.0||STAGGER<0.0)
        {
            llOwnerSay("Invalid timing.");
            return;
        }
        integer i;
        for(i=0;i<6;++i)
        {
            float p=(ELAPSED-i*STAGGER)/DURATION;
            if(p<0.0)p=0.0;
            if(p>1.0)p=1.0;
            llOwnerSay("Item "+(string)i+" progress="+(string)p);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Shape a curve using endpoint tangents

Evaluate a cubic Hermite segment defined by two positions and two tangent vectors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set endpoints A/B, tangent vectors TA/TB and T0..1. Owner touch prints calculations only.

Stop / restore: Disable/remove. No prim motion or appearance is changed.

Tangents are derivatives with respect to normalized parameter, not automatically metres-per-second.

// Original Incoprea. MIT. Motion planning only.
vector A=ZERO_VECTOR;
vector B=<6.0,0.0,0.0>;
vector TA=<2.0,5.0,0.0>;
vector TB=<2.0,-3.0,0.0>;
float T=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(T<0.0||T>1.0)
        {
            llOwnerSay("T must be0..1.");
            return;
        }
        float t2=T*T;
        float t3=t2*T;
        vector p=(2.0*t3-3.0*t2+1.0)*A+(t3-2.0*t2+T)*TA+(-2.0*t3+3.0*t2)*B+(t3-t2)*TB;
        llOwnerSay("Hermite point="+(string)p);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Short keyframed shuttle

Move a whole object smoothly along a half-meter world-X shuttle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical unattached root with keyframed-motion-compatible prim accounting, commonly an appropriate Convex Hull shape configured manually. Owner-touch starts.

Stop / restore: Owner-touch clears keyframed motion at the current position. It does not return Home; reposition manually if needed.

Do not change link topology, attachment state or physics while running. Selection can pause simulator motion. One-shot examples keep their armed flag until the next owner touch clears it, even after the path finishes; they do not infer completion from wall-clock timers. KFM affects actual collision geometry and can push physical objects. Use a clear test area. It ignores nonphysical collision obstacles; this script never changes physics shape or physical status. OpenSim support must be checked.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)llSetKeyframedMotion([<0.5,0.0,0.0>,4.0],[KFM_DATA,KFM_TRANSLATION,KFM_MODE,KFM_PING_PONG]);
        else llSetKeyframedMotion([],[]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llSetKeyframedMotion([],[]);
            active=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Shuttle with endpoint dwell

Move an exhibit along a short rail and pause at both ends.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child at the first stop. Travel is 0.6 meters along root X. Owner-touch begins a repeating 12-second cycle.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Each leg takes four seconds with a two-second dwell at each end. The movement is time-based, so lag does not accumulate as extra steps.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            float t=llGetTime();
            t-=12.0*llFloor(t/12.0);
            float f=0.0;
            if(t<4.0)f=t/4.0;
            else if(t<6.0)f=1.0;
            else if(t<10.0)f=1.0-(t-6.0)/4.0;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home+<0.6*f,0.0,0.0>]);
            llSetTimerEvent(0.2);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        float t=llGetTime();
        t-=12.0*llFloor(t/12.0);
        float f=0.0;
        if(t<4.0)f=t/4.0;
        else if(t<6.0)f=1.0;
        else if(t<10.0)f=1.0-(t-6.0)/4.0;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home+<0.6*f,0.0,0.0>]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Sliding child drawer

Move a linked drawer half a meter along its own forward axis on owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child drawer in its closed position. Change TRAVEL to the desired distance in meters. The child local X axis is its travel direction.

Stop / restore: Touch again to restore the captured closed position. Do not reset, remove, or relink while open.

The saved pose survives normal running but not script reset. Link-distance limits still apply.

// Original Incoprea example. MIT. Not compiled or tested in-world.
float TRAVEL = 0.5;
vector closed;
vector travel;
integer opened;
default
{
    state_entry()
    {
        closed = llGetLocalPos();
        travel = <TRAVEL, 0.0, 0.0> * llGetLocalRot();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() < 2) return;
        if (llGetStatus(STATUS_PHYSICS)) return;
        opened = !opened;
        vector target = closed;
        if (opened) target += travel;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POS_LOCAL, target]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Beginner

Slow automatic rotation

A gentle, continuous turn with no clicking. About 63 seconds per revolution.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical object. For an orbit, link the shark first and the center sphere last, then put this script in the sphere root. Position the shark away from the sphere and point its nose along the circular path. Both linked parts turn together.

Stop / restore: Disable any scripts restarting rotation, then run Stop linked rotation. Deleting a rotation script alone may leave the effect active.

This is a visual effect on nonphysical objects: collision geometry does not orbit. It preserves the shark’s existing alignment; it does not automatically find the mesh’s nose.

// Original Incoprea example. MIT. Nonphysical object; root prim.
default
{
    state_entry()
    {
        llTargetOmega(<0.0, 0.0, 1.0>, 0.10, 1.0);
    }
    on_rez(integer parameter)
    {
        llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Movement · Beginner

Spin the linked decorations

Turn child prims on their own axes while leaving the root still.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical linkset with the decorative prims linked as children. Put in the root.

Stop / restore: Use Stop linked rotation. It clears target-omega from every prim in this linkset.

This spins each child in place; it does not move child prims around the root. Visual only for nonphysical objects.

// Original Incoprea example. Nonphysical linked build; root prim.
default
{
    state_entry()
    {
        llSetLinkPrimitiveParamsFast(LINK_ALL_CHILDREN,
        [PRIM_OMEGA, <0.0, 0.0, 1.0>, 0.05, 1.0]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Three-stop child rail

Move a child exhibit between three positions on a root-local rail, with a home position first.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical child. Edit STOPS as offsets from its startup location; keep the first entry ZERO_VECTOR.

Stop / restore: Cycle until Home restored before removing or resetting. Do not relink while offset.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. A step is immediate. Use short offsets within the link limits.

// Original Incoprea. MIT. Not compiled or tested in-world.
list STOPS=[ZERO_VECTOR,<0.5,0.0,0.0>,<0.5,0.5,0.0>];
integer index;
vector home;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||!llGetListLength(STOPS))return;
        index=(index+1)%llGetListLength(STOPS);
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home+llList2Vector(STOPS,index)]);
        if(!index)llOwnerSay("Home restored.");
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Two-part exploded view

Separate a named child from the root to reveal a model assembly, then restore.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child part. Owner-touch moves it half a meter radially away from the root. Child must not be centered on root.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. This is a single component reveal, useful when each child needs its own independent switch.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_POS_LOCAL]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||llVecMag(llList2Vector(saved,0))<0.01)return;
        preview = !preview;
        if (preview)
        {
            vector pos=llList2Vector(saved,0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,pos+llVecNorm(pos)*0.5]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Movement · Intermediate

Uniform child size preview

Preview a 20 percent enlargement of one child to test fit, then restore its dimensions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a small nonphysical child prim. Verify there are no seated avatars or tight collision clearances.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Use a small nonphysical rezzed build with room around it. This changes real geometry, not just a viewer effect. Restore before reset, relink, or removal; a script-memory snapshot is not a permanent backup. Simulator size limits may clamp the requested scale. The prim center stays fixed.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_SIZE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SIZE,llList2Vector(saved,0)*1.2]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SIZE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Movement · Intermediate

Vehicle speed display

Display measured object speed in meters per second and kilometers per hour.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a moving object or a suitable attachment. Owner-touch turns the instrument on and off.

Stop / restore: Touch to stop and restore the original hover text before removal.

Reads existing velocity only; it never changes physical status, vehicle settings, or movement. Teleports and scripted position jumps need not appear as meaningful velocity.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
list original;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active) llSetTimerEvent(0.5);
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
        }
    }
    timer()
    {
        float speed = llVecMag(llGetVel());
        llSetText((string)(llRound(speed * 10.0) / 10.0) + " m/s\n"
        + (string)(llRound(speed * 36.0) / 10.0) + " km/h", <0.7, 1.0, 0.8>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Movement · Intermediate

Velocity direction arrow

Point a child arrow along the current object velocity while it moves.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in an arrow child on an already moving object. For this example use nonphysical scripted movement that reports velocity meaningfully.

Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. It never enables physics or drives the vehicle. Position jumps may have zero reported velocity. Stationary states preserve the last direction.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector home;
rotation rest;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        rest=llGetLocalRot();
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        active=!active;
        if(active)
        {
            llResetTime();
            vector velocity=llGetVel();
            if(llVecMag(velocity)>0.05)
            {
                vector local=llVecNorm(velocity)/llGetRootRotation();
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]);
            }
            llSetTimerEvent(0.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]);
        }
    }
    timer()
    {
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        vector velocity=llGetVel();
        if(llVecMag(velocity)>0.05)
        {
            vector local=llVecNorm(velocity)/llGetRootRotation();
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpersMeasure, inspect, and understand your objects.193 scripts

Download this category (.zip)

Building helpers · Intermediate

Arrange exhibits facing an arc center

Print positions and inward-facing yaw values along an arc.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set radius, sweep and count2..12. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Assumes each exhibit faces local+X; a mesh modeled along another axis needs an additional offset.

// Original Incoprea. MIT. Planning only.
float RADIUS=5.0;
float SWEEP=150.0;
integer COUNT=7;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||COUNT<2||COUNT>12)
        {
            llOwnerSay("Invalid radius/count.");
            return;
        }
        integer i;
        for(i=0;i<COUNT;++i)
        {
            float degrees=-SWEEP*0.5+SWEEP*(float)i/(COUNT-1);
            float a=degrees*DEG_TO_RAD;
            llOwnerSay("Position="+(string)<RADIUS*llCos(a),RADIUS*llSin(a),0.0>+" inward yaw="+(string)(degrees+180.0));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Audit live diffuse-asset transitions

Watch up to32 faces and count how often each face’s diffuse asset changes during a session.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Place inside a prim running a slideshow or texture selector. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Observes texture UUID changes only, not UV animation, pixel changes or PBR assets. Fast intermediate swaps can be missed.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
list assets;
list counts;
integer faces;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    integer i;
    for(i=0;i<faces;++i)llOwnerSay("Face "+(string)i+" observed asset transitions="+(string)llList2Integer(counts,i));
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        faces=llGetNumberOfSides();
        if(faces>32)return;
        assets=[];
        counts=[];
        integer i;
        for(i=0;i<faces;++i)
        {
            assets += [llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,i]),0)];
            counts += [0];
        }
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        if(llGetNumberOfSides()!=faces)
        {
            llOwnerSay("Face count changed; ending session.");
            finish();
            return;
        }
        integer i;
        for(i=0;i<faces;++i)
        {
            string asset=llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,i]),0);
            if(asset!=llList2String(assets,i))
            {
                assets=llListReplaceList(assets,[asset],i,i);
                counts=llListReplaceList(counts,[llList2Integer(counts,i)+1],i,i);
            }
        }
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Average four measured feature positions

Calculate a four-point centroid and maximum sample distance from it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch four landmarks on the same object/linkset. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

All samples have equal weight; this is not a volume or mass centroid. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector centre=(a+b+c+d)*0.25;
        float maximum;
        integer i;
        for(i=0;i<4;++i)
        {
            float distance=llVecDist(centre,llList2Vector(points,i));
            if(distance>maximum)maximum=distance;
        }
        llOwnerSay("Sample centroid="+(string)centre+" maximum sample radius="+(string)maximum);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Balance alternating items across two rows

Split a sequence into two rows while centering each row independently.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set COUNT1..16 and spacing. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Odd totals produce one longer row; centering avoids an unintended half-cell shift.

// Original Incoprea. MIT. Planning only.
integer COUNT=9;
float SPACING=1.0;
float ROW_GAP=1.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(COUNT<1||COUNT>16||SPACING<=0.0)
        {
            llOwnerSay("Invalid count/spacing.");
            return;
        }
        integer i;
        for(i=0;i<COUNT;++i)
        {
            integer row=i%2;
            integer column=i/2;
            integer rowCount=COUNT/2;
            if(row==0)rowCount=(COUNT+1)/2;
            float x=(column-(rowCount-1)*0.5)*SPACING;
            llOwnerSay((string)i+": "+(string)<x,row*ROW_GAP,0.0>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Beginner

Box material estimator

Calculate the volume and surface area of a full rectangular box from its scale.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use an uncut solid box and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

This is a mathematical box estimate, not mesh volume, physics volume, land impact, or a material-price quote. Hollow and cut prims are not accounted for.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector s = llGetScale();
        float volume = s.x * s.y * s.z;
        float area = 2.0 * (s.x*s.y + s.x*s.z + s.y*s.z);
        llOwnerSay("Full-box volume: " + (string)volume + " cubic meters.");
        llOwnerSay("Full-box surface area: " + (string)area + " square meters.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Bridge between two build anchors

Calculate a beam’s center, length and rotation so its localX points from one anchor to another.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set endpoints A/B and choose a beam modeled along localX. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Rotation uses the shortest alignment; roll around the beam is not independently controlled.

// Original Incoprea. MIT. Calculation only.
vector A=<2.0,3.0,1.0>;
vector B=<8.0,7.0,4.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector delta=B-A;
        float length=llVecMag(delta);
        if(length<0.000001)
        {
            llOwnerSay("Anchors coincide.");
            return;
        }
        rotation r=llRotBetween(<1.0,0.0,0.0>,delta/length);
        llOwnerSay("Centre="+(string)((A+B)*0.5)+" length="+(string)length+" rotation="+(string)r);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Calculate a connecting-rod slider position

Evaluate slider position and connecting rod angle for a crank and longer rod.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set rod length greater than crank radius and crank angle degrees. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Ideal planar slider-crank; no offsets or joint thickness. This complements visual crank models with exact position math.

// Original Incoprea. MIT. Planning only.
float CRANK=1.0;
float ROD=3.0;
float ANGLE=60.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(CRANK<=0.0||ROD<=CRANK)
        {
            llOwnerSay("Need rod>crank>0.");
            return;
        }
        float a=ANGLE*DEG_TO_RAD;
        float y=CRANK*llSin(a);
        float x=CRANK*llCos(a)+llSqrt(ROD*ROD-y*y);
        llOwnerSay("SliderX="+(string)x+" rod angle degrees="+(string)(llAsin(-y/ROD)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Calculate a corner-rounded platform

Calculate area and perimeter of a rectangle with four equal quarter-circle corners.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set width/height and radius no greater than half the smaller dimension. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Ideal outline only; no geometry or collision shape is generated.

// Original Incoprea. MIT. Calculation only.
float W=8.0;
float H=5.0;
float R=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(W<=0.0||H<=0.0||R<0.0||2.0*R>W||2.0*R>H)
        {
            llOwnerSay("Radius does not fit.");
            return;
        }
        llOwnerSay("Area="+(string)(W*H-(4.0-PI)*R*R)+" perimeter="+(string)(2.0*(W+H)-8.0*R+TWO_PI*R));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Calculate a frame aperture with mat borders

Calculate visible opening and outer frame size around an artwork.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set image width/height, overlap, mat width and frame width. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Overlap must leave positive visible image dimensions; borders are symmetric.

// Original Incoprea. MIT. Calculation only.
float IMAGE_W=2.0;
float IMAGE_H=1.4;
float OVERLAP=0.02;
float MAT=0.15;
float FRAME=0.08;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IMAGE_W<=2.0*OVERLAP||IMAGE_H<=2.0*OVERLAP||OVERLAP<0.0||MAT<0.0||FRAME<0.0)
        {
            llOwnerSay("Invalid frame inputs.");
            return;
        }
        float apertureW=IMAGE_W-2.0*OVERLAP;
        float apertureH=IMAGE_H-2.0*OVERLAP;
        llOwnerSay("Aperture="+(string)<apertureW,apertureH,0.0>+" outer="+(string)<apertureW+2.0*(MAT+FRAME),apertureH+2.0*(MAT+FRAME),0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Calculate matching gear pitch dimensions

Translate module and tooth counts into pitch diameters and center separation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive MODULE and tooth counts at least8. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Ideal spur-gear pitch geometry, not a printable tooth profile or structural design.

// Original Incoprea. MIT. Planning only.
float MODULE=0.1;
integer TEETH_A=24;
integer TEETH_B=36;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MODULE<=0.0||TEETH_A<8||TEETH_B<8)
        {
            llOwnerSay("Invalid module/tooth counts.");
            return;
        }
        float da=MODULE*TEETH_A;
        float db=MODULE*TEETH_B;
        llOwnerSay("Pitch diameters="+(string)da+","+(string)db+" center spacing="+(string)((da+db)*0.5)+" output/input speed="+(string)(-(float)TEETH_A/(float)TEETH_B));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Capture a child’s local animation bounds

Record local position minima and maxima for the child containing this script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Put in an animated child; start by touching that child. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Root movement does not affect the local envelope. Stops if the script prim ceases to be a child; no animation is changed.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
vector low;
vector high;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Observed child local envelope min="+(string)low+" max="+(string)high+" span="+(string)(high-low));
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        if(llGetLinkNumber()<2)
        {
            llOwnerSay("Use a linked child.");
            return;
        }
        low=llGetLocalPos();
        high=low;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        if(llGetLinkNumber()<2)
        {
            finish();
            return;
        }
        vector p=llGetLocalPos();
        if(p.x<low.x)low.x=p.x;
        if(p.y<low.y)low.y=p.y;
        if(p.z<low.z)low.z=p.z;
        if(p.x>high.x)high.x=p.x;
        if(p.y>high.y)high.y=p.y;
        if(p.z>high.z)high.z=p.z;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Advanced

Center a child between two named anchors

Place the selected child center halfway between two uniquely named child markers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Name two other children anchor_a and anchor_b. Owner-touch the child to preview; touch again to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Copies only their midpoint. Both anchors must be distinct from the selected part; no root or avatar anchors.

// Original Incoprea. MIT. Test on a spare copy first.
integer selected;
key identity;
list original;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(selected)
        {
            if(llGetLinkKey(selected)==identity)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,llList2Vector(original,0),PRIM_ROT_LOCAL,llList2Rot(original,1),PRIM_SIZE,llList2Vector(original,2)]);
            else llOwnerSay("Topology changed; restore manually from backup.");
            selected=0;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))
        {
            llOwnerSay("Touch a child prim.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL,PRIM_SIZE]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        vector size=llList2Vector(data,2);
        integer i;
        integer a;
        integer b;
        integer ca;
        integer cb;
        integer total=llGetObjectPrimCount(llGetKey());
        if(total>32)return;
        for(i=2;i<=total;++i)
        {
            if(llGetLinkName(i)=="anchor_a")
            {
                a=i;
                ++ca;
            }
            if(llGetLinkName(i)=="anchor_b")
            {
                b=i;
                ++cb;
            }
        }
        if(ca!=1||cb!=1||a==link||b==link)
        {
            llOwnerSay("Need two unique other anchor children.");
            return;
        }
        p=(llList2Vector(llGetLinkPrimitiveParams(a,[PRIM_POS_LOCAL]),0)+llList2Vector(llGetLinkPrimitiveParams(b,[PRIM_POS_LOCAL]),0))*0.5;
        selected=link;
        identity=llGetLinkKey(link);
        original=data;
        llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r,PRIM_SIZE,size]);
        llOwnerSay("Preview applied; touch again to restore.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Center child on named part

Preview a child centered on one uniquely named linked reference.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name another child reference_center. Use nonphysical moving child. Touch again restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Copies position only. Overlap intentional.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector home;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            integer i;
            integer target;
            integer count;
            for(i=2;i<=llGetNumberOfPrims();++i)if(i!=llGetLinkNumber()&&llGetLinkName(i)=="reference_center")
            {
                target=i;
                ++count;
            }
            if(count!=1)
            {
                preview=FALSE;
                llOwnerSay("Need one other reference_center child.");
                return;
            }
            vector p=llList2Vector(llGetLinkPrimitiveParams(target,[PRIM_POS_LOCAL]),0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Check a four-corner frame for squareness

Compare opposite sides and diagonals of four sampled frame corners.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch corners in boundary order. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Equal diagonals alone do not prove a rectangle; the full side/diagonal report helps diagnose the shape. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        llOwnerSay("Opposite side differences="+(string)llFabs(llVecDist(a,b)-llVecDist(c,d))+","+(string)llFabs(llVecDist(b,c)-llVecDist(d,a)));
        llOwnerSay("Diagonal difference="+(string)llFabs(llVecDist(a,c)-llVecDist(b,d)));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Check a planned polygon for consistent turns

Inspect consecutive edge cross products for mixed turn directions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set ordered XY VERTICES, at least3. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Consistent turns are a convexity indicator for a simple polygon; this alone does not rule out every self-intersection or repeated vertex.

// Original Incoprea. MIT. Planning only.
list VERTICES=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<2.0,1.0,0.0>,<4.0,4.0,0.0>,<0.0,4.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(VERTICES);
        if(n<3)
        {
            llOwnerSay("Need three vertices.");
            return;
        }
        integer positive;
        integer negative;
        integer i;
        for(i=0;i<n;++i)
        {
            vector a=llList2Vector(VERTICES,(i+1)%n)-llList2Vector(VERTICES,i);
            vector b=llList2Vector(VERTICES,(i+2)%n)-llList2Vector(VERTICES,(i+1)%n);
            float cross=a.x*b.y-a.y*b.x;
            if(cross>0.000001)positive=TRUE;
            if(cross< -0.000001)negative=TRUE;
        }
        llOwnerSay("Mixed turns/concavity="+(string)(positive&&negative)+" all collinear="+(string)(!positive&&!negative));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Check a prim Description budget

Report ASCII-only and forbidden-pipe findings before using Description as configuration.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the prim and touch as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Second Life Description is limited to 127 bytes and printable ASCII excluding pipe. This examines the stored value, which may already have been normalized or truncated.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        string description=llGetObjectDesc();
        integer issues;
        integer i;
        for(i=0;i<llStringLength(description);++i)
        {
            integer code=llOrd(description,i);
            if(code<32 || code>126 || code==124) ++issues;
        }
        llOwnerSay("Stored length: "+(string)llStringLength(description)+"; nonpermitted-character findings: "+(string)issues);
        if(llStringLength(description)>127) llOwnerSay("Exceeds the documented 127-byte ASCII budget.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Check a radial component layout

Compare horizontal root-local child distances against a planned radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set RADIUS and TOLERANCE. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Ignores Z height and does not infer a mesh’s visual center. A radial layout can legitimately contain off-ring components such as a hub.

// Original Incoprea example. MIT.
float RADIUS=3.0;
float TOLERANCE=0.05;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(RADIUS<0 || TOLERANCE<0)
        {
            llOwnerSay("Use nonnegative radius and tolerance.");
            return;
        }
        integer i;
        for(i=2;i<=total;++i)
        {
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            float radius=llSqrt(p.x*p.x+p.y*p.y);
            if(llFabs(radius-RADIUS)>TOLERANCE)llOwnerSay("Link "+(string)i+" radius="+(string)radius+" m");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Check a turned rectangle inside a frame

Calculate axis-aligned extents of a rotated rectangular artwork and compare with an opening.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive artwork width/height, frame width/height and yaw. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Tests the bounding rectangle at the chosen rotation; no search for the best angle is performed.

// Original Incoprea. MIT. Planning only.
float W=3.0;
float H=2.0;
float FRAME_W=4.0;
float FRAME_H=3.0;
float ANGLE=25.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(W<=0.0||H<=0.0||FRAME_W<=0.0||FRAME_H<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        float a=ANGLE*DEG_TO_RAD;
        float width=llFabs(W*llCos(a))+llFabs(H*llSin(a));
        float height=llFabs(W*llSin(a))+llFabs(H*llCos(a));
        llOwnerSay("Turned bounds="+(string)<width,height,0.0>+" fits="+(string)(width<=FRAME_W&&height<=FRAME_H));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Check child centers against a local plane

Find child prim centers that do not share a configured root-local Z level.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set LEVEL and TOLERANCE. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Checks centers only, not bottoms or mesh vertices. The plane rotates with the root; it is not necessarily horizontal in the region.

// Original Incoprea example. MIT.
float LEVEL=0.0;
float TOLERANCE=0.01;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(TOLERANCE<0)
        {
            llOwnerSay("Tolerance cannot be negative.");
            return;
        }
        integer i;
        for(i=2;i<=total;++i)
        {
            vector position=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            if(llFabs(position.z-LEVEL)>TOLERANCE)llOwnerSay("Link "+(string)i+" local Z="+(string)position.z+" differs from level "+(string)LEVEL);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Check component scales against a reference

Compare prim scales to a configured reference scale within a tolerance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set REFERENCE and TOLERANCE. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Compares scale settings, not visible geometry. Useful for a set of intended identical modules; intentionally varied parts will be reported.

// Original Incoprea example. MIT.
vector REFERENCE=<1,1,1>;
float TOLERANCE=0.001;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(TOLERANCE<0)
        {
            llOwnerSay("Tolerance cannot be negative.");
            return;
        }
        integer i;
        integer findings;
        for(i=1;i<=total;++i)
        {
            vector size=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_SIZE]),0);
            if(llVecDist(size,REFERENCE)>TOLERANCE)
            {
                ++findings;
                llOwnerSay("Scale differs at "+(string)i+": "+(string)size);
            }
        }
        llOwnerSay("Findings: "+(string)findings);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Check parallelism of two sampled edges

Measure the smaller direction angle and start-to-line offset between two clicked edges.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch endpoints of edgeA, then endpoints of edgeB. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The angle is direction-independent; reversing an edge does not turn parallel into180 degrees. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector u=b-a;
        vector v=d-c;
        if(llVecMag(u)<0.000001||llVecMag(v)<0.000001)
        {
            llOwnerSay("Zero-length edge.");
            return;
        }
        float dot=llFabs(llVecNorm(u)*llVecNorm(v));
        if(dot>1.0)dot=1.0;
        float angle=llAcos(dot)*RAD_TO_DEG;
        float offset=llVecMag((c-a)%u)/llVecMag(u);
        llOwnerSay("Parallelism angle="+(string)angle+" first-start offset="+(string)offset);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Check spacing between round display bounds

Calculate the surface gap between every pair of small bounding spheres.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set alternating CENTER/RADIUS pairs, up to six spheres. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Spherical bounds are conservative for many shapes; a negative gap indicates overlapping bounds, not necessarily intersecting meshes.

// Original Incoprea. MIT. Planning only.
list BOUNDS=[<0.0,0.0,0.0>,1.0,<3.0,0.0,0.0>,1.2,<1.5,2.0,0.0>,0.8];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(BOUNDS);
        if(n%2||n>12)
        {
            llOwnerSay("Use at most six center/radius pairs.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<n;i+=2)
        {
            float ri=llList2Float(BOUNDS,i+1);
            if(ri<0.0)
            {
                llOwnerSay("Negative radius.");
                return;
            }
            for(j=i+2;j<n;j+=2)
            {
                float rj=llList2Float(BOUNDS,j+1);
                if(rj<0.0)
                {
                    llOwnerSay("Negative radius.");
                    return;
                }
                float gap=llVecDist(llList2Vector(BOUNDS,i),llList2Vector(BOUNDS,j))-ri-rj;
                llOwnerSay("Pair "+(string)(i/2)+"/"+(string)(j/2)+" gap="+(string)gap);
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Check vertical overlap in a spiral stair plan

Calculate angular step and rise per revolution from a planned step count and total rise.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set step count, total turns and total rise positive. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Rise per revolution is a geometric clearance indicator only; it excludes tread thickness and avatar collision dimensions.

// Original Incoprea. MIT. Calculation only.
integer STEPS=24;
float TURNS=1.5;
float RISE=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(STEPS<1||TURNS<=0.0||RISE<=0.0)
        {
            llOwnerSay("Positive inputs required.");
            return;
        }
        llOwnerSay("Angle per step="+(string)(360.0*TURNS/STEPS)+" rise per step="+(string)(RISE/STEPS)+" vertical rise per revolution="+(string)(RISE/TURNS));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Check whether bounds surround the root

Compare the local bounding-box center with the root origin.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object without seated avatars. Touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

The physical bounds center is not necessarily a visual or mass center. This helps explain why a rotation can look offset, without deciding the correct artistic pivot.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed object.");
            return;
        }
        list b=llGetBoundingBox(llGetKey());
        if(llGetListLength(b)!=2)
        {
            llOwnerSay("Bounds unavailable.");
            return;
        }
        vector center=(llList2Vector(b,0)+llList2Vector(b,1))*0.5;
        llOwnerSay("Bounds center relative to root: "+(string)center);
        llOwnerSay("Root-to-bounds-center distance: "+(string)llVecMag(center)+" m");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Check whether links were reordered

Record linked prim keys, then compare link positions on subsequent touches.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed linkset of 2-64 prims and touch as owner. Seated avatars are excluded.

Stop / restore: Remove or disable. This inspector changes no build properties.

Snapshot persists only until reset. Relinking can reorder keys; this check reports topology changes without identifying avatars.

// Original Incoprea example. MIT.
list prior;
integer ready;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed linkset.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>64)
        {
            llOwnerSay("Use a linkset of 2-64 prims.");
            return;
        }
        list current=[];
        integer i;
        for(i=1;i<=total;++i) current += [llGetLinkKey(i)];
        if(!ready)
        {
            prior=current;
            ready=TRUE;
            llOwnerSay("Topology snapshot recorded.");
            return;
        }
        if(llGetListLength(prior)!=total) llOwnerSay("Prim count changed from "+(string)llGetListLength(prior)+" to "+(string)total);
        for(i=0;i<total;++i) if(llList2Key(current,i)!=llList2Key(prior,i)) llOwnerSay("Different prim at link "+(string)(i+1));
        prior=current;
        llOwnerSay("Topology baseline updated.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Check whether planned vertices share a plane

Use the first three points to form a plane and measure every point’s deviation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set at least3 POINTS with a noncollinear first triple and nonnegative tolerance. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

A degenerate first triple is rejected rather than searching for another triple.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<3.0,0.0,0.0>,<0.0,3.0,0.0>,<2.0,2.0,0.02>];
float TOLERANCE=0.01;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<3||TOLERANCE<0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        vector origin=llList2Vector(POINTS,0);
        vector normal=(llList2Vector(POINTS,1)-origin)%(llList2Vector(POINTS,2)-origin);
        if(llVecMag(normal)<0.000001)
        {
            llOwnerSay("First triple is collinear.");
            return;
        }
        normal=llVecNorm(normal);
        float maximum;
        integer i;
        for(i=0;i<n;++i)
        {
            float d=llFabs((llList2Vector(POINTS,i)-origin)*normal);
            if(d>maximum)maximum=d;
        }
        llOwnerSay("Maximum deviation="+(string)maximum+" within tolerance="+(string)(maximum<=TOLERANCE));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Child orientation trim menu

Trim child rotation in 15-degree local-axis increments and return to Home.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child at its resting orientation. Owner-touch opens the axis menu.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Multiplication applies each increment in the child local frame; axes therefore move with the child.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
rotation home;
init()
{
    home=llGetLocalRot();
}
show()
{
    menu("Child local rotation: 15 degree steps",["X+","X-","Y+","Y-","Z+","Z-","Home"]);
}
choose(string s)
{
    if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
    rotation target=llGetLocalRot();
    vector step=ZERO_VECTOR;
    if(s=="Home")target=home;
    else
    {
        if(s=="X+")step.x=15.0;
        else if(s=="X-")step.x=-15.0;
        else if(s=="Y+")step.y=15.0;
        else if(s=="Y-")step.y=-15.0;
        else if(s=="Z+")step.z=15.0;
        else if(s=="Z-")step.z=-15.0;
        else return;
        target=llEuler2Rot(step*DEG_TO_RAD)*target;
    }
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,target]);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Child position nudge menu

Move a child in five-centimeter root-local steps with a Home action.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a nonphysical child; owner-touch opens X/Y/Z step buttons and Home.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Actual geometry moves. Keep within link distances and do not relink while offset.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
vector home;
init()
{
    home=llGetLocalPos();
}
show()
{
    menu("Child position: 5 cm root-local steps",["X+","X-","Y+","Y-","Z+","Z-","Home"]);
}
choose(string s)
{
    if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))
    {
        llOwnerSay("Use a nonphysical child.");
        close();
        return;
    }
    vector p=llGetLocalPos();
    if(s=="Home")p=home;
    else if(s=="X+")p.x+=0.05;
    else if(s=="X-")p.x-=0.05;
    else if(s=="Y+")p.y+=0.05;
    else if(s=="Y-")p.y-=0.05;
    else if(s=="Z+")p.z+=0.05;
    else if(s=="Z-")p.z-=0.05;
    else return;
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,p]);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Beginner

Child prim local transform

Read a child prim’s position and rotation relative to its root.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put the script inside a child prim of a linkset and touch that child as owner.

Stop / restore: Remove or disable the script. It does not change the build.

The script refuses root and unlinked prims because their local-position semantics differ. Rotation is printed as Euler degrees for convenient editing.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetLinkNumber() < 2)
        {
            llOwnerSay("Place this inside a child prim, not the root.");
            return;
        }
        llOwnerSay("Root-local position: " + (string)llGetLocalPos());
        llOwnerSay("Root-local Euler degrees: " + (string)(llRot2Euler(llGetLocalRot()) * RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Choose columns for a display board

Calculate how many minimum-width cards fit in a board and the exact equal card width.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set board width, minimum card width and gap. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Returns a layout plan, not a browser CSS setting. Count is bounded to64 and never drops below one.

// Original Incoprea. MIT. Planning only.
float WIDTH=12.0;
float MINIMUM=2.5;
float GAP=0.4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||MINIMUM<=0.0||GAP<0.0)
        {
            llOwnerSay("Invalid dimensions.");
            return;
        }
        integer columns=llFloor((WIDTH+GAP)/(MINIMUM+GAP));
        if(columns<1)columns=1;
        if(columns>64)columns=64;
        float card=(WIDTH-(columns-1)*GAP)/(float)columns;
        llOwnerSay("Columns="+(string)columns+" card width="+(string)card+" pitch="+(string)(card+GAP));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Clamp a child center to an annular work area

Keep a child’s horizontal root-local radius within a configured inner and outer boundary.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Set INNER and OUTER radii in meters. Owner-touch the child to preview; touch again to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Preserves height and radial bearing. A center exactly on the axis uses +X as its defined fallback direction.

// Original Incoprea. MIT. Test on a spare copy first.
integer selected;
key identity;
list original;
float INNER=1.0;
float OUTER=3.0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(selected)
        {
            if(llGetLinkKey(selected)==identity)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,llList2Vector(original,0),PRIM_ROT_LOCAL,llList2Rot(original,1),PRIM_SIZE,llList2Vector(original,2)]);
            else llOwnerSay("Topology changed; restore manually from backup.");
            selected=0;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))
        {
            llOwnerSay("Touch a child prim.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL,PRIM_SIZE]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        vector size=llList2Vector(data,2);
        if(INNER<0.0||OUTER<INNER||OUTER>10.0)return;
        vector flat=<p.x,p.y,0.0>;
        float radius=llVecMag(flat);
        float chosen=radius;
        if(chosen<INNER)chosen=INNER;
        if(chosen>OUTER)chosen=OUTER;
        vector direction=<1.0,0.0,0.0>;
        if(radius>0.00001)direction=flat/radius;
        flat=direction*chosen;
        p=<flat.x,flat.y,p.z>;
        selected=link;
        identity=llGetLinkKey(link);
        original=data;
        llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r,PRIM_SIZE,size]);
        llOwnerSay("Preview applied; touch again to restore.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Compare child orientations

Report children whose local rotation differs from a chosen reference quaternion.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set REFERENCE and LIMIT_DEGREES. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Uses quaternion angular distance, avoiding Euler wraparound errors. Does not detect whether differently authored meshes visually face the same way.

// Original Incoprea example. MIT.
rotation REFERENCE=ZERO_ROTATION;
float LIMIT_DEGREES=1.0;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(LIMIT_DEGREES<0 || LIMIT_DEGREES>180)
        {
            llOwnerSay("Angle limit must be 0-180.");
            return;
        }
        integer i;
        for(i=2;i<=total;++i)
        {
            rotation r=llList2Rot(llGetLinkPrimitiveParams(i,[PRIM_ROT_LOCAL]),0);
            float angle=llAngleBetween(r,REFERENCE)*RAD_TO_DEG;
            if(angle>LIMIT_DEGREES)llOwnerSay("Link "+(string)i+" differs by "+(string)angle+" degrees.");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Compare fabricated dimensions with a target

Report per-axis absolute and percentage deviations from a planned size.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive TARGET and nonnegative ACTUAL dimensions plus tolerance. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

This is a numerical inspection helper; tolerances are user-selected and not manufacturing advice.

// Original Incoprea. MIT. Planning only.
vector TARGET=<4.0,2.0,1.0>;
vector ACTUAL=<4.02,1.98,1.005>;
float TOLERANCE=0.015;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TARGET.x<=0.0||TARGET.y<=0.0||TARGET.z<=0.0||ACTUAL.x<0.0||ACTUAL.y<0.0||ACTUAL.z<0.0||TOLERANCE<0.0)
        {
            llOwnerSay("Invalid dimensions/tolerance.");
            return;
        }
        vector delta=ACTUAL-TARGET;
        vector percent=<100.0*delta.x/TARGET.x,100.0*delta.y/TARGET.y,100.0*delta.z/TARGET.z>;
        llOwnerSay("Delta="+(string)delta+" percent="+(string)percent+" within="+(string)(llFabs(delta.x)<=TOLERANCE&&llFabs(delta.y)<=TOLERANCE&&llFabs(delta.z)<=TOLERANCE));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Compare face finish settings

Compare every face’s glow and fullbright settings to face zero.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the inspected prim and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

This checks only two legacy finish settings. Different textures, colors, PBR materials, or normals can still make faces look different.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list reference=llGetPrimitiveParams([PRIM_GLOW,0,PRIM_FULLBRIGHT,0]);
        integer face;
        for(face=1;face<llGetNumberOfSides();++face)
        {
            list finish=llGetPrimitiveParams([PRIM_GLOW,face,PRIM_FULLBRIGHT,face]);
            if(llList2Float(finish,0)!=llList2Float(reference,0) || llList2Integer(finish,1)!=llList2Integer(reference,1))llOwnerSay("Finish differs on face "+(string)face+": glow="+llList2String(finish,0)+", fullbright="+llList2String(finish,1));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Compare two sampled feature spans

Report the ratio between two independently clicked spans.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch endpoints of the reference span, then endpoints of the comparison span. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Spans may have different directions. The first span must have nonzero length. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float reference=llVecDist(a,b);
        float measured=llVecDist(c,d);
        if(reference<0.000001)
        {
            llOwnerSay("Reference span is zero.");
            return;
        }
        llOwnerSay("Reference="+(string)reference+" comparison="+(string)measured+" ratio="+(string)(measured/reference));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Convert a three-dimensional grid index

Map a flat index to XYZ cell coordinates and reconstruct the same index.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set NX/NY/NZ and INDEX; total cell count limited to1000000. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

X changes fastest, thenY, thenZ. This is useful for deterministic storage and generated layouts.

// Original Incoprea. MIT. Planning only.
integer NX=5;
integer NY=4;
integer NZ=3;
integer INDEX=37;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(NX<1||NY<1||NZ<1||NX>100||NY>100||NZ>100||INDEX<0||INDEX>=NX*NY*NZ)
        {
            llOwnerSay("Invalid grid/index.");
            return;
        }
        integer x=INDEX%NX;
        integer y=(INDEX/NX)%NY;
        integer z=INDEX/(NX*NY);
        llOwnerSay("Cell="+(string)<x,y,z>+" restored index="+(string)(x+NX*(y+NY*z)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Convert pinion turns into rack travel

Calculate ideal straight rack travel from gear module, tooth count and turns.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive MODULE/TEETH and signed TURNS. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Ignores backlash, tooth shape, friction and mechanical loading.

// Original Incoprea. MIT. Planning only.
float MODULE=0.08;
integer TEETH=20;
float TURNS=1.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MODULE<=0.0||TEETH<1)
        {
            llOwnerSay("Positive module/teeth required.");
            return;
        }
        float diameter=MODULE*TEETH;
        llOwnerSay("Travel="+(string)(PI*diameter*TURNS)+" travel per tooth="+(string)(PI*MODULE));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Convert roof pitch formats

Translate rise-per-run ratio into degrees and percentage grade.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive RUN_UNITS and nonnegative RISE_UNITS. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Output formats describe the same ideal slope; they do not evaluate real construction suitability.

// Original Incoprea. MIT. Calculation only.
float RISE_UNITS=5.0;
float RUN_UNITS=12.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RISE_UNITS<0.0||RUN_UNITS<=0.0)
        {
            llOwnerSay("Invalid rise/run.");
            return;
        }
        llOwnerSay("Angle="+(string)(llAtan2(RISE_UNITS,RUN_UNITS)*RAD_TO_DEG)+" grade="+(string)(100.0*RISE_UNITS/RUN_UNITS)+" rise per metre="+(string)(RISE_UNITS/RUN_UNITS));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Convert screw rotation into linear advance

Calculate lead, travel and time for an ideal multi-start lead screw.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive pitch, starts andRPM; turns may be signed. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Lead equals thread pitch times starts. This only plans a virtual mechanism.

// Original Incoprea. MIT. Planning only.
float PITCH=0.02;
integer STARTS=2;
float TURNS=12.0;
float RPM=30.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PITCH<=0.0||STARTS<1||RPM<=0.0)
        {
            llOwnerSay("Invalid screw inputs.");
            return;
        }
        float lead=PITCH*STARTS;
        llOwnerSay("Lead="+(string)lead+" travel="+(string)(lead*TURNS)+" seconds="+(string)(60.0*llFabs(TURNS)/RPM));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Count distinct face texture references

Count exposed legacy texture identifiers on the current prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Counts references, not texture memory, resolution, download size, or PBR maps. Repeated identifiers are counted once; hidden UUIDs are counted separately as unavailable.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list textures=[];
        integer hidden;
        integer face;
        for(face=0;face<llGetNumberOfSides();++face)
        {
            key texture=llList2Key(llGetPrimitiveParams([PRIM_TEXTURE,face]),0);
            if(texture==NULL_KEY)++hidden;
            else if(llListFindList(textures,[texture])==-1)textures += [texture];
        }
        llOwnerSay("Unique exposed base textures: "+(string)llGetListLength(textures)+"; unavailable face keys: "+(string)hidden);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Count model crossings of a reference plane

Count signed crossings of a plane through the start point using a dead band to suppress jitter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Set a nonzero region-space NORMAL and positive DEADBAND; move only this model. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Crossings between samples can be missed. Start-point plane is fixed for the session; stops at a region change.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
vector NORMAL=<1.0,0.0,0.0>;
float DEADBAND=0.05;
vector origin;
vector normal;
vector region;
integer side;
integer forward;
integer reverse;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Negative-to-positive crossings="+(string)forward+" reverse="+(string)reverse);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        if(llVecMag(NORMAL)<0.001||DEADBAND<=0.0)return;
        origin=llGetPos();
        normal=llVecNorm(NORMAL);
        region=llGetRegionCorner();
        side=0;
        forward=0;
        reverse=0;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        if(llGetRegionCorner()!=region)
        {
            finish();
            return;
        }
        float d=(llGetPos()-origin)*normal;
        integer next=side;
        if(d>DEADBAND)next=1;
        else if(d< -DEADBAND)next=-1;
        if(side==-1&&next==1)++forward;
        if(side==1&&next==-1)++reverse;
        side=next;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Count steps between hex cells

Calculate the shortest number of neighboring-cell steps on an axial hex grid.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set integer axial endpoints Q1/R1 and Q2/R2. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

This ignores blocked cells and terrain costs; it is a lower bound for obstacle-aware routes.

// Original Incoprea. MIT. Planning only.
integer Q1=0;
integer R1=0;
integer Q2=4;
integer R2=-2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer dq=Q2-Q1;
        integer dr=R2-R1;
        integer ds=-dq-dr;
        integer distance=(llAbs(dq)+llAbs(dr)+llAbs(ds))/2;
        llOwnerSay("Hex neighbor steps="+(string)distance);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Create a center bookmark between surface points

Print the midpoint between two actual clicked locations in region coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch two symmetric boundary points of the feature to center. Collect 2 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The arithmetic midpoint does not necessarily lie on a curved surface. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=2)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<2)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 2.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector midpoint=(a+b)*0.5;
        llOwnerSay("Midpoint="+(string)midpoint+" span="+(string)llVecDist(a,b));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Detect texture mapping changes

Record one face’s texture identifier, repeats, offset, and angle; report changed fields later.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Touch as owner before and after editing the face.

Stop / restore: Remove or disable. This inspector changes no build properties.

Base/legacy texture mapping only. No values are restored. Texture identifiers may be hidden by permissions; the script checks actual returned values.

// Original Incoprea example. MIT.
integer FACE=0;
list baseline;
integer ready;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(FACE<0 || FACE>=llGetNumberOfSides())
        {
            llOwnerSay("Invalid face.");
            return;
        }
        list current=llGetPrimitiveParams([PRIM_TEXTURE,FACE]);
        if(!ready)
        {
            baseline=current;
            ready=TRUE;
            llOwnerSay("Texture mapping baseline recorded.");
            return;
        }
        list labels=["texture","repeats","offset","angle"];
        integer i;
        for(i=0;i<4;++i) if(llList2String(current,i)!=llList2String(baseline,i)) llOwnerSay(llList2String(labels,i)+" changed: "+llList2String(baseline,i)+" -> "+llList2String(current,i));
        llOwnerSay("Comparison complete.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Detect when a moved model settles

Wait for three consecutive sampled positions within a small movement tolerance, or stop at thirty samples.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Start while moving a test model; set TOLERANCE for your build scale. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

No forces are applied. A quiet sample streak is not proof of physics sleep or future stability.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
float TOLERANCE=0.005;
vector previous;
integer quiet;
integer settled;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Settled="+(string)settled+" quiet samples="+(string)quiet+" elapsed seconds="+(string)(llGetTime()-began));
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        if(TOLERANCE<=0.0||TOLERANCE>0.5)return;
        previous=llGetPos();
        quiet=0;
        settled=FALSE;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        vector current=llGetPos();
        if(llVecDist(previous,current)<=TOLERANCE)++quiet;
        else quiet=0;
        previous=current;
        if(quiet>=3)
        {
            settled=TRUE;
            finish();
            return;
        }
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Dimension trim menu

Adjust one prim dimension in small increments while preserving a Home size.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical prim no larger than ten meters per axis. Owner-touch; Home restores captured scale.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Prim center stays fixed. Mesh visual bounds and collision bounds may differ. Clamps dimensions between 0.05 and 10 meters.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
vector home;
init()
{
    home=llGetScale();
}
show()
{
    menu("Size: 5 cm increments (0.05 to 10 m)",["X+","X-","Y+","Y-","Z+","Z-","Home"]);
}
choose(string s)
{
    if(llGetStatus(STATUS_PHYSICS))return;
    vector size=llGetScale();
    if(s=="Home")size=home;
    else
    {
        if(s=="X+")size.x+=0.05;
        else if(s=="X-")size.x-=0.05;
        else if(s=="Y+")size.y+=0.05;
        else if(s=="Y-")size.y-=0.05;
        else if(s=="Z+")size.z+=0.05;
        else if(s=="Z-")size.z-=0.05;
        else return;
        if(size.x<0.05)size.x=0.05;
        if(size.y<0.05)size.y=0.05;
        if(size.z<0.05)size.z=0.05;
        if(size.x>10.0)size.x=10.0;
        if(size.y>10.0)size.y=10.0;
        if(size.z>10.0)size.z=10.0;
    }
    llSetScale(size);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Distribute low-clumping rectangle samples

Generate twelve deterministic low-discrepancy positions using base2/base3 Halton coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive WIDTH and HEIGHT. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Deterministic quasi-random positions are not guaranteed to have minimum clearance and are not secure random values.

// Original Incoprea. MIT. Planning only.
float WIDTH=8.0;
float HEIGHT=5.0;
float radical(integer index,integer base)
{
    float value;
    float factor=1.0/(float)base;
    while(index>0)
    {
        value+=(index%base)*factor;
        index/=base;
        factor/=(float)base;
    }
    return value;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||HEIGHT<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        integer i;
        for(i=1;i<=12;++i)llOwnerSay((string)<WIDTH*radical(i,2),HEIGHT*radical(i,3),0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Distribute terrace depths by a taper

Calculate a series of linearly changing step depths whose sum equals a specified run.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set count2..12, total run and positive first-to-last ratio. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

This is a terrace layout calculation rather than a staircase usability recommendation.

// Original Incoprea. MIT. Calculation only.
integer COUNT=6;
float RUN=9.0;
float FIRST_TO_LAST=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(COUNT<2||COUNT>12||RUN<=0.0||FIRST_TO_LAST<=0.0)
        {
            llOwnerSay("Invalid series.");
            return;
        }
        float last=2.0*RUN/((float)COUNT*(FIRST_TO_LAST+1.0));
        float first=last*FIRST_TO_LAST;
        float start;
        integer i;
        for(i=0;i<COUNT;++i)
        {
            float depth=first+(last-first)*(float)i/(float)(COUNT-1);
            llOwnerSay("Step "+(string)i+" start="+(string)start+" depth="+(string)depth);
            start+=depth;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Estimate a helical handrail length

Calculate exact ideal helix length from radius, total height and turns.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set radius positive and number of turns nonnegative. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Does not include rail fittings, thickness, end extensions or segmentation error.

// Original Incoprea. MIT. Calculation only.
float RADIUS=2.0;
float HEIGHT=5.0;
float TURNS=1.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||TURNS<0.0)
        {
            llOwnerSay("Invalid radius/turns.");
            return;
        }
        float run=TWO_PI*RADIUS*TURNS;
        llOwnerSay("Helix length="+(string)llSqrt(run*run+HEIGHT*HEIGHT)+" slope angle="+(string)(llAtan2(HEIGHT,run)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Estimate a small-angle pendulum period

Calculate the ideal small-angle period for a pendulum length and gravity magnitude.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive LENGTH and GRAVITY. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Educational idealization: large angles, damping and simulator physics change the real period.

// Original Incoprea. MIT. Planning only.
float LENGTH=2.0;
float GRAVITY=9.81;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LENGTH<=0.0||GRAVITY<=0.0)
        {
            llOwnerSay("Positive length/gravity required.");
            return;
        }
        llOwnerSay("Small-angle period seconds="+(string)(TWO_PI*llSqrt(LENGTH/GRAVITY)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Estimate objects needed for concentric rings

Allocate a segment count to each ring to keep arc spacing below a target.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set first radius, radial step, number of rings1..8 and maximum spacing. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Ring counts are independent; angular alignment between rings is not guaranteed. This estimates object count before construction.

// Original Incoprea. MIT. Planning only.
float FIRST_RADIUS=1.0;
float RADIAL_STEP=1.0;
integer RINGS=4;
float MAX_SPACING=1.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(FIRST_RADIUS<=0.0||RADIAL_STEP<=0.0||RINGS<1||RINGS>8||MAX_SPACING<=0.0)
        {
            llOwnerSay("Invalid ring inputs.");
            return;
        }
        integer total;
        integer i;
        for(i=0;i<RINGS;++i)
        {
            float radius=FIRST_RADIUS+i*RADIAL_STEP;
            integer count=llCeil(TWO_PI*radius/MAX_SPACING);
            if(count<3)count=3;
            total+=count;
            llOwnerSay("Radius="+(string)radius+" count="+(string)count+" angle="+(string)(360.0/count));
        }
        llOwnerSay("Total objects planned="+(string)total);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Estimate stopping distance with reaction delay

Combine reaction travel and constant-deceleration braking distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set nonnegative SPEED and REACTION_TIME and positive DECELERATION. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Ideal kinematics for a virtual controller. It does not predict simulator physics or guarantee a collision-free stop.

// Original Incoprea. MIT. Planning only.
float SPEED=5.0;
float REACTION_TIME=0.2;
float DECELERATION=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPEED<0.0||REACTION_TIME<0.0||DECELERATION<=0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        float reaction=SPEED*REACTION_TIME;
        float braking=SPEED*SPEED/(2.0*DECELERATION);
        llOwnerSay("Reaction travel="+(string)reaction+" braking="+(string)braking+" total="+(string)(reaction+braking));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Evaluate a dwell-rise-dwell-return cam

Calculate a smooth cam follower displacement from one normalized revolution.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set phase0..1 and positive lift. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Each quarter of the revolution is assigned one stage. Uses cosine rise/return with zero endpoint velocity.

// Original Incoprea. MIT. Planning only.
float PHASE=0.35;
float LIFT=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PHASE<0.0||PHASE>1.0||LIFT<0.0)
        {
            llOwnerSay("Invalid phase/lift.");
            return;
        }
        float value;
        string stage;
        if(PHASE<0.25)
        {
            stage="low dwell";
            value=0.0;
        }
        else if(PHASE<0.5)
        {
            stage="rise";
            float t=(PHASE-0.25)*4.0;
            value=0.5*(1.0-llCos(PI*t));
        }
        else if(PHASE<0.75)
        {
            stage="high dwell";
            value=1.0;
        }
        else
        {
            stage="return";
            float t=(PHASE-0.75)*4.0;
            value=0.5*(1.0+llCos(PI*t));
        }
        llOwnerSay(stage+" lift="+(string)(LIFT*value));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Export child offsets and rotations

Print each child’s root-local offset and quaternion for build notes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed linkset of 2-64 prims and touch as owner. Seated avatars are excluded.

Stop / restore: Remove or disable. This inspector changes no build properties.

Root excluded because its local-position semantics differ. Output is not a full object backup; mesh, materials, inventory, and root transform are absent.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed linkset.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>64)
        {
            llOwnerSay("Use a linkset of 2-64 prims.");
            return;
        }
        integer i;
        for(i=2;i<=total;++i)
        {
            list p=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
            llOwnerSay((string)i+" "+llGetLinkName(i)+" position="+llList2String(p,0)+" rotation="+llList2String(p,1));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Export component world positions

Print each linked prim’s region position and world rotation for build notes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

A transform manifest, not a complete backup. Does not capture meshes, textures, inventory, physics, or permissions.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        integer i;
        for(i=1;i<=total;++i)
        {
            list data=llGetLinkPrimitiveParams(i,[PRIM_POSITION,PRIM_ROTATION]);
            llOwnerSay("Link "+(string)i+" position="+llList2String(data,0)+" rotation="+llList2String(data,1));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Extract child along its own axis

Pull a part outward along its local +X axis for inspection.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set DISTANCE between -5 and 5 meters. Use nonphysical child; touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Displacement follows saved child orientation, not root axes.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
float DISTANCE=0.3;
vector home;
rotation r;
default
{
    state_entry()
    {
        home=llGetLocalPos();
        r=llGetLocalRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||llFabs(DISTANCE)>5.0)return;
        preview=!preview;
        if(preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home+<DISTANCE,0.0,0.0>*r]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Face child toward root center

Turn child +X axis toward the root origin without moving it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use offset nonphysical child; owner-touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Roll is chosen by llRotBetween, not a camera-style up-vector constraint.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
rotation home;
default
{
    state_entry()
    {
        home=llGetLocalRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||llVecMag(llGetLocalPos())<0.01)return;
        preview=!preview;
        if(preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,-llVecNorm(llGetLocalPos()))]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Beginner

Face tint and transparency audit

Read each face’s legacy tint and alpha without changing them.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim to inspect and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Reports legacy face color/alpha settings, not texture pixel transparency or all PBR material settings. Copy the report to your notes before experimenting with a recoloring script.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer face;
        integer total = llGetNumberOfSides();
        for (face = 0; face < total; ++face)
        llOwnerSay("Face " + (string)face + " tint " + (string)llGetColor(face)
        + " alpha " + (string)llGetAlpha(face));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Fill a panel and calculate image crop

Calculate centered normalized UV span for an aspect-preserving image that fully covers a panel.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set image width/height and panel width/height. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

The crop assumes centered image alignment. Applying UV values depends on the actual face mapping and texture conventions.

// Original Incoprea. MIT. Planning only.
float IW=1920.0;
float IH=1080.0;
float PW=3.0;
float PH=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IW<=0.0||IH<=0.0||PW<=0.0||PH<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        float scale=PW/IW;
        if(PH/IH>scale)scale=PH/IH;
        float u=PW/(IW*scale);
        float v=PH/(IH*scale);
        llOwnerSay("Visible UV span="+(string)<u,v,0.0>+"; minimum UV="+(string)<(1.0-u)*0.5,(1.0-v)*0.5,0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Find a build’s dominant bounds axis

Report bounding-box proportions and whether the longest axis is X, Y, or Z.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object without seated avatars; touch as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Bounds are root-local and based on physical representation. Seated avatars can enlarge them; mesh visible geometry can differ.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed object.");
            return;
        }
        list bounds=llGetBoundingBox(llGetKey());
        if(llGetListLength(bounds)!=2)
        {
            llOwnerSay("Bounds unavailable.");
            return;
        }
        vector extent=llList2Vector(bounds,1)-llList2Vector(bounds,0);
        float longest=extent.x;
        string axis="X";
        if(extent.y>longest)
        {
            longest=extent.y;
            axis="Y";
        }
        if(extent.z>longest)
        {
            longest=extent.z;
            axis="Z";
        }
        if(longest<=0.0)
        {
            llOwnerSay("Degenerate bounds.");
            return;
        }
        llOwnerSay("Dominant local axis: "+axis+"; relative proportions: "+(string)(extent/longest));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Find an intercept for a moving target

Solve for a constant-speed intercept with a target moving at a known velocity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set relative TARGET_POSITION, TARGET_VELOCITY and positive CHASER_SPEED. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Uses supplied vectors only; no avatar tracking. Assumes straight constant velocity and no obstacles.

// Original Incoprea. MIT. Planning only.
vector TARGET_POSITION=<12.0,4.0,0.0>;
vector TARGET_VELOCITY=<0.0,1.0,0.0>;
float CHASER_SPEED=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(CHASER_SPEED<=0.0)
        {
            llOwnerSay("Positive speed required.");
            return;
        }
        float a=TARGET_VELOCITY*TARGET_VELOCITY-CHASER_SPEED*CHASER_SPEED;
        float b=2.0*(TARGET_POSITION*TARGET_VELOCITY);
        float c=TARGET_POSITION*TARGET_POSITION;
        float t=-1.0;
        if(llFabs(a)<0.000001)
        {
            if(llFabs(b)>0.000001)t=-c/b;
        }
        else
        {
            float d=b*b-4.0*a*c;
            if(d>=0.0)
            {
                float root=llSqrt(d);
                float t1=(-b-root)/(2.0*a);
                float t2=(-b+root)/(2.0*a);
                if(t1>0.0)t=t1;
                if(t2>0.0&&(t<0.0||t2<t))t=t2;
            }
        }
        if(t<=0.0)
        {
            llOwnerSay("No future intercept.");
            return;
        }
        llOwnerSay("Time="+(string)t+" relative intercept="+(string)(TARGET_POSITION+t*TARGET_VELOCITY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Find coincident component centers

Report pairs of child prims whose local centers are within a small tolerance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed linkset of 2-64 prims and touch as owner. Seated avatars are excluded. Edit TOLERANCE in meters.

Stop / restore: Remove or disable. This inspector changes no build properties.

This compares centers, not mesh overlap or collision shapes. Pairs at identical centers may be intentional. Bounded to 64 prims.

// Original Incoprea example. MIT.
float TOLERANCE=0.001;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed linkset.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>64)
        {
            llOwnerSay("Use a linkset of 2-64 prims.");
            return;
        }
        if(TOLERANCE<=0.0 || TOLERANCE>1.0)
        {
            llOwnerSay("Use a tolerance above zero and at most one meter.");
            return;
        }
        list positions=[];
        integer i;
        integer j;
        integer matches;
        for(i=2;i<=total;++i) positions+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
        for(i=0;i<llGetListLength(positions);++i) for(j=i+1;j<llGetListLength(positions);++j)
        {
            if(llVecDist(llList2Vector(positions,i),llList2Vector(positions,j))<TOLERANCE)
            {
                ++matches;
                llOwnerSay("Near-coincident child centers: "+(string)(i+2)+" / "+(string)(j+2));
            }
        }
        llOwnerSay("Pairs found: "+(string)matches);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Find mirrored child-center pairs

Report pairs whose centers mirror each other across the root-local X=0 plane.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner. Edit TOLERANCE.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Only matches center positions; orientation, scale, mesh shape, and appearance are not compared. Points on the mirror plane can match each other.

// Original Incoprea example. MIT.
float TOLERANCE=0.01;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(TOLERANCE<0 || TOLERANCE>1)
        {
            llOwnerSay("Use a tolerance from 0 to 1 meter.");
            return;
        }
        list positions=[];
        integer i;
        integer j;
        for(i=2;i<=total;++i)positions+=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]);
        for(i=0;i<llGetListLength(positions);++i)
        {
            vector p=llList2Vector(positions,i);
            vector mirror=<-p.x,p.y,p.z>;
            for(j=i+1;j<llGetListLength(positions);++j)if(llVecDist(mirror,llList2Vector(positions,j))<=TOLERANCE)llOwnerSay("Mirror-center pair: "+(string)(i+2)+" / "+(string)(j+2));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Find mirrored texture repeats

Report faces whose legacy texture repeats have a negative X or Y value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Negative repeats can intentionally mirror images. This is a diagnostic report, not a correction; mesh UV orientation can also mirror an image.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer face;
        integer findings;
        for(face=0;face<llGetNumberOfSides();++face)
        {
            vector repeats=llList2Vector(llGetPrimitiveParams([PRIM_TEXTURE,face]),1);
            if(repeats.x<0 || repeats.y<0)
            {
                ++findings;
                llOwnerSay("Mirrored repeat on face "+(string)face+": "+(string)repeats);
            }
        }
        llOwnerSay("Faces with negative repeat: "+(string)findings);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Find nearly coincident planned vertices

Report all point pairs separated by less than a chosen tolerance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINTS with at most12 positions and positive TOLERANCE. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

This is a small quadratic comparison; it reports proximity without merging points.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<1.0,0.0,0.0>,<1.001,0.0,0.0>,<2.0,1.0,0.0>];
float TOLERANCE=0.01;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n>12||TOLERANCE<=0.0)
        {
            llOwnerSay("Use at most12 points and positive tolerance.");
            return;
        }
        integer found;
        integer i;
        integer j;
        for(i=0;i<n;++i)for(j=i+1;j<n;++j)if(llVecDist(llList2Vector(POINTS,i),llList2Vector(POINTS,j))<TOLERANCE)
        {
            ++found;
            llOwnerSay("Close pair="+(string)i+","+(string)j);
        }
        llOwnerSay("Close pairs="+(string)found);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Find the child nearest the root center

Identify the smallest root-local child offset magnitude.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Compares prim centers, not surfaces or collision distance. This can help identify a hub component before selecting a pivot manually.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        float closest=1e30;
        integer chosen;
        integer i;
        for(i=2;i<=total;++i)
        {
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            float distance=llVecMag(p);
            if(distance<closest)
            {
                closest=distance;
                chosen=i;
            }
        }
        llOwnerSay("Nearest child center: "+(string)chosen+" "+llGetLinkName(chosen)+" at "+(string)closest+" m");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Find the nearest planned anchor

Select the closest point from a small supplied anchor list and report its index and distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set ANCHORS and QUERY. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

This uses provided coordinates only, not nearby avatars or scene sensing. Ties choose the first anchor.

// Original Incoprea. MIT. Planning only.
list ANCHORS=[<0.0,0.0,0.0>,<5.0,0.0,0.0>,<2.0,4.0,0.0>];
vector QUERY=<3.0,2.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(ANCHORS);
        if(n==0)
        {
            llOwnerSay("No anchors.");
            return;
        }
        integer best=0;
        float distance=llVecDist(QUERY,llList2Vector(ANCHORS,0));
        integer i;
        for(i=1;i<n;++i)
        {
            float d=llVecDist(QUERY,llList2Vector(ANCHORS,i));
            if(d<distance)
            {
                distance=d;
                best=i;
            }
        }
        llOwnerSay("Anchor="+(string)best+" position="+(string)llList2Vector(ANCHORS,best)+" distance="+(string)distance);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Find the six neighboring hex cells

Print six adjacent pointy-top axial hex centers around a selected cell.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set axial Q/R and positive hex RADIUS. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Axial coordinates are integers; radius is center-to-corner distance.

// Original Incoprea. MIT. Planning only.
integer Q=2;
integer R=-1;
float RADIUS=1.0;
list DIRECTIONS=[<1.0,0.0,0.0>,<1.0,-1.0,0.0>,<0.0,-1.0,0.0>,<-1.0,0.0,0.0>,<-1.0,1.0,0.0>,<0.0,1.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0)
        {
            llOwnerSay("Positive radius required.");
            return;
        }
        integer i;
        for(i=0;i<6;++i)
        {
            vector d=llList2Vector(DIRECTIONS,i);
            float q=Q+d.x;
            float r=R+d.y;
            llOwnerSay("Neighbor axial="+(string)<q,r,0.0>+" center="+(string)<RADIUS*llSqrt(3.0)*(q+r*0.5),1.5*RADIUS*r,0.0>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Fit an X-axis beam between live anchors

Position, orient and resize a child beam so its local X length spans two named child centers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Use a boxlike child beam whose length axis is +X; name other children beam_a and beam_b. Owner-touch the child to preview; touch again to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Uses bounding dimensions. Length must be0.01–64 meters; simulator link/build limits may reject or clamp. Clear surrounding geometry first.

// Original Incoprea. MIT. Test on a spare copy first.
integer selected;
key identity;
list original;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(selected)
        {
            if(llGetLinkKey(selected)==identity)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,llList2Vector(original,0),PRIM_ROT_LOCAL,llList2Rot(original,1),PRIM_SIZE,llList2Vector(original,2)]);
            else llOwnerSay("Topology changed; restore manually from backup.");
            selected=0;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))
        {
            llOwnerSay("Touch a child prim.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL,PRIM_SIZE]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        vector size=llList2Vector(data,2);
        integer i;
        integer a;
        integer b;
        integer ca;
        integer cb;
        integer total=llGetObjectPrimCount(llGetKey());
        if(total>32)return;
        for(i=2;i<=total;++i)
        {
            if(llGetLinkName(i)=="beam_a")
            {
                a=i;
                ++ca;
            }
            if(llGetLinkName(i)=="beam_b")
            {
                b=i;
                ++cb;
            }
        }
        if(ca!=1||cb!=1||a==link||b==link)return;
        vector ap=llList2Vector(llGetLinkPrimitiveParams(a,[PRIM_POS_LOCAL]),0);
        vector bp=llList2Vector(llGetLinkPrimitiveParams(b,[PRIM_POS_LOCAL]),0);
        float length=llVecDist(ap,bp);
        if(length<0.01||length>64.0)return;
        p=(ap+bp)*0.5;
        r=llRotBetween(<1.0,0.0,0.0>,llVecNorm(bp-ap));
        size.x=length;
        selected=link;
        identity=llGetLinkKey(link);
        original=data;
        llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r,PRIM_SIZE,size]);
        llOwnerSay("Preview applied; touch again to restore.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Fit artwork inside a display rectangle

Calculate the largest aspect-preserving image rectangle that fits entirely inside a panel.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set image pixel dimensions and panel metre dimensions. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Returns displayed width/height and symmetric margins; does not upload or apply an image.

// Original Incoprea. MIT. Planning only.
float IW=1920.0;
float IH=1080.0;
float PW=4.0;
float PH=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IW<=0.0||IH<=0.0||PW<=0.0||PH<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        float scale=PW/IW;
        if(PH/IH<scale)scale=PH/IH;
        float w=IW*scale;
        float h=IH*scale;
        llOwnerSay("Image size="+(string)<w,h,0.0>+"; margins="+(string)<(PW-w)*0.5,(PH-h)*0.5,0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Fit fence pickets between posts

Choose the greatest picket count fitting a minimum clear gap and equalize all gaps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set clear span, picket width and minimum gap. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Includes gaps adjacent to both end posts. If none fit, it reports that instead of returning negative dimensions.

// Original Incoprea. MIT. Calculation only.
float SPAN=5.0;
float WIDTH=0.12;
float MIN_GAP=0.08;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPAN<=0.0||WIDTH<=0.0||MIN_GAP<0.0)
        {
            llOwnerSay("Invalid dimensions.");
            return;
        }
        integer count=llFloor((SPAN-MIN_GAP)/(WIDTH+MIN_GAP));
        if(count<1)
        {
            llOwnerSay("No picket fits.");
            return;
        }
        float gap=(SPAN-count*WIDTH)/(count+1);
        llOwnerSay("Pickets="+(string)count+" clear gaps="+(string)gap+" first centre="+(string)(gap+WIDTH*0.5));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Five-layer cutaway control

Peel away named model layers one touch at a time, preserving each face alpha.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name children layer1 through layer5. Put script in root. First touch hides layer5, then4,3,2,1; sixth restores all.

Stop / restore: Complete the six-touch cycle before removal; relinking invalidates stored link indices.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Only visibility changes; transparent parts still collide. PBR appearance and special alpha modes may differ.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
integer step;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer link;
        for(link=2;link<=llGetObjectPrimCount(llGetKey());++link)
        {
            string name=llGetLinkName(link);
            integer layer=llListFindList(["layer1","layer2","layer3","layer4","layer5"],[name])+1;
            if(layer)
            {
                integer f;
                for(f=0;f<llGetLinkNumberOfSides(link);++f)saved+=[link,f,layer]+llGetLinkPrimitiveParams(link,[PRIM_COLOR,f]);
            }
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        step=(step+1)%6;
        integer i;
        for(i=0;i<llGetListLength(saved);i+=5)
        {
            float alpha=llList2Float(saved,i+4);
            if(step&&llList2Integer(saved,i+2)>5-step)alpha=0.0;
            llSetLinkPrimitiveParamsFast(llList2Integer(saved,i),[PRIM_COLOR,llList2Integer(saved,i+1),llList2Vector(saved,i+3),alpha]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Flag a thin triangle by altitude ratio

Calculate the shortest altitude relative to the longest edge for a triangle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set A/B/C. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

A small ratio identifies a skinny triangle; this is a diagnostic metric, not a mesh-quality guarantee.

// Original Incoprea. MIT. Planning only.
vector A=ZERO_VECTOR;
vector B=<5.0,0.0,0.0>;
vector C=<2.0,0.1,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float ab=llVecDist(A,B);
        float bc=llVecDist(B,C);
        float ca=llVecDist(C,A);
        float longest=ab;
        if(bc>longest)longest=bc;
        if(ca>longest)longest=ca;
        if(longest<0.000001)
        {
            llOwnerSay("Coincident triangle.");
            return;
        }
        float twiceArea=llVecMag((B-A)%(C-A));
        float altitude=twiceArea/longest;
        llOwnerSay("Shortest altitude="+(string)altitude+" slenderness ratio="+(string)(altitude/longest));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Flag steep segments in a planned walkway

Calculate rise divided by horizontal run for each path segment and compare with a chosen grade limit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINTS and nonnegative MAX_GRADE_PERCENT. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

User-selected threshold is a virtual-design preference, not a legal accessibility standard.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.3>,<6.0,2.0,1.2>];
float MAX_GRADE_PERCENT=10.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MAX_GRADE_PERCENT<0.0)
        {
            llOwnerSay("Nonnegative limit required.");
            return;
        }
        integer i;
        for(i=1;i<llGetListLength(POINTS);++i)
        {
            vector d=llList2Vector(POINTS,i)-llList2Vector(POINTS,i-1);
            float run=llSqrt(d.x*d.x+d.y*d.y);
            if(run<0.000001)llOwnerSay("Segment "+(string)i+" vertical or zero-length.");
            else
            {
                float grade=100.0*d.z/run;
                llOwnerSay("Segment "+(string)i+" grade="+(string)grade+" exceeds="+(string)(llFabs(grade)>MAX_GRADE_PERCENT));
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Generate a face-finish restoration snippet

Print LSL statements restoring current face color, alpha, glow, and fullbright values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim before an experiment and touch as owner. Copy the reported statements into your own restore script.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Output is source text only and is not run automatically. Does not capture textures, PBR materials, normal/specular maps, or future changes.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer face;
        for(face=0;face<llGetNumberOfSides();++face)
        {
            list p=llGetPrimitiveParams([PRIM_COLOR,face,PRIM_GLOW,face,PRIM_FULLBRIGHT,face]);
            llOwnerSay("llSetPrimitiveParams([PRIM_COLOR, "+(string)face+", "+llList2String(p,0)+", "+llList2String(p,1)+", PRIM_GLOW, "+(string)face+", "+llList2String(p,2)+", PRIM_FULLBRIGHT, "+(string)face+", "+llList2String(p,3)+"]);");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Beginner

How many material faces?

Report how many faces LSL exposes on this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim or mesh and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Mesh material faces are not individual polygons. Face indices start at zero.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer faces = llGetNumberOfSides();
        llOwnerSay((string)faces + " faces; valid indices 0 through " + (string)(faces - 1) + ".");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Identify sharp turns in a planned route

Report signed horizontal heading changes at each interior route vertex.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINTS with3..12 vertices. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Repeated points are skipped with a warning. Angles do not imply whether a physical object can traverse the turn.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<5.0,3.0,0.0>,<2.0,5.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<3||n>12)
        {
            llOwnerSay("Use3..12 points.");
            return;
        }
        integer i;
        for(i=1;i<n-1;++i)
        {
            vector incoming=llList2Vector(POINTS,i)-llList2Vector(POINTS,i-1);
            vector outgoing=llList2Vector(POINTS,i+1)-llList2Vector(POINTS,i);
            incoming.z=0.0;
            outgoing.z=0.0;
            if(llVecMag(incoming)<0.000001||llVecMag(outgoing)<0.000001)llOwnerSay("Repeated XY point near index "+(string)i);
            else llOwnerSay("Turn "+(string)i+" degrees="+(string)(llAtan2(incoming.x*outgoing.y-incoming.y*outgoing.x,incoming*outgoing)*RAD_TO_DEG));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Inset a regular polygon border

Calculate inner apothem, inner circumradius and border area for a regular polygon frame.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set sides>=3, outer circumradius and inward border width. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

The inset uses parallel edges and must remain inside the original apothem.

// Original Incoprea. MIT. Calculation only.
integer SIDES=6;
float RADIUS=5.0;
float BORDER=0.4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SIDES<3||RADIUS<=0.0||BORDER<0.0)
        {
            llOwnerSay("Invalid polygon.");
            return;
        }
        float angle=PI/SIDES;
        float apothem=RADIUS*llCos(angle);
        if(BORDER>=apothem)
        {
            llOwnerSay("Border consumes the polygon.");
            return;
        }
        float inner=(apothem-BORDER)/llCos(angle);
        float factor=0.5*SIDES*llSin(TWO_PI/SIDES);
        llOwnerSay("Inner circumradius="+(string)inner+" border area="+(string)(factor*(RADIUS*RADIUS-inner*inner)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Inset atlas UVs to reduce edge bleed

Calculate normalized inset bounds for an atlas cell with a pixel gutter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set image dimensions, cell pixel bounds and inset pixels. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Padding reduces neighboring-cell sampling but cannot eliminate every mipmap or filtering artifact.

// Original Incoprea. MIT. Planning only.
float IW=1024.0;
float IH=1024.0;
float X=256.0;
float Y=512.0;
float W=256.0;
float H=256.0;
float PAD=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IW<=0.0||IH<=0.0||W<=2.0*PAD||H<=2.0*PAD||PAD<0.0||X<0.0||Y<0.0||X+W>IW||Y+H>IH)
        {
            llOwnerSay("Invalid cell or padding.");
            return;
        }
        llOwnerSay("U="+(string)((X+PAD)/IW)+".."+(string)((X+W-PAD)/IW)+"; V="+(string)(1.0-(Y+H-PAD)/IH)+".."+(string)(1.0-(Y+PAD)/IH));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Inspect a bounded PID control step

Calculate proportional, integral and derivative terms with output and integral clamping.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch repeatedly to feed the next predefined measurement. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

A teaching controller with fixed sample time, not a ready physics controller. Real control needs measured dt, reset handling and tuning.

// Original Incoprea. MIT. Planning only.
list MEASUREMENTS=[0.0,0.4,0.7,0.9,1.1,1.0];
integer cursor;
float integral;
float previousError;
integer initialized;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float measured=llList2Float(MEASUREMENTS,cursor);
        cursor=(cursor+1)%llGetListLength(MEASUREMENTS);
        float dt=0.1;
        float error=1.0-measured;
        integral+=error*dt;
        if(integral>0.5)integral=0.5;
        if(integral< -0.5)integral=-0.5;
        float derivative=0.0;
        if(initialized)derivative=(error-previousError)/dt;
        previousError=error;
        initialized=TRUE;
        float output=2.0*error+0.8*integral+0.1*derivative;
        if(output>1.0)output=1.0;
        if(output< -1.0)output=-1.0;
        llOwnerSay("Measurement="+(string)measured+" error="+(string)error+" output="+(string)output);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Inspect a prim’s world axes

Print where this prim’s local X, Y, and Z directions point in the region.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed prim and touch as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Directions are unit vectors. They do not identify a mesh’s artistic front; the creator may model the nose or face along any local axis.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed prim.");
            return;
        }
        rotation orientation=llGetRot();
        llOwnerSay("Local +X in world: "+(string)llRot2Fwd(orientation));
        llOwnerSay("Local +Y in world: "+(string)llRot2Left(orientation));
        llOwnerSay("Local +Z in world: "+(string)llRot2Up(orientation));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Beginner

Inspect a touched face

Read the base texture transform of the face you touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the inspected prim. Touch one of its faces as owner; in a linkset the touched prim must contain this script.

Stop / restore: Remove or disable the script. It does not change the build.

Reports legacy/base texture settings. It does not inspect PBR material parameters. Texture UUID visibility depends on permissions.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer ownLink = llGetLinkNumber();
        integer touchedLink = llDetectedLinkNumber(0);
        if (ownLink > 0 && touchedLink != ownLink)
        {
            llOwnerSay("Touch the prim containing this script.");
            return;
        }
        integer face = llDetectedTouchFace(0);
        if (face == TOUCH_INVALID_FACE)
        {
            llOwnerSay("The viewer did not provide a face.");
            return;
        }
        list p = llGetPrimitiveParams([PRIM_TEXTURE, face]);
        llOwnerSay("Face " + (string)face + ": " + llList2CSV(p));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Inspect a triangular opening’s clear heights

Calculate each triangle altitude from live corners and identify the smallest.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch three corners around the opening. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Altitudes are geometric face dimensions, not a guarantee that an avatar or object will pass through. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float ab=llVecDist(a,b);
        float bc=llVecDist(b,c);
        float ca=llVecDist(c,a);
        float twiceArea=llVecMag((b-a)%(c-a));
        if(ab<0.000001||bc<0.000001||ca<0.000001)
        {
            llOwnerSay("Repeated vertex.");
            return;
        }
        llOwnerSay("Altitudes oppositeAB/BC/CA="+(string)<twiceArea/ab,twiceArea/bc,twiceArea/ca>);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Beginner

Inspect the physics shape setting

Report whether this prim uses Prim, Convex Hull, or None for its physics shape.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the prim to inspect and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

This does not display the actual collision mesh or change land impact. Physics-shape support can vary by simulator; a visual mesh is not necessarily its collision shape.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list result = llGetPrimitiveParams([PRIM_PHYSICS_SHAPE_TYPE]);
        if (llGetListLength(result) != 1)
        {
            llOwnerSay("Physics shape data unavailable.");
            return;
        }
        integer shape = llList2Integer(result, 0);
        string name = "Unknown (" + (string)shape + ")";
        if (shape == PRIM_PHYSICS_SHAPE_PRIM) name = "Prim";
        else if (shape == PRIM_PHYSICS_SHAPE_CONVEX) name = "Convex Hull";
        else if (shape == PRIM_PHYSICS_SHAPE_NONE) name = "None";
        llOwnerSay("Physics shape setting: " + name);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Inspect the touched surface frame

Read surface normal and binormal and derive the third tangent direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch a visible surface as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

These are viewer-supplied touch vectors in region coordinates. Invalid or degenerate data is rejected; no object is rotated.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llDetectedTouchFace(0)==TOUCH_INVALID_FACE)
        {
            llOwnerSay("Surface data unavailable.");
            return;
        }
        vector normal=llDetectedTouchNormal(0);
        vector binormal=llDetectedTouchBinormal(0);
        if(llVecMag(normal)<0.0001 || llVecMag(binormal)<0.0001)
        {
            llOwnerSay("Degenerate touch frame.");
            return;
        }
        vector tangent=llVecNorm(binormal % normal);
        llOwnerSay("Normal: "+(string)normal+" / binormal: "+(string)binormal+" / tangent: "+(string)tangent);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Inspect triangle areas in a polygon fan

Triangulate from the first vertex and report each fan triangle area.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set ordered convex planar POINTS. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

A simple fan is appropriate for convex polygons; concave or nonplanar inputs can overlap or misrepresent area.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<5.0,3.0,0.0>,<2.0,5.0,0.0>,<0.0,3.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<3)
        {
            llOwnerSay("Need three vertices.");
            return;
        }
        vector origin=llList2Vector(POINTS,0);
        float total;
        integer i;
        for(i=1;i<n-1;++i)
        {
            vector a=llList2Vector(POINTS,i)-origin;
            vector b=llList2Vector(POINTS,i+1)-origin;
            float area=0.5*llVecMag(a%b);
            total+=area;
            llOwnerSay("Triangle0,"+(string)i+","+(string)(i+1)+" area="+(string)area);
        }
        llOwnerSay("Fan total area="+(string)total);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Lay out unequal parts with equal edge gaps

Arrange children along root-local X using each rotated bounding-box projected width, not equal center spacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Set GAP and START_X. Limit12 actual prims. Owner-touch applies/restores; all children are included in link order.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Preserves each part’s Y, Z and rotation. Bounding-box gaps are not exact gaps between irregular meshes. Use an isolated copied assembly.

// Original Incoprea. MIT. Test on a spare copy first.
float GAP=0.2;
float START_X=-2.0;
list saved;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        integer i;
        if(active)
        {
            for(i=0;i<llGetListLength(saved);i+=3)
            {
                integer link=llList2Integer(saved,i);
                if(llGetLinkKey(link)==llList2Key(saved,i+1))llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,llList2Vector(saved,i+2)]);
            }
            active=FALSE;
            saved=[];
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2||total>12||GAP<0.0||GAP>2.0)return;
        list targets;
        float cursor=START_X;
        for(i=2;i<=total;++i)
        {
            list data=llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL,PRIM_SIZE,PRIM_ROT_LOCAL]);
            vector p=llList2Vector(data,0);
            vector size=llList2Vector(data,1);
            rotation r=llList2Rot(data,2);
            vector x=<1.0,0.0,0.0>*r;
            vector y=<0.0,1.0,0.0>*r;
            vector z=<0.0,0.0,1.0>*r;
            float width=llFabs(x.x)*size.x+llFabs(y.x)*size.y+llFabs(z.x)*size.z;
            p.x=cursor+width*0.5;
            if(llFabs(p.x)>20.0)
            {
                llOwnerSay("Planned row exceeds20 meter local bound.");
                return;
            }
            targets += [p];
            cursor += width+GAP;
        }
        for(i=2;i<=total;++i)
        {
            saved += [i,llGetLinkKey(i),llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0)];
            llSetLinkPrimitiveParamsFast(i,[PRIM_POS_LOCAL,llList2Vector(targets,i-2)]);
        }
        active=TRUE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Linked direction-vector arrow

Aim one child arrow along a checked three-number vector message.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name child vector_arrow with its front along +X. Root owner-touch arms; root script sends code8063 and x,y,z integers from -100 to100.

Stop / restore: Owner-touch disarms and restores the arrow rotation.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Direction is root-local; magnitude is ignored. Zero vector rejected; nonphysical build only.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer target;
rotation home;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        integer count;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)if(llGetLinkName(i)=="vector_arrow")
        {
            target=i;
            ++count;
        }
        if(count!=1)
        {
            valid=FALSE;
            return;
        }
        home=llList2Rot(llGetLinkPrimitiveParams(target,[PRIM_ROT_LOCAL]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!valid)return;
        active=!active;
        if(!active)llSetLinkPrimitiveParamsFast(target,[PRIM_ROT_LOCAL,home]);
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||!valid||sender!=1||code!=8063||llGetStatus(STATUS_PHYSICS))return;
        list values=llCSV2List(s);
        if(llGetListLength(values)!=3)return;
        integer i;
        for(i=0;i<3;++i)
        {
            string value=llStringTrim(llList2String(values,i),STRING_TRIM);
            integer v=(integer)value;
            if((string)v!=value||llAbs(v)>100)return;
        }
        vector direction=<llList2Float(values,0),llList2Float(values,1),llList2Float(values,2)>;
        if(llVecMag(direction)<0.01)return;
        llSetLinkPrimitiveParamsFast(target,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,llVecNorm(direction))]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            active=FALSE;
            valid=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Beginner

Linkset bounding box

Report a rezzed linkset’s local bounding-box corners and extent.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object; touch as owner. Deselect seated avatars when measuring a bare build.

Stop / restore: Remove or disable the script. It does not change the build.

Bounds use root-local axes and physical representation. Seated avatars can affect them; attachments have different behavior. Mesh visible geometry may differ.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list bounds = llGetBoundingBox(llGetKey());
        if (llGetListLength(bounds) != 2)
        {
            llOwnerSay("Bounds unavailable.");
            return;
        }
        vector low = llList2Vector(bounds, 0);
        vector high = llList2Vector(bounds, 1);
        llOwnerSay("Local minimum: " + (string)low);
        llOwnerSay("Local maximum: " + (string)high);
        llOwnerSay("Extent: " + (string)(high - low));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

List all eight corners of a rotated box

Enumerate local half-extents and transform each corner by a planned box pose.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive SIZE, CENTER and Euler ANGLES. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

An oriented ideal box, not a mesh-bound query. The corner order follows three binary sign bits.

// Original Incoprea. MIT. Planning only.
vector SIZE=<4.0,2.0,3.0>;
vector CENTER=<5.0,5.0,2.0>;
vector ANGLES=<0.0,0.0,30.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SIZE.x<=0.0||SIZE.y<=0.0||SIZE.z<=0.0)
        {
            llOwnerSay("Positive size required.");
            return;
        }
        rotation r=llEuler2Rot(ANGLES*DEG_TO_RAD);
        integer i;
        for(i=0;i<8;++i)
        {
            float x=-0.5;
            float y=-0.5;
            float z=-0.5;
            if(i&1)x=0.5;
            if(i&2)y=0.5;
            if(i&4)z=0.5;
            llOwnerSay((string)i+": "+(string)(CENTER+<SIZE.x*x,SIZE.y*y,SIZE.z*z>*r));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

List components by local X position

Sort child prims from left to right along root-local X.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims. Touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Sorting affects only report order, not link numbers. Equal X positions may retain simulator/list-sort tie behavior; no topology changes occur.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        list rows=[];
        integer i;
        for(i=2;i<=total;++i)
        {
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            rows += [p.x,i];
        }
        rows=llListSort(rows,2,TRUE);
        for(i=0;i<llGetListLength(rows);i+=2)
        {
            integer link=llList2Integer(rows,i+1);
            llOwnerSay("X="+llList2String(rows,i)+": "+(string)link+" "+llGetLinkName(link));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Locate a frame inside an atlas

Calculate a sprite frame’s row, column and normalized UV bounds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set COLUMNS, ROWS and zero-based FRAME. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Row zero starts at the top of the image; V coordinates are reported bottom-up. Texture animation APIs may use their own order.

// Original Incoprea. MIT. Planning only.
integer COLUMNS=4;
integer ROWS=3;
integer FRAME=6;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(COLUMNS<1||ROWS<1||COLUMNS>64||ROWS>64||FRAME<0||FRAME>=COLUMNS*ROWS)
        {
            llOwnerSay("Invalid atlas dimensions/frame.");
            return;
        }
        integer column=FRAME%COLUMNS;
        integer row=FRAME/COLUMNS;
        float left=(float)column/(float)COLUMNS;
        float right=(float)(column+1)/(float)COLUMNS;
        float top=1.0-(float)row/(float)ROWS;
        float bottom=1.0-(float)(row+1)/(float)ROWS;
        llOwnerSay("Column="+(string)column+" row="+(string)row+" bounds U="+(string)left+".."+(string)right+" V="+(string)bottom+".."+(string)top);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Locate a touch relative to a sampled rail

Find the closest point on a two-touch rail to a third clicked point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch rail start, rail end, then a point to compare. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The rail is a finite segment; projection clamps at either endpoint. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector rail=b-a;
        float den=rail*rail;
        if(den<0.000001)
        {
            llOwnerSay("Rail endpoints coincide.");
            return;
        }
        float t=((c-a)*rail)/den;
        if(t<0.0)t=0.0;
        if(t>1.0)t=1.0;
        vector point=a+t*rail;
        llOwnerSay("Along fraction="+(string)t+" rail point="+(string)point+" perpendicular/clamped distance="+(string)llVecDist(c,point));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Match reference child dimensions

Preview the dimensions of a uniquely named reference part on this child.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name one other child reference_size. Use nonphysical child; owner-touch applies/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Copies bounding dimensions, not geometry, rotation, material or mesh shape.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector home;
default
{
    state_entry()
    {
        home=llGetScale();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            integer i;
            integer target;
            integer count;
            for(i=2;i<=llGetNumberOfPrims();++i)if(i!=llGetLinkNumber()&&llGetLinkName(i)=="reference_size")
            {
                target=i;
                ++count;
            }
            if(count!=1)
            {
                preview=FALSE;
                llOwnerSay("Need one other reference_size child.");
                return;
            }
            llSetScale(llList2Vector(llGetLinkPrimitiveParams(target,[PRIM_SIZE]),0));
        }
        else
        {
            llSetScale(home);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Match texture density across surfaces

Convert a desired pixels-per-metre density into repeat counts for a rectangular surface.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set surface size, source image dimensions, and target density. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Assumes conventional rectangular UV mapping. Mesh UV islands and viewer texture limits may prevent the target density.

// Original Incoprea. MIT. Planning only.
float W=5.0;
float H=3.0;
float PIXELS_W=1024.0;
float PIXELS_H=1024.0;
float PIXEL_DENSITY=256.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(W<=0.0||H<=0.0||PIXELS_W<=0.0||PIXELS_H<=0.0||PIXEL_DENSITY<=0.0)
        {
            llOwnerSay("Positive values required.");
            return;
        }
        llOwnerSay("Suggested repeats U="+(string)(W*PIXEL_DENSITY/PIXELS_W)+" V="+(string)(H*PIXEL_DENSITY/PIXELS_H));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Match wheel rotation to distance traveled

Convert accumulated signed path distance into wheel angle modulo a revolution.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive RADIUS and signed DISTANCE. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Assumes rolling without slip; actual simulated wheel contact may differ.

// Original Incoprea. MIT. Planning only.
float RADIUS=0.5;
float DISTANCE=7.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0)
        {
            llOwnerSay("Positive radius required.");
            return;
        }
        float radians=DISTANCE/RADIUS;
        float phase=radians-TWO_PI*llFloor(radians/TWO_PI);
        llOwnerSay("Total turns="+(string)(radians/TWO_PI)+" phase degrees="+(string)(phase*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Measure a circle fitting a clicked triangle

Calculate the incenter and incircle radius from three live corner measurements.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch three triangle vertices. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The center and radius belong to the mathematical triangle, not a curved patch. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float sideA=llVecDist(b,c);
        float sideB=llVecDist(a,c);
        float sideC=llVecDist(a,b);
        float perimeter=sideA+sideB+sideC;
        float twiceArea=llVecMag((b-a)%(c-a));
        if(perimeter<0.000001||twiceArea<0.000001)
        {
            llOwnerSay("Degenerate triangle.");
            return;
        }
        llOwnerSay("Incenter="+(string)((sideA*a+sideB*b+sideC*c)/perimeter)+" radius="+(string)(twiceArea/perimeter));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Measure a circular arc from three touches

Estimate the radius of the circle through three sampled points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch three separated points around a circular edge. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The three points define a circle in3D. Near-collinear clicks make the radius unstable. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float ab=llVecDist(a,b);
        float bc=llVecDist(b,c);
        float ca=llVecDist(c,a);
        float twiceArea=llVecMag((b-a)%(c-a));
        if(twiceArea<0.000001)
        {
            llOwnerSay("Points are nearly collinear.");
            return;
        }
        llOwnerSay("Fitted radius="+(string)(ab*bc*ca/(2.0*twiceArea)));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Measure a clicked line’s compass bearing

Report the bearing from the first touch to the second in a north-zero clockwise convention.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch two points whose horizontal positions differ. Collect 2 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Region+Y is north and+X east. This does not read avatar heading. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=2)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<2)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 2.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector delta=b-a;
        delta.z=0.0;
        if(llVecMag(delta)<0.000001)
        {
            llOwnerSay("No horizontal separation.");
            return;
        }
        float degrees=llAtan2(delta.x,delta.y)*RAD_TO_DEG;
        if(degrees<0.0)degrees+=360.0;
        llOwnerSay("North-clockwise bearing="+(string)degrees+" degrees");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Measure a corner with three touches

Measure the interior angle formed by three real surface points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch one edge point, the corner, then the other edge point. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The middle touch is the angle vertex. Repeated points are rejected. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector u=a-b;
        vector v=c-b;
        if(llVecMag(u)<0.000001||llVecMag(v)<0.000001)
        {
            llOwnerSay("Repeated corner point.");
            return;
        }
        float dot=llVecNorm(u)*llVecNorm(v);
        if(dot>1.0)dot=1.0;
        if(dot< -1.0)dot=-1.0;
        llOwnerSay("Corner degrees="+(string)(llAcos(dot)*RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Measure a five-point traced feature

Calculate the length and directness of a four-segment manually traced path.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch five ordered points along the feature. Collect 5 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Straight segment sums underestimate curved paths. Touches are not automatically captured during a drag. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=5)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<5)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 5.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float length;
        integer i;
        for(i=1;i<5;++i)length+=llVecDist(llList2Vector(points,i-1),llList2Vector(points,i));
        float direct=llVecDist(a,llList2Vector(points,4));
        llOwnerSay("Traced length="+(string)length+" endpoint distance="+(string)direct);
        if(length>0.000001)llOwnerSay("Directness="+(string)(direct/length));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Measure a four-corner surface patch

Calculate two triangle areas across a chosen quadrilateral diagonal.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch four corners around the boundary in order. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Assumes a simple roughly planar patch and uses diagonal0-to2; concave or twisted patches need care. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float first=0.5*llVecMag((b-a)%(c-a));
        float second=0.5*llVecMag((c-a)%(d-a));
        llOwnerSay("Triangulated patch area="+(string)(first+second)+" triangles="+(string)first+","+(string)second);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Advanced

Measure a model’s traveled path

Accumulate sampled travel distance and compare it with net displacement during one bounded session.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Move your own model with Edit or its existing animation. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

One-second samples underestimate curved or rapid paths. Stops when region coordinates change; does not track avatars.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
vector origin;
vector previous;
vector region;
float distance;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Sampled travel="+(string)distance+" m; net displacement="+(string)llVecDist(origin,previous)+" m; elapsed="+(string)(llGetTime()-began));
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        origin=llGetRootPosition();
        previous=origin;
        region=llGetRegionCorner();
        distance=0.0;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        if(llGetRegionCorner()!=region)
        {
            llOwnerSay("Region changed; stopping before coordinate discontinuity.");
            finish();
            return;
        }
        vector current=llGetRootPosition();
        distance += llVecDist(previous,current);
        previous=current;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Measure a plane’s tilt from horizontal

Use a three-point plane to calculate its unsigned tilt relative to world horizontal.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch three noncollinear points on a planar surface. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Reversing winding does not change the reported tilt. A vertical plane reports90 degrees. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector normal=(b-a)%(c-a);
        if(llVecMag(normal)<0.000001)
        {
            llOwnerSay("Collinear samples.");
            return;
        }
        normal=llVecNorm(normal);
        float z=llFabs(normal.z);
        if(z>1.0)z=1.0;
        llOwnerSay("Plane tilt degrees="+(string)(llAcos(z)*RAD_TO_DEG)+" normal="+(string)normal);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Measure a point’s height above a sampled plane

Fit a plane through the first three touches and measure the fourth point’s signed distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch three noncollinear plane points, then the point to compare. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Normal direction follows the first triple’s winding. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector normal=(b-a)%(c-a);
        if(llVecMag(normal)<0.000001)
        {
            llOwnerSay("First three points are collinear.");
            return;
        }
        normal=llVecNorm(normal);
        float height=(d-a)*normal;
        llOwnerSay("Signed height="+(string)height+" projected point="+(string)(d-height*normal));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Advanced

Measure a scripted point light’s sampled duty

Estimate enabled time and time-weighted intensity of this prim’s point light.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Start while an existing light-control script runs. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Uses previous sampled state over each elapsed interval; short flashes can be missed. This is not electrical energy or measured illumination.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
integer wasOn;
float intensity;
float prior;
float onTime;
float exposure;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    float duration=prior-began;
    float duty=0.0;
    if(duration>0.0)duty=onTime/duration;
    llOwnerSay("Sampled on-seconds="+(string)onTime+" duty fraction="+(string)duty+" intensity-seconds="+(string)exposure);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        list light=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_POINT_LIGHT]);
        wasOn=llList2Integer(light,0);
        intensity=llList2Float(light,2);
        prior=llGetTime();
        onTime=0.0;
        exposure=0.0;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        float now=llGetTime();
        float dt=now-prior;
        if(wasOn)
        {
            onTime += dt;
            exposure += dt*intensity;
        }
        list light=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_POINT_LIGHT]);
        wasOn=llList2Integer(light,0);
        intensity=llList2Float(light,2);
        prior=now;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Measure a signed fold about a shared edge

Calculate the signed dihedral angle between face normals around a chosen hinge edge.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set nonzero NORMAL_A/NORMAL_B and shared EDGE direction. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

The edge must lie in both face planes. Reversing the edge reverses the signed fold direction.

// Original Incoprea. MIT. Planning only.
vector NORMAL_A=<0.0,0.0,1.0>;
vector NORMAL_B=<0.0,0.7071068,0.7071068>;
vector EDGE=<1.0,0.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL_A)<0.000001||llVecMag(NORMAL_B)<0.000001||llVecMag(EDGE)<0.000001)
        {
            llOwnerSay("Nonzero vectors required.");
            return;
        }
        vector a=llVecNorm(NORMAL_A);
        vector b=llVecNorm(NORMAL_B);
        vector edge=llVecNorm(EDGE);
        if(llFabs(a*edge)>0.001||llFabs(b*edge)>0.001)
        {
            llOwnerSay("Edge must be perpendicular to both normals.");
            return;
        }
        llOwnerSay("Signed fold degrees="+(string)(llAtan2(edge*(a%b),a*b)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Measure a tetrahedral corner volume

Compute the volume enclosed by four clicked vertices.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch four noncoplanar points. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

This is the tetrahedron through those samples, not the volume of the whole mesh. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float volume=llFabs((b-a)*((c-a)%(d-a)))/6.0;
        llOwnerSay("Tetrahedron volume="+(string)volume);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Measure a triangular surface patch

Calculate area and perimeter from three clicked corners.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch the three corners of a triangular patch. Collect 3 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

Uses the planar triangle through the clicks; a curved surface may have greater true area. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=3)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<3)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 3.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        float area=0.5*llVecMag((b-a)%(c-a));
        float perimeter=llVecDist(a,b)+llVecDist(b,c)+llVecDist(c,a);
        llOwnerSay("Triangle area="+(string)area+" perimeter="+(string)perimeter);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Advanced

Measure accumulated orientation travel

Accumulate shortest sampled orientation changes and record peak sampled angular speed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Rotate the actual model with Edit or server-side animation. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Viewer-only target omega may not appear. Motion over180 degrees between samples is ambiguous; this is not a turn counter.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
rotation previous;
float previousTime;
float totalAngle;
float peak;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Sampled angular travel degrees="+(string)(totalAngle*RAD_TO_DEG)+" peak degrees/sec="+(string)(peak*RAD_TO_DEG));
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        previous=llGetRot();
        previousTime=llGetTime();
        totalAngle=0.0;
        peak=0.0;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        rotation current=llGetRot();
        float now=llGetTime();
        float angle=llAngleBetween(previous,current);
        float dt=now-previousTime;
        totalAngle += angle;
        if(dt>0.0&&angle/dt>peak)peak=angle/dt;
        previous=current;
        previousTime=now;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Building helpers · Intermediate

Measure rise, run and slope between two touches

Separate a clicked segment into vertical rise and horizontal run.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch the start and end of a ramp or walkway. Collect 2 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The result uses worldZ as vertical and reports signed uphill/downhill grade. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=2)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<2)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 2.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector delta=b-a;
        float run=llSqrt(delta.x*delta.x+delta.y*delta.y);
        llOwnerSay("Rise="+(string)delta.z+" run="+(string)run+" length="+(string)llVecMag(delta));
        if(run>0.000001)llOwnerSay("Grade percent="+(string)(100.0*delta.z/run)+" angle="+(string)(llAtan2(delta.z,run)*RAD_TO_DEG));
        else llOwnerSay("Vertical segment: grade undefined.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Measure rotation since a bookmark

First touch records orientation; later touches report the angular change in degrees.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed prim and touch as owner before and after rotating it.

Stop / restore: Remove or disable. This inspector changes no build properties.

No rotation is applied. Uses quaternion angular difference, not a subtraction of Euler angles. Reset discards the bookmark.

// Original Incoprea example. MIT.
rotation original;
integer ready;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed prim.");
            return;
        }
        if(!ready)
        {
            original=llGetRot();
            ready=TRUE;
            llOwnerSay("Orientation bookmarked.");
            return;
        }
        llOwnerSay("Angular change: "+(string)(llAngleBetween(original,llGetRot())*RAD_TO_DEG)+" degrees.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Measure scale changes against baseline

Record scale on first touch and report per-axis size ratios on later touches.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the inspected prim. Touch as owner before and after resizing.

Stop / restore: Remove or disable. This inspector changes no build properties.

Uses prim scale, not mesh visible dimensions. It does not restore or enforce the baseline. Reset forgets the bookmark.

// Original Incoprea example. MIT.
vector original;
integer ready;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        vector current=llGetScale();
        if(!ready)
        {
            original=current;
            ready=TRUE;
            llOwnerSay("Scale baseline: "+(string)original);
            return;
        }
        if(original.x<=0.0 || original.y<=0.0 || original.z<=0.0)
        {
            llOwnerSay("Invalid baseline.");
            return;
        }
        vector ratios=<current.x/original.x,current.y/original.y,current.z/original.z>;
        llOwnerSay("Scale ratios X/Y/Z: "+(string)ratios);
        llOwnerSay("Size delta: "+(string)(current-original));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Measure shortest distance between two infinite guide lines

Find the separation between two lines defined by four touches.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch first line start/end, then second line start/end. Collect 4 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

The lines are infinite; closest positions can lie beyond clicked segments. Parallel lines use perpendicular point-to-line distance. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=4)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<4)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 4.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector u=b-a;
        vector v=d-c;
        if(llVecMag(u)<0.000001||llVecMag(v)<0.000001)
        {
            llOwnerSay("Repeated endpoint.");
            return;
        }
        vector normal=u%v;
        float length=llVecMag(normal);
        float distance;
        if(length<0.000001)distance=llVecMag((c-a)%u)/llVecMag(u);
        else distance=llFabs((c-a)*normal)/length;
        llOwnerSay("Infinite guide-line separation="+(string)distance);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Beginner

Measure this prim

Report the width, depth, and height of the prim containing the script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim to inspect; touch as its owner.

Stop / restore: Remove or disable the script. It does not change the build.

These are the prim scale settings, not the visible bounds of a mesh or the whole linkset.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector size = llGetScale();
        llOwnerSay("Prim size in meters: " + (string)size);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Mirror a child position across a local plane

Reflect a child center across a plane defined in root-local coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Set NORMAL and PLANE_POINT. Owner-touch the child to preview; touch again to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Mirrors position only; it does not reverse mesh handedness or reflect orientation. The original position, rotation and size are restored together.

// Original Incoprea. MIT. Test on a spare copy first.
integer selected;
key identity;
list original;
vector NORMAL=<1.0,0.0,0.0>;
vector PLANE_POINT=ZERO_VECTOR;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(selected)
        {
            if(llGetLinkKey(selected)==identity)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,llList2Vector(original,0),PRIM_ROT_LOCAL,llList2Rot(original,1),PRIM_SIZE,llList2Vector(original,2)]);
            else llOwnerSay("Topology changed; restore manually from backup.");
            selected=0;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))
        {
            llOwnerSay("Touch a child prim.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL,PRIM_SIZE]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        vector size=llList2Vector(data,2);
        if(llVecMag(NORMAL)<0.001)return;
        vector normal=llVecNorm(NORMAL);
        p=p-2.0*((p-PLANE_POINT)*normal)*normal;
        selected=link;
        identity=llGetLinkKey(link);
        original=data;
        llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r,PRIM_SIZE,size]);
        llOwnerSay("Preview applied; touch again to restore.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Miter extension at a path corner

Calculate the outer offset intersection distance for two equal-width path strips.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set bend angle0..170 degrees and positive half-width. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Sharp bends create long miters; the example reports a miter-limit ratio before actual construction.

// Original Incoprea. MIT. Calculation only.
float BEND=70.0;
float HALF_WIDTH=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(BEND<0.0||BEND>=170.0||HALF_WIDTH<=0.0)
        {
            llOwnerSay("Invalid angle/width.");
            return;
        }
        float length=HALF_WIDTH/llCos(BEND*DEG_TO_RAD*0.5);
        llOwnerSay("Miter length="+(string)length+" ratio="+(string)(length/HALF_WIDTH)+" outer extension="+(string)(HALF_WIDTH*llTan(BEND*DEG_TO_RAD*0.5)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Neutralize ordinary prim twist

Temporarily remove box, cylinder or prism twist while preserving other shape fields.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical ordinary prim. Touch compares/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Separates deformation from rotation. Mesh/sculpt and other types rejected.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TYPE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer type=llList2Integer(saved,0);
        if(llGetStatus(STATUS_PHYSICS)||(type!=PRIM_TYPE_BOX&&type!=PRIM_TYPE_CYLINDER&&type!=PRIM_TYPE_PRISM))return;
        preview=!preview;
        if(preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TYPE]+llListReplaceList(saved,[ZERO_VECTOR],4,4));
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TYPE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Number a grid in a continuous snake

Convert a sequence index into rows and columns with alternating row direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set COLUMNS, ROWS and cell spacing; total cells at most16. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Useful for scan paths and ordered installations; output stays in one plane and includes cell centers.

// Original Incoprea. MIT. Planning only.
integer COLUMNS=4;
integer ROWS=3;
float SPACING=1.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(COLUMNS<1||ROWS<1||COLUMNS*ROWS>16||SPACING<=0.0)
        {
            llOwnerSay("Use1..16 total cells and positive spacing.");
            return;
        }
        integer i;
        for(i=0;i<COLUMNS*ROWS;++i)
        {
            integer row=i/COLUMNS;
            integer column=i%COLUMNS;
            if(row%2)column=COLUMNS-1-column;
            llOwnerSay((string)i+": "+(string)<column*SPACING,row*SPACING,0.0>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Number tiles outward from a central tile

Generate the first sixteen square-spiral grid coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive SPACING. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

The walk expands right/up/left/down in pairs of growing run lengths; it is a placement plan only.

// Original Incoprea. MIT. Planning only.
float SPACING=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPACING<=0.0)
        {
            llOwnerSay("Positive spacing required.");
            return;
        }
        integer x;
        integer y;
        integer direction;
        integer run=1;
        integer printed=1;
        llOwnerSay("0: "+(string)ZERO_VECTOR);
        while(printed<16)
        {
            integer pair;
            for(pair=0;pair<2&&printed<16;++pair)
            {
                integer step;
                for(step=0;step<run&&printed<16;++step)
                {
                    if(direction==0)++x;
                    else if(direction==1)++y;
                    else if(direction==2)--x;
                    else --y;
                    llOwnerSay((string)printed+": "+(string)<x*SPACING,y*SPACING,0.0>);
                    ++printed;
                }
                direction=(direction+1)%4;
            }
            ++run;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Offset a polyline corner by width

Intersect two offset edge lines at one path corner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set noncollinear XY points PREV/CORNER/NEXT and signed OFFSET. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Positive offset is left of travel. Nearly parallel offset lines are rejected; sharp corners may require beveling.

// Original Incoprea. MIT. Calculation only.
vector PREV=<0.0,0.0,0.0>;
vector CORNER=<5.0,0.0,0.0>;
vector NEXT=<7.0,4.0,0.0>;
float OFFSET=0.5;
float cross2(vector a,vector b)
{
    return a.x*b.y-a.y*b.x;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector d1=CORNER-PREV;
        vector d2=NEXT-CORNER;
        d1.z=0.0;
        d2.z=0.0;
        if(llVecMag(d1)<0.000001||llVecMag(d2)<0.000001)
        {
            llOwnerSay("Repeated vertex.");
            return;
        }
        d1=llVecNorm(d1);
        d2=llVecNorm(d2);
        vector p=CORNER+OFFSET*<-d1.y,d1.x,0.0>;
        vector q=CORNER+OFFSET*<-d2.y,d2.x,0.0>;
        float den=cross2(d1,d2);
        if(llFabs(den)<0.000001)
        {
            llOwnerSay("Parallel corner; handle straight path separately.");
            return;
        }
        llOwnerSay("Offset corner="+(string)(p+d1*(cross2(q-p,d2)/den)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Order exhibits by distance from a point

Sort provided exhibit coordinates by squared distance while retaining original indexes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINTS and CENTRE. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

The strided sort key is consistently float; equal-distance ties may use implementation-dependent order.

// Original Incoprea. MIT. Planning only.
list POINTS=[<4.0,0.0,0.0>,<1.0,1.0,0.0>,<2.0,3.0,0.0>];
vector CENTRE=ZERO_VECTOR;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list rows;
        integer i;
        for(i=0;i<llGetListLength(POINTS);++i)
        {
            vector delta=llList2Vector(POINTS,i)-CENTRE;
            rows+=[delta*delta,i];
        }
        rows=llListSort(rows,2,TRUE);
        for(i=0;i<llGetListLength(rows);i+=2)llOwnerSay("Index="+(string)llList2Integer(rows,i+1)+" distance="+(string)llSqrt(llList2Float(rows,i)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Ordinary-prim hollow preview

Compare a solid ordinary prim with a fifty-percent hollow profile.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical box, cylinder or prism; owner-touch toggles.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Keeps the saved hole shape, cuts, twist and other shape fields. Does not apply to mesh/sculpt prims; collision geometry changes.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TYPE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetStatus(STATUS_PHYSICS))return;
        integer type=llList2Integer(saved,0);
        if(type!=PRIM_TYPE_BOX&&type!=PRIM_TYPE_CYLINDER&&type!=PRIM_TYPE_PRISM)return;
        preview=!preview;
        if(preview)
        {
            list shape=llListReplaceList(saved,[0.5],3,3);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TYPE]+shape);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TYPE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Pack display points on a triangular lattice

Generate three staggered rows with equilateral nearest-neighbor spacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive SPACING. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

This is a triangular point lattice, useful for dense round-item arrangements; it does not check actual object footprints.

// Original Incoprea. MIT. Planning only.
float SPACING=1.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPACING<=0.0)
        {
            llOwnerSay("Positive spacing required.");
            return;
        }
        integer row;
        integer column;
        for(row=0;row<3;++row)for(column=0;column<4;++column)
        {
            float offset=0.0;
            if(row%2)offset=0.5;
            llOwnerSay((string)<SPACING*(column+offset),SPACING*llSqrt(3.0)*0.5*row,0.0>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Pause and restore visual linked rotation

Capture each prim’s target-omega settings, set them to zero, then restore the saved settings on the next touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Use at most32 actual prims. Stop scripts that would reapply rotation. Owner-touch toggles pause.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Pauses viewer-side target omega only. It does not freeze physics, KFM or timer-driven pose changes. Restoring resumes speed, not the former visual phase.

// Original Incoprea. MIT. Test on a spare copy first.
list saved;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        integer i;
        if(active)
        {
            for(i=0;i<llGetListLength(saved);i+=5)
            {
                integer link=llList2Integer(saved,i);
                if(llGetLinkKey(link)==llList2Key(saved,i+1))llSetLinkPrimitiveParamsFast(link,[PRIM_OMEGA]+llList2List(saved,i+2,i+4));
                else llOwnerSay("Skipped changed link.");
            }
            active=FALSE;
            saved=[];
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2||total>32)return;
        for(i=1;i<=total;++i)
        {
            saved += [i,llGetLinkKey(i)]+llGetLinkPrimitiveParams(i,[PRIM_OMEGA]);
            llSetLinkPrimitiveParamsFast(i,[PRIM_OMEGA,ZERO_VECTOR,0.0,0.0]);
        }
        active=TRUE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Place evenly spaced markers along a route

Print six equal-distance positions on a multi-segment path.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set POINTS with at least two positions. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Duplicate points are allowed, but total route length must be positive. This plans positions without creating markers.

// Original Incoprea. MIT. Calculation only.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<4.0,6.0,0.0>,<8.0,6.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<2)
        {
            llOwnerSay("Need two points.");
            return;
        }
        float total;
        integer i;
        for(i=1;i<n;++i)total+=llVecDist(llList2Vector(POINTS,i-1),llList2Vector(POINTS,i));
        if(total<0.000001)
        {
            llOwnerSay("Zero-length path.");
            return;
        }
        integer marker;
        for(marker=0;marker<6;++marker)
        {
            float remaining=total*(float)marker/5.0;
            vector result=llList2Vector(POINTS,-1);
            integer found;
            for(i=1;i<n&&!found;++i)
            {
                vector a=llList2Vector(POINTS,i-1);
                vector b=llList2Vector(POINTS,i);
                float length=llVecDist(a,b);
                if(length>0.0&&remaining<=length)
                {
                    result=a+(b-a)*(remaining/length);
                    found=TRUE;
                }
                else remaining-=length;
            }
            llOwnerSay("Marker "+(string)marker+" "+(string)result);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Place small items on bounded shelves

Use first-fit shelf packing for a list of item widths and a fixed shelf capacity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive widths no larger than CAPACITY; at most twenty items. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

One-dimensional width packing with no gaps; first-fit is a heuristic and may use more shelves than an optimal arrangement.

// Original Incoprea. MIT. Planning only.
list WIDTHS=[3.0,2.0,4.0,1.5,2.5,1.0];
float CAPACITY=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(WIDTHS);
        if(n>20||CAPACITY<=0.0)
        {
            llOwnerSay("Invalid capacity/count.");
            return;
        }
        list used;
        integer i;
        for(i=0;i<n;++i)
        {
            float width=llList2Float(WIDTHS,i);
            if(width<=0.0||width>CAPACITY)
            {
                llOwnerSay("Invalid item width.");
                return;
            }
            integer shelf=0;
            integer placed=FALSE;
            while(shelf<llGetListLength(used)&&!placed)
            {
                float consumed=llList2Float(used,shelf);
                if(consumed+width<=CAPACITY)
                {
                    llOwnerSay("Item "+(string)i+" shelf "+(string)shelf+" x="+(string)consumed);
                    used=llListReplaceList(used,[consumed+width],shelf,shelf);
                    placed=TRUE;
                }
                else ++shelf;
            }
            if(!placed)
            {
                llOwnerSay("Item "+(string)i+" new shelf "+(string)llGetListLength(used));
                used+=[width];
            }
        }
        llOwnerSay("Shelf loads="+llDumpList2String(used,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan a crossed belt route

Calculate ideal crossed-belt length between two pulley circles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set radii and center distance greater than their sum. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Crossed belts reverse relative rotation; a real belt needs clearance where it crosses. This is geometry only.

// Original Incoprea. MIT. Planning only.
float R1=1.5;
float R2=1.0;
float DISTANCE=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(R1<=0.0||R2<=0.0||DISTANCE<=R1+R2)
        {
            llOwnerSay("Pulleys need sufficient separation.");
            return;
        }
        float sum=R1+R2;
        float angle=llAsin(sum/DISTANCE);
        float straight=llSqrt(DISTANCE*DISTANCE-sum*sum);
        llOwnerSay("Crossed length="+(string)(2.0*straight+(PI+2.0*angle)*sum)+" wrap degrees="+(string)((PI+2.0*angle)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan a nine-slice border layout

Calculate three columns and rows for a panel with fixed border widths.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set outer width/height and left/right/top/bottom border sizes. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Returns dimensions, not rendered panels. Opposing borders cannot exceed the outer span.

// Original Incoprea. MIT. Planning only.
float W=6.0;
float H=4.0;
float LEFT=0.4;
float RIGHT=0.6;
float TOP=0.5;
float BOTTOM=0.3;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LEFT<0.0||RIGHT<0.0||TOP<0.0||BOTTOM<0.0||W<=LEFT+RIGHT||H<=TOP+BOTTOM)
        {
            llOwnerSay("Borders leave no positive centre.");
            return;
        }
        llOwnerSay("Column widths="+(string)<LEFT,W-LEFT-RIGHT,RIGHT>+"; row heights bottom/centre/top="+(string)<BOTTOM,H-TOP-BOTTOM,TOP>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan a root pivot shift

Calculate a new root world position and adjusted child offsets that preserve child positions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set SHIFT in root-local meters. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

A planning calculation only. Assumes root orientation remains unchanged; moving the root geometry itself is intentional. It neither unlinks nor moves anything.

// Original Incoprea example. MIT.
vector SHIFT=<1.0,0.0,0.0>;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        rotation rootRot=llGetRootRotation();
        vector rootPos=llGetRootPosition();
        llOwnerSay("Proposed root position: "+(string)(rootPos+SHIFT*rootRot));
        integer i;
        for(i=2;i<=total;++i)
        {
            vector position=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            llOwnerSay("Child "+(string)i+" proposed offset: "+(string)(position-SHIFT));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan a rounded-end platform

Calculate perimeter and area of a stadium shape: rectangle plus two semicircles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set overall LENGTH greater than WIDTH and positive WIDTH. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Unlike a rounded rectangle, the end radius is exactly half the width.

// Original Incoprea. MIT. Calculation only.
float LENGTH=12.0;
float WIDTH=5.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||LENGTH<WIDTH)
        {
            llOwnerSay("Need length>=width>0.");
            return;
        }
        float straight=LENGTH-WIDTH;
        float radius=WIDTH*0.5;
        llOwnerSay("Straight middle length="+(string)straight+" perimeter="+(string)(2.0*straight+TWO_PI*radius)+" area="+(string)(straight*WIDTH+PI*radius*radius));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Plan a speed-limited move

Calculate acceleration, cruise and deceleration times for a rest-to-rest straight move.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive DISTANCE, MAX_SPEED and ACCELERATION. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Selects a triangular profile when the move is too short to reach maximum speed. It does not move an object.

// Original Incoprea. MIT. Planning only.
float DISTANCE=12.0;
float MAX_SPEED=3.0;
float ACCELERATION=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DISTANCE<=0.0||MAX_SPEED<=0.0||ACCELERATION<=0.0)
        {
            llOwnerSay("Positive inputs required.");
            return;
        }
        float ramp=MAX_SPEED/ACCELERATION;
        float rampDistance=ACCELERATION*ramp*ramp;
        float cruise=0.0;
        float peak=MAX_SPEED;
        if(DISTANCE<rampDistance)
        {
            ramp=llSqrt(DISTANCE/ACCELERATION);
            peak=ACCELERATION*ramp;
        }
        else cruise=(DISTANCE-rampDistance)/MAX_SPEED;
        llOwnerSay("Accelerate="+(string)ramp+" cruise="+(string)cruise+" decelerate="+(string)ramp+" total="+(string)(2.0*ramp+cruise)+" peak="+(string)peak);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan an open belt between unequal pulleys

Calculate an ideal open-belt length and each pulley’s wrap angle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set radii R1/R2 and center distance greater than their absolute difference. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

The formula models tangent straight segments plus contact arcs; pulleys must also avoid physical overlap for a practical arrangement.

// Original Incoprea. MIT. Planning only.
float R1=2.0;
float R2=1.0;
float DISTANCE=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(R1<=0.0||R2<=0.0||DISTANCE<=llFabs(R1-R2))
        {
            llOwnerSay("Invalid pulley layout.");
            return;
        }
        float big=R1;
        float small=R2;
        if(small>big)
        {
            float temp=big;
            big=small;
            small=temp;
        }
        float angle=llAsin((big-small)/DISTANCE);
        float straight=llSqrt(DISTANCE*DISTANCE-(big-small)*(big-small));
        float length=2.0*straight+PI*(big+small)+2.0*angle*(big-small);
        llOwnerSay("Belt length="+(string)length+" big wrap="+(string)((PI+2.0*angle)*RAD_TO_DEG)+" small wrap="+(string)((PI-2.0*angle)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Plan repeats for a rectangular panel

Calculate horizontal and vertical texture repeats from panel dimensions and desired meters per tile.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set WIDTH, HEIGHT, and METERS_PER_TILE to your measured flat panel values; touch as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Read-only planning for a flat rectangular mapping. Mesh UVs and planar mapping may differ; the script does not infer face orientation or apply repeats.

// Original Incoprea example. MIT.
float WIDTH=4.0;
float HEIGHT=2.0;
float METERS_PER_TILE=0.5;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(WIDTH<=0.0 || HEIGHT<=0.0 || METERS_PER_TILE<=0.0)
        {
            llOwnerSay("Use positive dimensions and tile size.");
            return;
        }
        vector repeats=<WIDTH/METERS_PER_TILE,HEIGHT/METERS_PER_TILE,0.0>;
        llOwnerSay("Suggested repeats: "+(string)repeats);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Beginner

Position bookmark

Print the current region, position, and world rotation for your build notes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed object and touch as owner. Copy the report into your own build notes.

Stop / restore: Remove or disable the script. It does not change the build.

This records nothing permanently by itself and does not move the object. Region coordinates are not global grid coordinates.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Region: " + llGetRegionName());
        llOwnerSay("Position: " + (string)llGetPos());
        llOwnerSay("World Euler degrees: " + (string)(llRot2Euler(llGetRot()) * RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Predict closest approach of two moving points

Calculate the time and separation of closest approach under constant velocities.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set relative POSITION and VELOCITY. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Negative closest time is clamped to now. Only supplied test vectors are used; no sensors or avatar data.

// Original Incoprea. MIT. Planning only.
vector POSITION=<10.0,4.0,0.0>;
vector VELOCITY=<-2.0,-0.2,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float speed2=VELOCITY*VELOCITY;
        float t=0.0;
        if(speed2>0.000001)t=-(POSITION*VELOCITY)/speed2;
        if(t<0.0)t=0.0;
        llOwnerSay("Closest future time="+(string)t+" separation="+(string)llVecMag(POSITION+t*VELOCITY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Preview a root-local placement offset

Convert a planned root-local offset into a region position for placing a separate object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set OFFSET and use a rezzed build. Touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Reports the target location but does not rez or move anything. Uses the root orientation and position; object scale does not scale the offset.

// Original Incoprea example. MIT.
vector OFFSET=<2.0,0.0,1.0>;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        vector target=llGetRootPosition()+OFFSET*llGetRootRotation();
        llOwnerSay("Proposed region position: "+(string)target);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Preview a suspended-cable curve

Sample a symmetric catenary from a selected shape parameter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set positive SPAN and shape parameter A; supports are atZ0. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

A controls tension-like shape but this is not a structural simulation. Large span/A ratios can overflow and are rejected.

// Original Incoprea. MIT. Calculation only.
float SPAN=8.0;
float A=5.0;
float cosh(float x)
{
    return 0.5*(llPow(2.718281828,x)+llPow(2.718281828,-x));
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPAN<=0.0||A<=0.0||SPAN/A>20.0)
        {
            llOwnerSay("Invalid span/shape ratio.");
            return;
        }
        float edge=cosh(SPAN/(2.0*A));
        integer i;
        for(i=0;i<=6;++i)
        {
            float x=-SPAN*0.5+SPAN*(float)i/6.0;
            float z=A*(cosh(x/A)-edge);
            llOwnerSay((string)<x,0.0,z>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Preview a uniform linkset resize

Report proposed prim scales and child offsets for a uniform scale factor.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACTOR from 0.1 through 10. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

This does not apply scaling. Simulator size, link-distance, mesh physics, and land-impact limits still require testing; warning limits are conservative sample values.

// Original Incoprea example. MIT.
float FACTOR=1.5;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(FACTOR<0.1 || FACTOR>10)
        {
            llOwnerSay("Factor must be 0.1-10.");
            return;
        }
        integer i;
        for(i=1;i<=total;++i)
        {
            vector size=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_SIZE]),0)*FACTOR;
            llOwnerSay("Link "+(string)i+" scale -> "+(string)size);
            if(size.x<0.01 || size.y<0.01 || size.z<0.01 || size.x>64 || size.y>64 || size.z>64)llOwnerSay("Review simulator size limits for this prim.");
            if(i>1)
            {
                vector offset=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
                llOwnerSay("Offset -> "+(string)(offset*FACTOR));
            }
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Preview consistent component names

Print a proposed prefix plus link-number name for each real prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set PREFIX. Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

No names are changed. Existing name-based scripts could depend on current names, so review their dependencies before manually applying a plan.

// Original Incoprea example. MIT.
string PREFIX="GardenPart";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        if(PREFIX=="" || llStringLength(PREFIX)>20)
        {
            llOwnerSay("Use a prefix of 1-20 characters.");
            return;
        }
        integer i;
        for(i=1;i<=total;++i)llOwnerSay(llGetLinkName(i)+" -> "+PREFIX+"-"+(string)i);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Preview sequential child component names

Rename children in link order to a numbered family while retaining a reversible snapshot.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Set PREFIX. Limit32 actual prims; owner-touch applies/restores.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Renaming may affect scripts that find parts by name. Disable those scripts first. Root name and inventory names are unchanged.

// Original Incoprea. MIT. Test on a spare copy first.
string PREFIX="Part-";
list saved;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        integer i;
        if(active)
        {
            for(i=0;i<llGetListLength(saved);i+=3)
            {
                integer link=llList2Integer(saved,i);
                if(llGetLinkKey(link)==llList2Key(saved,i+1))llSetLinkPrimitiveParamsFast(link,[PRIM_NAME,llList2String(saved,i+2)]);
                else llOwnerSay("Skipped changed link="+(string)link);
            }
            saved=[];
            active=FALSE;
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2||total>32||llStringLength(PREFIX)>20)return;
        for(i=2;i<=total;++i)
        {
            saved += [i,llGetLinkKey(i),llGetLinkName(i)];
            llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,PREFIX+(string)(i-1)]);
        }
        active=TRUE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Prim section-slice preview

Temporarily slice the upper half off a supported ordinary prim for a section study.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical ordinary box, cylinder or prism. Owner-touch toggles its slice from startup to the lower half.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Shape and collision geometry change; mesh objects do not use the same slicing behavior. Verify on a copy first.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_SLICE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetStatus(STATUS_PHYSICS))return;
        integer type=llList2Integer(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TYPE]),0);
        if(type!=PRIM_TYPE_BOX&&type!=PRIM_TYPE_CYLINDER&&type!=PRIM_TYPE_PRISM)return;
        preview=!preview;
        if(preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SLICE,<0.0,0.5,0.0>]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SLICE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Project a build point into planar UVs

Convert an XYZ point into planar texture coordinates using an origin and perpendicular basis axes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINT, ORIGIN, U_AXIS and V_AXIS, each axis scaled to one texture repeat. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Axes must be nonzero and perpendicular. This does not inspect mesh UVs; it plans a projection.

// Original Incoprea. MIT. Planning only.
vector POINT=<3.0,4.0,2.0>;
vector ORIGIN=ZERO_VECTOR;
vector U_AXIS=<2.0,0.0,0.0>;
vector V_AXIS=<0.0,2.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float uu=U_AXIS*U_AXIS;
        float vv=V_AXIS*V_AXIS;
        if(uu<0.000001||vv<0.000001||llFabs(U_AXIS*V_AXIS)>0.0001)
        {
            llOwnerSay("Use nonzero perpendicular axes.");
            return;
        }
        vector delta=POINT-ORIGIN;
        llOwnerSay("Planar UV="+(string)<(delta*U_AXIS)/uu,(delta*V_AXIS)/vv,0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Project a direction onto a spherical image

Calculate equirectangular UV coordinates from a nonzero direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set DIRECTION; longitude seam lies on the negativeX axis. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

The poles have ambiguous longitude. This is one explicit mapping convention and may differ from a mesh UV layout.

// Original Incoprea. MIT. Planning only.
vector DIRECTION=<2.0,3.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(DIRECTION)<0.000001)
        {
            llOwnerSay("Nonzero direction required.");
            return;
        }
        vector n=llVecNorm(DIRECTION);
        float z=n.z;
        if(z>1.0)z=1.0;
        if(z< -1.0)z=-1.0;
        float u=0.5+llAtan2(n.y,n.x)/TWO_PI;
        float v=0.5+llAsin(z)/PI;
        llOwnerSay("Spherical UV="+(string)<u,v,0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Project a point around a cylinder

Calculate cylindrical UVs from a point relative to a vertical cylinder center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINT, CENTER, HEIGHT and angular SEAM degrees. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

U wraps around the cylinder; V is measured from center upward. Points on the axis have no unique U.

// Original Incoprea. MIT. Planning only.
vector POINT=<2.0,2.0,3.0>;
vector CENTER=ZERO_VECTOR;
float HEIGHT=4.0;
float SEAM=0.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector p=POINT-CENTER;
        if(HEIGHT<=0.0||p.x*p.x+p.y*p.y<0.000001)
        {
            llOwnerSay("Positive height and point off axis required.");
            return;
        }
        float u=(llAtan2(p.y,p.x)-SEAM*DEG_TO_RAD)/TWO_PI;
        u-=llFloor(u);
        llOwnerSay("Cylindrical UV="+(string)<u,p.z/HEIGHT,0.0>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Project child onto an authored rail

Snap a child center to the nearest point on a root-local line segment.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set A and B. Put in nonphysical child; owner-touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Centerline alignment, not a moving constraint. Degenerate endpoints rejected.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector A=<-1.0,0.0,0.0>;
vector B=<1.0,0.0,0.0>;
vector home;
default
{
    state_entry()
    {
        home=llGetLocalPos();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)||llVecDist(A,B)<0.001)return;
        preview=!preview;
        if(preview)
        {
            vector d=B-A;
            float t=((home-A)*d)/(d*d);
            if(t<0.0)t=0.0;
            if(t>1.0)t=1.0;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,A+d*t]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Quick rope sag through three constraints

Print a parabolic span with fixed endpoints and a chosen center sag.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set SPAN positive and SAG nonnegative. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

A parabola is a visual approximation, not the exact hanging-cable catenary. Endpoints areZ0.

// Original Incoprea. MIT. Calculation only.
float SPAN=8.0;
float SAG=1.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPAN<=0.0||SAG<0.0)
        {
            llOwnerSay("Invalid span/sag.");
            return;
        }
        integer i;
        for(i=0;i<=6;++i)
        {
            float t=(float)i/6.0;
            llOwnerSay((string)<SPAN*t,0.0,-4.0*SAG*t*(1.0-t)>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Read a notecard’s first line

Read and display the first line of a notecard in the prim’s inventory.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a notecard and set CARD_NAME to its exact inventory name. The script reads the first line after reset.

Stop / restore: Remove the script; clear the floating text if the card has no line.

Demonstration of asynchronous notecard reading. It intentionally reads only one line and exposes it as public hover text.

// Original Incoprea example. Add your own notecard to this prim.
string CARD_NAME = "museum_note";
key query;
default
{
    state_entry()
    {
        if (llGetInventoryType(CARD_NAME) == INVENTORY_NOTECARD)
        query = llGetNotecardLine(CARD_NAME, 0);
        else
        llSetText("Add the museum_note notecard", <1.0, 0.7, 0.5>, 1.0);
    }
    dataserver(key request, string data)
    {
        if (request == query)
        llSetText(data, <0.85, 0.92, 0.78>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Record a live resizing envelope

Capture minimum and maximum component dimensions and bounding volume while this prim is resized.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Resize this prim manually or with an existing animation during the session. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Bounding-box volume is not mesh/material volume. Samples do not include changes that happen entirely between callbacks.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
vector low;
vector high;
float minVolume;
float maxVolume;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    llOwnerSay("Dimension minima="+(string)low+" maxima="+(string)high+" box volume range="+(string)minVolume+" to "+(string)maxVolume);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        low=llGetScale();
        high=low;
        minVolume=low.x*low.y*low.z;
        maxVolume=minVolume;
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        vector s=llGetScale();
        if(s.x<low.x)low.x=s.x;
        if(s.y<low.y)low.y=s.y;
        if(s.z<low.z)low.z=s.z;
        if(s.x>high.x)high.x=s.x;
        if(s.y>high.y)high.y=s.y;
        if(s.z>high.z)high.z=s.z;
        float volume=s.x*s.y*s.z;
        if(volume<minVolume)minVolume=volume;
        if(volume>maxVolume)maxVolume=volume;
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Building helpers · Intermediate

Record an aligned measurement box

Use two opposite clicked points to define region-axis minimum and maximum bounds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a spare owned object/linkset. Child touch handlers may consume events. Touch opposite corners of the region-aligned area to measure. Collect 2 owner touches; the next touch starts another measurement.

Stop / restore: Reset clears collected points; disable/remove to stop. No geometry is changed.

This constructs an axis-aligned box even if the source object is rotated. Results use actual touch positions in region coordinates, not hidden mesh dimensions.

// Original Incoprea. MIT. Live touch measurements only.
list points;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        if(llGetListLength(points)>=2)points=[];
        points+=[llDetectedTouchPos(0)];
        integer collected=llGetListLength(points);
        if(collected<2)
        {
            llOwnerSay("Recorded point "+(string)collected+" of 2.");
            return;
        }
        vector a=llList2Vector(points,0);
        vector b=llList2Vector(points,1);
        vector c=llList2Vector(points,2);
        vector d=llList2Vector(points,3);
        vector low=a;
        vector high=a;
        if(b.x<low.x)low.x=b.x;
        if(b.y<low.y)low.y=b.y;
        if(b.z<low.z)low.z=b.z;
        if(b.x>high.x)high.x=b.x;
        if(b.y>high.y)high.y=b.y;
        if(b.z>high.z)high.z=b.z;
        llOwnerSay("Minimum="+(string)low+" maximum="+(string)high+" size="+(string)(high-low));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Relate two points on a rigid lever

Calculate arc travel at two radii for the same angular turn.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set nonnegative ARM_A/ARM_B and signed ANGLE. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

This reports motion ratios only; it does not calculate real force, efficiency or material strength.

// Original Incoprea. MIT. Planning only.
float ARM_A=1.0;
float ARM_B=3.0;
float ANGLE=15.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ARM_A<=0.0||ARM_B<=0.0)
        {
            llOwnerSay("Positive arm lengths required.");
            return;
        }
        float angle=ANGLE*DEG_TO_RAD;
        llOwnerSay("Arc travelA="+(string)(ARM_A*angle)+" B="+(string)(ARM_B*angle)+" travel ratio="+(string)(ARM_B/ARM_A));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Remove near-duplicate route points

Keep route points only when they are at least a selected distance from the last kept point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINTS and nonnegative MIN_DISTANCE. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

The final endpoint is always retained, which may leave a short final segment. This does not preserve sharp corners like a full simplifier.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<0.02,0.0,0.0>,<1.0,0.0,0.0>,<1.01,0.0,0.0>,<2.0,1.0,0.0>];
float MIN_DISTANCE=0.1;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n==0||MIN_DISTANCE<0.0)
        {
            llOwnerSay("Need points and nonnegative threshold.");
            return;
        }
        list kept=[llList2Vector(POINTS,0)];
        vector last=llList2Vector(POINTS,0);
        integer i;
        for(i=1;i<n;++i)
        {
            vector p=llList2Vector(POINTS,i);
            if(llVecDist(last,p)>=MIN_DISTANCE||i==n-1)
            {
                kept+=[p];
                last=p;
            }
        }
        llOwnerSay("Kept="+(string)llGetListLength(kept)+": "+llDumpList2String(kept," | "));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Advanced

Replace faces sharing one diffuse asset

Touch a face to select its existing diffuse asset, then replace all matching faces with a named inventory texture.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put inside a test prim with at most32 faces. Add a texture named replacement with permissions that allow reuse. Owner-touch a face; next touch restores.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Only this prim is edited. Preserves each face’s repeats, offsets and rotation. Does not touch normal, specular or PBR assets.

// Original Incoprea. MIT. Test on a spare copy first.
list saved;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        if(active)
        {
            for(i=0;i<llGetListLength(saved);i+=5)llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,llList2Integer(saved,i)]+llList2List(saved,i+1,i+4));
            saved=[];
            active=FALSE;
            return;
        }
        integer face=llDetectedTouchFace(0);
        if(face<0||llDetectedLinkNumber(0)!=llGetLinkNumber()||llGetNumberOfSides()>32)return;
        if(llGetInventoryType("replacement")!=INVENTORY_TEXTURE)
        {
            llOwnerSay("Add replacement texture.");
            return;
        }
        string asset=llList2String(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,face]),0);
        if((key)asset==NULL_KEY)
        {
            llOwnerSay("Selected texture key is not readable.");
            return;
        }
        for(i=0;i<llGetNumberOfSides();++i)
        {
            list data=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,i]);
            if(llList2String(data,0)==asset)
            {
                saved += [i]+data;
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,i,"replacement"]+llList2List(data,1,3));
            }
        }
        active=TRUE;
        llOwnerSay("Replaced matching faces="+(string)(llGetListLength(saved)/5));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Advanced

Replace only matching face tints

Preview a palette replacement only on faces close to a specified source tint, preserving alpha.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put inside one test prim with at most32 faces. Set SOURCE_TINT, TARGET_TINT and TOLERANCE; owner-touch toggles preview.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Uses Euclidean RGB distance, not perceptual color distance. Does not change textures or PBR material factors.

// Original Incoprea. MIT. Test on a spare copy first.
vector SOURCE_TINT=<1.0,1.0,1.0>;
vector TARGET_TINT=<0.2,0.7,0.5>;
float TOLERANCE=0.05;
list saved;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        if(active)
        {
            for(i=0;i<llGetListLength(saved);i+=3)llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_COLOR,llList2Integer(saved,i),llList2Vector(saved,i+1),llList2Float(saved,i+2)]);
            saved=[];
            active=FALSE;
            return;
        }
        integer faces=llGetNumberOfSides();
        if(faces>32||TOLERANCE<0.0||TOLERANCE>0.5)return;
        for(i=0;i<faces;++i)
        {
            list data=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,i]);
            vector tint=llList2Vector(data,0);
            float alpha=llList2Float(data,1);
            if(llVecDist(tint,SOURCE_TINT)<=TOLERANCE)
            {
                saved += [i,tint,alpha];
                llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_COLOR,i,TARGET_TINT,alpha]);
            }
        }
        active=TRUE;
        llOwnerSay("Changed faces="+(string)(llGetListLength(saved)/3));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Report the child-center envelope

Find minimum and maximum root-local center coordinates of all children.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

This is the envelope of centers only, unlike llGetBoundingBox. It ignores component sizes, shape, root size, and rotation of individual parts.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        vector low=llList2Vector(llGetLinkPrimitiveParams(2,[PRIM_POS_LOCAL]),0);
        vector high=low;
        integer i;
        for(i=3;i<=total;++i)
        {
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            if(p.x<low.x)low.x=p.x;
            if(p.y<low.y)low.y=p.y;
            if(p.z<low.z)low.z=p.z;
            if(p.x>high.x)high.x=p.x;
            if(p.y>high.y)high.y=p.y;
            if(p.z>high.z)high.z=p.z;
        }
        llOwnerSay("Child-center min: "+(string)low+" max: "+(string)high);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Rotate a UV coordinate about a pivot

Apply a two-dimensional rotation to a texture coordinate around a chosen UV center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set UV, PIVOT and ANGLE degrees. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

The result may leave0..1 and wrap on repeating textures. This is coordinate math, not a prim texture mutation.

// Original Incoprea. MIT. Planning only.
vector UV=<0.2,0.8,0.0>;
vector PIVOT=<0.5,0.5,0.0>;
float ANGLE=30.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float a=ANGLE*DEG_TO_RAD;
        vector q=UV-PIVOT;
        vector result=PIVOT+<q.x*llCos(a)-q.y*llSin(a),q.x*llSin(a)+q.y*llCos(a),0.0>;
        llOwnerSay("Rotated UV="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Round a corner with a circular fillet

Calculate tangent setbacks for a circular arc joining two straight runs.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set interior angle1..179 degrees and radius. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

The angle is the interior angle between rays leaving the corner, not the change in travel heading.

// Original Incoprea. MIT. Calculation only.
float INTERIOR=100.0;
float RADIUS=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(INTERIOR<=0.0||INTERIOR>=180.0||RADIUS<=0.0)
        {
            llOwnerSay("Invalid angle/radius.");
            return;
        }
        float half=INTERIOR*DEG_TO_RAD*0.5;
        llOwnerSay("Setback along each ray="+(string)(RADIUS/llTan(half))+" centre distance on bisector="+(string)(RADIUS/llSin(half))+" arc sweep degrees="+(string)(180.0-INTERIOR));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Sample an ideal projectile arc

Print five positions under constant gravity from a specified launch velocity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set START, VELOCITY, GRAVITY and positive DURATION. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

This is ideal kinematics with no collisions or drag. It does not rez or launch a projectile.

// Original Incoprea. MIT. Planning only.
vector START=<0.0,0.0,1.0>;
vector VELOCITY=<4.0,0.0,6.0>;
vector GRAVITY=<0.0,0.0,-9.81>;
float DURATION=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DURATION<=0.0)
        {
            llOwnerSay("Positive duration required.");
            return;
        }
        integer i;
        for(i=0;i<=4;++i)
        {
            float t=DURATION*(float)i/4.0;
            llOwnerSay("t="+(string)t+" position="+(string)(START+VELOCITY*t+0.5*GRAVITY*t*t));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Separate ascent and descent on a route

Sum positive and negative vertical changes independently across a planned path.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINTS with two or more positions. Touch for private results.

Stop / restore: Disable/remove; no scene properties change.

Net height change alone hides intermediate climbs; this reports both cumulative directions.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,0.0,0.0>,<2.0,0.0,3.0>,<4.0,0.0,1.0>,<6.0,0.0,4.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<2)
        {
            llOwnerSay("Need two points.");
            return;
        }
        float ascent;
        float descent;
        integer i;
        for(i=1;i<n;++i)
        {
            vector a=llList2Vector(POINTS,i-1);
            vector b=llList2Vector(POINTS,i);
            float dz=b.z-a.z;
            if(dz>0.0)ascent+=dz;
            else descent-=dz;
        }
        llOwnerSay("Ascent="+(string)ascent+" descent="+(string)descent+" net="+(string)(ascent-descent));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Simulate a damped spring in small steps

Run a bounded semi-implicit Euler spring simulation and report positions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive stiffness, nonnegative damping and target; use the supplied small step size. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

Numerical stability depends on step size and stiffness. The simulation is illustrative and does not drive prim physics.

// Original Incoprea. MIT. Planning only.
float STIFFNESS=12.0;
float DAMPING=5.0;
float TARGET=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(STIFFNESS<=0.0||DAMPING<0.0)
        {
            llOwnerSay("Invalid spring parameters.");
            return;
        }
        float x=0.0;
        float velocity=0.0;
        float dt=0.02;
        integer i;
        for(i=0;i<100;++i)
        {
            float acceleration=STIFFNESS*(TARGET-x)-DAMPING*velocity;
            velocity+=acceleration*dt;
            x+=velocity*dt;
            if((i+1)%20==0)llOwnerSay("t="+(string)((i+1)*dt)+" position="+(string)x+" velocity="+(string)velocity);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Size a display by viewing angle

Calculate the width a flat display needs to subtend a target horizontal view angle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set viewing distance positive and angle between0 and170 degrees. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Assumes centered perpendicular viewing. This is geometric planning, not a viewer camera adjustment.

// Original Incoprea. MIT. Calculation only.
float DISTANCE=6.0;
float ANGLE=45.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DISTANCE<=0.0||ANGLE<=0.0||ANGLE>=170.0)
        {
            llOwnerSay("Invalid distance/angle.");
            return;
        }
        llOwnerSay("Display width="+(string)(2.0*DISTANCE*llTan(ANGLE*DEG_TO_RAD*0.5)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Size a ring-sector floor panel

Calculate area and inner/outer arc lengths for an annular sector.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set outer radius greater than inner radius and sweep0..360 degrees. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Boundary edges are circular; straight-sided mesh approximations have different areas.

// Original Incoprea. MIT. Calculation only.
float OUTER=6.0;
float INNER=3.0;
float SWEEP=45.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(INNER<0.0||OUTER<=INNER||SWEEP<=0.0||SWEEP>360.0)
        {
            llOwnerSay("Invalid sector.");
            return;
        }
        float angle=SWEEP*DEG_TO_RAD;
        llOwnerSay("Area="+(string)(0.5*angle*(OUTER*OUTER-INNER*INNER))+" outer arc="+(string)(angle*OUTER)+" inner arc="+(string)(angle*INNER));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Slow near a destination

Calculate a distance-dependent arrival speed capped by both preferred speed and stopping distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set DISTANCE, PREFERRED_SPEED and DECELERATION. Touch for owner-only output.

Stop / restore: Remove/disable. The script calculates only; no scene properties change.

This is a speed planner only. Repeated control needs measured elapsed time, tolerances and simulator-specific limits.

// Original Incoprea. MIT. Planning only.
float DISTANCE=1.2;
float PREFERRED_SPEED=4.0;
float DECELERATION=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DISTANCE<0.0||PREFERRED_SPEED<0.0||DECELERATION<=0.0)
        {
            llOwnerSay("Invalid arrival inputs.");
            return;
        }
        float speed=llSqrt(2.0*DECELERATION*DISTANCE);
        if(speed>PREFERRED_SPEED)speed=PREFERRED_SPEED;
        llOwnerSay("Recommended maximum arrival speed="+(string)speed);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Snap a child to the root-local grid

Round all three child offset coordinates to a configured root-local spacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Set positive GRID up to1 meter. Owner-touch the child to preview; touch again to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

This is a one-time actual position preview, not a moving constraint; collision clearance is your responsibility.

// Original Incoprea. MIT. Test on a spare copy first.
integer selected;
key identity;
list original;
float GRID=0.25;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(selected)
        {
            if(llGetLinkKey(selected)==identity)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,llList2Vector(original,0),PRIM_ROT_LOCAL,llList2Rot(original,1),PRIM_SIZE,llList2Vector(original,2)]);
            else llOwnerSay("Topology changed; restore manually from backup.");
            selected=0;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))
        {
            llOwnerSay("Touch a child prim.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL,PRIM_SIZE]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        vector size=llList2Vector(data,2);
        if(GRID<=0.0||GRID>1.0)return;
        p=<llRound(p.x/GRID)*GRID,llRound(p.y/GRID)*GRID,llRound(p.z/GRID)*GRID>;
        selected=link;
        identity=llGetLinkKey(link);
        original=data;
        llSetLinkPrimitiveParamsFast(link,[PRIM_POS_LOCAL,p,PRIM_ROT_LOCAL,r,PRIM_SIZE,size]);
        llOwnerSay("Preview applied; touch again to restore.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Sort a ring of points by bearing

Order supplied XY points by their angle around a chosen center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINTS around CENTER. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

Angle sorting does not produce a valid polygon for every arbitrary point cloud; duplicate bearings and interior points need additional handling.

// Original Incoprea. MIT. Planning only.
list POINTS=[<0.0,3.0,0.0>,<-3.0,0.0,0.0>,<3.0,0.0,0.0>,<0.0,-3.0,0.0>];
vector CENTER=ZERO_VECTOR;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list ordered;
        integer i;
        for(i=0;i<llGetListLength(POINTS);++i)
        {
            vector p=llList2Vector(POINTS,i)-CENTER;
            if(p.x*p.x+p.y*p.y<0.000001)
            {
                llOwnerSay("Point at center has no bearing.");
                return;
            }
            ordered+=[llAtan2(p.y,p.x),i];
        }
        ordered=llListSort(ordered,2,TRUE);
        for(i=0;i<llGetListLength(ordered);i+=2)llOwnerSay("Index="+(string)llList2Integer(ordered,i+1)+" angle="+(string)(llList2Float(ordered,i)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Space railing posts on an arc

Calculate a post count and angular step to keep arc spacing below a maximum.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set radius, positive sweep up to360 degrees and maximum spacing. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

Both endpoints receive posts. A full circle duplicates the start/end location; omit one endpoint in a closed build.

// Original Incoprea. MIT. Calculation only.
float RADIUS=4.0;
float SWEEP=120.0;
float MAX_SPACING=1.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||SWEEP<=0.0||SWEEP>360.0||MAX_SPACING<=0.0)
        {
            llOwnerSay("Invalid arc.");
            return;
        }
        float arc=RADIUS*SWEEP*DEG_TO_RAD;
        integer intervals=llCeil(arc/MAX_SPACING);
        llOwnerSay("Posts="+(string)(intervals+1)+" angle step="+(string)(SWEEP/(float)intervals)+" arc spacing="+(string)(arc/(float)intervals));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Spread ornaments over a sphere

Print twelve approximately uniform spherical positions using a golden-angle spiral.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive RADIUS. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

This avoids latitude-grid pole clustering but does not optimize minimum separation exactly.

// Original Incoprea. MIT. Planning only.
float RADIUS=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0)
        {
            llOwnerSay("Positive radius required.");
            return;
        }
        integer n=12;
        float golden=PI*(3.0-llSqrt(5.0));
        integer i;
        for(i=0;i<n;++i)
        {
            float z=1.0-2.0*((float)i+0.5)/(float)n;
            float ring=llSqrt(1.0-z*z);
            float angle=golden*i;
            llOwnerSay((string)(RADIUS*<ring*llCos(angle),ring*llSin(angle),z>));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Spread seeds across a circular bed

Print twelve sunflower-style positions with radius proportional to the square root of index.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive RADIUS. Owner touch prints sample coordinates.

Stop / restore: Remove/disable. Nothing is rezzed or moved.

An approximately even-area disc pattern, not random sampling. It intentionally excludes a point exactly at the origin.

// Original Incoprea. MIT. Planning only.
float RADIUS=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0)
        {
            llOwnerSay("Positive radius required.");
            return;
        }
        integer n=12;
        float angleStep=PI*(3.0-llSqrt(5.0));
        integer i;
        for(i=0;i<n;++i)
        {
            float r=RADIUS*llSqrt(((float)i+0.5)/(float)n);
            float angle=i*angleStep;
            llOwnerSay((string)<r*llCos(angle),r*llSin(angle),0.0>);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Building helpers · Intermediate

Summarize component role tags

Count exact Description values as role labels across a build.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Descriptions are treated as complete literal role labels. A description used as complex configuration may not make a useful role label; nothing is edited.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        list roles=[];
        list counts=[];
        integer i;
        for(i=1;i<=total;++i)
        {
            string role=llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0);
            if(role=="")role="[blank]";
            integer index=llListFindList(roles,[role]);
            if(index==-1)
            {
                roles += [role];
                counts += [1];
            }
            else counts=llListReplaceList(counts,[llList2Integer(counts,index)+1],index,index);
        }
        for(i=0;i<llGetListLength(roles);++i)llOwnerSay(llList2String(roles,i)+": "+llList2String(counts,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Summarize configured face transparency

Count fully opaque, partially transparent, and zero-alpha faces on this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the inspected prim and touch as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Only reads legacy face alpha. Texture pixels, alpha modes, and PBR can change actual appearance; zero alpha does not make metadata private.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        integer opaque;
        integer partial;
        integer clear;
        integer face;
        for(face=0;face<llGetNumberOfSides();++face)
        {
            float alpha=llGetAlpha(face);
            if(alpha<=0.0) ++clear;
            else if(alpha>=1.0) ++opaque;
            else ++partial;
        }
        llOwnerSay("Opaque: "+(string)opaque+"; partial: "+(string)partial+"; alpha zero: "+(string)clear);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Summarize primitive shape families

Count documented PRIM_TYPE values across this linkset.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed linkset of 2-32 prims and touch as owner.

Stop / restore: Remove or disable. This planner does not apply the reported changes.

Mesh/sculpted objects can appear under the sculpt type family; this is not a mesh topology or polygon-count audit.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed build.");
            return;
        }
        integer total=llGetObjectPrimCount(llGetKey());
        if(total<2 || total>32)
        {
            llOwnerSay("Use a linkset of 2-32 prims.");
            return;
        }
        list types=[];
        list counts=[];
        integer i;
        for(i=1;i<=total;++i)
        {
            integer shape=llList2Integer(llGetLinkPrimitiveParams(i,[PRIM_TYPE]),0);
            integer index=llListFindList(types,[shape]);
            if(index==-1)
            {
                types += [shape];
                counts += [1];
            }
            else counts=llListReplaceList(counts,[llList2Integer(counts,index)+1],index,index);
        }
        for(i=0;i<llGetListLength(types);++i)llOwnerSay("PRIM_TYPE "+llList2String(types,i)+": "+llList2String(counts,i)+" prims");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Beginner

Surface coordinate probe

Display the touched face’s normalized surface and texture coordinates to the owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a build and touch its visible surface as owner.

Stop / restore: Remove or disable the script. It does not change the build.

ST is face-space; UV reflects texture mapping. Unsupported touches can return invalid coordinates. This only reports the owner’s deliberate touch.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer face = llDetectedTouchFace(0);
        if (face == TOUCH_INVALID_FACE)
        {
            llOwnerSay("Surface data unavailable.");
            return;
        }
        llOwnerSay("Face " + (string)face + " / link " + (string)llDetectedLinkNumber(0));
        llOwnerSay("ST: " + (string)llDetectedTouchST(0));
        llOwnerSay("UV: " + (string)llDetectedTouchUV(0));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Advanced

Swap two chosen child centers

Choose two child prims to exchange their local positions without changing dimensions or rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical rezzed linkset; disable competing scripts and do not edit or relink during the preview. Put this in the root. Touch first child, second child, then any prim to restore.

Stop / restore: Owner-touch again to restore before removing, resetting, relinking or transferring. Snapshots are memory-only; deletion/reset does not undo changes. Keep an untouched backup.

Moves real geometry. Seated avatars and root are excluded. A changed topology aborts the swap or restore.

// Original Incoprea. MIT. Test on a spare copy first.
integer first;
integer second;
key firstKey;
key secondKey;
vector firstPos;
vector secondPos;
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()||llGetStatus(STATUS_PHYSICS)||llGetLinkNumber()>1)
        {
            llOwnerSay("Use a nonphysical rezzed root.");
            return;
        }
        if(active)
        {
            if(llGetLinkKey(first)==firstKey&&llGetLinkKey(second)==secondKey)
            {
                llSetLinkPrimitiveParamsFast(first,[PRIM_POS_LOCAL,firstPos]);
                llSetLinkPrimitiveParamsFast(second,[PRIM_POS_LOCAL,secondPos]);
            }
            else llOwnerSay("Topology changed; restore manually.");
            first=0;
            active=FALSE;
            return;
        }
        integer link=llDetectedLinkNumber(0);
        if(link<2||link>llGetObjectPrimCount(llGetKey()))return;
        if(!first)
        {
            first=link;
            firstKey=llGetLinkKey(link);
            firstPos=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL]),0);
            llOwnerSay("Touch a different child.");
            return;
        }
        if(link==first)return;
        if(llGetLinkKey(first)!=firstKey)
        {
            first=0;
            return;
        }
        second=link;
        secondKey=llGetLinkKey(link);
        secondPos=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL]),0);
        llSetLinkPrimitiveParamsFast(first,[PRIM_POS_LOCAL,secondPos]);
        llSetLinkPrimitiveParamsFast(second,[PRIM_POS_LOCAL,firstPos]);
        active=TRUE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Beginner

Three-axis orientation sign

Show a prim’s position to help while building.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the object to inspect. Touch to print its region position privately to the owner.

Stop / restore: Disable or remove the script; it does not change object placement.

Reports the prim position in region coordinates. It is not a compass heading or teleport tool.

// Original Incoprea building helper.
default
{
    touch_start(integer count)
    {
        vector p = llGetPos();
        llOwnerSay("Position: " + (string)p);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Three-bar linked chart

Resize three authored bars from a checked percentage message while retaining their base height.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name three root-aligned box children bar1,bar2,bar3. Use nonphysical root. Owner-touch arms; root script sends code8062 and three comma-separated integers0–100.

Stop / restore: Owner-touch disarms and restores each position and scale.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Zero values retain a0.01m sliver; no automatic physics or link changes. Intended for small exhibit bars, not structural parts.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        for(i=1;i<=3;++i)
        {
            integer j;
            integer found;
            integer count;
            for(j=2;j<=llGetObjectPrimCount(llGetKey());++j)if(llGetLinkName(j)=="bar"+(string)i)
            {
                found=j;
                ++count;
            }
            if(count!=1)
            {
                valid=FALSE;
                return;
            }
            links+=[found];
            saved+=llGetLinkPrimitiveParams(found,[PRIM_SIZE,PRIM_POS_LOCAL]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!valid)return;
        active=!active;
        if(!active)
        {
            integer i;
            for(i=0;i<3;++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_SIZE,llList2Vector(saved,i*2),PRIM_POS_LOCAL,llList2Vector(saved,i*2+1)]);
        }
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||!valid||sender!=1||code!=8062||llGetStatus(STATUS_PHYSICS))return;
        list values=llCSV2List(s);
        if(llGetListLength(values)!=3)return;
        integer i;
        for(i=0;i<3;++i)
        {
            string value=llStringTrim(llList2String(values,i),STRING_TRIM);
            integer number=(integer)value;
            if((string)number!=value||number<0||number>100)return;
        }
        for(i=0;i<3;++i)
        {
            vector size=llList2Vector(saved,i*2);
            vector p=llList2Vector(saved,i*2+1);
            float old=size.z;
            size.z*=llList2Integer(values,i)/100.0;
            if(size.z<0.01)size.z=0.01;
            p.z+=(size.z-old)*0.5;
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_SIZE,size,PRIM_POS_LOCAL,p]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Touch position in root coordinates

Convert an owner-selected surface point from region coordinates into the root’s coordinate system.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object and touch a surface as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Attachments are rejected. Point conversion includes translation and inverse rotation; it does not compensate for mesh modelling offsets.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed object.");
            return;
        }
        if(llDetectedTouchFace(0)==TOUCH_INVALID_FACE)
        {
            llOwnerSay("Touch surface data unavailable.");
            return;
        }
        vector localPoint=(llDetectedTouchPos(0)-llGetRootPosition())/llGetRootRotation();
        llOwnerSay("Root-local point: "+(string)localPoint);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Touch to extract one model component

Pull the owner-selected child slightly away from the root for inspection.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a small nonphysical linkset. Put in root; children pass touches to root. Root-touch restores selection.

Stop / restore: Touch the root to restore before removing. Selecting another child restores the previous one first.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Moves at most 0.25 meters along the child center’s radial direction. Does not promise a collision-free path.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer selected;
vector home;
integer valid=TRUE;
restore()
{
    if(selected)llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,home]);
    selected=0;
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!valid)return;
        integer link=llDetectedLinkNumber(0);
        restore();
        if(link<2||link>llGetObjectPrimCount(llGetKey()))return;
        home=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL]),0);
        if(llVecMag(home)<0.01)
        {
            llOwnerSay("Part center coincides with root.");
            return;
        }
        selected=link;
        llSetLinkPrimitiveParamsFast(selected,[PRIM_POS_LOCAL,home+llVecNorm(home)*0.25]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            selected=0;
            valid=FALSE;
            llOwnerSay("Link change: restore moved component manually if necessary.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Touch-surface crosshair

Move one child marker to the position selected on an authored flat panel.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root with one child crosshair. Set FACE,WIDTH,HEIGHT for a root-local XY panel whose UV axes match X/Y. Owner-touch panel positions marker; root long-hold restores.

Stop / restore: Hold the root panel for two seconds to restore before removal.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. UV orientation varies by mesh/face; test authored mapping first. Nonphysical only; Z is preserved from marker Home.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
float WIDTH=1.0;
float HEIGHT=1.0;
integer target;
integer valid=TRUE;
vector home;
float pressed;
default
{
    state_entry()
    {
        integer i;
        integer count;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)if(llGetLinkName(i)=="crosshair")
        {
            target=i;
            ++count;
        }
        if(count!=1)
        {
            valid=FALSE;
            return;
        }
        home=llList2Vector(llGetLinkPrimitiveParams(target,[PRIM_POS_LOCAL]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())pressed=llGetTime();
    }
    touch_end(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!valid||llDetectedLinkNumber(0)>1)return;
        if(llGetTime()-pressed>=2.0)
        {
            llSetLinkPrimitiveParamsFast(target,[PRIM_POS_LOCAL,home]);
            return;
        }
        if(llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.y<0.0||st.x>1.0||st.y>1.0)return;
        llSetLinkPrimitiveParamsFast(target,[PRIM_POS_LOCAL,<(st.x-0.5)*WIDTH,(st.y-0.5)*HEIGHT,home.z>]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Building helpers · Intermediate

Trim a corner with a chamfer

Find the two cut points and new diagonal length when beveling a path corner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim. Set three vertices and a positive setback smaller than both adjacent runs. Touch to print the plan privately.

Stop / restore: Remove/disable; calculations do not alter objects.

The setback is measured along each adjoining segment. No actual mesh is edited.

// Original Incoprea. MIT. Calculation only.
vector A=<0.0,0.0,0.0>;
vector B=<5.0,0.0,0.0>;
vector C=<5.0,4.0,0.0>;
float SETBACK=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float first=llVecDist(A,B);
        float second=llVecDist(B,C);
        if(SETBACK<=0.0||SETBACK>=first||SETBACK>=second)
        {
            llOwnerSay("Setback does not fit adjacent runs.");
            return;
        }
        vector p=B+llVecNorm(A-B)*SETBACK;
        vector q=B+llVecNorm(C-B)*SETBACK;
        llOwnerSay("Cut endpoints="+(string)p+" and "+(string)q+"; chamfer length="+(string)llVecDist(p,q));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Beginner

Two-point touch ruler

Measure the straight-line distance between two owner-selected surface points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a stationary rezzed build. Touch one surface point, then another point on the same scripted build.

Stop / restore: Remove or reset to forget the first point. No build properties change.

Uses viewer-provided world touch positions. Moving the object between touches changes the meaning of the measurement; results are approximate.

// Original Incoprea example. MIT.
vector first;
integer hasFirst;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llDetectedTouchFace(0) == TOUCH_INVALID_FACE)
        {
            llOwnerSay("Touch data unavailable; try a visible surface.");
            return;
        }
        vector point = llDetectedTouchPos(0);
        if (!hasFirst)
        {
            first = point;
            hasFirst = TRUE;
            llOwnerSay("First point saved. Touch the second point.");
        }
        else
        {
            llOwnerSay("Distance: " + (string)llVecDist(first, point) + " meters.");
            hasFirst = FALSE;
        }
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Building helpers · Intermediate

Uniform fit in display box

Uniformly scale one prim to fit authored unrotated bounding dimensions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set BOX dimensions. Use nonphysical child or unlinked prim; touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Not a whole-linkset resizer. Checks 0.01–64 meter dimensions; grids may impose other limits.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector BOX=<1.0,1.0,1.0>;
vector home;
default
{
    state_entry()
    {
        home=llGetScale();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetStatus(STATUS_PHYSICS)||BOX.x<=0.0||BOX.y<=0.0||BOX.z<=0.0)return;
        preview=!preview;
        if(preview)
        {
            float factor=BOX.x/home.x;
            if(BOX.y/home.y<factor)factor=BOX.y/home.y;
            if(BOX.z/home.z<factor)factor=BOX.z/home.z;
            vector size=home*factor;
            if(size.x<0.01||size.y<0.01||size.z<0.01||size.x>64.0||size.y>64.0||size.z>64.0)
            {
                preview=FALSE;
                return;
            }
            llSetScale(size);
        }
        else
        {
            llSetScale(home);
        }
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

Volume-preserving height study

Double height and reduce width/depth to preserve bounding-box volume.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use an ordinary nonphysical prim well within build limits. Owner-touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Preserves bounding-box volume, not hollow or arbitrary mesh surface volume.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector home;
default
{
    state_entry()
    {
        home=llGetScale();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            vector size=<home.x/llSqrt(2.0),home.y/llSqrt(2.0),home.z*2.0>;
            if(size.x<0.01||size.y<0.01||size.z>64.0)
            {
                preview=FALSE;
                return;
            }
            llSetScale(size);
        }
        else
        {
            llSetScale(home);
        }
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Advanced

Watch component role names during a test

Detect and count linked-child name changes while another maintenance or configuration script operates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own rezzed test object. Put in the root of a rezzed linkset with2–32 actual prims. Owner-touch starts a thirty-sample session; touch again ends early.

Stop / restore: Automatically stops after thirty samples. Disable/remove to stop; no scene properties are changed.

Stops when link keys change, rather than confusing relinked components. Names are only read; reports contain link numbers and change counts.

// Original Incoprea. MIT. Test on a spare copy first.
integer active;
integer samples;
float began;
list keys;
list names;
list counts;
integer total;
finish()
{
    llSetTimerEvent(0.0);
    active=FALSE;
    integer i;
    for(i=0;i<llGetListLength(counts);++i)if(llList2Integer(counts,i)>0)llOwnerSay("Link "+(string)(i+2)+" name transitions="+(string)llList2Integer(counts,i));
    llOwnerSay("Component-name watch finished.");
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            finish();
            return;
        }
        samples=0;
        began=llGetTime();
        if(llGetAttached()||llGetLinkNumber()>1)return;
        total=llGetObjectPrimCount(llGetKey());
        if(total<2||total>32)return;
        keys=[];
        names=[];
        counts=[];
        integer i;
        for(i=2;i<=total;++i)
        {
            keys += [llGetLinkKey(i)];
            names += [llGetLinkName(i)];
            counts += [0];
        }
        active=TRUE;
        llSetTimerEvent(1.0);
        llOwnerSay("Measurement session started.");
    }
    timer()
    {
        if(!active)return;
        ++samples;
        if(llGetObjectPrimCount(llGetKey())!=total)
        {
            llOwnerSay("Prim count changed; stopped.");
            finish();
            return;
        }
        integer i;
        for(i=2;i<=total;++i)
        {
            integer at=i-2;
            if(llGetLinkKey(i)!=llList2Key(keys,at))
            {
                llOwnerSay("Link identity changed; stopped.");
                finish();
                return;
            }
            string name=llGetLinkName(i);
            if(name!=llList2String(names,at))
            {
                counts=llListReplaceList(counts,[llList2Integer(counts,at)+1],at,at);
                names=llListReplaceList(names,[name],at,at);
            }
        }
        if(samples>=30)finish();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6 · API reference 7

Building helpers · Intermediate

World-grid alignment preview

Snap root horizontal position to half-meter region grid while preserving height.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use unattached nonphysical root away from region edges. Owner-touch previews/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Region rules can clamp movement; failures are reported. Does not change rotation or link offsets.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
vector home;
default
{
    state_entry()
    {
        home=llGetRootPosition();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))return;
        preview=!preview;
        if(preview)
        {
            vector target=home;
            target.x=llRound(home.x*2.0)*0.5;
            target.y=llRound(home.y*2.0)*0.5;
            if(!llSetRegionPos(target))llOwnerSay("Move failed; inspect for clamping.");
        }
        else
        {
            if(!llSetRegionPos(home))llOwnerSay("Restore failed; inspect for clamping.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Building helpers · Intermediate

World-upright child preview

Make a child world-upright while preserving horizontal forward bearing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in nonphysical child; owner-touch previews/restores. Keep root still.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Converts world orientation into root-local rotation.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
rotation home;
default
{
    state_entry()
    {
        home=llGetLocalRot();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return;
        vector forward=llRot2Fwd(home*llGetRootRotation());
        forward.z=0.0;
        if(llVecMag(forward)<0.01)return;
        preview=!preview;
        if(preview)
        {
            rotation root=llGetRootRotation();
            vector f=llRot2Fwd(home*root);
            float yaw=llAtan2(f.y,f.x);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llEuler2Rot(<0.0,0.0,yaw>)/root]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,home]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Look & atmosphere 3 categories
Color & materialsColor, textures, transparency, glow, and light.100 scripts

Download this category (.zip)

Color & materials · Intermediate

Align classic material UV channels

Align normal and specular map transforms to the diffuse face transform while preserving their assets.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a classic material with readable texture settings. Owner-touch aligns; touch again restores the original normal/specular transforms.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Does not replace normal/specular images or change PBR transforms. Useful when maps unexpectedly drift apart.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
integer FACE=0;
list normal;
list specular;
default
{
    state_entry()
    {
        normal=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_NORMAL,FACE]);
        specular=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_SPECULAR,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        preview=!preview;
        if(preview)
        {
            list diffuse=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
            list uv=llList2List(diffuse,1,3);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NORMAL,FACE]+llListReplaceList(normal,uv,1,3)+[PRIM_SPECULAR,FACE]+llListReplaceList(specular,uv,1,3));
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NORMAL,FACE]+normal+[PRIM_SPECULAR,FACE]+specular);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Alpha cutout preview

Compare hard-edged alpha masking with a classic material’s saved alpha mode.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a diffuse texture with transparency. Set FACE and preview a 128 cutoff.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. Hard cutouts differ from blended transparency and can remove soft edges.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE=0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_ALPHA_MODE, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ALPHA_MODE,FACE,PRIM_ALPHA_MODE_MASK,128]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ALPHA_MODE,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Alpha-mode comparison menu

Compare opaque, blended and masked classic alpha rendering on a face.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a transparent diffuse texture. Owner-touch and choose a mode; Restore returns original alpha mode and mask cutoff.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. This changes the material alpha rule, not face color alpha. PBR has separate material controls.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
integer FACE=0;
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_ALPHA_MODE,FACE]);
}
show()
{
    menu("Classic alpha comparison",["Opaque","Blend","Mask","Restore"]);
}
choose(string s)
{
    if(s=="Restore")llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ALPHA_MODE,FACE]+saved);
    else
    {
        integer mode=PRIM_ALPHA_MODE_NONE;
        if(s=="Blend")mode=PRIM_ALPHA_MODE_BLEND;
        else if(s=="Mask")mode=PRIM_ALPHA_MODE_MASK;
        else if(s!="Opaque")return;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ALPHA_MODE,FACE,mode,128]);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Aspect-aware image crop

Center-crop a diffuse image to a known rectangular display aspect ratio.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE, IMAGE_WIDTH/HEIGHT and DISPLAY_WIDTH/HEIGHT to positive values. Use default texture mapping. Owner-touch applies/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Dimensions are supplied by you; the script cannot inspect image pixels or infer mesh face dimensions. It crops, rather than adding letterbox bars.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
integer FACE=0;
float IMAGE_WIDTH=1024.0;
float IMAGE_HEIGHT=512.0;
float DISPLAY_WIDTH=1.0;
float DISPLAY_HEIGHT=1.0;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IMAGE_WIDTH<=0.0||IMAGE_HEIGHT<=0.0||DISPLAY_WIDTH<=0.0||DISPLAY_HEIGHT<=0.0)return;
        preview=!preview;
        if(preview)
        {
            float source=IMAGE_WIDTH/IMAGE_HEIGHT;
            float target=DISPLAY_WIDTH/DISPLAY_HEIGHT;
            vector repeats=<1.0,1.0,0.0>;
            if(source>target)repeats.x=target/source;
            else repeats.y=source/target;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE,llList2String(saved,0),repeats,ZERO_VECTOR,0.0]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Blend colors in linear light

Compare direct channel averaging with an sRGB-decode/linear-blend/re-encode mixture.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set two sRGB colors and MIX0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Output is a mathematical display-color blend, not a prediction of every viewer lighting/material result.

// Original Incoprea. MIT. Color calculation only.
vector A=<1.0,0.0,0.0>;
vector B=<0.0,1.0,0.0>;
float MIX=0.5;
float dec(float v)
{
    if(v<=0.04045)return v/12.92;
    return llPow((v+0.055)/1.055,2.4);
}
float enc(float v)
{
    if(v<=0.0031308)return 12.92*v;
    return 1.055*llPow(v,1.0/2.4)-0.055;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MIX<0.0||MIX>1.0)
        {
            llOwnerSay("Mix must be0..1.");
            return;
        }
        vector la=<dec(A.x),dec(A.y),dec(A.z)>;
        vector lb=<dec(B.x),dec(B.y),dec(B.z)>;
        vector l=la+(lb-la)*MIX;
        llOwnerSay("Direct="+(string)(A+(B-A)*MIX)+" linear-light blend="+(string)<enc(l.x),enc(l.y),enc(l.z)>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Breathing texture zoom

Ease a texture between two scale settings using ping-pong animation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and use a centered repeating pattern on a spare prim. Owner-touch starts and stops.

Stop / restore: Touch to disable texture animation before removing. The saved diffuse texture/UV settings are restored, but an earlier animation is not recoverable.

Use a spare prim with readable classic diffuse texture settings. Material behavior can differ with PBR transforms. SCALE animation changes image scale, not prim dimensions.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer active;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)llSetTextureAnim(ANIM_ON|SMOOTH|SCALE|PING_PONG|LOOP,FACE,1,1,1.0,0.5,0.1);
        else
        {
            llSetTextureAnim(FALSE,FACE,0,0,0.0,0.0,1.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Build RGB from HSL design values

Convert hue, saturation and lightness into an RGB triple.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set HUE degrees and SATURATION/LIGHTNESS0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

HSL lightness is a geometric channel measure, not perceptual luminance.

// Original Incoprea. MIT. Color calculation only.
float HUE=220.0;
float SATURATION=0.6;
float LIGHTNESS=0.4;
float channel(float p,float q,float t)
{
    if(t<0.0)t+=1.0;
    if(t>1.0)t-=1.0;
    if(t<1.0/6.0)return p+(q-p)*6.0*t;
    if(t<0.5)return q;
    if(t<2.0/3.0)return p+(q-p)*(2.0/3.0-t)*6.0;
    return p;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SATURATION<0.0||SATURATION>1.0||LIGHTNESS<0.0||LIGHTNESS>1.0)
        {
            llOwnerSay("Saturation/lightness must be0..1.");
            return;
        }
        float h=HUE/360.0;
        h-=llFloor(h);
        float q=LIGHTNESS*(1.0+SATURATION);
        if(LIGHTNESS>=0.5)q=LIGHTNESS+SATURATION-LIGHTNESS*SATURATION;
        float p=2.0*LIGHTNESS-q;
        llOwnerSay("RGB="+(string)<channel(p,q,h+1.0/3.0),channel(p,q,h),channel(p,q,h-1.0/3.0)>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Calculate relative display luminance

Convert an sRGB triple into weighted linear relative luminance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set RGB in0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This uses the standard sRGB/Rec.709 channel weights, not perceived brightness in every viewing condition.

// Original Incoprea. MIT. Color calculation only.
vector RGB=<0.25,0.65,0.4>;
float dec(float v)
{
    if(v<=0.04045)return v/12.92;
    return llPow((v+0.055)/1.055,2.4);
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RGB.x<0.0||RGB.y<0.0||RGB.z<0.0||RGB.x>1.0||RGB.y>1.0||RGB.z>1.0)
        {
            llOwnerSay("RGB must be0..1.");
            return;
        }
        float y=0.2126*dec(RGB.x)+0.7152*dec(RGB.y)+0.0722*dec(RGB.z);
        llOwnerSay("Relative luminance="+(string)y);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Center-crop texture zoom

Preview a centered close-up without replacing the source texture.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Owner-touch halves the original repeats while keeping its offset and angle.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. A lower repeat count magnifies the image. Works best with default mapping.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE=0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXTURE, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            vector repeats=llList2Vector(saved,1)*0.5;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(saved,[repeats],1,1));
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Classic bump and shininess baseline

Compare a face with its legacy bump and shininess removed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a spare classic-material prim and owner-touch.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. This concerns legacy bump/shiny, separate from normal and specular maps.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE=0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_BUMP_SHINY, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_BUMP_SHINY,FACE,PRIM_SHINY_NONE,PRIM_BUMP_NONE]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_BUMP_SHINY,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Compare multiply and screen layer blends

Calculate two common component-wise color blending operations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set A and B as RGB0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

These artistic blend modes are not optical material simulations. Alpha is not included.

// Original Incoprea. MIT. Color calculation only.
vector A=<0.8,0.4,0.2>;
vector B=<0.2,0.6,0.9>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector multiply=<A.x*B.x,A.y*B.y,A.z*B.z>;
        vector screen=<1.0-(1.0-A.x)*(1.0-B.x),1.0-(1.0-A.y)*(1.0-B.y),1.0-(1.0-A.z)*(1.0-B.z)>;
        llOwnerSay("Multiply="+(string)multiply+" screen="+(string)screen);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Compare two display colors for contrast

Calculate the conventional luminance contrast ratio between two sRGB colors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set FOREGROUND and BACKGROUND components0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This is a numeric design aid; actual text readability also depends on size, weight, viewer rendering and lighting.

// Original Incoprea. MIT. Color calculation only.
vector FOREGROUND=<0.9,1.0,0.92>;
vector BACKGROUND=<0.05,0.12,0.08>;
float dec(float v)
{
    if(v<=0.04045)return v/12.92;
    return llPow((v+0.055)/1.055,2.4);
}
float lum(vector c)
{
    return 0.2126*dec(c.x)+0.7152*dec(c.y)+0.0722*dec(c.z);
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float a=lum(FOREGROUND);
        float b=lum(BACKGROUND);
        if(a<b)
        {
            float temp=a;
            a=b;
            b=temp;
        }
        llOwnerSay("Contrast ratio="+(string)((a+0.05)/(b+0.05))+":1");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Composite one translucent color over another

Calculate straight-alpha source-over RGB and resulting opacity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set source/destination colors and opacity values0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

The blend is performed directly in the supplied channel space; decode sRGB first for physically meaningful linear-light mixing.

// Original Incoprea. MIT. Color calculation only.
vector SOURCE=<1.0,0.2,0.0>;
vector DEST=<0.0,0.2,1.0>;
float SA=0.4;
float DA=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SA<0.0||SA>1.0||DA<0.0||DA>1.0)
        {
            llOwnerSay("Alphas must be0..1.");
            return;
        }
        float alpha=SA+DA*(1.0-SA);
        vector color=ZERO_VECTOR;
        if(alpha>0.000001)color=(SOURCE*SA+DEST*DA*(1.0-SA))/alpha;
        llOwnerSay("Composite RGB="+(string)color+" alpha="+(string)alpha);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Convert a hue wheel setting into RGB

Map hue degrees, saturation and value into an RGB triple.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set HUE, SATURATION and VALUE; latter two in0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Hue wraps cyclically. The calculation uses HSV, whose equal value is not equal perceived brightness.

// Original Incoprea. MIT. Color calculation only.
float HUE=145.0;
float SATURATION=0.7;
float VALUE=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SATURATION<0.0||SATURATION>1.0||VALUE<0.0||VALUE>1.0)
        {
            llOwnerSay("Saturation/value must be0..1.");
            return;
        }
        float h=HUE/60.0;
        h-=6.0*llFloor(h/6.0);
        float c=VALUE*SATURATION;
        float rem=h-2.0*llFloor(h/2.0);
        float x=c*(1.0-llFabs(rem-1.0));
        vector rgb;
        if(h<1.0)rgb=<c,x,0.0>;
        else if(h<2.0)rgb=<x,c,0.0>;
        else if(h<3.0)rgb=<0.0,c,x>;
        else if(h<4.0)rgb=<0.0,x,c>;
        else if(h<5.0)rgb=<x,0.0,c>;
        else rgb=<c,0.0,x>;
        float m=VALUE-c;
        llOwnerSay("RGB="+(string)(rgb+<m,m,m>));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Convert sRGB values to linear light

Apply the standard piecewise sRGB transfer function and convert back.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set RGB components between0 and1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Only a color-space calculation. Do not assume every LSL material parameter uses the same transfer convention.

// Original Incoprea. MIT. Color calculation only.
vector RGB=<0.2,0.5,0.8>;
float linear(float v)
{
    if(v<=0.04045)return v/12.92;
    return llPow((v+0.055)/1.055,2.4);
}
float srgb(float v)
{
    if(v<=0.0031308)return 12.92*v;
    return 1.055*llPow(v,1.0/2.4)-0.055;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RGB.x<0.0||RGB.y<0.0||RGB.z<0.0||RGB.x>1.0||RGB.y>1.0||RGB.z>1.0)
        {
            llOwnerSay("RGB must be0..1.");
            return;
        }
        vector l=<linear(RGB.x),linear(RGB.y),linear(RGB.z)>;
        llOwnerSay("Linear="+(string)l+" roundtrip="+(string)<srgb(l.x),srgb(l.y),srgb(l.z)>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Convert to and from premultiplied alpha

Multiply a color by opacity and safely reverse the operation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set RGB and ALPHA0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Zero alpha contains no recoverable RGB in premultiplied form. This is a data representation tool, not a viewer alpha-mode setter.

// Original Incoprea. MIT. Color calculation only.
vector RGB=<0.8,0.3,0.1>;
float ALPHA=0.4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ALPHA<0.0||ALPHA>1.0)
        {
            llOwnerSay("Alpha must be0..1.");
            return;
        }
        vector premultiplied=RGB*ALPHA;
        llOwnerSay("Premultiplied="+(string)premultiplied);
        if(ALPHA>0.000001)llOwnerSay("Recovered="+(string)(premultiplied/ALPHA));
        else llOwnerSay("Zero alpha: source RGB is unrecoverable.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Copy one face style to another

Preview a source face’s diffuse, tint, alpha, glow and fullbright on a second face.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set SOURCE and TARGET to different existing faces in one prim. Owner-touch copies the limited style; touch again restores target.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Does not copy PBR, normal/specular maps, alpha mode, texgen or texture animation. Source texture must be readable and reusable.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer SOURCE=0;
integer TARGET=1;
integer preview;
list saved;
list capture(integer face)
{
    return [PRIM_TEXTURE,TARGET]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,face])
    +[PRIM_COLOR,TARGET]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,face])
    +[PRIM_GLOW,TARGET]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_GLOW,face])
    +[PRIM_FULLBRIGHT,TARGET]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_FULLBRIGHT,face]);
}
default
{
    state_entry()
    {
        if(TARGET>=0&&TARGET<llGetNumberOfSides())saved=capture(TARGET);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||SOURCE==TARGET||SOURCE<0||SOURCE>=llGetNumberOfSides()||!llGetListLength(saved))return;
        preview=!preview;
        if(preview)llSetLinkPrimitiveParamsFast(LINK_THIS,capture(SOURCE));
        else llSetLinkPrimitiveParamsFast(LINK_THIS,saved);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Copy one face tint to named swatches

Preview the root face-zero tint on selected swatch children, then restore their own colors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name each target child palette_swatch. Targets use face 0. Owner-touch applies/restores.

Stop / restore: Touch to restore before reset/removal/relink.

This copies a tint, not texture pixels or PBR material values. Alpha is not changed. Limited to 24 targets for a compact sample board.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer preview;
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<24;++i)
        if(llGetLinkName(i)=="palette_swatch")
        {
            links+=[i];
            saved+=[llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_COLOR,0]),0)];
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        preview=!preview;
        integer i;
        vector root=llGetColor(0);
        for(i=0;i<llGetListLength(links);++i)
        {
            vector color=llList2Vector(saved,i);
            if(preview)color=root;
            llSetLinkColor(llList2Integer(links,i),color,0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Decode a normal-map pixel

Convert RGB0..1 into a signed tangent-space direction and normalize it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set encoded PIXEL. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Channel conventions vary, especially the green/Y channel. A neutral pixel should be near<0.5,0.5,1>.

// Original Incoprea. MIT. Color calculation only.
vector PIXEL=<0.65,0.4,0.95>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PIXEL.x<0.0||PIXEL.y<0.0||PIXEL.z<0.0||PIXEL.x>1.0||PIXEL.y>1.0||PIXEL.z>1.0)
        {
            llOwnerSay("Pixel must be0..1.");
            return;
        }
        vector normal=2.0*PIXEL-<1.0,1.0,1.0>;
        if(llVecMag(normal)<0.000001)
        {
            llOwnerSay("Pixel encodes a zero vector.");
            return;
        }
        llOwnerSay("Tangent normal="+(string)llVecNorm(normal));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Encode a direction as a normal-map pixel

Normalize a supplied direction and remap its components from minus1..1 to0..1.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set nonzero NORMAL. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This is numerical encoding only. A texture image also needs the intended tangent basis and channel convention.

// Original Incoprea. MIT. Color calculation only.
vector NORMAL=<0.3,-0.2,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Nonzero normal required.");
            return;
        }
        vector pixel=(llVecNorm(NORMAL)+<1.0,1.0,1.0>)*0.5;
        llOwnerSay("Encoded pixel="+(string)pixel);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Estimate a surface normal from height samples

Build a tangent-space normal from neighboring height samples and sample spacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set left/right/down/up heights, positive SPACING and strength. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Central differences assume evenly spaced samples. Strength changes slope scale; this does not create a normal-map asset.

// Original Incoprea. MIT. Color calculation only.
float LEFT=0.2;
float RIGHT=0.5;
float DOWN=0.3;
float UP=0.4;
float SPACING=1.0;
float STRENGTH=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SPACING<=0.0)
        {
            llOwnerSay("Positive spacing required.");
            return;
        }
        float dx=(RIGHT-LEFT)/(2.0*SPACING);
        float dy=(UP-DOWN)/(2.0*SPACING);
        llOwnerSay("Estimated normal="+(string)llVecNorm(<-dx*STRENGTH,-dy*STRENGTH,1.0>));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Estimate diffuse incidence on a planned surface

Calculate a clamped cosine between surface normal and direction toward a light.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set nonzero NORMAL and TO_LIGHT. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This is a Lambertian angular factor only; real lighting also involves distance, materials, shadows and environment.

// Original Incoprea. MIT. Color calculation only.
vector NORMAL=<0.0,0.0,1.0>;
vector TO_LIGHT=<2.0,1.0,3.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL)<0.000001||llVecMag(TO_LIGHT)<0.000001)
        {
            llOwnerSay("Nonzero vectors required.");
            return;
        }
        float factor=llVecNorm(NORMAL)*llVecNorm(TO_LIGHT);
        if(factor<0.0)factor=0.0;
        llOwnerSay("Diffuse angular factor="+(string)factor);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Evaluate an overlay color blend

Apply the piecewise overlay formula using the base color to choose darkening or lightening.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set BASE and BLEND colors0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Overlay is asymmetric: exchanging base and blend usually changes the result.

// Original Incoprea. MIT. Color calculation only.
vector BASE=<0.2,0.5,0.8>;
vector BLEND=<0.7,0.3,0.4>;
float overlay(float base,float blend)
{
    if(base<0.5)return 2.0*base*blend;
    return 1.0-2.0*(1.0-base)*(1.0-blend);
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("Overlay="+(string)<overlay(BASE.x,BLEND.x),overlay(BASE.y,BLEND.y),overlay(BASE.z,BLEND.z)>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Exclusive linked selection highlight

Highlight one touched child while returning the previous selection to its saved glow.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root of a small model. Children should pass touches to root. Root touch clears selection.

Stop / restore: Touch root to clear before removing.

Only face-zero glow on the most recently touched child is changed. The previous selection is restored before capturing a new one.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer selected;
float original;
clear()
{
    if(selected>1)llSetLinkPrimitiveParamsFast(selected,[PRIM_GLOW,0,original]);
    selected=0;
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        integer touched=llDetectedLinkNumber(0);
        clear();
        if(touched>1)
        {
            selected=touched;
            original=llList2Float(llGetLinkPrimitiveParams(selected,[PRIM_GLOW,0]),0);
            llSetLinkPrimitiveParamsFast(selected,[PRIM_GLOW,0,0.12]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Face appearance snapshot console

Capture one face’s classic appearance, experiment manually, then restore through a text command.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Saving captures diffuse, color, glow, fullbright, mapping and legacy bump. Touch, then enter RESTORE in the owner text box after manual experiments.

Stop / restore: Enter RESTORE before removing if you want the startup appearance. Removing alone does not undo manual edits.

Does not capture PBR, normal/specular maps or texture animation. Original texture access must permit restoration. Snapshot disappears at reset.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
list saved;
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        saved=[PRIM_TEXTURE,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
        saved+=[PRIM_COLOR,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,FACE]);
        saved+=[PRIM_GLOW,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_GLOW,FACE]);
        saved+=[PRIM_FULLBRIGHT,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_FULLBRIGHT,FACE]);
        saved+=[PRIM_TEXGEN,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXGEN,FACE]);
        saved+=[PRIM_BUMP_SHINY,FACE]+llGetLinkPrimitiveParams(LINK_THIS,[PRIM_BUMP_SHINY,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llTextBox(llGetOwner(),"Enter RESTORE to apply the startup snapshot to face "+(string)FACE,channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string message)
    {
        if(ch!=channel||id!=llGetOwner())return;
        close();
        if(llToUpper(llStringTrim(message,STRING_TRIM))=="RESTORE")llSetLinkPrimitiveParamsFast(LINK_THIS,saved);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Face transparency loupe

Select a single face to hide temporarily so you can inspect an object’s interior.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim. Menu lists up to nine face numbers; selecting another restores the previous face. Restore unhides the selected face.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. This is only a visual inspection tool and never changes collisions. It restores saved per-face alpha, not PBR alpha modes.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list alpha;
integer selected=-1;
init()
{
    integer i;
    for(i=0;i<llGetNumberOfSides();++i)alpha+=[llGetAlpha(i)];
}
show()
{
    list buttons=["Restore"];
    integer i;
    for(i=0;i<llGetListLength(alpha)&&i<9;++i)buttons+=[(string)i];
    menu("Hide one face for inspection",buttons);
}
choose(string s)
{
    if(s=="Restore")
    {
        if(selected>=0)llSetAlpha(llList2Float(alpha,selected),selected);
        selected=-1;
        show();
        return;
    }
    integer i=llListFindList(["0","1","2","3","4","5","6","7","8"],[s]);
    if(i<0||i>=llGetListLength(alpha))return;
    if(selected>=0)llSetAlpha(llList2Float(alpha,selected),selected);
    selected=i;
    llSetAlpha(0.0,selected);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Face-index diagnostic colors

Give each face a distinct temporary tint to identify its numbering.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim to inspect. Owner-touch toggles diagnostic colors.

Stop / restore: Touch again to restore every original face color and alpha.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Texture pixels still multiply the tint; use a plain-textured copy for the clearest face distinction.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
integer preview;
default
{
    state_entry()
    {
        integer f;
        for(f=0;f<llGetNumberOfSides();++f)saved+=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,f]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        preview=!preview;
        list palette=[<1.0,0.2,0.2>,<0.2,1.0,0.2>,<0.2,0.4,1.0>,<1.0,1.0,0.2>,<1.0,0.2,1.0>,<0.2,1.0,1.0>,<1.0,0.6,0.2>,<0.6,0.2,1.0>];
        integer f;
        for(f=0;f<llGetNumberOfSides()&&f*2+1<llGetListLength(saved);++f)
        {
            vector color=llList2Vector(saved,f*2);
            float alpha=llList2Float(saved,f*2+1);
            if(preview)
            {
                color=llList2Vector(palette,f%8);
                alpha=1.0;
            }
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_COLOR,f,color,alpha]);
        }
        llOwnerSay("Faces 0-7: red green blue yellow magenta cyan orange violet; repeats after 8.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Fading privacy window

Fade one classic-material face between its original alpha and 15 percent opacity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare window prim. Set FACE; owner-touch changes the target opacity. Use a face/material whose alpha mode supports blending.

Stop / restore: Touch to return to the original opacity, wait for the fade to finish, then remove. Resetting mid-fade captures the altered opacity.

Transparency is visual, not privacy or access security. It does not change the object’s collision geometry.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
float original;
float target;
float current;
integer clear;
default
{
    state_entry()
    {
        original = llGetAlpha(FACE);
        current = original;
        target = original;
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        clear = !clear;
        target = original;
        if (clear) target = 0.15;
        llSetTimerEvent(0.1);
    }
    timer()
    {
        float difference = target - current;
        if (llFabs(difference) <= 0.05)
        {
            current = target;
            llSetTimerEvent(0.0);
        }
        else if (difference > 0.0) current += 0.05;
        else current -= 0.05;
        llSetAlpha(current, FACE);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Find the nearest color in a small palette

Choose the palette entry with minimum squared RGB distance from a requested color.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set PALETTE vectors and TARGET. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

RGB Euclidean distance is fast but not perceptually uniform; use it for simple palette indexing rather than color-critical matching.

// Original Incoprea. MIT. Color calculation only.
list PALETTE=[<0.1,0.2,0.15>,<0.8,0.9,0.6>,<0.3,0.4,0.8>,<0.9,0.4,0.2>];
vector TARGET=<0.7,0.8,0.5>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(PALETTE);
        if(n==0)
        {
            llOwnerSay("Empty palette.");
            return;
        }
        integer best;
        vector delta=llList2Vector(PALETTE,0)-TARGET;
        float distance=delta*delta;
        integer i;
        for(i=1;i<n;++i)
        {
            delta=llList2Vector(PALETTE,i)-TARGET;
            float d=delta*delta;
            if(d<distance)
            {
                distance=d;
                best=i;
            }
        }
        llOwnerSay("Nearest index="+(string)best+" color="+(string)llList2Vector(PALETTE,best));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Four-panel image wall

Map quadrants of one image across four authored panels.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add texture art to root. Name four children tile00, tile10, tile01, tile11. Use face0/default mapping with matching face orientations.

Stop / restore: Owner-touch applies/restores the four saved diffuse mappings.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Names encode column,row with row0 at bottom in UV space. Duplicate or missing names reject the preview.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer preview;
integer valid=TRUE;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        integer i;
        if(preview)
        {
            for(i=0;i<4;++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXTURE,0]+llList2List(saved,i*4,i*4+3));
            preview=FALSE;
            return;
        }
        if(llGetInventoryType("art")!=INVENTORY_TEXTURE)return;
        links=[];
        saved=[];
        list names=["tile00","tile10","tile01","tile11"];
        for(i=0;i<4;++i)
        {
            integer j;
            integer found;
            integer count;
            for(j=2;j<=llGetObjectPrimCount(llGetKey());++j)if(llGetLinkName(j)==llList2String(names,i))
            {
                found=j;
                ++count;
            }
            if(count!=1)
            {
                llOwnerSay("Need four unique tile names.");
                return;
            }
            links+=[found];
        }
        for(i=0;i<4;++i)
        {
            integer link=llList2Integer(links,i);
            saved+=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,0]);
            vector offset=<-0.25,-0.25,0.0>;
            if(i%2)offset.x=0.25;
            if(i/2)offset.y=0.25;
            llSetLinkPrimitiveParamsFast(link,[PRIM_TEXTURE,0,"art",<0.5,0.5,0.0>,offset,0.0]);
        }
        preview=TRUE;
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Four-quadrant atlas viewer

Step through the four quadrants of a 2×2 texture atlas, then restore the original view.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a square atlas as the face diffuse texture. Set FACE; five owner touches cycle quadrants and restoration.

Stop / restore: Touch through all four quadrants and the fifth touch restores the original settings. Restore before removing or resetting.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. Uses 0.5 repeats and ±0.25 offsets. The atlas orientation depends on your image layout.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE = 0;
integer step;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(step==4)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
            step=0;
            llOwnerSay("Original restored.");
            return;
        }
        float x=-0.25;
        float y=0.25;
        if(step%2)x=0.25;
        if(step>1)y=-0.25;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE,llList2String(saved,0),<0.5,0.5,0.0>,<x,y,0.0>,0.0]);
        ++step;
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Beginner

Fullbright comparison switch

Compare a texture face under fullbright and its original lighting setting.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and place in a texture sample prim. Owner-touch toggles the classic face fullbright flag.

Stop / restore: Touch until Original lighting restored is reported, then remove.

Classic fullbright is not the same as PBR emissive. Viewer rendering and material choice may change the result.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
integer original;
integer preview;
default
{
    state_entry()
    {
        original = llList2Integer(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_FULLBRIGHT, FACE]), 0);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        integer value = original;
        if (preview) value = !original;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_FULLBRIGHT, FACE, value]);
        if (!preview) llOwnerSay("Original lighting restored.");
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Harmonious face palette

Preview a coordinated hue palette across the faces of a prim, then restore all original tints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare multi-face prim. Owner-touch creates a palette; the next touch restores. White or neutral textures show the palette most clearly.

Stop / restore: Touch to restore before removing or resetting. The original face tints are kept only in script memory.

Faces receive different hue offsets with fixed saturation and brightness. This does not alter alpha or PBR material settings.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list original;
integer preview;
vector hue(float h)
{
    float sector = h * 6.0;
    integer part = (integer)sector;
    float f = sector - part;
    float low = 0.35;
    float rising = low + (1.0 - low) * f;
    float falling = 1.0 - (1.0 - low) * f;
    if (part == 0) return <1.0, rising, low>;
    if (part == 1) return <falling, 1.0, low>;
    if (part == 2) return <low, 1.0, rising>;
    if (part == 3) return <low, falling, 1.0>;
    if (part == 4) return <rising, low, 1.0>;
    return <1.0, low, falling>;
}
default
{
    state_entry()
    {
        integer face;
        for (face = 0; face < llGetNumberOfSides(); ++face) original += [llGetColor(face)];
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        integer total = llGetListLength(original);
        integer face;
        float base = llFrand(1.0);
        for (face = 0; face < total; ++face)
        {
            if (!preview) llSetColor(llList2Vector(original, face), face);
            else
            {
                float h = base + (float)face / (float)total;
                if (h >= 1.0) h -= 1.0;
                llSetColor(hue(h), face);
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Hold-to-light lantern

A momentary lamp that shines while the owner holds a touch, then restores its previous light.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare lamp prim. Press and hold to illuminate. Releasing or a missed-touch timeout restores the saved light parameters.

Stop / restore: Release and wait three seconds before removal or reset.

A point light only, without changing glow or fullbright. Timer fallback protects against a missing touch_end event.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list original;
integer lit;
press()
{
    if (llDetectedKey(0) != llGetOwner()) return;
    if (!lit)
    {
        lit = TRUE;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POINT_LIGHT, TRUE, <1.0, 0.85, 0.6>, 0.4, 4.0, 1.0]);
    }
    llSetTimerEvent(3.0);
}
release()
{
    if (lit) llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POINT_LIGHT] + original);
    lit = FALSE;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_POINT_LIGHT]);
    }
    touch_start(integer count)
    {
        press();
    }
    touch(integer count)
    {
        press();
    }
    touch_end(integer count)
    {
        if (llDetectedKey(0) == llGetOwner()) release();
    }
    timer()
    {
        release();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Lamp radius and intensity menu

Tune a point light’s range and brightness independently with a restore command.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare lamp and owner-touch. Enable/Disable affect the point light; Restore reinstates its startup parameters.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Light color and falloff are preserved. Radius is capped at 10 meters and intensity at 0.7 for a modest exhibit light.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list saved;
list current;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_POINT_LIGHT]);
    current=saved;
}
show()
{
    menu("Point light controls",["Enable","Disable","Brighter","Dimmer","Wider","Narrower","Restore"]);
}
choose(string s)
{
    if(s=="Restore")current=saved;
    else
    {
        integer enabled=llList2Integer(current,0);
        float strength=llList2Float(current,2);
        float radius=llList2Float(current,3);
        if(s=="Enable")enabled=TRUE;
        else if(s=="Disable")enabled=FALSE;
        else if(s=="Brighter")strength+=0.1;
        else if(s=="Dimmer")strength-=0.1;
        else if(s=="Wider")radius+=0.5;
        else if(s=="Narrower")radius-=0.5;
        else return;
        if(strength<0.0)strength=0.0;
        if(strength>0.7)strength=0.7;
        if(radius<0.1)radius=0.1;
        if(radius>10.0)radius=10.0;
        current=[enabled,llList2Vector(current,1),strength,radius,llList2Float(current,4)];
    }
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POINT_LIGHT]+current);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Beginner

Linked color parade

Give every child prim in a small sculpture the same fresh tint.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical linkset with child prims. Touch it to recolor child prims, leaving the root prim alone.

Stop / restore: Disable the script and restore each child’s original color in Edit.

Original per-child colors are not saved. Mesh materials may not show the tint as expected.

// Original Incoprea example. Nonphysical linkset; root prim.
default
{
    touch_start(integer count)
    {
        vector tint = <llFrand(1.0), llFrand(1.0), llFrand(1.0)>;
        llSetLinkColor(LINK_ALL_CHILDREN, tint, ALL_SIDES);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Linked progress segments

Show a ten-step completion meter using named child segments and an owner button.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name up to ten child segments meter_segment in the desired link order. Each owner-touch advances; after full, next touch restores.

Stop / restore: Cycle once more after full to restore original face-zero colors.

This is a manually advanced exhibit meter, not tied to a download or external job. Keep link order unchanged during use.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer progress;
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<10;++i)
        if(llGetLinkName(i)=="meter_segment")
        {
            links+=[i];
            saved+=[llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_COLOR,0]),0)];
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||!llGetListLength(links))return;
        progress=(progress+1)%(llGetListLength(links)+1);
        integer i;
        for(i=0;i<llGetListLength(links);++i)
        {
            vector c=llList2Vector(saved,i);
            if(i<progress)c=<0.3,1.0,0.6>;
            llSetLinkColor(llList2Integer(links,i),c,0);
        }
        llOwnerSay((string)progress+" of "+(string)llGetListLength(links));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Linked texture contact sheet

Distribute the first twelve inventory textures across named gallery children.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put textures in root; name up to twelve children gallery_. Prefix matching accepts gallery_1 etc. Face0 is used; link order determines placement.

Stop / restore: Owner-touch applies; touch again restores each face0 diffuse transform.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Textures are inventory-sorted by name. Only their diffuse asset changes; child face count and permissions must be suitable.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer preview;
integer valid=TRUE;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        integer i;
        if(preview)
        {
            for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXTURE,0]+llList2List(saved,i*4,i*4+3));
            preview=FALSE;
            return;
        }
        links=[];
        saved=[];
        integer images=llGetInventoryNumber(INVENTORY_TEXTURE);
        integer placed;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&placed<12&&placed<images;++i)if(llSubStringIndex(llGetLinkName(i),"gallery_")==0)
        {
            links+=[i];
            list face=llGetLinkPrimitiveParams(i,[PRIM_TEXTURE,0]);
            saved+=face;
            llSetLinkPrimitiveParamsFast(i,[PRIM_TEXTURE,0,llGetInventoryName(INVENTORY_TEXTURE,placed),<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
            ++placed;
        }
        preview=placed>0;
        llOwnerSay("Assigned "+(string)placed+" textures.");
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            llOwnerSay("Relinked: snapshot invalid; manually restore if needed.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Manual sprite-sheet frame inspector

Step manually through a 4×4 sprite sheet to inspect each frame without animation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a square 16-frame sheet on FACE. Owner-touch advances through frames; the seventeenth restores original UV settings.

Stop / restore: Cycle through frame 16, then touch once to restore before removing.

Uses explicit UV repeats and offsets, no persistent texture-animation setting. Frame order is left-to-right, top-to-bottom. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer frame;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(frame==16)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
            frame=0;
            return;
        }
        float x=-0.375+(frame%4)*0.25;
        float y=0.375-(frame/4)*0.25;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE,llList2String(saved,0),<0.25,0.25,0.0>,<x,y,0.0>,0.0]);
        llOwnerSay("Frame "+(string)(frame+1));
        ++frame;
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Metric texture density setter

Apply a requested number of repeats per meter to a rectangular face with supplied dimensions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE, WIDTH, HEIGHT and REPEATS_PER_METER; use default mapping on a known rectangular face. Owner-touch applies/restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removal or reset, unless setup describes a different cycle. Do not relink during a preview.

Use a spare modifiable build. Saved state lives only in script memory. Face dimensions are explicit because mesh geometry cannot be inferred from bounding-box scale. Planar mapping has different units and is rejected.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
integer FACE=0;
float WIDTH=2.0;
float HEIGHT=1.0;
float REPEATS_PER_METER=2.0;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||HEIGHT<=0.0||REPEATS_PER_METER<=0.0||WIDTH*REPEATS_PER_METER>100.0||HEIGHT*REPEATS_PER_METER>100.0)return;
        if(llList2Integer(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXGEN,FACE]),0)!=PRIM_TEXGEN_DEFAULT)return;
        preview=!preview;
        if(preview)
        {
            vector repeats=<WIDTH*REPEATS_PER_METER,HEIGHT*REPEATS_PER_METER,0.0>;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(saved,[repeats],1,1));
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Mirror a diffuse texture

Preview a horizontal texture reflection by reversing its repeat direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Owner-touch toggles the mirror while preserving the saved offset and rotation.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE = 0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXTURE, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            vector repeats = llList2Vector(saved,1);
            repeats.x = -repeats.x;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(saved,[repeats],1,1));
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Momentary color scrubber

Hold and move a touch horizontally to preview a blend between two colors; release to restore.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE to a flat face on a spare prim. Owner-touch and drag across that face. Edit LEFT and RIGHT to choose endpoints.

Stop / restore: Release the touch and wait two seconds before removing. The watchdog also restores color if touch-end is missed.

Preview lasts only during interaction. UV texture transforms do not affect the ST coordinate used for blending.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
vector LEFT = <0.1, 0.3, 1.0>;
vector RIGHT = <1.0, 0.5, 0.1>;
vector original;
preview()
{
    if (llDetectedKey(0) != llGetOwner() || llDetectedTouchFace(0) != FACE) return;
    vector st = llDetectedTouchST(0);
    if (st.x < 0.0 || st.x > 1.0) return;
    llSetColor(LEFT * (1.0 - st.x) + RIGHT * st.x, FACE);
    llSetTimerEvent(2.0);
}
restore()
{
    llSetColor(original, FACE);
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        original = llGetColor(FACE);
    }
    touch_start(integer count)
    {
        preview();
    }
    touch(integer count)
    {
        preview();
    }
    touch_end(integer count)
    {
        if (llDetectedKey(0) == llGetOwner()) restore();
    }
    timer()
    {
        restore();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Beginner

Mood-wheel color swap

Choose a new calm tint every time the prim is touched.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use on a spare prim. The tint affects all of its faces.

Stop / restore: Set the original color again in Edit; the script does not keep a backup.

Textures may change how the color appears.

// Original Incoprea example.
default
{
    touch_start(integer count)
    {
        vector tint = <0.35 + llFrand(0.65), 0.45 + llFrand(0.55),
        0.35 + llFrand(0.65)>;
        llSetColor(tint, ALL_SIDES);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Named child visibility switch

Hide or restore only a child named exhibit_cover, preserving its per-face alpha.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root with one uniquely named exhibit_cover child. Owner-touch toggles.

Stop / restore: Restore visibility before removing, resetting, or relinking.

Visual hiding does not change collisions, privacy or access. Original alpha values remain only in script memory.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer target;
integer hidden;
list alpha;
default
{
    state_entry()
    {
        integer i;
        integer hits;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)if(llGetLinkName(i)=="exhibit_cover")
        {
            target=i;
            ++hits;
        }
        if(hits!=1)
        {
            target=0;
            llOwnerSay("Need one exhibit_cover child.");
            return;
        }
        for(i=0;i<llGetLinkNumberOfSides(target);++i)alpha+=[llList2Float(llGetLinkPrimitiveParams(target,[PRIM_COLOR,i]),1)];
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!target)return;
        hidden=!hidden;
        integer i;
        for(i=0;i<llGetListLength(alpha);++i)
        {
            float value=llList2Float(alpha,i);
            if(hidden)value=0.0;
            llSetLinkAlpha(target,value,i);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Named exhibit lighting scene

Apply a modest lighting scene to children named exhibit_light and restore their individual light settings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name up to eight children exhibit_light. Owner-touch toggles the scene.

Stop / restore: Touch to restore before removing, resetting, or relinking.

Captures five point-light parameters per target. A link change disables reuse until reset without guessing the old target links. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer scene;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<8;++i)if(llGetLinkName(i)=="exhibit_light")
        {
            links+=[i];
            saved+=llGetLinkPrimitiveParams(i,[PRIM_POINT_LIGHT]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        scene=!scene;
        integer i;
        for(i=0;i<llGetListLength(links);++i)
        {
            list rule=llList2List(saved,i*5,i*5+4);
            if(scene)rule=[TRUE,<1.0,0.85,0.6>,0.35,3.0,1.0];
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_POINT_LIGHT]+rule);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            llOwnerSay("Links changed. Check lighting manually and reset before reuse.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Named lamp chase

Advance a single highlight through children named chase_lamp.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a small linkset. Name up to 16 children chase_lamp. Owner-touch starts/stops.

Stop / restore: Touch to stop and restore every lamp’s original face-zero glow.

Changes face 0 only; name each lamp intentionally. Do not relink while running. Uses a moderate half-second step and low glow.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer active;
integer index;
restore()
{
    integer i;
    for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_GLOW,0,llList2Float(saved,i)]);
}
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<16;++i)
        if(llGetLinkName(i)=="chase_lamp")
        {
            links+=[i];
            saved+=llGetLinkPrimitiveParams(i,[PRIM_GLOW,0]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||!llGetListLength(links))return;
        active=!active;
        if(active)
        {
            index=0;
            llSetTimerEvent(0.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            restore();
        }
    }
    timer()
    {
        restore();
        llSetLinkPrimitiveParamsFast(llList2Integer(links,index),[PRIM_GLOW,0,0.12]);
        index=(index+1)%llGetListLength(links);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Night-aware lantern

After owner activation, enable a modest point light when the simulator sun drops below the horizon.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare lantern prim and owner-touch to enable automatic monitoring. Samples every 30 seconds.

Stop / restore: Touch to stop monitoring and restore the original point-light parameters before removal.

Reads the simulator parcel sun, which may differ from a visitor’s personal environment. It does not change glow, fullbright, region time, or the environment.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list original;
integer active;
integer previous = -1;
updateLight()
{
    vector sun = llGetSunDirection();
    integer night = sun.z < 0.0;
    if (night == previous) return;
    previous = night;
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POINT_LIGHT, night, <1.0, 0.8, 0.5>, 0.45, 4.0, 1.0]);
}
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_POINT_LIGHT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            previous = -1;
            updateLight();
            llSetTimerEvent(30.0);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POINT_LIGHT] + original);
        }
    }
    timer()
    {
        updateLight();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Normal-map contribution check

Temporarily remove a classic normal map to compare the surface shading.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a classic material face and set FACE. Ensure the original normal texture is readable and restorable.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. The original normal map parameters are kept in memory; no diffuse texture is changed.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE=0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_NORMAL, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NORMAL,FACE,NULL_KEY,<1.0,1.0,0.0>,ZERO_VECTOR,0.0]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_NORMAL,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Numbered texture picker

Select one of up to nine inventory textures from a numbered menu.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed textures to this prim and set FACE. Owner-touch displays names and number buttons; Restore returns the original diffuse settings.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Numbers keep dialog button labels short. The list is refreshed each time the menu opens and checks the selected inventory type before applying.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
integer FACE=0;
list saved;
list names;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
}
show()
{
    names=[];
    list buttons=["Restore"];
    string text="Choose a texture:\n";
    integer i;
    integer count=llGetInventoryNumber(INVENTORY_TEXTURE);
    if(count>9)count=9;
    for(i=0;i<count;++i)
    {
        string name=llGetInventoryName(INVENTORY_TEXTURE,i);
        names+=[name];
        buttons+=[(string)(i+1)];
        text+=(string)(i+1)+": "+llGetSubString(name,0,32)+"\n";
    }
    menu(text,buttons);
}
choose(string s)
{
    if(s=="Restore")
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        show();
        return;
    }
    integer index=llListFindList(["1","2","3","4","5","6","7","8","9"],[s]);
    if(index<0||index>=llGetListLength(names))return;
    string name=llList2String(names,index);
    if(llGetInventoryType(name)==INVENTORY_TEXTURE)llSetTexture(name,FACE);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

One-shot sprite-sheet cue

Play a four-frame cue once, then restore the original face appearance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and apply a 2×2 sheet. Owner-touch starts a two-second one-shot animation.

Stop / restore: Wait three seconds for explicit animation cleanup and UV restoration before removal.

No LOOP flag is used. The timer explicitly disables the stored animation after the cue; it cannot restore a previously configured animation.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer busy;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||busy)return;
        busy=TRUE;
        llSetTextureAnim(ANIM_ON,FACE,2,2,0.0,4.0,2.0);
        llSetTimerEvent(3.0);
    }
    timer()
    {
        llSetTimerEvent(0.0);
        llSetTextureAnim(FALSE,FACE,0,0,0.0,0.0,1.0);
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        busy=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Paint just the touched face

Toggle the touched face between a mint tint and its original color.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim. Owner-touch individual faces. The script captures every face color when saved.

Stop / restore: Touch each painted face again to restore it before deleting. Reset only when restored.

Touch-face support depends on the viewer. Does not change alpha, textures, or PBR material parameters.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list colors;
list painted;
default
{
    state_entry()
    {
        integer face;
        for (face = 0; face < llGetNumberOfSides(); ++face)
        {
            colors += [llGetColor(face)];
            painted += [FALSE];
        }
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer face = llDetectedTouchFace(0);
        if (face < 0 || face >= llGetListLength(colors)) return;
        integer on = !llList2Integer(painted, face);
        painted = llListReplaceList(painted, [on], face, face);
        if (on) llSetColor(<0.35, 0.95, 0.7>, face);
        else llSetColor(llList2Vector(colors, face), face);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Ping-pong sprite-sheet motion

Play a four-frame sprite sheet forward and backward for a returning motion.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and apply a 2×2 sheet whose frames form one outward movement. Owner-touch starts and stops.

Stop / restore: Touch to disable texture animation before removing. The saved diffuse texture/UV settings are restored, but an earlier animation is not recoverable.

Use a spare prim with readable classic diffuse texture settings. Material behavior can differ with PBR transforms. PING_PONG avoids a hard jump from the final frame to the first. Frames are read left-to-right, top-to-bottom.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer active;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)llSetTextureAnim(ANIM_ON|LOOP|PING_PONG,FACE,2,2,0.0,4.0,2.0);
        else
        {
            llSetTextureAnim(FALSE,FACE,0,0,0.0,0.0,1.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Planar mapping preview

Compare planar mapping with a face’s original texture mapping mode.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and place in a spare textured prim. Owner-touch toggles.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. Planar repeat units differ from default mapping.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE = 0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXGEN, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXGEN,FACE,PRIM_TEXGEN_PLANAR]);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXGEN,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Preview a four-by-four ordered dither

Print a binary tile using a Bayer threshold matrix and a single grey intensity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set GREY0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This is a tiny text preview, not a texture generator. Tile pattern is deterministic and spatially structured.

// Original Incoprea. MIT. Color calculation only.
float GREY=0.4;
list BAYER=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(GREY<0.0||GREY>1.0)
        {
            llOwnerSay("Grey must be0..1.");
            return;
        }
        integer row;
        integer col;
        for(row=0;row<4;++row)
        {
            string line="";
            for(col=0;col<4;++col)
            {
                float threshold=(llList2Integer(BAYER,row*4+col)+0.5)/16.0;
                if(GREY>threshold)line+="#";
                else line+=".";
            }
            llOwnerSay(line);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Preview a simple CMYK-to-RGB conversion

Calculate a basic subtractive-channel RGB approximation from CMYK values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set CYAN/MAGENTA/YELLOW/BLACK each0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This is not color-managed printing conversion and cannot replace an ICC profile.

// Original Incoprea. MIT. Color calculation only.
float CYAN=0.2;
float MAGENTA=0.5;
float YELLOW=0.1;
float BLACK=0.15;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(CYAN<0.0||CYAN>1.0||MAGENTA<0.0||MAGENTA>1.0||YELLOW<0.0||YELLOW>1.0||BLACK<0.0||BLACK>1.0)
        {
            llOwnerSay("Channels must be0..1.");
            return;
        }
        llOwnerSay("Approximate RGB="+(string)<(1.0-CYAN)*(1.0-BLACK),(1.0-MAGENTA)*(1.0-BLACK),(1.0-YELLOW)*(1.0-BLACK)>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Quantize an RGB color to fixed channel levels

Round normalized RGB channels to a selected number of evenly spaced values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set LEVELS2..256 and RGB0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

This produces a regular RGB cube palette; it is not adaptive image quantization.

// Original Incoprea. MIT. Color calculation only.
vector RGB=<0.18,0.53,0.87>;
integer LEVELS=6;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LEVELS<2||LEVELS>256||RGB.x<0.0||RGB.y<0.0||RGB.z<0.0||RGB.x>1.0||RGB.y>1.0||RGB.z>1.0)
        {
            llOwnerSay("Invalid levels/color.");
            return;
        }
        float steps=LEVELS-1;
        vector q=<llRound(RGB.x*steps)/steps,llRound(RGB.y*steps)/steps,llRound(RGB.z*steps)/steps>;
        llOwnerSay("Quantized="+(string)q+" error magnitude="+(string)llVecDist(q,RGB));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Beginner

Read a face color as HEX

Owner-touch reports the selected face tint as RGB values and a six-digit HEX color.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and place in the prim whose classic tint you want to inspect.

Stop / restore: Remove or disable; no setting is changed.

This reports the stored tint, not a sampled rendered pixel. Lighting, texture pixels, and material color spaces can make the visible surface different.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
string digits = "0123456789ABCDEF";
string channelHex(float value)
{
    integer byte = llRound(value * 255.0);
    return llGetSubString(digits, byte / 16, byte / 16) + llGetSubString(digits, byte % 16, byte % 16);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector color = llGetColor(FACE);
        llOwnerSay("RGB " + (string)color + " | #" + channelHex(color.x) + channelHex(color.y) + channelHex(color.z));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Read hue, saturation and value from RGB

Calculate HSV descriptors from an RGB triple.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set RGB components0..1. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

Achromatic colors have undefined hue; this example reports zero for that case.

// Original Incoprea. MIT. Color calculation only.
vector RGB=<0.2,0.7,0.4>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RGB.x<0.0||RGB.y<0.0||RGB.z<0.0||RGB.x>1.0||RGB.y>1.0||RGB.z>1.0)
        {
            llOwnerSay("RGB must be0..1.");
            return;
        }
        float high=RGB.x;
        float low=RGB.x;
        if(RGB.y>high)high=RGB.y;
        if(RGB.z>high)high=RGB.z;
        if(RGB.y<low)low=RGB.y;
        if(RGB.z<low)low=RGB.z;
        float delta=high-low;
        float hue;
        float saturation;
        if(high>0.0)saturation=delta/high;
        if(delta>0.000001)
        {
            if(high==RGB.x)hue=(RGB.y-RGB.z)/delta;
            else if(high==RGB.y)hue=2.0+(RGB.z-RGB.x)/delta;
            else hue=4.0+(RGB.x-RGB.y)/delta;
            hue*=60.0;
            if(hue<0.0)hue+=360.0;
        }
        llOwnerSay("HSV="+(string)<hue,saturation,high>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Reverse sprite sequence

Inspect a 4×4 animation sheet in reverse frame order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and use a 16-frame sheet. Owner-touch starts and stops.

Stop / restore: Touch to disable texture animation before removing. The saved diffuse texture/UV settings are restored, but an earlier animation is not recoverable.

Use a spare prim with readable classic diffuse texture settings. Material behavior can differ with PBR transforms. Useful for disassembly/reassembly inspection. This reverses frame order, not the prim orientation.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer active;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)llSetTextureAnim(ANIM_ON|LOOP|REVERSE,FACE,4,4,0.0,16.0,4.0);
        else
        {
            llSetTextureAnim(FALSE,FACE,0,0,0.0,0.0,1.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Rotating texture dial

Turn a painted dial without rotating the prim or its collision shape.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a spare dial with a readable diffuse texture. Owner-touch starts and stops.

Stop / restore: Touch to disable texture animation before removing. The saved diffuse texture/UV settings are restored, but an earlier animation is not recoverable.

Use a spare prim with readable classic diffuse texture settings. Material behavior can differ with PBR transforms. ROTATE affects UV orientation, not geometry; rate is radians per second.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer active;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)llSetTextureAnim(ANIM_ON|SMOOTH|ROTATE|LOOP,FACE,1,1,0.0,TWO_PI,0.15);
        else
        {
            llSetTextureAnim(FALSE,FACE,0,0,0.0,0.0,1.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Beginner

Slow drifting surface

Scroll a repeating texture slowly across all faces.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a repeating texture on a spare prim. Texture animation changes the texture coordinates, not the prim position.

Stop / restore: Run Stop surface animation below. The animation setting persists after removing its starter script.

PBR/material combinations and pre-rotated faces can change the apparent direction.

// Original Incoprea example. Nonphysical surface treatment.
default
{
    state_entry()
    {
        llSetTextureAnim(ANIM_ON | SMOOTH | LOOP, ALL_SIDES,
        1, 1, 0.0, 1.0, 0.035);
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Spatial checker tile tint

Tint named floor tiles according to root-local grid position instead of link order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name up to 32 children checker_tile, set CELL spacing, and align the root-local floor grid. Face0 only.

Stop / restore: Owner-touch applies/restores saved colors.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Alternating parity is based on rounded root-local X/Y cell coordinates; uneven or rotated tile centers need their own layout.

// Original Incoprea. MIT. Not compiled or tested in-world.
float CELL=1.0;
list links;
list saved;
integer preview;
integer valid=TRUE;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid||CELL<=0.0)return;
        integer i;
        if(preview)
        {
            for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_COLOR,0]+llList2List(saved,i*2,i*2+1));
            preview=FALSE;
            return;
        }
        links=[];
        saved=[];
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<32;++i)if(llGetLinkName(i)=="checker_tile")
        {
            links+=[i];
            list color=llGetLinkPrimitiveParams(i,[PRIM_COLOR,0]);
            saved+=color;
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            integer parity=(llRound(p.x/CELL)+llRound(p.y/CELL))%2;
            vector tint=<0.9,0.9,0.9>;
            if(parity)tint=<0.12,0.12,0.12>;
            llSetLinkPrimitiveParamsFast(i,[PRIM_COLOR,0,tint,llList2Float(color,1)]);
        }
        preview=TRUE;
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Specular contribution check

Temporarily suppress classic specular reflectance for a material comparison.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a classic material surface with readable specular settings.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview. Sets specular color, glossiness, and environment contribution to zero for the comparison.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer preview;
list saved;
integer FACE=0;
default
{
    state_entry()
    {
        saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_SPECULAR, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        preview = !preview;
        if (preview)
        {
            list test=llListReplaceList(saved,[ZERO_VECTOR,0,0],4,6);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SPECULAR,FACE]+test);
        }
        else
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_SPECULAR,FACE]+saved);
            llOwnerSay("Original setting restored.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Beginner

Tap-on lantern light

Toggle a modest point light on a lantern.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a copy of a prim. Touch to switch its point light on or off.

Stop / restore: Disable the script and turn the point light off in Edit if needed.

This affects only the prim containing the script. Viewers render local lights differently.

// Original Incoprea example.
integer isLit;
default
{
    state_entry()
    {
        isLit = FALSE;
        llSetLinkPrimitiveParamsFast(LINK_THIS,
        [PRIM_POINT_LIGHT, FALSE, <1.0, 0.72, 0.38>, 0.8, 8.0, 0.75]);
    }
    touch_start(integer count)
    {
        isLit = !isLit;
        llSetLinkPrimitiveParamsFast(LINK_THIS,
        [PRIM_POINT_LIGHT, isLit, <1.0, 0.72, 0.38>, 0.8, 8.0, 0.75]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Beginner

Temporary face highlight

Owner-touch briefly highlights one face, restoring its previous glow after three seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim and set FACE. The original glow is captured at startup. Keep other glow scripts off that face.

Stop / restore: Let the three-second timer complete before removing. Removing while lit leaves the glow until manually restored.

Glow can be unavailable or visually reduced in some viewer configurations. No point light is created.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
float original;
default
{
    state_entry()
    {
        original = llList2Float(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_GLOW, FACE]), 0);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_GLOW, FACE, 0.12]);
        llSetTimerEvent(3.0);
    }
    timer()
    {
        llSetTimerEvent(0.0);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_GLOW, FACE, original]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Beginner

Texture flipbook

Play a sprite-sheet texture as a looping little flipbook.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Apply a 4-by-4 sprite sheet with sixteen equal frames to a prim face. Adjust the grid settings to match your texture.

Stop / restore: Run Stop surface animation. Removing this script does not clear the saved animation setting.

Texture frame animation is a viewer effect and may look different on PBR materials.

// Original Incoprea example. Requires a 4 x 4 sprite sheet texture.
default
{
    state_entry()
    {
        llSetTextureAnim(ANIM_ON | LOOP, ALL_SIDES, 4, 4, 0.0, 16.0, 4.0);
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Texture offset jog menu

Position an image on one face using repeatable UV offset steps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a spare classic diffuse-textured prim. Owner-touch; Restore restores the entire captured diffuse rule.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Uses readable texture settings. Offsets are normalized/wrapped into the valid -1 to 1 range. Does not edit PBR-specific transforms.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
integer FACE=0;
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
}
show()
{
    menu("Diffuse UV offset: 0.05 steps",["Left","Right","Up","Down","Center","Restore"]);
}
choose(string s)
{
    if(s=="Restore")
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        show();
        return;
    }
    list rule=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    vector p=llList2Vector(rule,2);
    if(s=="Left")p.x-=0.05;
    else if(s=="Right")p.x+=0.05;
    else if(s=="Up")p.y+=0.05;
    else if(s=="Down")p.y-=0.05;
    else if(s=="Center")p=ZERO_VECTOR;
    else return;
    if(p.x>1.0)p.x-=2.0;
    if(p.x< -1.0)p.x+=2.0;
    if(p.y>1.0)p.y-=2.0;
    if(p.y< -1.0)p.y+=2.0;
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(rule,[p],2,2));
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Texture orientation preview

Step one face’s diffuse texture through quarter turns without rotating the prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and use an original texture you can read and restore. The script captures its texture and UV settings. Owner-touch cycles four orientations.

Stop / restore: After the fourth touch the original UV rotation is restored. Remove or reset only then.

Changes classic diffuse UV rotation. A PBR material has separate texture transforms.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
integer step;
list original;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXTURE, FACE]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        step = (step + 1) % 4;
        list settings = llListReplaceList(original, [llList2Float(original, 3) + step * PI_BY_TWO], 3, 3);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXTURE, FACE] + settings);
        if (!step) llOwnerSay("Original texture rotation restored.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Texture repeat ratio menu

Adjust horizontal and vertical texture density independently or together.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Buttons increase/decrease repeat magnitude by 20 percent; Restore returns the original texture rule.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Classic diffuse transforms only. Existing mirror signs are retained. Repeat magnitudes are capped to avoid runaway tiling.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
integer FACE=0;
list saved;
float cap(float v)
{
    if(v>20.0)return 20.0;
    if(v< -20.0)return -20.0;
    return v;
}
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
}
show()
{
    menu("Texture density",["U More","U Less","V More","V Less","Both More","Both Less","Restore"]);
}
choose(string s)
{
    if(s=="Restore")
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        show();
        return;
    }
    list rule=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    vector r=llList2Vector(rule,1);
    if(s=="U More")r.x*=1.2;
    else if(s=="U Less")r.x/=1.2;
    else if(s=="V More")r.y*=1.2;
    else if(s=="V Less")r.y/=1.2;
    else if(s=="Both More")r*=1.2;
    else if(s=="Both Less")r/=1.2;
    else return;
    r.x=cap(r.x);
    r.y=cap(r.y);
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(rule,[r],1,1));
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Timed texture slideshow

Show inventory textures in alphabetical order at a leisurely pace.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed textures to a spare display prim; set FACE. Owner-touch starts/stops a ten-second slideshow.

Stop / restore: Touch to restore captured diffuse settings before removing or resetting.

Original texture and UV settings are saved in memory. The script skips an empty inventory and rechecks texture count on each update. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer active;
integer index;
list saved;
show()
{
    integer n=llGetInventoryNumber(INVENTORY_TEXTURE);
    if(!n)
    {
        llOwnerSay("No inventory textures.");
        return;
    }
    index=index%n;
    llSetTexture(llGetInventoryName(INVENTORY_TEXTURE,index++),FACE);
}
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            index=0;
            show();
            llSetTimerEvent(10.0);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
        }
    }
    timer()
    {
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Tint channel isolation menu

Isolate red, green or blue components of saved face tints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch opens R, G, B and Restore. Affects tint components, not image pixel channels.

Stop / restore: Choose Restore before removal. Menu timeout leaves the selected preview visible.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. This cannot extract RGB channels from a texture image; it operates only on scripted face tint values.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        integer f;
        for(f=0;f<llGetNumberOfSides();++f)saved+=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,f]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llDialog(llGetOwner(),"Saved tint component preview",["R","G","B","Restore"],channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner()||llListFindList(["R","G","B","Restore"],[s])<0)return;
        integer f;
        for(f=0;f*2+1<llGetListLength(saved)&&f<llGetNumberOfSides();++f)
        {
            vector color=llList2Vector(saved,f*2);
            if(s=="R")
            {
                color.y=0.0;
                color.z=0.0;
            }
            else if(s=="G")
            {
                color.x=0.0;
                color.z=0.0;
            }
            else if(s=="B")
            {
                color.x=0.0;
                color.y=0.0;
            }
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_COLOR,f,color,llList2Float(saved,f*2+1)]);
        }
        close();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Beginner

Touch for a new color

Give every face of this prim a random tint when touched.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a copy of a simple prim; add the script and touch it. It changes the prim containing the script.

Stop / restore: Disable or remove the script. Restore the tint in Edit; deleting a script does not undo its color changes.

Textures and materials can alter the visible result. Original per-face colors are not saved.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        llSetColor(<llFrand(1.0), llFrand(1.0), llFrand(1.0)>, ALL_SIDES);
    }
}

MIT · original Incoprea example

API reference 1

Color & materials · Intermediate

Touch to inspect a bounded fractal plane

Map a touched point into the Mandelbrot plane and report escape iterations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Coordinates map to real[-2.2,0.8],imaginary[-1.5,1.5]. The forty-iteration cap is a preview; nonescape is not proof of membership. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        float cr=-2.2+3.0*uv.x;
        float ci=-1.5+3.0*uv.y;
        float x;
        float y;
        integer i;
        while(i<40&&x*x+y*y<=4.0)
        {
            float next=x*x-y*y+cr;
            y=2.0*x*y+ci;
            x=next;
            ++i;
        }
        llOwnerSay("Complex point="+(string)<cr,ci,0.0>+" iterations="+(string)i+" escaped="+(string)(x*x+y*y>4.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled alternating arc tiles

Measure distance to two quarter-circle arcs in a deterministically flipped tile grid.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The tile orientation alternates by parity. It demonstrates linked arc motifs, not random tile placement. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float REPEATS=4.0;
float LINE_WIDTH=0.06;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(REPEATS<=0.0||LINE_WIDTH<=0.0)
        {
            llOwnerSay("Invalid tile settings.");
            return;
        }
        float x=uv.x*REPEATS;
        float y=uv.y*REPEATS;
        integer parity=(llFloor(x)+llFloor(y))&1;
        x-=llFloor(x);
        y-=llFloor(y);
        if(parity)x=1.0-x;
        float a=llFabs(llSqrt(x*x+y*y)-0.5);
        float b=llFabs(llSqrt((1.0-x)*(1.0-x)+(1.0-y)*(1.0-y))-0.5);
        float distance=a;
        if(b<distance)distance=b;
        llOwnerSay("Tile orientation="+(string)parity+" on arc="+(string)(distance<LINE_WIDTH));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Color & materials · Intermediate

Touch-sampled angled stripes

Evaluate a repeatable stripe mask at live coordinates with selectable angle and duty cycle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

A stripe duty controls the fraction filled; it is not a smooth anti-aliased texture renderer. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float ANGLE=35.0;
float REPEATS=8.0;
float DUTY=0.4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(REPEATS<=0.0||DUTY<0.0||DUTY>1.0)
        {
            llOwnerSay("Invalid stripe settings.");
            return;
        }
        float angle=ANGLE*DEG_TO_RAD;
        float coordinate=REPEATS*(uv.x*llCos(angle)+uv.y*llSin(angle));
        float phase=coordinate-llFloor(coordinate);
        llOwnerSay("Stripe phase="+(string)phase+" filled="+(string)(phase<DUTY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Color & materials · Intermediate

Touch-sampled checkerboard cells

Identify checker parity and cell address at the touched point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Parity is calculated from integer cell coordinates, so negativeUV values also remain deterministic. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
integer COLUMNS=8;
integer ROWS=8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(COLUMNS<1||ROWS<1)
        {
            llOwnerSay("Positive grid counts required.");
            return;
        }
        integer x=llFloor(uv.x*COLUMNS);
        integer y=llFloor(uv.y*ROWS);
        llOwnerSay("Cell="+(string)x+","+(string)y+" checker="+(string)((x+y)&1));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled concentric bands

Evaluate ring index and alternating fill around the face center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Radius uses normalized surface coordinates; a physically rectangular face stretches the apparent circles. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float FREQUENCY=8.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(FREQUENCY<=0.0)
        {
            llOwnerSay("Positive frequency required.");
            return;
        }
        float radius=llSqrt(p.x*p.x+p.y*p.y);
        integer ring=llFloor(radius*FREQUENCY);
        llOwnerSay("Ring="+(string)ring+" fill="+(string)(ring&1));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled crescent cutout

Subtract one circle distance field from another to form a crescent mask.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The max combination performs a hard difference of ideal signed-distance regions; it does not modify a prim. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float OUTER_RADIUS=0.7;
float CUT_RADIUS=0.6;
vector CUT_OFFSET=<0.3,0.15,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(OUTER_RADIUS<=0.0||CUT_RADIUS<=0.0)
        {
            llOwnerSay("Positive radii required.");
            return;
        }
        float outer=llVecMag(p)-OUTER_RADIUS;
        float cut=llVecDist(p,CUT_OFFSET)-CUT_RADIUS;
        float distance=outer;
        if(-cut>distance)distance=-cut;
        llOwnerSay("Crescent mask="+(string)(distance<=0.0)+" field="+(string)distance);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled crossed line families

Combine two diagonal stripe families into a crosshatch mask.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The two families run at opposite slopes; line width is expressed in repeated-coordinate units. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float REPEATS=6.0;
float LINE_WIDTH=0.1;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(REPEATS<=0.0||LINE_WIDTH<=0.0||LINE_WIDTH>=0.5)
        {
            llOwnerSay("Invalid hatch settings.");
            return;
        }
        float a=(uv.x+uv.y)*REPEATS;
        float b=(uv.x-uv.y)*REPEATS;
        a=llFabs(a-llRound(a));
        b=llFabs(b-llRound(b));
        llOwnerSay("On hatch="+(string)(a<LINE_WIDTH||b<LINE_WIDTH)+" crossing="+(string)(a<LINE_WIDTH&&b<LINE_WIDTH));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled feathered rectangle mask

Calculate a soft rectangular mask around the face center with independently sized half-extents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The feather is a linear transition outside the rectangle; the signed distance combines corner and edge distances. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
vector HALF=<0.6,0.4,0.0>;
float FEATHER=0.15;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(HALF.x<=0.0||HALF.y<=0.0||FEATHER<=0.0)
        {
            llOwnerSay("Invalid rectangle.");
            return;
        }
        float x=llFabs(p.x)-HALF.x;
        float y=llFabs(p.y)-HALF.y;
        float ox=x;
        float oy=y;
        if(ox<0.0)ox=0.0;
        if(oy<0.0)oy=0.0;
        float inside=x;
        if(y>inside)inside=y;
        if(inside>0.0)inside=0.0;
        float distance=llSqrt(ox*ox+oy*oy)+inside;
        float mask=1.0-distance/FEATHER;
        if(mask<0.0)mask=0.0;
        if(mask>1.0)mask=1.0;
        llOwnerSay("Soft rectangle mask="+(string)mask);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled heart silhouette

Test a live surface coordinate against an implicit heart equation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

An algebraic silhouette test, not a signed distance function; scaling is centered on the face. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float SIZE=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(SIZE<=0.0)
        {
            llOwnerSay("Positive size required.");
            return;
        }
        float x=p.x/SIZE;
        float y=p.y/SIZE;
        float a=x*x+y*y-1.0;
        float value=a*a*a-x*x*y*y*y;
        llOwnerSay("Heart implicit value="+(string)value+" inside="+(string)(value<=0.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled multi-scale texture noise

Combine four smooth value-noise octaves with decreasing amplitude.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

This decorrelated multi-scale field is deterministic decoration, not a simulation of physical terrain. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float hash(float x,float y)
{
    float n=llSin(x*127.1+y*311.7)*43758.5453;
    return n-llFloor(n);
}
float noise(vector q)
{
    integer x=llFloor(q.x);
    integer y=llFloor(q.y);
    float u=q.x-x;
    float v=q.y-y;
    u=u*u*(3.0-2.0*u);
    v=v*v*(3.0-2.0*v);
    float a=hash(x,y);
    float b=hash(x+1,y);
    float c=hash(x,y+1);
    float d=hash(x+1,y+1);
    return (a+(b-a)*u)*(1.0-v)+(c+(d-c)*u)*v;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        float amplitude=0.5;
        float frequency=3.0;
        float total;
        float weight;
        integer i;
        for(i=0;i<4;++i)
        {
            total+=amplitude*noise(uv*frequency+<i*7.0,i*3.0,0.0>);
            weight+=amplitude;
            amplitude*=0.5;
            frequency*=2.0;
        }
        llOwnerSay("Four-octave noise="+(string)(total/weight));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled nearest-seed regions

Identify the nearest and second-nearest of several fixed texture seeds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The difference between first and second distance helps reveal cell boundaries but is not the exact distance to every Voronoi edge. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
list SEEDS=[<0.2,0.2,0.0>,<0.8,0.25,0.0>,<0.35,0.8,0.0>,<0.8,0.8,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        integer n=llGetListLength(SEEDS);
        if(n<2)
        {
            llOwnerSay("Need two seeds.");
            return;
        }
        integer best=-1;
        float first=1000000.0;
        float second=1000000.0;
        integer i;
        for(i=0;i<n;++i)
        {
            float distance=llVecDist(uv,llList2Vector(SEEDS,i));
            if(distance<first)
            {
                second=first;
                first=distance;
                best=i;
            }
            else if(distance<second)second=distance;
        }
        llOwnerSay("Cell="+(string)best+" nearest distance="+(string)first+" separation score="+(string)(second-first));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled radial menu sectors

Turn touch angle into a numbered radial sector with an optional dead center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Sector zero starts along positiveS; numbering advances counterclockwise in surface coordinates. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
integer SECTORS=8;
float DEAD_RADIUS=0.15;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(SECTORS<1||SECTORS>32||DEAD_RADIUS<0.0)
        {
            llOwnerSay("Invalid radial settings.");
            return;
        }
        if(llSqrt(p.x*p.x+p.y*p.y)<DEAD_RADIUS)
        {
            llOwnerSay("Inside center dead zone.");
            return;
        }
        float phase=llAtan2(p.y,p.x)/TWO_PI;
        phase-=llFloor(phase);
        integer sector=llFloor(phase*SECTORS);
        llOwnerSay("Sector="+(string)sector);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Color & materials · Intermediate

Touch-sampled repeating circular dots

Measure signed distance to the nearest centered dot in a square repeated cell.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Dot radius is in cell units; a radius below0.5 keeps neighboring dots separate. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float REPEATS=5.0;
float RADIUS=0.3;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(REPEATS<=0.0||RADIUS<=0.0||RADIUS>0.5)
        {
            llOwnerSay("Invalid dot settings.");
            return;
        }
        float x=uv.x*REPEATS;
        float y=uv.y*REPEATS;
        x=x-llFloor(x)-0.5;
        y=y-llFloor(y)-0.5;
        float distance=llSqrt(x*x+y*y)-RADIUS;
        llOwnerSay("Dot signed distance="+(string)distance+" inside="+(string)(distance<=0.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled rounded rectangle border

Calculate distance to a rounded rectangle and identify its thin border.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Half extents describe the outer rectangle; corner radius must fit inside both. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
vector HALF=<0.7,0.5,0.0>;
float RADIUS=0.15;
float BORDER=0.04;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(RADIUS<0.0||RADIUS>HALF.x||RADIUS>HALF.y||BORDER<=0.0)
        {
            llOwnerSay("Invalid rounded box.");
            return;
        }
        float x=llFabs(p.x)-HALF.x+RADIUS;
        float y=llFabs(p.y)-HALF.y+RADIUS;
        float ox=x;
        float oy=y;
        if(ox<0.0)ox=0.0;
        if(oy<0.0)oy=0.0;
        float inner=x;
        if(y>inner)inner=y;
        if(inner>0.0)inner=0.0;
        float d=llSqrt(ox*ox+oy*oy)+inner-RADIUS;
        llOwnerSay("Signed distance="+(string)d+" border="+(string)(llFabs(d)<BORDER));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled rounded-diamond shape

Evaluate a superellipse implicit boundary for different corner exponents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Exponent2 gives an ellipse,1 a diamond, and larger values squarer shapes. This is not an exact distance field. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float EXPONENT=4.0;
float HALF_W=0.7;
float HALF_H=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(EXPONENT<=0.0||HALF_W<=0.0||HALF_H<=0.0)
        {
            llOwnerSay("Positive settings required.");
            return;
        }
        float value=llPow(llFabs(p.x)/HALF_W,EXPONENT)+llPow(llFabs(p.y)/HALF_H,EXPONENT);
        llOwnerSay("Implicit value="+(string)value+" inside="+(string)(value<=1.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled smooth value noise

Interpolate deterministic values at the four corners of a repeated coordinate cell.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The sine hash is decorative and may vary slightly across floating-point implementations; it is not secure randomness. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float FREQUENCY=6.0;
float hash(float x,float y)
{
    float n=llSin(x*127.1+y*311.7)*43758.5453;
    return n-llFloor(n);
}
float noise(vector q)
{
    integer x=llFloor(q.x);
    integer y=llFloor(q.y);
    float u=q.x-x;
    float v=q.y-y;
    u=u*u*(3.0-2.0*u);
    v=v*v*(3.0-2.0*v);
    float a=hash(x,y);
    float b=hash(x+1,y);
    float c=hash(x,y+1);
    float d=hash(x+1,y+1);
    return (a+(b-a)*u)*(1.0-v)+(c+(d-c)*u)*v;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(FREQUENCY<=0.0)
        {
            llOwnerSay("Positive frequency required.");
            return;
        }
        llOwnerSay("Smooth noise="+(string)noise(uv*FREQUENCY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Color & materials · Intermediate

Touch-sampled soft union of two circles

Blend two circle distance fields with a controllable smoothing radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The polynomial smooth minimum rounds the join and slightly expands the combined silhouette. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float RADIUS=0.4;
float SMOOTH_RADIUS=0.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(RADIUS<=0.0||SMOOTH_RADIUS<=0.0)
        {
            llOwnerSay("Positive radius/smoothing required.");
            return;
        }
        float a=llVecDist(p,<-0.3,0.0,0.0>)-RADIUS;
        float b=llVecDist(p,<0.3,0.0,0.0>)-RADIUS;
        float h=0.5+0.5*(b-a)/SMOOTH_RADIUS;
        if(h<0.0)h=0.0;
        if(h>1.0)h=1.0;
        float d=b+(a-b)*h-SMOOTH_RADIUS*h*(1.0-h);
        llOwnerSay("Smooth union distance="+(string)d+" inside="+(string)(d<=0.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled spiral bands

Combine polar angle and radius to evaluate an Archimedean spiral stripe pattern.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

The center has an arbitrary angle; the seam convention follows atan2. This reports a mask rather than creating an image. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float TURNS=3.0;
float DUTY=0.3;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(DUTY<0.0||DUTY>1.0)
        {
            llOwnerSay("Duty must be0..1.");
            return;
        }
        float radius=llSqrt(p.x*p.x+p.y*p.y);
        float coordinate=llAtan2(p.y,p.x)/TWO_PI-TURNS*radius;
        float phase=coordinate-llFloor(coordinate);
        llOwnerSay("Spiral phase="+(string)phase+" band="+(string)(phase<DUTY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Color & materials · Intermediate

Touch-sampled staggered brick mortar

Classify a touched point as brick or mortar in offset rows.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Mortar width is expressed as a fraction of each cell, so horizontal and vertical physical widths differ if cells differ in aspect. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float COLUMNS=4.0;
float ROWS=6.0;
float MORTAR=0.08;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(COLUMNS<=0.0||ROWS<=0.0||MORTAR<0.0||MORTAR>=0.5)
        {
            llOwnerSay("Invalid brick settings.");
            return;
        }
        float y=uv.y*ROWS;
        integer row=llFloor(y);
        float x=uv.x*COLUMNS;
        if(row&1)x+=0.5;
        x-=llFloor(x);
        y-=llFloor(y);
        integer mortar=(x<MORTAR||x>1.0-MORTAR||y<MORTAR||y>1.0-MORTAR);
        llOwnerSay("Row="+(string)row+" mortar="+(string)mortar);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Color & materials · Intermediate

Touch-sampled wavy grid coordinates

Warp one coordinate by a sinusoid before evaluating grid lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare ordinary cube you own. Touch different places on one face to sample the procedural pattern at live surface coordinates. Edit the constants to design a pattern.

Stop / restore: Disable/remove. Only private owner messages are produced; no texture or tint is applied.

Warp amplitude is inUV units; large amplitudes fold the visual grid but do not change actual geometry. Surface coordinates depend on the viewer and mesh; ordinary prim faces are the clearest test surface.

// Original Incoprea. MIT. Live surface-coordinate sampler.
float REPEATS=6.0;
float WARP=0.08;
float LINE=0.06;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector uv=llDetectedTouchST(0);
        if(llDetectedTouchFace(0)<0||uv==TOUCH_INVALID_TEXCOORD)
        {
            llOwnerSay("Surface coordinates unavailable.");
            return;
        }
        vector p=2.0*uv-<1.0,1.0,0.0>;
        if(REPEATS<=0.0||LINE<=0.0||LINE>=0.5)
        {
            llOwnerSay("Invalid grid settings.");
            return;
        }
        float x=(uv.x+WARP*llSin(TWO_PI*uv.y*2.0))*REPEATS;
        float y=uv.y*REPEATS;
        float dx=llFabs(x-llRound(x));
        float dy=llFabs(y-llRound(y));
        llOwnerSay("Warped grid line="+(string)(dx<LINE||dy<LINE));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Color & materials · Intermediate

Transform a tangent normal into a planned world frame

Combine tangent, bitangent and surface normal axes to orient a sampled normal.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set normalized perpendicular axes T/B/N and TANGENT_NORMAL. Touch for owner-only numeric output.

Stop / restore: Remove/disable; no colors or materials are applied.

The basis must be orthonormal; this example checks perpendicularity and normalizes axes.

// Original Incoprea. MIT. Color calculation only.
vector T=<1.0,0.0,0.0>;
vector B=<0.0,0.7071068,0.7071068>;
vector N=<0.0,-0.7071068,0.7071068>;
vector TANGENT_NORMAL=<0.2,0.1,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(T)<0.000001||llVecMag(B)<0.000001||llVecMag(N)<0.000001||llVecMag(TANGENT_NORMAL)<0.000001)
        {
            llOwnerSay("Nonzero vectors required.");
            return;
        }
        T=llVecNorm(T);
        B=llVecNorm(B);
        N=llVecNorm(N);
        if(llFabs(T*B)>0.001||llFabs(T*N)>0.001||llFabs(B*N)>0.001)
        {
            llOwnerSay("Axes must be perpendicular.");
            return;
        }
        vector local=llVecNorm(TANGENT_NORMAL);
        llOwnerSay("World normal="+(string)llVecNorm(local.x*T+local.y*B+local.z*N));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

Two-picture comparison frame

Toggle one frame between two configured images and its original face settings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed textures before and after. Set FACE. Owner-touch cycles before, after, then original.

Stop / restore: The third touch restores original diffuse settings; remove then.

A controlled A/B presentation, useful for before/after exhibits. It does not generate captions or infer which image is better. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer stage;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(stage==2)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved);
            stage=0;
            llOwnerSay("Original restored.");
            return;
        }
        string name="before";
        if(stage==1)name="after";
        if(llGetInventoryType(name)!=INVENTORY_TEXTURE)
        {
            llOwnerSay("Missing texture "+name);
            return;
        }
        llSetTexture(name,FACE);
        llOwnerSay(name);
        ++stage;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Color & materials · Intermediate

Type a HEX face tint

Set one face’s tint from a six-digit HEX value entered by the owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE, put in the prim, then owner-touch. Enter a value such as 7ADFA7, optionally beginning with #, or RESTORE.

Stop / restore: Open the prompt and enter RESTORE before removing or resetting.

Validates the input length and characters. The listener expires after 30 seconds; original color is stored only until reset.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
vector original;
integer channel;
integer handle;
string digits = "0123456789abcdef";
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        original = llGetColor(FACE);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llTextBox(llGetOwner(), "Enter six HEX digits, or RESTORE.", channel);
        llSetTimerEvent(30.0);
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        close();
        message = llToLower(llStringTrim(message, STRING_TRIM));
        if (message == "restore")
        {
            llSetColor(original, FACE);
            return;
        }
        if (llGetSubString(message, 0, 0) == "#") message = llDeleteSubString(message, 0, 0);
        if (llStringLength(message) != 6)
        {
            llOwnerSay("Expected six HEX digits.");
            return;
        }
        integer packed;
        integer i;
        for (i = 0; i < 6; ++i)
        {
            integer digit = llSubStringIndex(digits, llGetSubString(message, i, i));
            if (digit < 0)
            {
                llOwnerSay("Use only 0-9 and A-F.");
                return;
            }
            packed = packed * 16 + digit;
        }
        vector color = <(float)((packed >> 16) & 255), (float)((packed >> 8) & 255), (float)(packed & 255)> / 255.0;
        llSetColor(color, FACE);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER)
        {
            close();
            llResetScript();
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Beginner

UV coordinate finder

Tell the owner which face and texture coordinate they touched.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the textured prim and touch points on its surface. Read owner chat while planning an atlas or clickable panel.

Stop / restore: Remove or disable; no prim property is changed.

UV uses texture coordinates after face transforms; ST uses surface coordinates. Unsupported touch data returns an invalid vector.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer face = llDetectedTouchFace(0);
        if (face < 0)
        {
            llOwnerSay("This touch did not provide face coordinates.");
            return;
        }
        llOwnerSay("Face " + (string)face + " | UV " + (string)llDetectedTouchUV(0)
        + " | ST " + (string)llDetectedTouchST(0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Color & materials · Intermediate

White-tint texture baseline

Temporarily neutralize the tint on every face while retaining each face’s alpha.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim whose texture colors you want to examine. Owner-touch previews; touch again restores.

Stop / restore: Owner-touch again to restore the startup snapshot before removing or resetting. A reset while previewing loses the original snapshot.

Classic-material controls only; PBR materials may display differently. Use a spare prim and textures whose settings you can read and restore. Another controller must not edit the same face during the preview.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
integer preview;
default
{
    state_entry()
    {
        integer f;
        for(f=0;f<llGetNumberOfSides();++f)saved+=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_COLOR,f]);
    }
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        preview=!preview;
        integer f;
        for(f=0;f<llGetListLength(saved)/2;++f)
        {
            vector tint=llList2Vector(saved,f*2);
            if(preview)tint=<1.0,1.0,1.0>;
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_COLOR,f,tint,llList2Float(saved,f*2+1)]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

SoundSound playback, ambience, and audio controls.47 scripts

Download this category (.zip)

Sound · Intermediate

Accented beat practice

Mark the first beat of each four-beat bar with a different sound.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add short sounds downbeat and beat, both shorter than the interval. Set BPM 30–180. Owner-touch starts/stops.

Stop / restore: Touch to stop and silence before removal.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Four-beat accent structure helps distinguish bar boundaries; it is not synchronized to music streams.

// Original Incoprea. MIT. Not compiled or tested in-world.
float BPM=80.0;
integer active;
integer beat;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            if(BPM<30.0)BPM=30.0;
            if(BPM>180.0)BPM=180.0;
            beat=0;
            llSetTimerEvent(60.0/BPM);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        string sound="beat";
        if(!beat)sound="downbeat";
        if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.2);
        beat=(beat+1)%4;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Ambient loop with graceful ending

Use first touch to loop ambience and second touch to replace it with an outro.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bed and outro. Touch once starts; second touch plays outro; a further touch silences it.

Stop / restore: Touch cycles loop, outro, silent. Reach silent before removal.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Outro is not automatically crossfaded; it replaces the attached loop. Status cycles idle, loop, outro.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer phase;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(phase==0)
        {
            if(llGetInventoryType("bed")==INVENTORY_SOUND)
            {
                phase=1;
                llLoopSound("bed",0.25);
            }
        }
        else if(phase==1)
        {
            llStopSound();
            phase=2;
            if(llGetInventoryType("outro")==INVENTORY_SOUND)llPlaySound("outro",0.25);
        }
        else
        {
            phase=0;
            llStopSound();
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Ambient sound fade switch

Owner-touch fades an inventory sound loop in or out over about three seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed looping sound named ambience to this prim. Touch to start; touch again to fade out.

Stop / restore: Fade out and wait for the sound to stop before removal. Use Stop sound in this prim if interrupted.

One attached sound per prim; do not run another sound controller in the same prim. Volume adjustments include API delays.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string SOUND = "ambience";
float volume;
integer wanted;
integer playing;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(SOUND) != INVENTORY_SOUND)
        {
            llOwnerSay("Add a sound named ambience.");
            return;
        }
        wanted = !wanted;
        if (wanted && !playing)
        {
            llLoopSound(SOUND, 0.0);
            playing = TRUE;
        }
        llSetTimerEvent(0.25);
    }
    timer()
    {
        if (wanted) volume += 0.025;
        else volume -= 0.025;
        if (volume >= 0.3)
        {
            volume = 0.3;
            llSetTimerEvent(0.0);
        }
        if (volume <= 0.0)
        {
            volume = 0.0;
            playing = FALSE;
            llStopSound();
            llSetTimerEvent(0.0);
        }
        else llAdjustSoundVolume(volume);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Authored rhythm pattern player

Play a repeating beat/rest pattern rather than a uniform metronome.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a very short tick sound. Edit PATTERN as 1=beat and 0=rest; owner-touch starts/stops.

Stop / restore: Touch to stop and silence before removing.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. A short step sequence can illustrate syncopation. STEP is clamped to at least 0.25 seconds; no precise audio synchronization is promised.

// Original Incoprea. MIT. Not compiled or tested in-world.
list PATTERN=[1,0,1,1,0,1,0,0];
float STEP=0.5;
integer active;
integer index;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            if(STEP<0.25)STEP=0.25;
            index=0;
            llSetTimerEvent(STEP);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        integer count=llGetListLength(PATTERN);
        if(!count)
        {
            active=FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        if(llList2Integer(PATTERN,index)&&llGetInventoryType("tick")==INVENTORY_SOUND)llPlaySound("tick",0.2);
        index=(index+1)%count;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Blind A/B audio comparison

Hear one of two clips without seeing its name, then reveal which was selected.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add short sounds sample_a and sample_b. Owner-touch plays one and opens an A/B guess dialog.

Stop / restore: Select A/B or wait 30 seconds; Stop sound in this prim can silence a remaining clip.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. A listening exercise, not a controlled scientific hearing test. Identical volume settings do not normalize source loudness.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer choice;
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        if(llGetInventoryType("sample_a")!=INVENTORY_SOUND||llGetInventoryType("sample_b")!=INVENTORY_SOUND)
        {
            llOwnerSay("Add sample_a and sample_b.");
            return;
        }
        choice=(integer)llFrand(2.0);
        string sound="sample_a";
        if(choice)sound="sample_b";
        llPlaySound(sound,0.3);
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llDialog(llGetOwner(),"Was that A or B?",["A","B"],channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner()||(s!="A"&&s!="B"))return;
        close();
        string actual="A";
        if(choice)actual="B";
        if(s==actual)llOwnerSay("Correct: "+actual);
        else llOwnerSay("This was "+actual);
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Box-bounded sound exhibit

Trigger a short sound with audibility constrained to a world-aligned box around the exhibit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add exhibit_sound to the prim. Owner-touch plays; adjust HALF_EXTENT in meters.

Stop / restore: A triggered sound cannot be stopped by llStopSound; let the short clip finish, then disable/remove.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Bounds use world/region axes, not object rotation. The sound stays at its trigger position if the prim moves.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector HALF_EXTENT=<3.0,3.0,2.0>;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetInventoryType("exhibit_sound")!=INVENTORY_SOUND)return;
        vector p=llGetPos();
        llTriggerSoundLimited("exhibit_sound",0.3,p+HALF_EXTENT,p-HALF_EXTENT);
    }
}

MIT · original Incoprea example

API reference 1

Sound · Intermediate

Call-and-response sound exhibit

Play a call and a delayed response from one prim without overlapping them.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed sounds call and response. Set CALL_SECONDS longer than the first clip. Owner-touch begins; touching during playback cancels.

Stop / restore: Touch during the call to cancel. After the response starts, use Stop sound in this prim if immediate silence is needed.

Timer scheduling and asset loading are approximate. The script does not infer sound duration. Playback is nearby and caption-free.

// Original Incoprea. MIT. Not compiled or tested in-world.
float CALL_SECONDS=3.0;
integer stage;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(stage)
        {
            stage=0;
            llSetTimerEvent(0.0);
            llStopSound();
            return;
        }
        if(llGetInventoryType("call")!=INVENTORY_SOUND||llGetInventoryType("response")!=INVENTORY_SOUND)
        {
            llOwnerSay("Add sounds call and response.");
            return;
        }
        if(CALL_SECONDS<0.5)CALL_SECONDS=0.5;
        stage=1;
        llPlaySound("call",0.3);
        llSetTimerEvent(CALL_SECONDS);
    }
    timer()
    {
        llSetTimerEvent(0.0);
        stage=0;
        if(llGetInventoryType("response")==INVENTORY_SOUND)llPlaySound("response",0.3);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Captioned sound exhibit

Play a short inventory sound with a temporary matching visual caption.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed sound named exhibit_sound. Set CAPTION to accurately describe that sound and SECONDS to its approximate duration. Owner-touch plays it.

Stop / restore: Wait for the caption timer to restore the original text before removing. Stop sound in this prim can silence a remaining clip.

Caption is authored text, not automatic transcription. Helps visitors who mute sound or cannot hear it; no recording or external service is involved.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string SOUND = "exhibit_sound";
string CAPTION = "[A soft wooden chime rings once]";
float SECONDS = 4.0;
list original;
integer busy;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || busy) return;
        if (llGetInventoryType(SOUND) != INVENTORY_SOUND)
        {
            llOwnerSay("Add exhibit_sound to this prim.");
            return;
        }
        if (SECONDS < 1.0) SECONDS = 1.0;
        busy = TRUE;
        llSetText(CAPTION, <0.95, 0.95, 0.85>, 1.0);
        llPlaySound(SOUND, 0.35);
        llSetTimerEvent(SECONDS);
    }
    timer()
    {
        busy = FALSE;
        llSetTimerEvent(0.0);
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Counted chime input

Enter a small number and hear that many evenly spaced chimes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short chime sound. Owner-touch opens a text box for 1–8. A touch during ringing cancels.

Stop / restore: Touch during ringing to stop; unanswered input closes after 30 seconds.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. The count is bounded. Use clips shorter than the 1.5-second spacing; this does not signal real emergencies or official time.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer left;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(left)
        {
            left=0;
            llSetTimerEvent(0.0);
            llStopSound();
            return;
        }
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llTextBox(llGetOwner(),"Chime count 1-8",channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        close();
        llSetTimerEvent(0.0);
        s=llStringTrim(s,STRING_TRIM);
        integer index=llSubStringIndex("12345678",s);
        if(llStringLength(s)!=1||index<0)
        {
            llOwnerSay("Expected one digit 1-8.");
            return;
        }
        if(llGetInventoryType("chime")!=INVENTORY_SOUND)
        {
            llOwnerSay("Add chime sound.");
            return;
        }
        left=index+1;
        llSetTimerEvent(1.5);
    }
    timer()
    {
        if(handle)
        {
            close();
            llSetTimerEvent(0.0);
            return;
        }
        if(left>0)
        {
            if(llGetInventoryType("chime")==INVENTORY_SOUND)llPlaySound("chime",0.2);
            --left;
        }
        if(!left)llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Crossfade source receiver

Play an ambient loop at the gain assigned by a linked A/B mixer.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put a licensed ambience loop in each of two children. Name them audio_a and audio_b; use the paired root named audio_mixer.

Stop / restore: Owner-touch a source stops its own sound; a held touch on the mixer stops both. Remove only after stopping.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. Receives only root messages on code 7910. Other scripts in the same linkset can still send messages; this is coordination, not a secret protocol.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer playing;
stop()
{
    playing=FALSE;
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())stop();
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(sender!=1||llGetLinkName(1)!="audio_mixer"||code!=7910)return;
        if(s=="stop")
        {
            stop();
            return;
        }
        integer i;
        integer dots;
        integer digits;
        if(llStringLength(s)>12)return;
        for(i=0;i<llStringLength(s);++i)
        {
            string c=llGetSubString(s,i,i);
            if(c==".")
            {
                ++dots;
                if(dots>1)return;
            }
            else if(llSubStringIndex("0123456789",c)<0)return;
            else ++digits;
        }
        if(!digits)return;
        float mix=(float)s;
        if(mix<0.0||mix>1.0)return;
        float volume=mix;
        if(llGetObjectName()=="audio_a")volume=1.0-mix;
        else if(llGetObjectName()!="audio_b")return;
        volume*=0.3;
        if(llGetInventoryType("ambience")!=INVENTORY_SOUND)return;
        if(!playing)
        {
            llLoopSound("ambience",volume);
            playing=TRUE;
        }
        else llAdjustSoundVolume(volume);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)stop();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Distance-spaced movement sounds

Play one short cue after each accumulated meter traveled by this object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add step. Owner-touch arms; move using your existing mechanism.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Samples root movement, not avatar footsteps. Large jumps reset the accumulator rather than emitting a burst.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
vector previous;
float distance;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        if(llGetInventoryType("step")!=INVENTORY_SOUND)
        {
            stop();
            return;
        }
        previous=llGetRootPosition();
        distance=0.0;
        if(active)llSetTimerEvent(0.25);
    }
    timer()
    {
        if(active)
        {
            vector p=llGetRootPosition();
            float delta=llVecDist(p,previous);
            previous=p;
            if(delta>5.0)
            {
                distance=0.0;
                return;
            }
            distance+=delta;
            if(distance>=1.0)
            {
                distance-=1.0;
                if(llGetInventoryType("step")==INVENTORY_SOUND)llPlaySound("step",0.15);
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Editable eight-step sound sequencer

Toggle beats in an eight-step pattern while it plays.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short tick. Owner-touch opens menu; 1-8 toggle steps, Play starts, Stop silences.

Stop / restore: Reopen the menu and choose Stop before removal. Menu timeout does not stop playback.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Input listener expires after thirty seconds without stopping an explicitly playing pattern. Reopen to Stop; this is approximate rhythm.

// Original Incoprea. MIT. Not compiled or tested in-world.
list beats=[1,0,0,0,1,0,0,0];
integer step;
integer playing;
integer channel;
integer handle;
float expiry;
show()
{
    llDialog(llGetOwner(),"Pattern "+llDumpList2String(beats,""),["1","2","3","4","5","6","7","8","Play","Stop"],channel);
    expiry=llGetTime()+30.0;
    llSetTimerEvent(0.5);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(handle)llListenRemove(handle);
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        show();
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        integer p=llSubStringIndex("12345678",s);
        if(llStringLength(s)==1&&p>=0)beats=llListReplaceList(beats,[!llList2Integer(beats,p)],p,p);
        else if(s=="Play")
        {
            playing=TRUE;
            step=0;
        }
        else if(s=="Stop")
        {
            playing=FALSE;
            llStopSound();
        }
        else return;
        show();
    }
    timer()
    {
        if(handle&&llGetTime()>expiry)
        {
            llListenRemove(handle);
            handle=0;
        }
        if(playing)
        {
            if(llList2Integer(beats,step)&&llGetInventoryType("tick")==INVENTORY_SOUND)llPlaySound("tick",0.15);
            step=(step+1)%8;
        }
        else if(!handle)llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Beginner

Four-level ambient volume

Cycle an ambient loop through three quiet volume levels and off.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed loop named ambience to this prim. Owner-touch cycles 0.1, 0.2, 0.35, and off.

Stop / restore: Touch until Off appears in owner chat, then remove.

Controls attached sound in the prim containing the script. Another script playing sound here can interfere.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string SOUND = "ambience";
list levels = [0.0, 0.1, 0.2, 0.35];
integer level;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(SOUND) != INVENTORY_SOUND)
        {
            llOwnerSay("Add a sound named ambience.");
            return;
        }
        integer previous = level;
        level = (level + 1) % 4;
        float volume = llList2Float(levels, level);
        if (!level)
        {
            llStopSound();
            llOwnerSay("Off");
        }
        else
        {
            if (!previous) llLoopSound(SOUND, volume);
            else llAdjustSoundVolume(volume);
            llOwnerSay("Volume: " + (string)volume);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Four-zone inventory drum pad

Choose one of four short percussion assets by touch location.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE and add kick, snare, hat, clap. Owner-touch corresponding quadrants; hold at least two seconds to silence.

Stop / restore: Hold for at least two seconds to silence, then remove.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Uses valid surface coordinates only. One attached sound at a time; this is not a polyphonic sampler.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
float pressed;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())pressed=llGetTime();
    }
    touch_end(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetTime()-pressed>=2.0)
        {
            llStopSound();
            return;
        }
        if(llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.y<0.0||st.x>1.0||st.y>1.0)return;
        integer slot=0;
        if(st.x>=0.5)slot+=1;
        if(st.y>=0.5)slot+=2;
        string sound=llList2String(["kick","snare","hat","clap"],slot);
        if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.25);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Intro followed by ambient loop

Play an authored introduction, then continue with a looping bed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add intro and bed sounds. Edit INTRO_SECONDS to the actual intro duration; owner-touch starts/stops.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. The transition is duration-driven, not detection of file completion.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
float INTRO_SECONDS=4.0;
integer phase;
float began;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        if(llGetInventoryType("intro")!=INVENTORY_SOUND||llGetInventoryType("bed")!=INVENTORY_SOUND)
        {
            stop();
            llOwnerSay("Add intro and bed.");
            return;
        }
        phase=0;
        began=llGetTime();
        llPlaySound("intro",0.25);
        if(active)llSetTimerEvent(0.5);
    }
    timer()
    {
        if(active)
        {
            if(!phase&&llGetTime()-began>=INTRO_SECONDS)
            {
                phase=1;
                llLoopSound("bed",0.25);
                llSetTimerEvent(0.0);
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Beginner

Inventory sound audition

Owner-touch auditions the next inventory sound at a modest volume.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed sounds to the same prim. Touch to cycle alphabetically through them.

Stop / restore: Disable or remove and run Stop sound in this prim if a clip is still playing.

Playback is audible nearby; owner-only triggering does not make audio private. A new selection interrupts the previous attached sound.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer index;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetInventoryNumber(INVENTORY_SOUND);
        if (!total)
        {
            llOwnerSay("Add a licensed sound to this prim.");
            return;
        }
        index = index % total;
        string sound = llGetInventoryName(INVENTORY_SOUND, index++);
        llStopSound();
        llPlaySound(sound, 0.35);
        llOwnerSay("Preview: " + sound);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Linked audio ducking receiver

Reduce an ambient loop while a linked narrator signals an announcement.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bed. Put in child; root named narrator sends code 8050 with duck or release. Owner-touch arms/stops.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Ducking automatically releases after ten seconds, preventing a lost release message from leaving permanent low volume.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer ducked;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            if(llGetInventoryType("bed")!=INVENTORY_SOUND)
            {
                active=FALSE;
                return;
            }
            llLoopSound("bed",0.25);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
            ducked=FALSE;
        }
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||sender!=1||llGetLinkName(1)!="narrator"||code!=8050)return;
        if(s=="duck")
        {
            ducked=TRUE;
            llAdjustSoundVolume(0.04);
            llSetTimerEvent(10.0);
        }
        else if(s=="release")
        {
            ducked=FALSE;
            llAdjustSoundVolume(0.25);
            llSetTimerEvent(0.0);
        }
    }
    timer()
    {
        if(active&&ducked)
        {
            ducked=FALSE;
            llAdjustSoundVolume(0.25);
        }
        llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Beginner

Looping ambient sound

Start a quiet loop of an ambient sound stored in the prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add your properly licensed sound to this prim and use its exact inventory name below. Touch once to start.

Stop / restore: Touch again to stop, or remove the script. It starts stopped after reset.

Uses only the sound in this prim’s inventory. Keep volume low and get permission for supplied assets.

// Original Incoprea example. Add your own ambient sound to this prim.
string AMBIENT_SOUND = "ambient_loop";
integer playing;
default
{
    state_entry()
    {
        playing = FALSE;
        llStopSound();
    }
    touch_start(integer count)
    {
        if (playing)
        {
            llStopSound();
            playing = FALSE;
        }
        else
        {
            llLoopSound(AMBIENT_SOUND, 0.12);
            playing = TRUE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Minute-boundary sound cue

While armed, play one cue when the UTC minute changes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short sound cue. Owner-touch arms/disarms; first cue happens at the next minute boundary.

Stop / restore: Touch to disarm and stop attached playback.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Samples every second. A delayed script plays at most one cue, rather than catching up with a burst.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer minute;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            minute=llGetUnixTime()/60;
            llSetTimerEvent(1.0);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        integer now=llGetUnixTime()/60;
        if(now!=minute)
        {
            minute=now;
            if(llGetInventoryType("cue")==INVENTORY_SOUND)llPlaySound("cue",0.2);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Morse audio beacon

Play authored dot/dash symbols as quiet short and long tones.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a clean tone loop. Edit SYMBOLS using dot, dash and spaces; owner-touch starts/cancels.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Each symbol is a separate loop interval; spaces add word gaps. This is approximate demonstration timing, not radio signaling.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
string SYMBOLS="... --- ...";
integer index;
integer sounding;
float due;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        if(llGetInventoryType("tone")!=INVENTORY_SOUND)
        {
            stop();
            return;
        }
        index=0;
        sounding=FALSE;
        due=llGetTime();
        if(active)llSetTimerEvent(0.1);
    }
    timer()
    {
        if(active)
        {
            if(llGetTime()<due)return;
            if(sounding)
            {
                llStopSound();
                sounding=FALSE;
                due=llGetTime()+0.25;
                return;
            }
            if(index>=llStringLength(SYMBOLS))
            {
                stop();
                return;
            }
            string symbol=llGetSubString(SYMBOLS,index,index);
            ++index;
            if(symbol=="."||symbol=="-")
            {
                float duration=0.25;
                if(symbol=="-")duration=0.75;
                llLoopSound("tone",0.1);
                sounding=TRUE;
                due=llGetTime()+duration;
            }
            else due=llGetTime()+0.75;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Movement start and stop cues

Play one cue when an object begins moving and another after it settles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in an object already capable of moving. Add start_cue and stop_cue. Owner-touch arms; speed thresholds are in meters per second.

Stop / restore: Touch to disarm and silence. It never changes movement or physics.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Separate start/stop thresholds reduce chatter. Measures the object, not nearby avatars.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer moving;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            moving=llVecMag(llGetVel())>0.3;
            llSetTimerEvent(0.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        float speed=llVecMag(llGetVel());
        string sound="";
        if(!moving&&speed>0.3)
        {
            moving=TRUE;
            sound="start_cue";
        }
        else if(moving&&speed<0.05)
        {
            moving=FALSE;
            sound="stop_cue";
        }
        if(sound!=""&&llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.25);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Mute loop while remembering gain

Keep a user-selected gain while switching a loop between muted and audible.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bed. Owner-touch opens Low, Mid, High, Mute, Unmute, Stop.

Stop / restore: Choose Stop before removing; the menu expires but an audible or muted loop remains.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Mute changes gain to zero without ending the loop; Stop really stops playback.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer playing;
integer muted;
float gain=0.15;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
show()
{
    llDialog(llGetOwner(),"Loop gain / mute",["Low","Mid","High","Mute","Unmute","Stop"],channel);
    llSetTimerEvent(30.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        show();
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        if(s=="Stop")
        {
            playing=FALSE;
            llStopSound();
            close();
            return;
        }
        if(s=="Low")gain=0.05;
        else if(s=="Mid")gain=0.15;
        else if(s=="High")gain=0.3;
        else if(s=="Mute")muted=TRUE;
        else if(s=="Unmute")muted=FALSE;
        else return;
        float volume=gain;
        if(muted)volume=0.0;
        if(!playing)
        {
            if(llGetInventoryType("bed")!=INVENTORY_SOUND)
            {
                llOwnerSay("Add bed.");
                close();
                return;
            }
            llLoopSound("bed",volume);
            playing=TRUE;
        }
        else llAdjustSoundVolume(volume);
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Named sound button bank

A root script plays the sound whose inventory name matches the touched child’s description.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put script and licensed sounds in root. Put exact sound names in child descriptions; child buttons should pass touch events. Owner-touch a child.

Stop / restore: Disable/remove; Stop sound in the root can silence the current clip.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Uses a fixed inventory lookup, not arbitrary remote sound identifiers. Children provide labels only.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        integer link=llDetectedLinkNumber(0);
        if(link<2)return;
        string sound=llList2String(llGetLinkPrimitiveParams(link,[PRIM_DESC]),0);
        if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.3);
        else llOwnerSay("No sound named "+sound+" in root.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Notecard-captioned sound player

Read a sound-name and caption pair from a notecard before playing a short clip.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add cues with lines sound_name|caption plus the licensed sounds. Owner-touch advances one cue.

Stop / restore: Disable/remove; Stop sound in this prim can silence current audio. Captions are owner chat, not persistent text.

Caption precedes playback and remains readable when sound is muted. Only inventory sound names are accepted. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer line;
key request;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||request!=NULL_KEY)return;
        if(llGetInventoryType("cues")!=INVENTORY_NOTECARD)return;
        request=llGetNotecardLine("cues",line);
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        if(data==EOF)
        {
            line=0;
            llOwnerSay("End of sound cues.");
            return;
        }
        ++line;
        list pair=llParseStringKeepNulls(data,["|"],[]);
        if(llGetListLength(pair)!=2)
        {
            llOwnerSay("Expected sound_name|caption.");
            return;
        }
        string name=llStringTrim(llList2String(pair,0),STRING_TRIM);
        llOwnerSay(llGetSubString(llList2String(pair,1),0,800));
        if(llGetInventoryType(name)==INVENTORY_SOUND)llPlaySound(name,0.3);
        else llOwnerSay("Missing sound "+name);
    }
    timer()
    {
        request=NULL_KEY;
        llSetTimerEvent(0.0);
    }
    changed(integer change)
    {
        if(change&CHANGED_INVENTORY)
        {
            request=NULL_KEY;
            line=0;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Numbered sound sampler

Select a short inventory clip from a compact numbered menu.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed sounds to the script prim. Owner-touch shows up to nine sounds; Stop silences current attached playback.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. No original sound can be captured for restoration. Menu operations are not a private listening mode; audio is audible nearby.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list names;
init()
{
}
show()
{
    names=[];
    list buttons=["Stop"];
    string text="Sound samples:\n";
    integer i;
    integer count=llGetInventoryNumber(INVENTORY_SOUND);
    if(count>9)count=9;
    for(i=0;i<count;++i)
    {
        string name=llGetInventoryName(INVENTORY_SOUND,i);
        names+=[name];
        buttons+=[(string)(i+1)];
        text+=(string)(i+1)+": "+llGetSubString(name,0,32)+"\n";
    }
    menu(text,buttons);
}
choose(string s)
{
    if(s=="Stop")
    {
        llStopSound();
        show();
        return;
    }
    integer index=llListFindList(["1","2","3","4","5","6","7","8","9"],[s]);
    if(index<0||index>=llGetListLength(names))return;
    string name=llList2String(names,index);
    if(llGetInventoryType(name)==INVENTORY_SOUND)llPlaySound(name,0.3);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Pauseable local audio tour

Advance through a short audio tour with Play, Next, Previous and Stop controls.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add intro, detail and conclusion sounds. Owner-touch opens the controls.

Stop / restore: Choose Stop before removal. The menu itself expires after thirty seconds.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. Play restarts the selected clip; LSL does not seek into a clip or resume a paused playhead. The label makes this limitation explicit.

// Original Incoprea. MIT. Not compiled or tested in-world.
list tracks=["intro","detail","conclusion"];
integer index;
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
show()
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),"Selected: "+llList2String(tracks,index)+"\nPlay restarts the clip.",["Previous","Play","Next","Stop"],channel);
    llSetTimerEvent(30.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())
        {
            close();
            show();
        }
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        if(s=="Previous")index=(index+llGetListLength(tracks)-1)%llGetListLength(tracks);
        else if(s=="Next")index=(index+1)%llGetListLength(tracks);
        else if(s=="Stop")llStopSound();
        else if(s=="Play")
        {
            string sound=llList2String(tracks,index);
            if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.3);
            else llOwnerSay("Missing "+sound);
        }
        else return;
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Practice metronome

Play a quiet inventory tick at a configurable practice tempo.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short licensed sound named tick. Set BPM between 30 and 180. Owner-touch starts and stops.

Stop / restore: Touch to stop before removal; Stop sound in this prim can silence any remaining tick.

Simulator timers and asset loading introduce jitter. This is a practice aid, not a sample-accurate sequencer. Keep the tick shorter than the beat interval.

// Original Incoprea example. MIT. Not compiled or tested in-world.
float BPM = 60.0;
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            if (llGetInventoryType("tick") != INVENTORY_SOUND)
            {
                active = FALSE;
                llOwnerSay("Add a sound named tick.");
                return;
            }
            if (BPM < 30.0) BPM = 30.0;
            if (BPM > 180.0) BPM = 180.0;
            llSetTimerEvent(60.0 / BPM);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        if (llGetInventoryType("tick") == INVENTORY_SOUND) llPlaySound("tick", 0.2);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Press and release audio button

Use different short cues for pressing and releasing a button.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add short sounds press and release. Owner presses and releases the prim.

Stop / restore: Remove/disable; Stop sound in this prim silences a remaining clip.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Uses attached sound so the release can interrupt a long press clip.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner()&&llGetInventoryType("press")==INVENTORY_SOUND)llPlaySound("press",0.25);
    }
    touch_end(integer n)
    {
        if(llDetectedKey(0)==llGetOwner()&&llGetInventoryType("release")==INVENTORY_SOUND)llPlaySound("release",0.25);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Priority sound cue receiver

Allow a high-priority linked cue to interrupt a lower-priority cue while rejecting lower interruptions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add notice, warning and complete clips, each shorter than three seconds. Root named cue_controller sends code 8052 with those names. Owner-touch arms/disarms.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Priority is authored: notice=1, complete=2, warning=3. A three-second lock expires independently of exact clip duration.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer priority;
float until;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        priority=0;
        llStopSound();
        llSetTimerEvent(0.0);
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!armed||sender!=1||llGetLinkName(1)!="cue_controller"||code!=8052)return;
        integer p=llListFindList(["notice","complete","warning"],[s])+1;
        if(!p||llGetInventoryType(s)!=INVENTORY_SOUND)return;
        if(llGetTime()>=until)priority=0;
        if(p<priority)return;
        priority=p;
        until=llGetTime()+3.0;
        llPlaySound(s,0.2);
        llSetTimerEvent(3.0);
    }
    timer()
    {
        priority=0;
        llSetTimerEvent(0.0);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            armed=FALSE;
            priority=0;
            llStopSound();
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Randomly spaced soundscape

Play sparse authored cues at irregular quiet intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bird, leaf and bell. Owner-touch arms/stops.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Each interval is 8–20 seconds, not a rapid effect. Missing sound inventory is skipped.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
list sounds=["bird","leaf","bell"];
float due;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        due=llGetTime()+8.0;
        if(active)llSetTimerEvent(1.0);
    }
    timer()
    {
        if(active)
        {
            if(llGetTime()>=due)
            {
                string sound=llList2String(sounds,(integer)llFrand(3.0));
                if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.12);
                due=llGetTime()+8.0+llFrand(12.0);
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Rotation detent sound

Audibly mark transitions between eight horizontal heading sectors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add tick. Owner-touch arms, then rotate the object with an existing tool.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Uses root forward heading and ignores nearly vertical forward directions. At most one cue per sample.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer sector;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        sector=-1;
        if(active)llSetTimerEvent(0.25);
    }
    timer()
    {
        if(active)
        {
            vector f=llRot2Fwd(llGetRootRotation());
            if(llFabs(f.z)>0.98)return;
            integer next=(integer)llFloor((llAtan2(f.y,f.x)+PI)/(TWO_PI/8.0));
            if(next>7)next=7;
            if(sector>=0&&next!=sector&&llGetInventoryType("tick")==INVENTORY_SOUND)llPlaySound("tick",0.15);
            sector=next;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Session timeline sound cues

Schedule three named cues relative to the moment the owner starts a session.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add intro, midpoint and finish sounds. Edit TIMES and SOUNDS together; owner-touch starts/stops.

Stop / restore: Touch to stop and silence. The sequence ends automatically after its last scheduled cue.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. Uses elapsed time and skips no more than one cue per tick; closely packed or overdue clips can interrupt each other. Keep schedule gaps longer than clips.

// Original Incoprea. MIT. Not compiled or tested in-world.
list TIMES=[0.0,30.0,60.0];
list SOUNDS=["intro","midpoint","finish"];
integer active;
integer index;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            index=0;
            llResetTime();
            llSetTimerEvent(0.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        integer count=llGetListLength(TIMES);
        if(count!=llGetListLength(SOUNDS)||index>=count)
        {
            active=FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        if(llGetTime()>=llList2Float(TIMES,index))
        {
            string sound=llList2String(SOUNDS,index++);
            if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.25);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Shuffled sound collection

Play each inventory sound once in a shuffled order before stopping.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use clips shorter than GAP seconds in a dedicated sound prim. Owner-touch starts or cancels.

Stop / restore: Touch during the sequence to stop. After the final clip, Stop sound in this prim can silence it immediately.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. The sound names are shuffled once when starting; inventory changes mid-run are safely skipped.

// Original Incoprea. MIT. Not compiled or tested in-world.
float GAP=12.0;
list bag;
integer active;
next()
{
    if(!llGetListLength(bag))
    {
        active=FALSE;
        llSetTimerEvent(0.0);
        return;
    }
    string name=llList2String(bag,0);
    bag=llDeleteSubList(bag,0,0);
    if(llGetInventoryType(name)==INVENTORY_SOUND)llPlaySound(name,0.25);
    llSetTimerEvent(GAP);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llSetTimerEvent(0.0);
            llStopSound();
            return;
        }
        if(GAP<1.0)GAP=1.0;
        bag=[];
        integer i;
        for(i=0;i<llGetInventoryNumber(INVENTORY_SOUND);++i)bag+=[llGetInventoryName(INVENTORY_SOUND,i)];
        bag=llListRandomize(bag,1);
        next();
    }
    timer()
    {
        next();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Small audio listening zone

Play a short clip only within a modest camera-distance radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed sound named exhibit_sound to a dedicated audio prim. Owner-touch plays at volume 0.3 with a four-meter cutoff.

Stop / restore: Disable/remove, then Stop sound in this prim if needed. The four-meter radius remains configured; use a dedicated audio prim.

Sound-radius state cannot be read back here. Use a dedicated prim; this does not make audio private or limit recordings. It uses viewer camera distance.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetInventoryType("exhibit_sound")!=INVENTORY_SOUND)
        {
            llOwnerSay("Add exhibit_sound to this prim.");
            return;
        }
        llSetSoundRadius(4.0);
        llPlaySound("exhibit_sound",0.3);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Sound and silence interval study

Alternate a short loop interval with an equally explicit silent interval.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add ambience. Owner-touch starts ten seconds of sound then ten seconds of silence.

Stop / restore: Touch to stop and silence before removing.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. A composition/listening exercise. Sound is restarted on each sounding interval; no sample-accurate phase or musical synchronization is implied.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer sounding;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llSetTimerEvent(0.0);
            llStopSound();
            return;
        }
        if(llGetInventoryType("ambience")!=INVENTORY_SOUND)
        {
            active=FALSE;
            llOwnerSay("Add ambience.");
            return;
        }
        sounding=TRUE;
        llLoopSound("ambience",0.25);
        llSetTimerEvent(10.0);
    }
    timer()
    {
        sounding=!sounding;
        if(sounding&&llGetInventoryType("ambience")==INVENTORY_SOUND)llLoopSound("ambience",0.25);
        else llStopSound();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Sound preload station

Owner-touch requests preloading for each sound in the prim, one at a time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add only the sounds needed for your exhibit to this prim, then touch before a nearby demonstration.

Stop / restore: Touch again to cancel remaining requests. Remove when finished; it plays no sound.

Preloading is a viewer request, not a guarantee of instant playback. Each API call has a built-in delay and is spaced by a timer.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer index;
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            index = 0;
            llSetTimerEvent(1.5);
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Preload queue canceled.");
        }
    }
    timer()
    {
        if (index >= llGetInventoryNumber(INVENTORY_SOUND))
        {
            active = FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Preload requests finished.");
            return;
        }
        string sound = llGetInventoryName(INVENTORY_SOUND, index++);
        if (llGetInventoryType(sound) == INVENTORY_SOUND) llPreloadSound(sound);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Spoken digit reader

Read a short owner-entered number using ten recorded digit assets.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add short sounds named digit_0 through digit_9. Owner-touch asks for up to eight digits. Touch during speech cancels.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Not text-to-speech: all ten spoken digits are supplied inventory assets. One digit per second.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
string digits;
integer index;
integer playing;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(playing)
        {
            playing=FALSE;
            digits="";
            llStopSound();
            close();
            return;
        }
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llTextBox(llGetOwner(),"Enter 1-8 digits to hear.",channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        close();
        s=llStringTrim(s,STRING_TRIM);
        if(llStringLength(s)<1||llStringLength(s)>8)return;
        integer i;
        for(i=0;i<llStringLength(s);++i)if(llSubStringIndex("0123456789",llGetSubString(s,i,i))<0)return;
        digits=s;
        index=0;
        playing=TRUE;
        llSetTimerEvent(1.0);
    }
    timer()
    {
        if(handle)
        {
            close();
            return;
        }
        if(index>=llStringLength(digits))
        {
            playing=FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        string sound="digit_"+llGetSubString(digits,index,index);
        ++index;
        if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.25);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Spoken start countdown

Play configured three, two, one and go clips at one-second intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add very short sounds three, two, one and go. Owner-touch begins; touch again cancels.

Stop / restore: Touch while active to cancel and silence. Finished audio can be stopped with Stop sound in this prim.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. Suitable for a casual exhibit cue, not a race adjudication system. All clips must be shorter than one second.

// Original Incoprea. MIT. Not compiled or tested in-world.
list cues=["three","two","one","go"];
integer active;
integer index;
next()
{
    if(index>=4)
    {
        active=FALSE;
        llSetTimerEvent(0.0);
        return;
    }
    string sound=llList2String(cues,index++);
    if(llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.3);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            index=0;
            next();
            llSetTimerEvent(1.0);
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        next();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Beginner

Tap for a chime

Play a sound in this prim when it is touched.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a sound you have rights to use to this prim’s Contents. Replace inventory_chime with its exact inventory name.

Stop / restore: Remove or disable the script. Touching it is the only playback trigger.

Uses one sound already in the prim. Sound rights and object permissions remain your responsibility.

// Original Incoprea example. Add your own sound to this prim.
string SOUND_IN_INVENTORY = "inventory_chime";
default
{
    touch_start(integer count)
    {
        llPlaySound(SOUND_IN_INVENTORY, 0.55);
    }
}

MIT · original Incoprea example

API reference 1

Sound · Intermediate

Tap-tempo sound clock

Set an approximate metronome interval with two owner taps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short tick. First touch arms, second within 0.25–2 seconds sets tempo, third stops.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. A long gap cancels tempo capture instead of producing a very slow timer. Server event latency affects results.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer phase;
float first;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(phase==0)
        {
            phase=1;
            first=llGetTime();
            llOwnerSay("Tap again to set tempo.");
            llSetTimerEvent(3.0);
        }
        else if(phase==1)
        {
            float interval=llGetTime()-first;
            if(interval<0.25||interval>2.0)
            {
                phase=0;
                llSetTimerEvent(0.0);
                llOwnerSay("Use a quarter to two seconds between taps.");
                return;
            }
            phase=2;
            llSetTimerEvent(interval);
            llOwnerSay("Approximate BPM "+(string)(60.0/interval));
        }
        else
        {
            phase=0;
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        if(phase==1)
        {
            phase=0;
            llSetTimerEvent(0.0);
        }
        else if(phase==2&&llGetInventoryType("tick")==INVENTORY_SOUND)llPlaySound("tick",0.15);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Timed audio envelope

Fade a loop in, sustain it briefly, then fade out and stop.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bed. Owner-touch starts a fifteen-second envelope or cancels.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Three-second attack, nine-second sustain, three-second release. Not a music compressor or limiter.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
float began;
stop()
{
    active=FALSE;
    llSetTimerEvent(0.0);
    llStopSound();
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        active=TRUE;
        if(llGetInventoryType("bed")!=INVENTORY_SOUND)
        {
            stop();
            return;
        }
        began=llGetTime();
        llLoopSound("bed",0.0);
        if(active)llSetTimerEvent(0.5);
    }
    timer()
    {
        if(active)
        {
            float t=llGetTime()-began;
            if(t>=15.0)
            {
                stop();
                return;
            }
            float gain=0.25;
            if(t<3.0)gain*=t/3.0;
            else if(t>12.0)gain*=(15.0-t)/3.0;
            llAdjustSoundVolume(gain);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Sound · Intermediate

Timed inventory playlist

Play an ordered list of short sounds with a specified duration for each.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add sounds first, second and third; edit TRACKS as alternating sound name and seconds. Owner-touch starts or stops.

Stop / restore: Touch to stop and silence the current attached sound before removing.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. Duration is supplied by you; the script does not detect clip length.

// Original Incoprea. MIT. Not compiled or tested in-world.
list TRACKS=["first",4.0,"second",5.0,"third",3.0];
integer index;
integer active;
next()
{
    if(index>=llGetListLength(TRACKS))
    {
        active=FALSE;
        llSetTimerEvent(0.0);
        return;
    }
    string name=llList2String(TRACKS,index);
    float seconds=llList2Float(TRACKS,index+1);
    index+=2;
    if(seconds<1.0)seconds=1.0;
    if(llGetInventoryType(name)==INVENTORY_SOUND)llPlaySound(name,0.3);
    else llOwnerSay("Missing sound: "+name);
    llSetTimerEvent(seconds);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(active)
        {
            index=0;
            next();
        }
        else
        {
            llSetTimerEvent(0.0);
            llStopSound();
        }
    }
    timer()
    {
        next();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Touch-strip loop volume

Control a loop’s loudness using the horizontal touch position on one face.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add ambience and set FACE to a flat panel face. Owner-touch starts the loop at a level from 0 to 0.4; drag to adjust.

Stop / restore: Touch within the leftmost five percent to stop before removing.

Use licensed sounds in the exact prim containing the script. Playback is audible nearby. Asset loading and simulator timers can introduce delays; these are exhibit cues, not sample-accurate audio. The left edge is a stop zone. Uses ST surface coordinates, not transformed UV.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
integer playing;
float last;
setVolume()
{
    if(llDetectedKey(0)!=llGetOwner()||llDetectedTouchFace(0)!=FACE)return;
    vector st=llDetectedTouchST(0);
    if(st.x<0.0||st.x>1.0)return;
    if(st.x<0.05)
    {
        llStopSound();
        playing=FALSE;
        return;
    }
    if(llGetInventoryType("ambience")!=INVENTORY_SOUND)return;
    float v=st.x*0.4;
    if(!playing)
    {
        llLoopSound("ambience",v);
        playing=TRUE;
        last=v;
    }
    else if(llFabs(last-v)>0.02)
    {
        last=v;
        llAdjustSoundVolume(v);
    }
}
default
{
    touch_start(integer n)
    {
        setVolume();
    }
    touch(integer n)
    {
        setVolume();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Two-source crossfade controller

Blend two linked ambient sources with an owner-controlled touch strip.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name root audio_mixer and put this script there. Pair with Crossfade source receiver in two children named audio_a and audio_b; set FACE.

Stop / restore: Hold the root for at least two seconds to send Stop to both sources. Then remove if finished.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. A short touch sets an A/B mix; a held touch sends Stop. Receiver sound assets belong in their own prims.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
float pressed;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())pressed=llGetTime();
    }
    touch_end(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        if(llGetTime()-pressed>=2.0)
        {
            llMessageLinked(LINK_ALL_CHILDREN,7910,"stop",NULL_KEY);
            return;
        }
        if(llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.x>1.0)return;
        llMessageLinked(LINK_ALL_CHILDREN,7910,(string)st.x,NULL_KEY);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sound · Intermediate

Velocity-responsive sound loop

Modulate a loop’s volume from the object’s measured speed without changing pitch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed engine loop. Owner-touch arms; move the object using its existing mechanism.

Stop / restore: Touch to stop the loop before removal.

Use licensed inventory sounds in the specified prim. Audio is nearby, not private. Simulator timers and viewer loading are approximate. Reads the object, not visitors. Volume ranges 0–0.35 and reaches maximum at 5 m/s; it does not change pitch, propulsion or physics.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
float previous;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            llSetTimerEvent(0.0);
            llStopSound();
            return;
        }
        if(llGetInventoryType("engine")!=INVENTORY_SOUND)
        {
            llOwnerSay("Add engine loop.");
            return;
        }
        active=TRUE;
        previous=0.0;
        llLoopSound("engine",0.0);
        llSetTimerEvent(0.5);
    }
    timer()
    {
        float volume=llVecMag(llGetVel())*0.07;
        if(volume>0.35)volume=0.35;
        if(llFabs(volume-previous)>0.01)
        {
            previous=volume;
            llAdjustSoundVolume(volume);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sound · Intermediate

Watchdog-protected loop receiver

Run an armed loop only while a named linked controller renews its lease.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add bed in child. Root named sound_driver sends code 8051 and alive every two seconds. Owner-touch arms/disarms.

Stop / restore: Owner-touch the script prim to stop an active session before removing or resetting it. Loop state can survive script removal; use Stop sound in this prim if necessary.

Use licensed sounds in this prim. Audio is nearby, not private. Timer timing and asset loading are approximate; no sample synchronization is promised. Five seconds without a valid root heartbeat stops sound but leaves receiver armed. This is local coordination, not authenticated remote control.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer playing;
float until;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        playing=FALSE;
        llStopSound();
        llSetTimerEvent(0.0);
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!armed||sender!=1||llGetLinkName(1)!="sound_driver"||code!=8051||s!="alive")return;
        if(llGetInventoryType("bed")!=INVENTORY_SOUND)return;
        until=llGetTime()+5.0;
        if(!playing)
        {
            playing=TRUE;
            llLoopSound("bed",0.2);
        }
        llSetTimerEvent(1.0);
    }
    timer()
    {
        if(llGetTime()>=until)
        {
            playing=FALSE;
            llStopSound();
            llSetTimerEvent(0.0);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            armed=FALSE;
            playing=FALSE;
            llStopSound();
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

ParticlesSmall atmospheric effects and particle systems.20 scripts

Download this category (.zip)

Particles · Intermediate

Flat particle fan

Emit particles across a two-dimensional angular fan instead of a cone.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim; rotate the prim to orient the fan plane. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. ANGLE uses a planar spread. Particle sprites themselves normally face the camera; the fan is a distribution of positions.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_ANGLE,PSYS_SRC_ANGLE_BEGIN,0.0,PSYS_SRC_ANGLE_END,1.0,
        PSYS_PART_START_COLOR,<0.6,1.0,0.8>,PSYS_PART_END_COLOR,<0.6,1.0,0.8>,PSYS_PART_START_ALPHA,0.7,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.04,0.04,0.0>,PSYS_PART_MAX_AGE,2.0,PSYS_SRC_BURST_RATE,0.25,PSYS_SRC_BURST_PART_COUNT,2,
        PSYS_SRC_BURST_SPEED_MIN,0.5,PSYS_SRC_BURST_SPEED_MAX,0.6]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Inventory icon particle preview

Preview a licensed icon texture as a slowly rising particle sprite.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a transparent-background texture named particle_icon to this exact prim. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. This previews your asset as a particle, not as a prim face. Transparent padding changes apparent sprite size and texture rights still apply.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(!active&&llGetInventoryType("particle_icon")!=INVENTORY_TEXTURE)
        {
            llOwnerSay("Add particle_icon texture.");
            return;
        }
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_COLOR_MASK|PSYS_PART_INTERP_SCALE_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_ANGLE_CONE,PSYS_SRC_TEXTURE,"particle_icon",
        PSYS_SRC_ANGLE_BEGIN,0.0,PSYS_SRC_ANGLE_END,0.0,PSYS_PART_START_COLOR,<1.0,1.0,1.0>,PSYS_PART_END_COLOR,<1.0,1.0,1.0>,
        PSYS_PART_START_ALPHA,0.9,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.15,0.15,0.0>,PSYS_PART_END_SCALE,<0.3,0.3,0.0>,
        PSYS_PART_MAX_AGE,3.0,PSYS_SRC_BURST_RATE,1.0,PSYS_SRC_BURST_PART_COUNT,1,PSYS_SRC_BURST_SPEED_MIN,0.15,PSYS_SRC_BURST_SPEED_MAX,0.15]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Linked energy tether

Send a sparse stream of particles from a child prim toward its own root.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a linked object with a visible gap between a child and root. Put this script in the child; owner-touch toggles.

Stop / restore: Touch to clear before removal. Relinking automatically stops the emitter.

Targets only this object’s root, never an avatar. Particle paths are visual and may vary by viewer; prior particle settings are replaced.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() < 2) return;
        active = !active;
        if (!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_TARGET_POS_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_EMISSIVE_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP,
        PSYS_SRC_TARGET_KEY, llGetLinkKey(1),
        PSYS_PART_START_COLOR, <0.4, 1.0, 0.7>, PSYS_PART_END_COLOR, <0.2, 0.6, 1.0>,
        PSYS_PART_START_ALPHA, 0.7, PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.06, 0.06, 0.0>,
        PSYS_PART_MAX_AGE, 1.5, PSYS_SRC_BURST_RATE, 0.25,
        PSYS_SRC_BURST_PART_COUNT, 1
        ]);
    }
    changed(integer change)
    {
        if (change & CHANGED_LINK)
        {
            llParticleSystem([]);
            active = FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Particles · Intermediate

Linked operation acknowledgment pulse

Show one brief success or failure pulse for an explicitly armed linked operation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Root named job_controller sends code 8053 and success or failure. Owner-touch arms/disarms this particle-free child.

Stop / restore: Owner-touch or choose Off as described; let finite pulses expire. Clear particles before removal. These examples cannot recover a pre-existing particle system.

Use an otherwise particle-free prim. Particle systems persist independently of scripts. This is an indicator only; it does not know whether a job actually succeeded. Rate-limited to one pulse per second.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float next;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        llParticleSystem([]);
        llSetTimerEvent(0.0);
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!armed||sender!=1||llGetLinkName(1)!="job_controller"||code!=8053||llGetTime()<next)return;
        vector color;
        if(s=="success")color=<0.2,1.0,0.3>;
        else if(s=="failure")color=<1.0,0.3,0.2>;
        else return;
        next=llGetTime()+1.0;
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_EMISSIVE_MASK|PSYS_PART_INTERP_COLOR_MASK,PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,PSYS_PART_START_COLOR,color,PSYS_PART_START_ALPHA,0.8,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.06,0.06,0.0>,PSYS_PART_MAX_AGE,0.7,PSYS_SRC_BURST_PART_COUNT,3,PSYS_SRC_BURST_SPEED_MIN,0.1,PSYS_SRC_BURST_SPEED_MAX,0.3,PSYS_SRC_MAX_AGE,0.1]);
        llSetTimerEvent(1.0);
    }
    timer()
    {
        llParticleSystem([]);
        llSetTimerEvent(0.0);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            armed=FALSE;
            llParticleSystem([]);
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Miniature rain cloud

Create a small downward shower beneath a decorative cloud.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare emitter above a miniature scene. Owner-touch toggles. Acceleration is world-down, regardless of prim rotation.

Stop / restore: Touch to stop; remaining drops disappear after two seconds.

A compact rain effect, not region weather. Uses eight particles per second and replaces prior particle settings.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE,
        PSYS_SRC_BURST_RADIUS, 0.3,
        PSYS_PART_START_COLOR, <0.6, 0.75, 0.9>, PSYS_PART_END_COLOR, <0.6, 0.75, 0.9>,
        PSYS_PART_START_ALPHA, 0.5, PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.025, 0.12, 0.0>, PSYS_PART_MAX_AGE, 2.0,
        PSYS_SRC_BURST_RATE, 0.25, PSYS_SRC_BURST_PART_COUNT, 2,
        PSYS_SRC_BURST_SPEED_MIN, 0.0, PSYS_SRC_BURST_SPEED_MAX, 0.05,
        PSYS_SRC_ACCEL, <0.0, 0.0, -1.0>
        ]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Movement-gated particle trail

Emit small world-space dots only while this object is moving.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare particle-free prim. Owner-touch arms; touch again clears.

Stop / restore: Owner-touch or choose Off as described; let finite pulses expire. Clear particles before removal. These examples cannot recover a pre-existing particle system.

Use an otherwise particle-free prim. Particle systems persist independently of scripts. Samples object speed, not avatars. Dots remain briefly in world space because FOLLOW_SRC is not set.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer emitting;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        emitting=FALSE;
        llParticleSystem([]);
        if(armed)llSetTimerEvent(0.5);
        else llSetTimerEvent(0.0);
    }
    timer()
    {
        integer moving=llVecMag(llGetVel())>0.2;
        if(moving==emitting)return;
        emitting=moving;
        if(moving)llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_EMISSIVE_MASK,PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_DROP,PSYS_PART_START_COLOR,<0.5,1.0,0.6>,PSYS_PART_START_SCALE,<0.04,0.04,0.0>,PSYS_PART_MAX_AGE,2.0,PSYS_SRC_BURST_RATE,0.2,PSYS_SRC_BURST_PART_COUNT,1]);
        else llParticleSystem([]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Owned-object collision pulse

Make a small brief particle pulse when an owned non-avatar object collides.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use an already suitable collision-enabled root in a clear test area. Owner-touch arms/disarms.

Stop / restore: Owner-touch or choose Off as described; let finite pulses expire. Clear particles before removal. These examples cannot recover a pre-existing particle system.

Use an otherwise particle-free prim. Particle systems persist independently of scripts. Does not enable physics. Ignores avatar contacts and objects not owned by you; uses a two-second cooldown.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float next;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        llParticleSystem([]);
        llSetTimerEvent(0.0);
    }
    collision_start(integer n)
    {
        if(!armed||llGetTime()<next)return;
        integer i;
        integer found;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())found=TRUE;
        if(!found)return;
        next=llGetTime()+2.0;
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_SCALE_MASK|PSYS_PART_INTERP_COLOR_MASK,PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,PSYS_PART_START_COLOR,<1.0,0.8,0.2>,PSYS_PART_START_ALPHA,0.8,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.05,0.05,0.0>,PSYS_PART_END_SCALE,<0.01,0.01,0.0>,PSYS_PART_MAX_AGE,0.8,PSYS_SRC_BURST_RATE,0.1,PSYS_SRC_BURST_PART_COUNT,4,PSYS_SRC_BURST_SPEED_MIN,0.1,PSYS_SRC_BURST_SPEED_MAX,0.3,PSYS_SRC_MAX_AGE,0.1]);
        llSetTimerEvent(1.0);
    }
    timer()
    {
        llParticleSystem([]);
        llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Particle bounce-plane demonstration

Demonstrate the special particle bounce plane at the emitter’s world height.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare prim at the desired bounce height with local Z upward. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. Bounce is against an invisible horizontal plane at source height, not the terrain or nearby objects. Keep the emitter stationary while comparing.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_BOUNCE_MASK|PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_ANGLE_CONE,PSYS_SRC_ANGLE_BEGIN,0.0,PSYS_SRC_ANGLE_END,0.3,
        PSYS_PART_START_COLOR,<1.0,0.7,0.4>,PSYS_PART_END_COLOR,<1.0,0.7,0.4>,PSYS_PART_START_ALPHA,0.8,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.08,0.08,0.0>,PSYS_PART_MAX_AGE,4.0,PSYS_SRC_BURST_RATE,0.4,PSYS_SRC_BURST_PART_COUNT,1,
        PSYS_SRC_BURST_SPEED_MIN,1.2,PSYS_SRC_BURST_SPEED_MAX,1.5,PSYS_SRC_ACCEL,<0.0,0.0,-2.0>]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Particle budget comparison menu

Compare restrained low and medium emission budgets in the same system.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a particle-free prim. Owner-touch selects Low, Medium or Off. Effects automatically end after thirty seconds.

Stop / restore: Owner-touch or choose Off as described; let finite pulses expire. Clear particles before removal. These examples cannot recover a pre-existing particle system.

Use an otherwise particle-free prim. Particle systems persist independently of scripts. Demonstrates birth rate versus particle lifetime; viewer budgets may suppress particles. It does not change viewer preferences.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llParticleSystem([]);
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llDialog(llGetOwner(),"Compare particle birth rate",["Low","Medium","Off"],channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        if(s=="Off")
        {
            close();
            return;
        }
        integer count;
        if(s=="Low")count=1;
        else if(s=="Medium")count=3;
        else return;
        llParticleSystem([PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,PSYS_PART_START_COLOR,<0.4,0.8,1.0>,PSYS_PART_START_SCALE,<0.05,0.05,0.0>,PSYS_PART_MAX_AGE,1.0,PSYS_SRC_BURST_RATE,0.25,PSYS_SRC_BURST_PART_COUNT,count,PSYS_SRC_BURST_SPEED_MIN,0.1,PSYS_SRC_BURST_SPEED_MAX,0.2,PSYS_SRC_MAX_AGE,30.0]);
        llSetTimerEvent(30.0);
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Particle shell boundary

Visualize a small spherical emission boundary using burst radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim with half a meter of clear space. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. Burst radius shifts where particles begin; it does not make a solid sphere. The points are sparse samples, not a measured collision boundary.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,PSYS_SRC_BURST_RADIUS,0.5,
        PSYS_PART_START_COLOR,<0.8,0.7,1.0>,PSYS_PART_END_COLOR,<0.8,0.7,1.0>,PSYS_PART_START_ALPHA,0.6,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.04,0.04,0.0>,PSYS_PART_MAX_AGE,3.0,PSYS_SRC_BURST_RATE,0.25,PSYS_SRC_BURST_PART_COUNT,2,
        PSYS_SRC_BURST_SPEED_MIN,0.0,PSYS_SRC_BURST_SPEED_MAX,0.0]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Rotating particle nozzle

Rotate the particle emitter direction while the prim itself remains still.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a stationary nozzle prop, with room for a one-meter effect. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. PSYS_SRC_OMEGA is a viewer-side emitter rotation, not prim rotation. Viewers may start its orientation at different times.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_ANGLE_CONE,PSYS_SRC_ANGLE_BEGIN,0.0,PSYS_SRC_ANGLE_END,0.06,
        PSYS_SRC_OMEGA,<0.0,0.5,0.0>,PSYS_PART_START_COLOR,<0.7,0.8,1.0>,PSYS_PART_END_COLOR,<0.7,0.8,1.0>,
        PSYS_PART_START_ALPHA,0.7,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.05,0.05,0.0>,PSYS_PART_MAX_AGE,1.5,
        PSYS_SRC_BURST_RATE,0.2,PSYS_SRC_BURST_PART_COUNT,1,PSYS_SRC_BURST_SPEED_MIN,0.7,PSYS_SRC_BURST_SPEED_MAX,0.7]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Short ribbon tracer

Join emitted particles into a short ribbon while the prim moves.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Activate a spare prim, then move it slowly in Edit. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. Ribbon support depends on viewer and grid implementation. Y scale remains set for visibility calculations. No automatic attachment or movement occurs.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_RIBBON_MASK|PSYS_PART_INTERP_COLOR_MASK|PSYS_PART_INTERP_SCALE_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_DROP,PSYS_SRC_TEXTURE,TEXTURE_BLANK,
        PSYS_PART_START_COLOR,<0.4,0.9,0.8>,PSYS_PART_END_COLOR,<0.7,0.6,1.0>,PSYS_PART_START_ALPHA,0.6,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.08,0.08,0.0>,PSYS_PART_END_SCALE,<0.01,0.08,0.0>,PSYS_PART_MAX_AGE,2.0,
        PSYS_SRC_BURST_RATE,0.1,PSYS_SRC_BURST_PART_COUNT,1,PSYS_SRC_ACCEL,<0.0,0.0,0.01>]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Slow teacup steam

A sparse, slowly expanding plume for a miniature cup or vent.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare emitter at the cup surface, local Z upward. Owner-touch toggles. Optionally add your own soft particle texture to the rules.

Stop / restore: Touch to stop before removing; existing particles fade within four seconds.

Default particles are abstract, not photorealistic steam. Two particles per second; no heat, physics, or saved prior emitter settings.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
        PSYS_SRC_ANGLE_BEGIN, 0.0, PSYS_SRC_ANGLE_END, 0.1,
        PSYS_PART_START_COLOR, <0.9, 0.9, 0.9>, PSYS_PART_END_COLOR, <1.0, 1.0, 1.0>,
        PSYS_PART_START_ALPHA, 0.15, PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.04, 0.04, 0.0>, PSYS_PART_END_SCALE, <0.3, 0.3, 0.0>,
        PSYS_PART_MAX_AGE, 4.0, PSYS_SRC_BURST_RATE, 0.5,
        PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_SPEED_MIN, 0.08,
        PSYS_SRC_BURST_SPEED_MAX, 0.14, PSYS_SRC_ACCEL, <0.02, 0.0, 0.03>
        ]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Small celebration burst

Owner-touch releases a short, low-count confetti burst that clears itself.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare emitter prim with local Z upward. Touch once and wait for the burst to finish.

Stop / restore: The emitter clears after half a second; emitted particles fade after three seconds. Stop particle effect also clears it.

Default particles are abstract flecks. This replaces prior emitter settings and creates no inventory objects.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer busy;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || busy) return;
        busy = TRUE;
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
        PSYS_SRC_ANGLE_BEGIN, 0.0, PSYS_SRC_ANGLE_END, 0.8,
        PSYS_PART_START_COLOR, <1.0, 0.5, 0.1>, PSYS_PART_END_COLOR, <0.4, 0.8, 1.0>,
        PSYS_PART_START_ALPHA, 0.9, PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.08, 0.04, 0.0>, PSYS_PART_END_SCALE, <0.04, 0.02, 0.0>,
        PSYS_PART_MAX_AGE, 3.0, PSYS_SRC_MAX_AGE, 0.4,
        PSYS_SRC_BURST_RATE, 0.1, PSYS_SRC_BURST_PART_COUNT, 4,
        PSYS_SRC_BURST_SPEED_MIN, 1.0, PSYS_SRC_BURST_SPEED_MAX, 2.0,
        PSYS_SRC_ACCEL, <0.0, 0.0, -1.5>
        ]);
        llSetTimerEvent(0.5);
    }
    timer()
    {
        llParticleSystem([]);
        llSetTimerEvent(0.0);
        busy = FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Source-following particle cloud

Show how particles can remain relative to a moving emitter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare nonphysical prim; activate, then gently move the prim in Edit. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. FOLLOW_SRC makes particles translate with the source. This does not animate the prim or turn it physical.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_FOLLOW_SRC_MASK|PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,PSYS_PART_START_COLOR,<0.6,0.8,1.0>,PSYS_PART_END_COLOR,<0.6,0.8,1.0>,
        PSYS_PART_START_ALPHA,0.4,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.12,0.12,0.0>,PSYS_PART_MAX_AGE,3.0,
        PSYS_SRC_BURST_RATE,0.25,PSYS_SRC_BURST_PART_COUNT,1,PSYS_SRC_BURST_SPEED_MIN,0.08,PSYS_SRC_BURST_SPEED_MAX,0.15]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Straight linked transfer stream

Send evenly spaced particles directly from a child toward its root.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child offset from its root. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. TARGET_LINEAR ignores the non-DROP trajectory controls and acceleration. Targets only this linkset root, never a visitor.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetLinkNumber()<2)return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_TARGET_LINEAR_MASK|PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_DROP,PSYS_SRC_TARGET_KEY,llGetLinkKey(1),
        PSYS_PART_START_COLOR,<0.5,1.0,0.8>,PSYS_PART_END_COLOR,<0.5,1.0,0.8>,PSYS_PART_START_ALPHA,0.7,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.05,0.05,0.0>,PSYS_PART_MAX_AGE,1.5,PSYS_SRC_BURST_RATE,0.2,PSYS_SRC_BURST_PART_COUNT,1]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

Tabletop particle fountain

A small upward spray with gravity pulling the droplets into an arc.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare emitter prim with local Z pointing upward. Owner-touch toggles. Uses the default particle texture and does not require a water asset.

Stop / restore: Touch to clear the emitter before removing. Stop particle effect can clear a stranded emitter.

Viewer-only droplets do not collide or make water. Uses about ten particles per second. Prior particle settings are not saved.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
        PSYS_SRC_ANGLE_BEGIN, 0.0, PSYS_SRC_ANGLE_END, 0.18,
        PSYS_PART_START_COLOR, <0.5, 0.8, 1.0>, PSYS_PART_END_COLOR, <0.8, 0.95, 1.0>,
        PSYS_PART_START_ALPHA, 0.7, PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.06, 0.06, 0.0>, PSYS_PART_END_SCALE, <0.02, 0.02, 0.0>,
        PSYS_PART_MAX_AGE, 1.8, PSYS_SRC_BURST_RATE, 0.2,
        PSYS_SRC_BURST_PART_COUNT, 2, PSYS_SRC_BURST_SPEED_MIN, 2.0,
        PSYS_SRC_BURST_SPEED_MAX, 2.5, PSYS_SRC_ACCEL, <0.0, 0.0, -3.0>
        ]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Touch-selected linked particle target

Select a child destination by touching it, then show a short stream from the root.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root of a spare particle-free linkset. Owner-touch a child selects it; root-touch clears particles.

Stop / restore: Owner-touch or choose Off as described; let finite pulses expire. Clear particles before removal. These examples cannot recover a pre-existing particle system.

Use an otherwise particle-free prim. Particle systems persist independently of scripts. Particles are viewer effects, not moved inventory or transported material.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        integer target=llDetectedLinkNumber(0);
        if(target<2)
        {
            llParticleSystem([]);
            llSetTimerEvent(0.0);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_EMISSIVE_MASK|PSYS_PART_TARGET_POS_MASK,PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_DROP,PSYS_SRC_TARGET_KEY,llGetLinkKey(target),PSYS_PART_START_COLOR,<0.3,0.8,1.0>,PSYS_PART_START_SCALE,<0.05,0.05,0.0>,PSYS_PART_MAX_AGE,1.5,PSYS_SRC_BURST_RATE,0.15,PSYS_SRC_BURST_PART_COUNT,1,PSYS_SRC_MAX_AGE,3.0]);
        llSetTimerEvent(4.0);
    }
    timer()
    {
        llParticleSystem([]);
        llSetTimerEvent(0.0);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            llParticleSystem([]);
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Particles · Intermediate

Windborne seed emitter

Let simulator wind carry a sparse stream of seed-like particles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a small stationary seed-head prop, local Z upward. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. Wind behavior varies by region and height; this illustrates wind influence rather than real botany.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_WIND_MASK|PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_ANGLE_CONE,PSYS_SRC_ANGLE_BEGIN,0.0,PSYS_SRC_ANGLE_END,0.4,
        PSYS_PART_START_COLOR,<0.85,0.9,0.6>,PSYS_PART_END_COLOR,<0.85,0.9,0.6>,PSYS_PART_START_ALPHA,0.7,PSYS_PART_END_ALPHA,0.0,
        PSYS_PART_START_SCALE,<0.06,0.06,0.0>,PSYS_PART_MAX_AGE,6.0,PSYS_SRC_BURST_RATE,0.5,PSYS_SRC_BURST_PART_COUNT,1,
        PSYS_SRC_BURST_SPEED_MIN,0.1,PSYS_SRC_BURST_SPEED_MAX,0.3]);
    }
}

MIT · original Incoprea example

API reference 1

Particles · Intermediate

World-space trace dots

Leave a short-lived dotted trace while you move an emitter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a small prim and move it gently in Edit after activation. Owner-touch toggles the emitter.

Stop / restore: Touch to clear the emitter before removing. Existing particles fade according to their lifetime; use Stop particle effect if the starter was removed early.

Viewer-only particles do not provide collision geometry. Uses a sparse emission rate and replaces any previous emitter settings. Without FOLLOW_SRC, already-emitted particles remain behind. No path is stored, exported, or associated with an avatar.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        if(!active)
        {
            llParticleSystem([]);
            return;
        }
        llParticleSystem([PSYS_PART_FLAGS,PSYS_PART_INTERP_COLOR_MASK|PSYS_PART_EMISSIVE_MASK,
        PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_DROP,PSYS_PART_START_COLOR,<1.0,0.8,0.3>,PSYS_PART_END_COLOR,<1.0,0.8,0.3>,
        PSYS_PART_START_ALPHA,0.7,PSYS_PART_END_ALPHA,0.0,PSYS_PART_START_SCALE,<0.06,0.06,0.0>,
        PSYS_PART_MAX_AGE,4.0,PSYS_SRC_BURST_RATE,0.15,PSYS_SRC_BURST_PART_COUNT,1]);
    }
}

MIT · original Incoprea example

API reference 1

Play & communicate 4 categories
Text & signsLabels, clocks, displays, and readable information.34 scripts

Download this category (.zip)

Text & signs · Intermediate

Caption language selector

Switch a short exhibit caption between three authored languages.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the English, Spanish and French texts in captions. Owner-touch selects language; Restore reinstates prior hover text.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Translations are supplied in the script, not generated online. Text is public hover text and should stay concise.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list captions=["A small garden of possible worlds.","Un pequeño jardín de mundos posibles.","Un petit jardin de mondes possibles."];
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
}
show()
{
    menu("Exhibit caption",["English","Español","Français","Restore"]);
}
choose(string s)
{
    if(s=="Restore")llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    else
    {
        integer i=llListFindList(["English","Español","Français"],[s]);
        if(i<0)return;
        llSetText(llList2String(captions,i),<0.9,0.95,1.0>,1.0);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Contents stock overview sign

Show counts of objects, textures, sounds, and notecards in this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a display prim with assets you are comfortable summarizing publicly.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

Counts inventory entries, not quantities inside objects and not sales stock. No assets are given or sold. Refreshes when Contents change.

// Original Incoprea example. MIT.
show()
{
    llSetText("Contents overview\nObjects: "+(string)llGetInventoryNumber(INVENTORY_OBJECT)+"\nTextures: "+(string)llGetInventoryNumber(INVENTORY_TEXTURE)+"\nSounds: "+(string)llGetInventoryNumber(INVENTORY_SOUND)+"\nNotecards: "+(string)llGetInventoryNumber(INVENTORY_NOTECARD),<0.8,0.9,1>,1);
}
default
{
    state_entry()
    {
        show();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)
        {
            llResetScript();
            return;
        }
        if(flags & CHANGED_INVENTORY)show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Beginner

Current UTC weekday

Report today’s UTC weekday from the Unix day number.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. No timezone configuration is needed because the report uses UTC.

Stop / restore: Remove or disable the script. It does not change the build.

Unix day zero was a Thursday. This calculation is for nonnegative Unix timestamps; it is not a historical calendar or local-time converter.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
        integer dayNumber = llGetUnixTime() / 86400;
        integer weekday = (dayNumber + 4) % 7;
        llOwnerSay("UTC " + llGetDate() + ": " + llList2String(days, weekday));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Beginner

Deadline countdown

Count down to a configured Unix timestamp, or demonstrate a fifteen-minute countdown.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set DEADLINE to an event’s Unix UTC timestamp. Leave it at zero for a fifteen-minute demo from each script reset.

Stop / restore: Disable or remove, then clear floating text. Reset restarts the demo but does not change a fixed deadline.

This is a sign, not a precise scheduler. Timer delivery can be late. Unix time uses a signed integer in classic LSL.

// Original Incoprea example. MIT.
integer DEADLINE = 0;
integer target;
show()
{
    integer remaining = target - llGetUnixTime();
    if (remaining <= 0)
    {
        llSetText("The time has arrived.", <0.8, 1.0, 0.7>, 1.0);
        llSetTimerEvent(0.0);
        return;
    }
    integer hours = remaining / 3600;
    integer minutes = (remaining % 3600) / 60;
    integer seconds = remaining % 60;
    llSetText((string)hours + "h " + (string)minutes + "m " + (string)seconds + "s remaining",
    <0.8, 1.0, 0.7>, 1.0);
}
default
{
    state_entry()
    {
        target = DEADLINE;
        if (target == 0) target = llGetUnixTime() + 900;
        llSetTimerEvent(1.0);
        show();
    }
    timer()
    {
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Beginner

Description becomes a label

Use the prim’s Description field as simple editable label content.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set the prim Description in Edit, add this script, and touch as owner after changing the Description.

Stop / restore: Disable or remove, then clear floating text. The Description field itself is never changed.

Other scripts may also use Description as configuration. The label is public and changes only on startup or owner touch.

// Original Incoprea example. MIT.
refresh()
{
    llSetText(llGetObjectDesc(), <0.8, 0.9, 1.0>, 1.0);
}
default
{
    state_entry()
    {
        refresh();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) == llGetOwner()) refresh();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Eight-bit linked lamp bank

Show an integer as eight physical indicator tints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name children bit0 to bit7, least-significant bit first. Owner-touch root arms; root script sends code8061 with integer0–255.

Stop / restore: Owner-touch disarms and restores face0 tints.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Uses fixed decimal validation; leading zeros are rejected to avoid ambiguous formatting.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        for(i=0;i<8;++i)
        {
            integer j;
            integer found;
            integer count;
            for(j=2;j<=llGetObjectPrimCount(llGetKey());++j)if(llGetLinkName(j)=="bit"+(string)i)
            {
                found=j;
                ++count;
            }
            if(count!=1)
            {
                valid=FALSE;
                return;
            }
            links+=[found];
            saved+=llGetLinkPrimitiveParams(found,[PRIM_COLOR,0]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        active=!active;
        if(!active)
        {
            integer i;
            for(i=0;i<8;++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_COLOR,0]+llList2List(saved,i*2,i*2+1));
        }
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||!valid||sender!=1||code!=8061)return;
        integer value=(integer)s;
        if(value<0||value>255||(string)value!=s)return;
        integer i;
        for(i=0;i<8;++i)
        {
            vector color=<0.03,0.03,0.03>;
            if(value&(1<<i))color=<0.1,0.8,1.0>;
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_COLOR,0,color,llList2Float(saved,i*2+1)]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Eight-character physical sign

Distribute a short word across eight separately positioned child labels.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name children char1 through char8. Root owner-touch arms; root script sends code8065 with up to8 basic ASCII characters.

Stop / restore: Owner-touch restores all original child labels.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Uses hover labels, not texture glyphs. Author child positions to set visual letter spacing; missing characters become blank.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        for(i=1;i<=8;++i)
        {
            integer j;
            integer found;
            integer count;
            for(j=2;j<=llGetObjectPrimCount(llGetKey());++j)if(llGetLinkName(j)=="char"+(string)i)
            {
                found=j;
                ++count;
            }
            if(count!=1)
            {
                valid=FALSE;
                return;
            }
            links+=[found];
            saved+=llGetLinkPrimitiveParams(found,[PRIM_TEXT]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        active=!active;
        if(!active)
        {
            integer i;
            for(i=0;i<8;++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXT]+llList2List(saved,i*3,i*3+2));
        }
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||!valid||sender!=1||code!=8065||llStringLength(s)>8)return;
        integer i;
        for(i=0;i<llStringLength(s);++i)if(llSubStringIndex("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 .!?-",llGetSubString(s,i,i))<0)return;
        for(i=0;i<8;++i)
        {
            string ch="";
            if(i<llStringLength(s))ch=llGetSubString(s,i,i);
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXT,ch,<1.0,1.0,1.0>,1.0]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            active=FALSE;
            valid=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Exhibit chapter controller

Read a small exhibit narrative one chapter at a time with next/previous controls.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit CHAPTERS. Owner-touch opens navigation; Restore recovers original hover text.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. The complete text is local and public once displayed. Keep chapters short enough for useful hover text.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list CHAPTERS=["1. A quiet seed\nEvery workshop begins with a question.","2. A small mechanism\nTry one moving part at a time.","3. An open door\nShare what worked, and what still needs testing."];
integer chapter;
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
}
show()
{
    menu("Exhibit chapter "+(string)(chapter+1),["Previous","Next","Display","Restore"]);
}
choose(string s)
{
    integer n=llGetListLength(CHAPTERS);
    if(!n)return;
    if(s=="Restore")
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
        show();
        return;
    }
    if(s=="Next")chapter=(chapter+1)%n;
    else if(s=="Previous")chapter=(chapter+n-1)%n;
    else if(s!="Display")return;
    llSetText(llList2String(CHAPTERS,chapter),<0.9,0.9,0.75>,1.0);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Beginner

Floating text label

Add a readable label above a prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim to label. Replace Welcome with your text; RGB values run from 0 to 1.

Stop / restore: Run Clear floating text in the same prim. Deleting the label script alone does not clear the stored text.

Hover text is public. Do not put secrets in it.

// Original Incoprea example. MIT.
default
{
    state_entry()
    {
        llSetText("Welcome", <0.65, 1.0, 0.85>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1

Text & signs · Intermediate

Label actual dial component bearings

Temporarily label named dial components with their measured root-local center bearings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name up to16 children dial_tick, with centers offset from root. Root owner-touch labels/restores.

Stop / restore: Touch again to restore labels before removal.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Uses position bearing, not the child rotation. Text is public and can be occluded by the model.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer preview;
integer valid=TRUE;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        integer i;
        if(preview)
        {
            for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXT]+llList2List(saved,i*3,i*3+2));
            preview=FALSE;
            return;
        }
        links=[];
        saved=[];
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<16;++i)if(llGetLinkName(i)=="dial_tick")
        {
            links+=[i];
            saved+=llGetLinkPrimitiveParams(i,[PRIM_TEXT]);
            vector p=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_POS_LOCAL]),0);
            string label="Center";
            if(p.x*p.x+p.y*p.y>0.0001)label=(string)llRound(llAtan2(p.y,p.x)*RAD_TO_DEG)+" degrees";
            llSetLinkPrimitiveParamsFast(i,[PRIM_TEXT,label,<1.0,1.0,1.0>,1.0]);
        }
        preview=TRUE;
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Linked exhibit caption selector

Owner-touch a child and show its configured description as a caption above the root.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; give child prims meaningful public descriptions. Children should pass touch events to root. Touch root to restore its original text.

Stop / restore: Touch root to restore before removing.

Descriptions are authored metadata, not fetched from visitors. Text is public. Long descriptions are limited by normal hover-text display behavior.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        integer link=llDetectedLinkNumber(0);
        if(link<=1)
        {
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
            return;
        }
        string description=llList2String(llGetLinkPrimitiveParams(link,[PRIM_DESC]),0);
        llSetText(description,<0.9,0.95,1.0>,1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Local exhibit glossary

Look up authored glossary definitions through a short owner text box.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TERMS as alternating term/definition strings. Owner-touch and type a listed term.

Stop / restore: Remove/disable; listener expires after 45 seconds.

Answers come from the local table, not an online source. The example includes a few scripting terms and can become a museum vocabulary aid. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
list TERMS=["root","The main prim of a linked object.","child","A prim linked under the root.","face","A material surface on a prim or mesh.","alpha","A value describing transparency."];
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llTextBox(llGetOwner(),"Term: root, child, face, alpha",channel);
        llSetTimerEvent(45.0);
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        close();
        message=llToLower(llStringTrim(message,STRING_TRIM));
        integer i;
        for(i=0;i<llGetListLength(TERMS);i+=2)if(llList2String(TERMS,i)==message)
        {
            llOwnerSay(llList2String(TERMS,i+1));
            return;
        }
        llOwnerSay("Term not in this local glossary.");
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Manual availability board

Cycle Open, Busy, and Away states with one owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a public sign. Touch as owner to change your displayed status.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

This is a manual sign; it does not track avatars, online status, or parcel occupants. It controls no access.

// Original Incoprea example. MIT.
integer mode;
show()
{
    list labels=["OPEN — please ask","BUSY — leave a note","AWAY — back later"];
    list colors=[<0.6,1,0.6>,<1,0.8,0.4>,<0.7,0.8,1>];
    llSetText(llList2String(labels,mode),llList2Vector(colors,mode),1);
}
default
{
    state_entry()
    {
        show();
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        mode=(mode+1)%3;
        show();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Text & signs · Intermediate

Manual build progress bar

Advance a ten-segment text progress indicator one step per owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TITLE and use each touch to mark one of ten planned steps complete.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

A manual estimate, not an automated measure of task completion. Progress is lost on reset; after ten steps the next touch starts over.

// Original Incoprea example. MIT.
string TITLE="Build progress";
integer done;
show()
{
    string bar="";
    integer i;
    for(i=0;i<10;++i)
    {
        if(i<done)bar+="#";
        else bar+="-";
    }
    llSetText(TITLE+"\n["+bar+"] "+(string)(done*10)+"%",<0.7,1,0.8>,1);
}
default
{
    state_entry()
    {
        show();
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        done=(done+1)%11;
        show();
    }
}

MIT · original Incoprea example

API reference 1

Text & signs · Intermediate

Manual progress caption

Maintain a named task’s completion percentage with explicit +10, -10 and reset controls.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set TASK. Owner-touch adjusts the local display; Restore returns original text.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. This is manually updated status, not a measure of actual downloads or external work. No remote tasks are created.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
string TASK="Build study";
integer progress;
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
}
show()
{
    menu(TASK+": "+(string)progress+"%",["+10","-10","Zero","Display","Restore"]);
}
choose(string s)
{
    if(s=="Restore")
    {
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
        show();
        return;
    }
    if(s=="+10")progress+=10;
    else if(s=="-10")progress-=10;
    else if(s=="Zero")progress=0;
    else if(s!="Display")return;
    if(progress<0)progress=0;
    if(progress>100)progress=100;
    string bar="";
    integer i;
    for(i=0;i<10;++i)
    {
        if(i<progress/10)bar+="#";
        else bar+="-";
    }
    llSetText(TASK+"\n["+bar+"] "+(string)progress+"%",<0.6,1.0,0.8>,1.0);
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Model annotation labels

Toggle child descriptions into individual hover labels for an annotated model.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root; name up to 16 children annotate. Give each a short description. Choose Labels or Restore.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. Captures each target’s original text. No visitor information is involved; all displayed descriptions are public. Do not relink during use.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list links;
list saved;
init()
{
    integer i;
    for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<16;++i)if(llGetLinkName(i)=="annotate")
    {
        links+=[i];
        saved+=llGetLinkPrimitiveParams(i,[PRIM_TEXT]);
    }
}
show()
{
    menu("Model annotations",["Labels","Restore"]);
}
choose(string s)
{
    if(s!="Labels"&&s!="Restore")return;
    integer i;
    for(i=0;i<llGetListLength(links);++i)
    {
        integer link=llList2Integer(links,i);
        if(s=="Restore")llSetLinkPrimitiveParamsFast(link,[PRIM_TEXT]+llList2List(saved,i*3,i*3+2));
        else llSetLinkPrimitiveParamsFast(link,[PRIM_TEXT,llList2String(llGetLinkPrimitiveParams(link,[PRIM_DESC]),0),<0.85,0.95,1.0>,1.0]);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Next UTC midnight sign

Display minutes until the next UTC day begins.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a sign; starts automatically.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

UTC midnight may be a different local time. Uses Unix-day arithmetic and updates once a minute; it is a sign rather than an event scheduler.

// Original Incoprea example. MIT.
show()
{
    integer remaining=86400-(llGetUnixTime()%86400);
    integer minutes=(remaining+59)/60;
    llSetText("Next UTC day in about "+(string)minutes+" minutes",<0.8,0.9,1>,1);
}
default
{
    state_entry()
    {
        show();
        llSetTimerEvent(60);
    }
    timer()
    {
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Notice with an expiry time

Show a configured notice for a limited session, then clear it automatically.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit NOTICE and LIFETIME. Touch as owner to start a notice session.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

Reset cancels the countdown and clears the notice. Timer delays may postpone clearing; do not use this for access enforcement.

// Original Incoprea example. MIT.
string NOTICE="Workshop starting soon";
integer LIFETIME=300;
integer deadline;
default
{
    state_entry()
    {
        llSetText("",ZERO_VECTOR,0);
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LIFETIME<1 || LIFETIME>86400)
        {
            llOwnerSay("Use a lifetime from 1 to 86400 seconds.");
            return;
        }
        deadline=llGetUnixTime()+LIFETIME;
        llSetText(NOTICE,<1,0.9,0.7>,1);
        llSetTimerEvent(1);
    }
    timer()
    {
        if(llGetUnixTime()>=deadline)
        {
            llSetText("",ZERO_VECTOR,0);
            llSetTimerEvent(0);
            llOwnerSay("Notice expired.");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Paced notecard caption show

Present authored notecard lines as a slow sequence, stopping at the end.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add captions with one short caption per line. Owner-touch starts or stops. Each caption stays eight seconds.

Stop / restore: Touch to stop and restore original hover text. At EOF the script restores automatically.

No endless reread loop. A request timeout stops the show; the notecard should contain only text intended for public display. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer active;
integer line;
integer waiting;
key request;
list saved;
stop()
{
    active=FALSE;
    waiting=FALSE;
    request=NULL_KEY;
    llSetTimerEvent(0.0);
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
}
fetch()
{
    waiting=TRUE;
    request=llGetNotecardLine("captions",line);
    llSetTimerEvent(15.0);
}
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        if(llGetInventoryType("captions")!=INVENTORY_NOTECARD)return;
        active=TRUE;
        line=0;
        fetch();
    }
    dataserver(key id,string data)
    {
        if(!active||id!=request)return;
        request=NULL_KEY;
        waiting=FALSE;
        if(data==EOF)
        {
            stop();
            return;
        }
        ++line;
        llSetText(llGetSubString(data,0,220),<0.9,0.95,1.0>,1.0);
        llSetTimerEvent(8.0);
    }
    timer()
    {
        if(waiting)
        {
            stop();
            llOwnerSay("Caption read timed out.");
        }
        else if(active)
        {
            if(llGetInventoryType("captions")!=INVENTORY_NOTECARD)
            {
                stop();
                return;
            }
            fetch();
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_INVENTORY)stop();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Paged instruction sign

Let the owner advance numbered help pages displayed above a prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit PAGES with short text and touch as owner to advance.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

The displayed page is public. Visitors cannot change the page. Reset returns to page one.

// Original Incoprea example. MIT.
list PAGES=["1. Choose a spare prim.","2. Add a script to Contents.","3. Save and check compiler output."];
integer page;
show()
{
    integer total=llGetListLength(PAGES);
    if(!total)
    {
        llSetText("No pages",<1,1,1>,1);
        return;
    }
    llSetText("Guide "+(string)(page+1)+"/"+(string)total+"\n"+llList2String(PAGES,page),<0.8,1,0.8>,1);
}
default
{
    state_entry()
    {
        show();
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(PAGES)) page=(page+1)%llGetListLength(PAGES);
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Private caption on demand

Read an object’s authored description to the owner in chat without adding hover text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set the prim description to a short caption. Owner-touch reads it.

Stop / restore: Remove/disable; no persistent setting is changed.

Useful when hover text overlaps nearby exhibits. It does not inspect or record visitors and does not synthesize audio. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string caption=llGetObjectDesc();
        if(caption=="")caption="No caption configured in this prim description.";
        llOwnerSay(caption);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Beginner

Private owner stopwatch

Touch once to begin timing and again to receive the elapsed seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in an object and touch as its owner.

Stop / restore: Remove or reset the script to cancel. No floating text or build settings change.

Stores only the current run in script memory. A reset loses the run; event delays make this unsuitable for precision competition timing.

// Original Incoprea example. MIT.
integer running;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (!running)
        {
            running = TRUE;
            llResetTime();
            llOwnerSay("Stopwatch started. Touch again to stop.");
        }
        else
        {
            float elapsed = llGetTime();
            running = FALSE;
            llOwnerSay("Elapsed: " + (string)elapsed + " seconds.");
        }
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Beginner

Second Life time sign

Show the current Second Life time on a sign and update once a minute.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the sign prim. Second Life time follows the simulator’s Pacific time clock.

Stop / restore: Disable or remove; clear the label with Clear floating text.

Only updates the sign. The clock display is public hover text.

// Original Incoprea example.
string twoDigits(integer number)
{
    if (number < 10) return "0" + (string)number;
    return (string)number;
}
updateClock()
{
    integer t = (integer)llGetWallclock();
    integer hour = t / 3600;
    integer minute = (t / 60) % 60;
    llSetText("SLT  " + twoDigits(hour) + ":" + twoDigits(minute),
    <0.75, 0.95, 0.80>, 1.0);
}
default
{
    state_entry()
    {
        llSetTimerEvent(60.0);
        updateClock();
    }
    timer()
    {
        updateClock();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Sequential component lesson

Reveal one authored component annotation at a time across a linked model.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name up to12 children lesson and put short ASCII descriptions in them. Link order is lesson order; root owner-touch advances.

Stop / restore: After the last component, one more touch restores every original label.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. One-at-a-time labels reduce visual clutter without changing geometry. This is an owner-paced exhibit rehearsal.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
list captions;
integer step=-1;
integer valid=TRUE;
restore()
{
    integer i;
    for(i=0;i<llGetListLength(links);++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXT]+llList2List(saved,i*3,i*3+2));
}
default
{
    state_entry()
    {
        integer i;
        for(i=2;i<=llGetObjectPrimCount(llGetKey())&&llGetListLength(links)<12;++i)if(llGetLinkName(i)=="lesson")
        {
            links+=[i];
            saved+=llGetLinkPrimitiveParams(i,[PRIM_TEXT]);
            captions+=llGetLinkPrimitiveParams(i,[PRIM_DESC]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        ++step;
        if(step>=llGetListLength(links))
        {
            step=-1;
            restore();
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(links);++i)
        {
            string text="";
            if(i==step)text=llGetSubString(llList2String(captions,i),0,99);
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_TEXT,text,<1.0,1.0,1.0>,1.0]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)valid=FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Seven-segment linked digit

Render one decimal digit with seven named child segments.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name children seg_a through seg_g in standard seven-segment order. Root owner-touch arms; another root script sends code8060 with one digit. Face0 tints only.

Stop / restore: Owner-touch disarms and restores seven face colors.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Bright versus dark tint represents on/off; geometry remains visible and collision unchanged.

// Original Incoprea. MIT. Not compiled or tested in-world.
list links;
list saved;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        list names=["seg_a","seg_b","seg_c","seg_d","seg_e","seg_f","seg_g"];
        integer i;
        for(i=0;i<7;++i)
        {
            integer j;
            integer found;
            integer count;
            for(j=2;j<=llGetObjectPrimCount(llGetKey());++j)if(llGetLinkName(j)==llList2String(names,i))
            {
                found=j;
                ++count;
            }
            if(count!=1)
            {
                valid=FALSE;
                return;
            }
            links+=[found];
            saved+=llGetLinkPrimitiveParams(found,[PRIM_COLOR,0]);
        }
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||!valid)return;
        active=!active;
        if(!active)
        {
            integer i;
            for(i=0;i<7;++i)llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_COLOR,0]+llList2List(saved,i*2,i*2+1));
        }
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||!valid||sender!=1||code!=8060||llStringLength(s)!=1)return;
        integer digit=llSubStringIndex("0123456789",s);
        if(digit<0)return;
        integer bits=llList2Integer([63,6,91,79,102,109,125,7,127,111],digit);
        integer i;
        for(i=0;i<7;++i)
        {
            vector color=<0.03,0.03,0.03>;
            if(bits&(1<<i))color=<1.0,0.25,0.05>;
            llSetLinkPrimitiveParamsFast(llList2Integer(links,i),[PRIM_COLOR,0,color,llList2Float(saved,i*2+1)]);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            active=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Short linked caption queue

Display a bounded queue of short status captions, one every three seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root. Owner-touch arms; other root script sends code8064 and short ASCII text. Eight pending captions maximum.

Stop / restore: Owner-touch disarms, clears queue and restores original label.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Captions are public. Overflow is dropped, not persisted or acknowledged. No remote chat listener.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
list queue;
integer active;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        active=!active;
        queue=[];
        llSetTimerEvent(0.0);
        if(!active)llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!active||sender!=1||code!=8064||llGetListLength(queue)>=8||s=="")return;
        if(!llGetListLength(queue))llSetTimerEvent(3.0);
        queue+=[llGetSubString(s,0,59)];
    }
    timer()
    {
        if(!llGetListLength(queue))
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
            return;
        }
        llSetText(llList2String(queue,0),<1.0,1.0,1.0>,1.0);
        queue=llDeleteSubList(queue,0,0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Beginner

Small text marquee

Move a short text message through a 24-character hover-text window.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit MESSAGE and put in a sign prim. Starts automatically.

Stop / restore: Disable or remove and clear floating text to erase the final stored frame.

This changes hover text, not a texture or mesh lettering. It updates only once per second; keep the source message short.

// Original Incoprea example. MIT.
string MESSAGE = "Welcome to our little workshop";
string strip;
integer offset;
default
{
    state_entry()
    {
        strip = MESSAGE + "     ";
        if (llStringLength(strip) < 24) strip += "                        ";
        llSetTimerEvent(1.0);
    }
    timer()
    {
        string doubled = strip + strip;
        llSetText(llGetSubString(doubled, offset, offset + 23), <0.9, 0.9, 0.7>, 1.0);
        ++offset;
        if (offset >= llStringLength(strip)) offset = 0;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Text & signs · Intermediate

Temporarily hide all linkset labels

Suppress hover text throughout a small exhibit without hiding its geometry.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in unattached root of at most 32 prims. Owner-touch hides/restores.

Stop / restore: Restore with another touch before removal or relinking.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Captures text, color and alpha for every prim. No audio or geometry changes.

// Original Incoprea. MIT. Not compiled or tested in-world.
list saved;
integer count;
integer hidden;
integer valid=TRUE;
default
{
    state_entry()
    {
        count=llGetObjectPrimCount(llGetKey());
        if(count<1||count>32)return;
        integer i;
        for(i=1;i<=count;++i)saved+=llGetLinkPrimitiveParams(i,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetAttached()||!valid||llGetListLength(saved)!=count*3)return;
        hidden=!hidden;
        integer i;
        for(i=1;i<=count;++i)
        {
            list value=["",<1.0,1.0,1.0>,0.0];
            if(!hidden)value=llList2List(saved,(i-1)*3,(i-1)*3+2);
            llSetLinkPrimitiveParamsFast(i,[PRIM_TEXT]+value);
        }
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            valid=FALSE;
            llOwnerSay("Relinked: stop using this snapshot. Restore affected text manually if necessary.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Temporary expanded caption

Show a longer authored hover caption briefly, then restore the original label.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit CAPTION and place in the exhibit prim. Owner-touch expands for twelve seconds; another touch restarts the timeout.

Stop / restore: Wait for the original label to return before removing.

Captures original text/color/alpha. The expanded caption is public; put only intended exhibit content in it. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
string CAPTION="A working model: the root holds the center while child prims provide the moving detail.";
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llSetText(CAPTION,<0.95,0.95,0.85>,1.0);
        llSetTimerEvent(12.0);
    }
    timer()
    {
        llSetTimerEvent(0.0);
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Two-language exhibit card

Display a title and two short language versions together on one exhibit label.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TITLE, LINE_A, and LINE_B; starts automatically.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

This does not translate text. Provide your own checked translations; all text is public and subject to the hover-text byte limit.

// Original Incoprea example. MIT.
string TITLE="Glass Garden";
string LINE_A="English: A small world of light.";
string LINE_B="Español: Un pequeño mundo de luz.";
default
{
    state_entry()
    {
        llSetText(TITLE+"\n"+LINE_A+"\n"+LINE_B,<0.8,1,0.9>,1);
    }
}

MIT · original Incoprea example

API reference 1

Text & signs · Intermediate

Type a new label

Let the owner set short floating text through a temporary text box.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner; type up to 120 characters. Enter /clear to erase the label.

Stop / restore: The input closes after a response or 45 seconds. Disable the script and clear floating text to remove the label.

The label becomes publicly visible. The private channel is not encryption; access is restricted by owner key. Long input is clipped.

// Original Incoprea example. MIT.
integer handle;
integer channel;
closeInput()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        closeInput();
        channel = -100000 - (integer)llFrand(1000000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llSetTimerEvent(45.0);
        llTextBox(llGetOwner(), "Type a public label (120 characters max). /clear erases it.", channel);
    }
    listen(integer heardChannel, string name, key speaker, string message)
    {
        if (speaker != llGetOwner() || heardChannel != channel) return;
        closeInput();
        if (message == "/clear") message = "";
        llSetText(llGetSubString(message, 0, 119), <0.8, 1.0, 0.8>, 1.0);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Label input closed.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Text & signs · Beginner

UTC timestamp sign

Display a current UTC date/time string, refreshed every minute.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a sign prim. Starts automatically.

Stop / restore: Disable or remove the script, then use Clear floating text to erase the stored label.

UTC is not Second Life local time. The display includes seconds from the latest update but refreshes only once per minute.

// Original Incoprea example. MIT.
show()
{
    llSetText("UTC\n" + llGetTimestamp(), <0.7, 0.95, 1.0>, 1.0);
}
default
{
    state_entry()
    {
        show();
        llSetTimerEvent(60.0);
    }
    timer()
    {
        show();
    }
    on_rez(integer start)
    {
        llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Weekly schedule board

Display the configured schedule text for the current UTC weekday.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit SCHEDULE in Sunday-through-Saturday order. Starts automatically.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

The text is informational and does not grant access or make booking decisions. Updates every minute; no local timezone conversion occurs.

// Original Incoprea example. MIT.
list SCHEDULE=["Closed","10:00-16:00 UTC","10:00-16:00 UTC","Workshop day","10:00-16:00 UTC","By appointment","12:00-15:00 UTC"];
list DAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
show()
{
    if(llGetListLength(SCHEDULE)!=7)
    {
        llSetText("Configure seven daily schedule entries.",<1,0.6,0.4>,1);
        return;
    }
    integer today=(llGetUnixTime()/86400+4)%7;
    llSetText(llList2String(DAYS,today)+"\n"+llList2String(SCHEDULE,today),<0.8,1,0.8>,1);
}
default
{
    state_entry()
    {
        show();
        llSetTimerEvent(60);
    }
    timer()
    {
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Text & signs · Intermediate

Workshop checklist progress

Display the next checklist item and completion count as the owner advances.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TASKS. Each owner touch marks the current item done; a touch after completion restarts.

Stop / restore: Disable or remove the script, then run Clear floating text in the same prim. Stored hover text survives script removal.

This is a manual in-memory checklist, not verification that work happened. Reset loses progress; displayed tasks are public.

// Original Incoprea example. MIT.
list TASKS=["Check dependencies","Compile the script","Test on a spare prim","Record results"];
integer done;
show()
{
    integer total=llGetListLength(TASKS);
    string next="All checklist items marked done.";
    if(done<total) next="Next: "+llList2String(TASKS,done);
    llSetText("Checklist "+(string)done+"/"+(string)total+"\n"+next,<0.8,0.9,1>,1);
}
default
{
    state_entry()
    {
        show();
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ++done;
        if(done>llGetListLength(TASKS))done=0;
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interactTouch, menus, games, and playful controls.91 scripts

Download this category (.zip)

Play & interact · Beginner

A little six-sided die

Touch to roll a fresh number from one to six.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare die-shaped prim and touch it.

Stop / restore: Disable the script and clear its text if desired.

Uses the simulator’s pseudorandom number generator; it is for play, never wagers.

// Original Incoprea example.
default
{
    state_entry()
    {
        llSetText("Touch to roll", <1.0, 0.9, 0.6>, 1.0);
    }
    touch_start(integer count)
    {
        integer roll = 1 + (integer)llFrand(6.0);
        llSetText("✦  " + (string)roll + "  ✦", <1.0, 0.9, 0.6>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

Adjacent token swap puzzle

Move numbered tokens into order using adjacent swaps, with a move budget.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter 1-5 to swap that position with its right neighbor. Goal 123456. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list tokens;
integer moves;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    tokens=[3,1,5,2,6,4];
    moves=0;
}
string board()
{
    return llDumpList2String(tokens,"")+" | moves "+(string)moves;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter 1-5 to swap that position with its right neighbor. Goal 123456. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==1)
            {
                integer p=llSubStringIndex("12345",input);
                if(p>=0)
                {
                    integer a=llList2Integer(tokens,p);
                    integer b=llList2Integer(tokens,p+1);
                    tokens=llListReplaceList(tokens,[b,a],p,p+1);
                    ++moves;
                    if(llDumpList2String(tokens,"")=="123456")llOwnerSay("Sorted! Try fewer moves next time.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Alphabet order challenge

Sort four distinct letters into alphabetical order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch and enter the four displayed letters with no spaces, ordered A to Z.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Uses ASCII English letters. The letters are selected without replacement, so every prompt has one unambiguous ordering.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
string expected;
start()
{
    list alphabet;
    integer i;
    for(i=0;i<26;++i)alphabet+=[llGetSubString("ABCDEFGHIJKLMNOPQRSTUVWXYZ",i,i)];
    list chosen=llList2List(llListRandomize(alphabet,1),0,3);
    expected=llDumpList2String(llListSort(chosen,1,TRUE),"");
    ask("Alphabetize: "+llDumpList2String(chosen," ")+"\nEnter four letters without spaces.");
}
answer(string s)
{
    if(llToUpper(s)==expected)
    {
        close();
        llOwnerSay("Correct: "+expected);
    }
    else ask("Not yet. Sort the same four letters A to Z.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Anagram checker

Check whether two short words contain the same letters.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch and enter two ASCII words separated by one space, such as listen silent.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Ignores letter case. It checks letter multiplicity, not whether the inputs are dictionary words.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
start()
{
    ask("Enter two ASCII words, for example: listen silent");
}
answer(string s)
{
    list words=llParseString2List(llToLower(s),[" "],[]);
    if(llGetListLength(words)!=2)
    {
        ask("Enter exactly two words separated by spaces.");
        return;
    }
    list signatures;
    integer w;
    for(w=0;w<2;++w)
    {
        string word=llList2String(words,w);
        if(llStringLength(word)>24)
        {
            ask("Use words of at most 24 letters.");
            return;
        }
        list letters;
        integer i;
        for(i=0;i<llStringLength(word);++i)
        {
            string c=llGetSubString(word,i,i);
            if(llSubStringIndex("abcdefghijklmnopqrstuvwxyz",c)<0)
            {
                ask("ASCII letters a-z only.");
                return;
            }
            letters+=[c];
        }
        signatures+=[llDumpList2String(llListSort(letters,1,TRUE),"")];
    }
    close();
    if(llList2String(signatures,0)==llList2String(signatures,1))llOwnerSay("Same letters: anagram match.");
    else llOwnerSay("The letter counts differ.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Armed owner gesture receiver

Trigger one approved short owner animation from a named linked scene controller.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child with gesture. Name the root gesture_controller. Owner-touch arms and explicitly grants animation permission; root code 7920 and message play triggers it.

Stop / restore: Owner-touch disarms/stops; each trigger also stops after four seconds. Use Stop Animating Me if interrupted.

Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. Validates root name, code, message and owner permission. Only one configured inventory animation is accepted; no arbitrary animation UUID is executed.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer pending;
integer playing;
integer permitted()
{
    return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner();
}
stop()
{
    if(playing&&permitted())llStopAnimation("gesture");
    playing=FALSE;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(armed)
        {
            armed=FALSE;
            stop();
            return;
        }
        if(pending)return;
        pending=TRUE;
        llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
    }
    run_time_permissions(integer p)
    {
        if(!pending)return;
        pending=FALSE;
        armed=permitted();
    }
    link_message(integer sender,integer code,string s,key data)
    {
        if(!armed||!permitted()||sender!=1||llGetLinkName(1)!="gesture_controller"||code!=7920||s!="play"||llGetInventoryType("gesture")!=INVENTORY_ANIMATION)return;
        stop();
        playing=TRUE;
        llStartAnimation("gesture");
        llSetTimerEvent(4.0);
    }
    timer()
    {
        stop();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
        else if(change&CHANGED_LINK)
        {
            armed=FALSE;
            stop();
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Backward word practice

Read an editable word presented in reverse order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch, then type the forward spelling of the displayed reverse word.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. A short language/pattern toy, separate from an arbitrary letter shuffle.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list words=["garden","planet","window","ribbon","marble"];
string secret;
start()
{
    secret=llList2String(words,(integer)llFrand((float)llGetListLength(words)));
    string reverse="";
    integer i;
    for(i=llStringLength(secret)-1;i>=0;--i)reverse+=llGetSubString(secret,i,i);
    ask("Read this backward word: "+reverse);
}
answer(string s)
{
    if(llToLower(s)==secret)
    {
        close();
        llOwnerSay("Correct: "+secret);
    }
    else ask("Try the forward spelling again.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Bridge and torch puzzle

Move four travelers across with a shared torch and a seventeen-minute target.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter a or ab etc. Travel times a=1,b=2,c=5,d=10. One or two on torch side move. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list banks;
integer torch;
integer elapsed;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    banks=[0,0,0,0];
    torch=0;
    elapsed=0;
}
string board()
{
    return "Far banks a,b,c,d: "+llList2CSV(banks)+" | torch "+(string)torch+" | minutes "+(string)elapsed;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter a or ab etc. Travel times a=1,b=2,c=5,d=10. One or two on torch side move. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            integer len=llStringLength(input);
            if(len>=1&&len<=2)
            {
                integer a=llSubStringIndex("abcd",llGetSubString(input,0,0));
                integer b=a;
                if(len==2)b=llSubStringIndex("abcd",llGetSubString(input,1,1));
                if(a>=0&&b>=0&&(len==1||a!=b)&&llList2Integer(banks,a)==torch&&llList2Integer(banks,b)==torch)
                {
                    list times=[1,2,5,10];
                    integer cost=llList2Integer(times,a);
                    if(llList2Integer(times,b)>cost)cost=llList2Integer(times,b);
                    torch=1-torch;
                    banks=llListReplaceList(banks,[torch],a,a);
                    banks=llListReplaceList(banks,[torch],b,b);
                    elapsed+=cost;
                    if(llList2CSV(banks)=="1, 1, 1, 1")llOwnerSay("All crossed in "+(string)elapsed+" minutes.");
                }
                else llOwnerSay("Traveler unavailable or repeated.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Calibrate a slider from two actual touches

Use the first two taps as minimum and maximum references, then convert later taps into normalized values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Tap the intended minimum and maximum positions; subsequent touches read the calibrated range. Reset to recalibrate. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

References must be on the same link/face and have distinctS coordinates.

// Original Incoprea. MIT. Owner input only.
integer stage;
integer face;
integer link;
float low;
float high;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        integer f=llDetectedTouchFace(0);
        integer l=llDetectedLinkNumber(0);
        if(stage==0)
        {
            face=f;
            link=l;
            low=uv.x;
            stage=1;
            llOwnerSay("Minimum captured; tap maximum.");
            return;
        }
        if(f!=face||l!=link)
        {
            llOwnerSay("Use the calibrated face.");
            return;
        }
        if(stage==1)
        {
            high=uv.x;
            if(llFabs(high-low)<0.01)
            {
                llOwnerSay("Endpoints too close; try maximum again.");
                return;
            }
            stage=2;
            llOwnerSay("Calibrated; tap to read.");
            return;
        }
        float value=(uv.x-low)/(high-low);
        if(value<0.0)value=0.0;
        if(value>1.0)value=1.0;
        llOwnerSay("Calibrated value="+(string)value);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Capture a compactUV drag trail

Store at most twelve sufficiently separatedUV samples from one owner drag and print them on release.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press, drag on one face, then release. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

The sample cap prevents memory growth. Points closer than0.04UV to the last sample are skipped.

// Original Incoprea. MIT. Owner input only.
integer active;
integer face;
integer link;
list trail;
sample()
{
    vector uv=llDetectedTouchST(0);
    if(!usable(uv)||face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))return;
    integer length=llGetListLength(trail);
    if(length>=12)return;
    if(length==0||llVecDist(uv,llList2Vector(trail,-1))>=0.04)trail+=[uv];
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        active=TRUE;
        trail=[];
        face=llDetectedTouchFace(0);
        link=llDetectedLinkNumber(0);
        sample();
    }
    touch(integer n)
    {
        if(ownerTouch()&&active)sample();
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        sample();
        active=FALSE;
        integer i;
        for(i=0;i<llGetListLength(trail);++i)llOwnerSay((string)i+": "+(string)llList2Vector(trail,i));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Chess-square color trainer

Practice identifying light and dark squares from algebraic coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Answer LIGHT or DARK for a random square such as c5.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Uses the standard convention that a1 is dark. It teaches the board pattern, not chess moves or rules.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer file;
integer rank;
string square;
start()
{
    file=(integer)llFrand(8.0);
    rank=1+(integer)llFrand(8.0);
    square=llGetSubString("abcdefgh",file,file)+(string)rank;
    ask("Is "+square+" LIGHT or DARK? a1 is dark.");
}
answer(string s)
{
    s=llToLower(s);
    if(s!="light"&&s!="dark")
    {
        ask("Enter LIGHT or DARK.");
        return;
    }
    string correct="dark";
    if((file+rank)%2==0)correct="light";
    close();
    if(s==correct)llOwnerSay("Correct: "+square+" is "+correct);
    else llOwnerSay(square+" is "+correct);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Choose a bounded range with two touches

Use two horizontal positions as lower and upper values in a normalized range.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Touch one endpoint, then another; the next pair starts a new selection. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Endpoint order does not matter. Values are clamped to the face range.

// Original Incoprea. MIT. Owner input only.
integer waiting;
float first;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        float value=uv.x;
        if(value<0.0)value=0.0;
        if(value>1.0)value=1.0;
        if(!waiting)
        {
            first=value;
            waiting=TRUE;
            llOwnerSay("First endpoint recorded.");
        }
        else
        {
            float low=first;
            float high=value;
            if(high<low)
            {
                float temp=low;
                low=high;
                high=temp;
            }
            waiting=FALSE;
            llOwnerSay("Range="+(string)low+".."+(string)high+" width="+(string)(high-low));
        }
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Choose a circle with a center and edge tap

Capture a face-space center then use a second touch to choose a radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Tap the center then a point on the intended circumference. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Radius is measured in normalizedUV distance, so rectangular faces stretch the visual circle.

// Original Incoprea. MIT. Owner input only.
integer waiting;
integer face;
integer link;
vector centre;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        if(!waiting)
        {
            centre=uv;
            face=llDetectedTouchFace(0);
            link=llDetectedLinkNumber(0);
            waiting=TRUE;
            llOwnerSay("Center captured; tap circle edge.");
            return;
        }
        if(face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))
        {
            llOwnerSay("Use the same face.");
            return;
        }
        waiting=FALSE;
        llOwnerSay("Circle center="+(string)centre+" UV radius="+(string)llVecDist(centre,uv));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Classify an owner swipe gesture

Recognize a tap or dominant horizontal/vertical swipe on one face.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press and drag, then release on the same face. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Direction is measured in surface coordinates, not screen pixels. Minimum travel distinguishes taps.

// Original Incoprea. MIT. Owner input only.
integer active;
integer face;
integer link;
vector start;
float MIN_TRAVEL=0.08;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        active=TRUE;
        start=uv;
        face=llDetectedTouchFace(0);
        link=llDetectedLinkNumber(0);
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        active=FALSE;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv)||face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))return;
        vector delta=uv-start;
        string gesture="tap";
        if(llVecMag(delta)>=MIN_TRAVEL)
        {
            if(llFabs(delta.x)>=llFabs(delta.y))
            {
                gesture="right";
                if(delta.x<0.0)gesture="left";
            }
            else
            {
                gesture="up";
                if(delta.y<0.0)gesture="down";
            }
        }
        llOwnerSay("Gesture="+gesture+" delta="+(string)delta);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Color-channel mixing quiz

Name which additive RGB channel pair makes a familiar secondary color.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Answer with RG, RB, or GB.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. A simple idealized additive-light lesson, not pigment mixing or a color-management measurement.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list names=["yellow","magenta","cyan"];
list pairs=["rg","rb","gb"];
integer choice;
start()
{
    choice=(integer)llFrand(3.0);
    ask("Which two additive RGB channels make "+llList2String(names,choice)+"? Enter RG, RB, or GB.");
}
answer(string s)
{
    s=llToLower(s);
    if(llListFindList(pairs,[s])<0)
    {
        ask("Use RG, RB, or GB.");
        return;
    }
    close();
    if(s==llList2String(pairs,choice))llOwnerSay("Correct.");
    else llOwnerSay("This pair is "+llToUpper(llList2String(pairs,choice))+".");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Count owner taps separately for each touched face

Maintain a bounded link/face tally while testing a multi-face control panel.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Touch faces across a small linkset; reset to clear counts. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Stores at most24 distinct link/face combinations. It does not count visitors or track other avatars.

// Original Incoprea. MIT. Owner input only.
list keys;
list counts;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch()||llDetectedTouchFace(0)<0)return;
        string label=(string)llDetectedLinkNumber(0)+":"+(string)llDetectedTouchFace(0);
        integer index=llListFindList(keys,[label]);
        if(index<0)
        {
            if(llGetListLength(keys)>=24)
            {
                llOwnerSay("24-face tally full; reset to clear.");
                return;
            }
            keys+=[label];
            counts+=[0];
            index=llGetListLength(keys)-1;
        }
        integer total=llList2Integer(counts,index)+1;
        counts=llListReplaceList(counts,[total],index,index);
        llOwnerSay("Link:face "+label+" owner taps="+(string)total);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Coupled wheel lock

Solve four linked digit wheels where each turn advances a neighbor too.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter wheel 1-4. That wheel and the next wheel increase modulo 4. Goal all zero. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list wheels;
integer moves;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    wheels=[1,2,1,0];
    moves=0;
}
string board()
{
    return "Wheels "+llList2CSV(wheels)+" | turns "+(string)moves;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter wheel 1-4. That wheel and the next wheel increase modulo 4. Goal all zero. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==1)
            {
                integer p=llSubStringIndex("1234",input);
                if(p>=0)
                {
                    integer next=(p+1)%4;
                    wheels=llListReplaceList(wheels,[(llList2Integer(wheels,p)+1)%4],p,p);
                    wheels=llListReplaceList(wheels,[(llList2Integer(wheels,next)+1)%4],next,next);
                    ++moves;
                    if(llDumpList2String(wheels,"")=="0000")llOwnerSay("Unlocked!");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Domino chain table

Build a chain from a fixed small hand, reversing tiles when required.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter tile index 1-6 to append it to the right. A used tile cannot be selected again. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list tiles;
list used;
integer end;
string chain;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    tiles=[0,1,2,3,1,2,3,0,0,2,2,2];
    used=[];
    end=0;
    chain="[0]";
}
string board()
{
    string s="";
    integer i;
    for(i=0;i<6;++i)if(llListFindList(used,[i])<0)s+=(string)(i+1)+":"+llList2String(tiles,i*2)+"-"+llList2String(tiles,i*2+1)+" ";
    return chain+" | available "+s;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter tile index 1-6 to append it to the right. A used tile cannot be selected again. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==1)
            {
                integer p=llSubStringIndex("123456",input);
                if(p>=0&&llListFindList(used,[p])<0)
                {
                    integer a=llList2Integer(tiles,p*2);
                    integer b=llList2Integer(tiles,p*2+1);
                    if(a==end||b==end)
                    {
                        if(a==end)end=b;
                        else end=a;
                        used+=[p];
                        chain+="-"+(string)end;
                        if(llGetListLength(used)==6)llOwnerSay("All tiles used.");
                    }
                    else llOwnerSay("No matching endpoint.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Drag out a normalized selection rectangle

Capture the lower-left and upper-right corners of a dragged face region.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press one corner and release at the opposite corner on the same face. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

The same link and face are required; leaving the face can make the release unavailable.

// Original Incoprea. MIT. Owner input only.
integer active;
integer face;
integer link;
vector start;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        start=uv;
        face=llDetectedTouchFace(0);
        link=llDetectedLinkNumber(0);
        active=TRUE;
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        active=FALSE;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv)||face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))
        {
            llOwnerSay("Selection canceled: release on same face required.");
            return;
        }
        vector low=start;
        vector high=start;
        if(uv.x<low.x)low.x=uv.x;
        if(uv.y<low.y)low.y=uv.y;
        if(uv.x>high.x)high.x=uv.x;
        if(uv.y>high.y)high.y=uv.y;
        llOwnerSay("Selection min="+(string)low+" max="+(string)high+" UV area="+(string)((high.x-low.x)*(high.y-low.y)));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Drag through snap cells without boundary chatter

Keep a snapped horizontal cell until the pointer passes a margin beyond its center boundary.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press and drag slowly across one face. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

The hysteresis margin is in cell units. This is a stable discrete controller, not geometric grid snapping of the object.

// Original Incoprea. MIT. Owner input only.
integer active;
integer cell;
integer CELLS=8;
float MARGIN=0.15;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        cell=llFloor(uv.x*CELLS);
        if(cell<0)cell=0;
        if(cell>=CELLS)cell=CELLS-1;
        active=TRUE;
        llOwnerSay("Cell="+(string)cell);
    }
    touch(integer n)
    {
        if(!ownerTouch()||!active)return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        float x=uv.x*CELLS;
        integer previous=cell;
        while(cell<CELLS-1&&x>(cell+1)+MARGIN)++cell;
        while(cell>0&&x<cell-MARGIN)--cell;
        if(cell!=previous)llOwnerSay("Cell="+(string)cell);
    }
    touch_end(integer n)
    {
        if(ownerTouch())active=FALSE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Exhibit reference browser button

Offer a viewer browser prompt for a configured reference page.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set URL and DESCRIPTION to an intended reference. Owner-touch requests the viewer’s URL confirmation.

Stop / restore: Remove/disable. The viewer controls whether the URL opens.

Does not automatically launch external content without the viewer prompt or send data to the site. Use a trustworthy HTTPS reference and keep descriptions accurate. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
string URL="https://wiki.secondlife.com/wiki/LSL_Portal";
string DESCRIPTION="Open the official Second Life scripting reference.";
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())llLoadURL(llGetOwner(),DESCRIPTION,URL);
    }
}

MIT · original Incoprea example

API reference 1

Play & interact · Intermediate

Exhibit scene command bus

Use an owner dialog to send named scene requests to linked exhibit receivers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in root. Receivers you author can handle link code 7890 with Preview, Quiet, Restore, or Describe. Owner-touch opens the menu.

Stop / restore: Use Restore to request restoration from receivers, then remove. This sender itself changes no display.

Commands are requests, not guaranteed acknowledgments. Receivers should validate root sender and implement their own restore actions. No regional chat or visitor records. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1)return;
        close();
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
        llDialog(llGetOwner(),"Request an exhibit scene",["Preview","Quiet","Restore","Describe"],channel);
        llSetTimerEvent(30.0);
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner()||llListFindList(["Preview","Quiet","Restore","Describe"],[message])<0)return;
        close();
        llMessageLinked(LINK_ALL_CHILDREN,7890,message,NULL_KEY);
        llOwnerSay("Scene request sent: "+message);
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

Find the lit face

A small face-finding game that briefly highlights one face for the owner to touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare multi-face prim with modest original glow. Owner-touch starts. Rotate the camera or object to find and touch the glowing face.

Stop / restore: Correct touch or a 15-second timeout restores all original glow values. Wait for restoration before deleting or resetting.

Faces on complex meshes may be hard to locate; start with a simple cube. Uses touch-face data and does not change colors, lights, or ownership.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list original;
integer active;
integer target;
restore()
{
    integer face;
    for (face = 0; face < llGetListLength(original); ++face)
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_GLOW, face, llList2Float(original, face)]);
    active = FALSE;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        integer face;
        for (face = 0; face < llGetNumberOfSides(); ++face)
        original += llGetLinkPrimitiveParams(LINK_THIS, [PRIM_GLOW, face]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (!active)
        {
            target = (integer)llFrand((float)llGetListLength(original));
            active = TRUE;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_GLOW, target, 0.15]);
            llSetTimerEvent(15.0);
            llOwnerSay("Find and touch the glowing face.");
        }
        else if (llDetectedTouchFace(0) == target)
        {
            restore();
            llOwnerSay("Found it! Touch to start another round.");
        }
    }
    timer()
    {
        restore();
        llOwnerSay("Round ended; original glow restored.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Five-by-five knight tour

Visit every square with legal knight moves and no revisits.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter coordinates a1 through e5. Start a1; no square may be revisited. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer x;
integer y;
list visited;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    x=0;
    y=0;
    visited=[0];
}
string board()
{
    return "Current "+llGetSubString("abcde",x,x)+(string)(y+1)+" | visited "+(string)llGetListLength(visited)+"/25";
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter coordinates a1 through e5. Start a1; no square may be revisited. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==2)
            {
                integer nx=llSubStringIndex("abcde",llGetSubString(input,0,0));
                integer ny=llSubStringIndex("12345",llGetSubString(input,1,1));
                integer dx=llAbs(nx-x);
                integer dy=llAbs(ny-y);
                integer square=ny*5+nx;
                if(nx>=0&&ny>=0&&((dx==1&&dy==2)||(dx==2&&dy==1))&&llListFindList(visited,[square])<0)
                {
                    x=nx;
                    y=ny;
                    visited+=[square];
                    if(llGetListLength(visited)==25)llOwnerSay("Tour complete!");
                }
                else llOwnerSay("Not a fresh knight move.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Five-cell nonogram study

Solve one row of filled blocks from run-length clues.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter five characters using x and dot. Clue: 2 then 1, separated by empty cells. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer attempts;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    attempts=0;
}
string board()
{
    return "Clue [2,1], length5. Attempts "+(string)attempts;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter five characters using x and dot. Clue: 2 then 1, separated by empty cells. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==5)
            {
                integer valid=TRUE;
                integer i;
                for(i=0;i<5;++i)if(llSubStringIndex("x.",llGetSubString(input,i,i))<0)valid=FALSE;
                if(valid)
                {
                    ++attempts;
                    list runs=[];
                    integer count=0;
                    for(i=0;i<5;++i)
                    {
                        if(llGetSubString(input,i,i)=="x")++count;
                        else if(count)
                        {
                            runs+=[count];
                            count=0;
                        }
                    }
                    if(count)runs+=[count];
                    if(llList2CSV(runs)=="2, 1")llOwnerSay("Correct row!");
                    else llOwnerSay("Runs: "+llList2CSV(runs));
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Five-letter feedback word

Guess an authored word with position-aware feedback that handles repeated letters.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter five letters. G=right place, Y=elsewhere, -=absent. Six guesses. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
string answer;
integer tries;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    answer="pearl";
    tries=0;
}
string board()
{
    return "Five-letter word. Guesses used: "+(string)tries;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter five letters. G=right place, Y=elsewhere, -=absent. Six guesses. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(tries<6&&llStringLength(input)==5)
            {
                integer valid=TRUE;
                integer i;
                for(i=0;i<5;++i)if(llSubStringIndex("abcdefghijklmnopqrstuvwxyz",llGetSubString(input,i,i))<0)valid=FALSE;
                if(valid)
                {
                    ++tries;
                    list result=["-","-","-","-","-"];
                    string remaining=answer;
                    for(i=0;i<5;++i)if(llGetSubString(input,i,i)==llGetSubString(answer,i,i))
                    {
                        result=llListReplaceList(result,["G"],i,i);
                        remaining=llDeleteSubString(remaining,i,i);
                        remaining=llInsertString(remaining,i," ");
                    }
                    for(i=0;i<5;++i)if(llList2String(result,i)!="G")
                    {
                        integer pos=llSubStringIndex(remaining,llGetSubString(input,i,i));
                        if(pos>=0)
                        {
                            result=llListReplaceList(result,["Y"],i,i);
                            remaining=llDeleteSubString(remaining,pos,pos);
                            remaining=llInsertString(remaining,pos," ");
                        }
                    }
                    llOwnerSay(input+" "+llDumpList2String(result,""));
                    if(input==answer)
                    {
                        tries=6;
                        llOwnerSay("Solved!");
                    }
                    else if(tries==6)llOwnerSay("Answer: "+answer);
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Five-position rating pad

Turn horizontal owner touches into a one-to-five local score without logging anyone.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a face marked with five equal-width regions and set FACE. Owner-touch reports a selected integer.

Stop / restore: Remove or disable; no settings or records persist.

A controller example, not a public survey. No avatar identifiers, votes, or remote analytics are collected.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.x>1.0)return;
        integer score=1+(integer)(st.x*5.0);
        if(score>5)score=5;
        llOwnerSay("Selected "+(string)score+" of 5");
        llMessageLinked(LINK_ALL_OTHERS,7846,(string)score,NULL_KEY);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

Four-by-four minefield

Reveal safe cells or flag suspected mines in a fixed learning board.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter r1-r16 to reveal or f1-f16 to toggle flags. Three mines; reset repeats layout. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list mines;
list shown;
list flags;
integer lost;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    mines=[2,9,15];
    shown=[];
    flags=[];
    lost=FALSE;
}
string board()
{
    string s="";
    integer i;
    for(i=0;i<16;++i)
    {
        if(llListFindList(flags,[i])>=0)s+="F ";
        else if(llListFindList(shown,[i])>=0)
        {
            integer count=0;
            integer j;
            for(j=0;j<3;++j)
            {
                integer m=llList2Integer(mines,j);
                if(llAbs(m%4-i%4)<=1&&llAbs(m/4-i/4)<=1)++count;
            }
            s+=(string)count+" ";
        }
        else s+="? ";
        if(i%4==3)s+="/ ";
    }
    return s;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter r1-r16 to reveal or f1-f16 to toggle flags. Three mines; reset repeats layout. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(!lost)
            {
                string mode=llGetSubString(input,0,0);
                string digits=llGetSubString(input,1,-1);
                integer cell=(integer)digits-1;
                if((string)(cell+1)==digits&&cell>=0&&cell<16)
                {
                    if(mode=="f")
                    {
                        integer f=llListFindList(flags,[cell]);
                        if(f<0)flags+=[cell];
                        else flags=llDeleteSubList(flags,f,f);
                    }
                    else if(mode=="r"&&llListFindList(flags,[cell])<0&&llListFindList(shown,[cell])<0)
                    {
                        if(llListFindList(mines,[cell])>=0)
                        {
                            lost=TRUE;
                            llOwnerSay("Mine. Reset to retry.");
                        }
                        else
                        {
                            shown+=[cell];
                            if(llGetListLength(shown)==13)llOwnerSay("All safe cells revealed!");
                        }
                    }
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Four-column connect-three

Play both sides of a compact gravity board and seek three in a line.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter column 1-4. X and O alternate. Three in a line wins. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list cells;
integer turn;
integer done;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    cells=[];
    integer i;
    for(i=0;i<16;++i)cells+=["."];
    turn=0;
    done=FALSE;
}
string board()
{
    string s="";
    integer r;
    for(r=3;r>=0;--r)s+=llDumpList2String(llList2List(cells,r*4,r*4+3),"")+" / ";
    return s;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter column 1-4. X and O alternate. Three in a line wins. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(!done&&llStringLength(input)==1)
            {
                integer col=llSubStringIndex("1234",input);
                if(col>=0)
                {
                    integer row=0;
                    while(row<4&&llList2String(cells,row*4+col)!=".")++row;
                    if(row<4)
                    {
                        string mark="X";
                        if(turn)mark="O";
                        cells=llListReplaceList(cells,[mark],row*4+col,row*4+col);
                        integer y;
                        integer x;
                        integer d;
                        list dxs=[1,0,1,-1];
                        list dys=[0,1,1,1];
                        for(y=0;y<4;++y)for(x=0;x<4;++x)for(d=0;d<4;++d)
                        {
                            integer dx=llList2Integer(dxs,d);
                            integer dy=llList2Integer(dys,d);
                            integer ex=x+dx*2;
                            integer ey=y+dy*2;
                            if(ex>=0&&ex<4&&ey<4&&llList2String(cells,y*4+x)==mark&&llList2String(cells,(y+dy)*4+x+dx)==mark&&llList2String(cells,ey*4+ex)==mark)done=TRUE;
                        }
                        if(done)llOwnerSay(mark+" wins!");
                        turn=!turn;
                    }
                    else llOwnerSay("Column full.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Four-digit codebreaker

Find a hidden four-digit code using exact-position and wrong-position clues.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Enter exactly four digits from 1–6; repeated digits are allowed.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Counts each matching symbol once, including repeated symbols. This is a puzzle, not an access lock or security mechanism.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
string secret;
start()
{
    secret="";
    integer i;
    for(i=0;i<4;++i)secret+=(string)(1+(integer)llFrand(6.0));
    ask("Guess four digits 1-6. Repeats allowed.");
}
answer(string s)
{
    if(llStringLength(s)!=4)
    {
        ask("Enter exactly four digits 1-6.");
        return;
    }
    integer i;
    integer exact;
    list a;
    list b;
    for(i=0;i<4;++i)
    {
        string x=llGetSubString(s,i,i);
        if(digit(x,1,6)<0)
        {
            ask("Use only digits 1-6.");
            return;
        }
        string y=llGetSubString(secret,i,i);
        if(x==y)++exact;
        else
        {
            a+=[x];
            b+=[y];
        }
    }
    integer misplaced;
    for(i=0;i<llGetListLength(a);++i)
    {
        integer p=llListFindList(b,[llList2String(a,i)]);
        if(p>=0)
        {
            ++misplaced;
            b=llDeleteSubList(b,p,p);
        }
    }
    if(exact==4)
    {
        close();
        llOwnerSay("Code solved: "+secret);
    }
    else ask((string)exact+" exact; "+(string)misplaced+" correct digit, wrong place.\nGuess again.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Four-pair memory board

Find matching pairs among eight hidden cards.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Enter card numbers 1–8. Remember revealed symbols while matching four pairs.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Symbols are shown in private prompts and owner chat; no textures or inventory cards are required.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
list cards;
list found;
integer first=-1;
integer pairs;
string view()
{
    string out="";
    integer i;
    for(i=0;i<8;++i)
    {
        if(llListFindList(found,[i])>=0)out+=llList2String(cards,i);
        else out+=(string)(i+1);
        out+=" ";
    }
    return out;
}
start()
{
    cards=llListRandomize(["A","A","B","B","C","C","D","D"],1);
    found=[];
    pairs=0;
    first=-1;
    ask(view()+"\nChoose a card.");
}
answer(string s)
{
    integer p=digit(s,1,8)-1;
    if(p<0||llListFindList(found,[p])>=0||p==first)
    {
        ask(view()+"\nChoose a different hidden card.");
        return;
    }
    string symbol=llList2String(cards,p);
    if(first<0)
    {
        first=p;
        ask("Card "+s+" is "+symbol+". Choose its partner.");
        return;
    }
    string old=llList2String(cards,first);
    string result="No match: "+old+" and "+symbol;
    if(old==symbol)
    {
        found+=[first,p];
        ++pairs;
        result="Pair found: "+symbol;
    }
    first=-1;
    if(pairs==4)
    {
        close();
        llOwnerSay("All four pairs found.");
    }
    else ask(result+"\n"+view()+"\nChoose another card.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Four-seat constraint puzzle

Arrange four guests under simple adjacency and position constraints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter a permutation of abcd from left to right. A left of C; B beside D; C not at an end. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer attempts;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    attempts=0;
}
string board()
{
    return "Seat order puzzle; attempts "+(string)attempts;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter a permutation of abcd from left to right. A left of C; B beside D; C not at an end. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==4)
            {
                integer a=llSubStringIndex(input,"a");
                integer b=llSubStringIndex(input,"b");
                integer c=llSubStringIndex(input,"c");
                integer d=llSubStringIndex(input,"d");
                if(a>=0&&b>=0&&c>=0&&d>=0)
                {
                    ++attempts;
                    if(a<c&&llAbs(b-d)==1&&c>0&&c<3)llOwnerSay("All constraints satisfied!");
                    else llOwnerSay("At least one constraint fails.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Four-zone touch panel

Divide one flat face into four touch zones that send different linked commands.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE. Owner-touch a quadrant; owner chat names the action and link code 7844 carries it to optional receivers.

Stop / restore: Remove or disable; no stored properties change.

Uses ST coordinates and four named commands. Receivers should validate the code and sender rather than trusting all link messages.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.y<0.0||st.x>1.0||st.y>1.0)return;
        string action="Back";
        if(st.x>=0.5)action="Next";
        if(st.y>=0.5)
        {
            action="Stop";
            if(st.x>=0.5)action="Start";
        }
        llOwnerSay(action);
        llMessageLinked(LINK_ALL_OTHERS,7844,action,NULL_KEY);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

Gauge touch controller

Send a normalized horizontal touch value to a linked gauge needle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name the root gauge_controller, put this script there and set FACE. Pair with Linked gauge needle receiver in a child. Owner-touch a flat face.

Stop / restore: Remove or disable. This sender changes no prim properties; disarm the paired receiver separately.

Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. This controller alone only emits local link messages and reports the value. The receiver must be separately armed.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llDetectedTouchFace(0)!=FACE)return;
        vector st=llDetectedTouchST(0);
        if(st.x<0.0||st.x>1.0)return;
        llMessageLinked(LINK_ALL_CHILDREN,7860,(string)st.x,NULL_KEY);
        llOwnerSay("Gauge value "+(string)st.x);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

Heavier coin investigation

Find one heavy coin among nine with at most two equal-count balance weighings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter abc/def to weigh equal-size disjoint groups, or guess a-i. Heavy coin is authored for repeatable teaching. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer weighings;
integer finished;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    weighings=0;
    finished=FALSE;
}
string board()
{
    return "Coins a-i; one is heavier. Weighings used "+(string)weighings;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter abc/def to weigh equal-size disjoint groups, or guess a-i. Heavy coin is authored for repeatable teaching. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(!finished)
            {
                if(llGetSubString(input,0,5)=="guess ")
                {
                    string guess=llGetSubString(input,6,-1);
                    if(llStringLength(guess)==1&&llSubStringIndex("abcdefghi",guess)>=0)
                    {
                        finished=TRUE;
                        if(guess=="h")llOwnerSay("Correct.");
                        else llOwnerSay("Heavy coin was h.");
                    }
                }
                else if(weighings<2)
                {
                    list sides=llParseStringKeepNulls(input,["/"],[]);
                    if(llGetListLength(sides)==2)
                    {
                        string a=llList2String(sides,0);
                        string b=llList2String(sides,1);
                        integer valid=llStringLength(a)>0&&llStringLength(a)==llStringLength(b);
                        string all=a+b;
                        integer i;
                        for(i=0;i<llStringLength(all);++i)
                        {
                            string c=llGetSubString(all,i,i);
                            if(llSubStringIndex("abcdefghi",c)<0||llSubStringIndex(all,c)!=i)valid=FALSE;
                        }
                        if(valid)
                        {
                            ++weighings;
                            if(llSubStringIndex(a,"h")>=0)llOwnerSay("Left heavier.");
                            else if(llSubStringIndex(b,"h")>=0)llOwnerSay("Right heavier.");
                            else llOwnerSay("Balanced.");
                        }
                    }
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Higher or lower

Guess a hidden number from 1 to 100 with higher/lower hints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a prim to start. Enter a whole number in the text box. Each accepted guess renews a 60-second idle timeout.

Stop / restore: Stop responding to close the listener, touch to restart, or remove the script.

For casual play with no prizes, persistent scores, or visitor tracking. Input is validated before conversion.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer answer;
integer attempts;
integer channel;
integer handle;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
ask(string hint)
{
    llTextBox(llGetOwner(), hint + " Enter 1 to 100.", channel);
    llSetTimerEvent(60.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        answer = 1 + (integer)llFrand(100.0);
        attempts = 0;
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        ask("Find the hidden number.");
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        message = llStringTrim(message, STRING_TRIM);
        integer length = llStringLength(message);
        integer i;
        if (length < 1 || length > 3)
        {
            ask("Whole numbers only.");
            return;
        }
        for (i = 0; i < length; ++i)
        if (llSubStringIndex("0123456789", llGetSubString(message, i, i)) < 0)
        {
            ask("Whole numbers only.");
            return;
        }
        integer guess = (integer)message;
        if (guess < 1 || guess > 100)
        {
            ask("Out of range.");
            return;
        }
        ++attempts;
        if (guess == answer)
        {
            close();
            llOwnerSay("Found it in " + (string)attempts + " guesses.");
        }
        else if (guess < answer) ask("Higher!");
        else ask("Lower!");
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Letter-reveal word puzzle

Reveal a hidden workshop word one letter at a time before six misses.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch, then submit one ASCII letter per guess. Edit WORDS to change the vocabulary.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. No gallows or violent imagery; wrong guesses simply use the six-miss budget.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list WORDS=["texture","sculpture","lantern","workshop","particle"];
string secret;
string guessed;
integer misses;
string view()
{
    string out="";
    integer i;
    for(i=0;i<llStringLength(secret);++i)
    {
        string c=llGetSubString(secret,i,i);
        if(llSubStringIndex(guessed,c)>=0)out+=c;
        else out+="_";
    }
    return out;
}
start()
{
    secret=llList2String(WORDS,(integer)llFrand((float)llGetListLength(WORDS)));
    guessed="";
    misses=0;
    ask(view()+"\nGuess one letter.");
}
answer(string s)
{
    s=llToLower(s);
    if(llStringLength(s)!=1||llSubStringIndex("abcdefghijklmnopqrstuvwxyz",s)<0)
    {
        ask(view()+"\nOne letter a-z.");
        return;
    }
    if(llSubStringIndex(guessed,s)>=0)
    {
        ask(view()+"\nAlready guessed. Try another.");
        return;
    }
    guessed+=s;
    if(llSubStringIndex(secret,s)<0)++misses;
    if(view()==secret)
    {
        close();
        llOwnerSay("Solved: "+secret);
        return;
    }
    if(misses>=6)
    {
        close();
        llOwnerSay("Word was "+secret);
        return;
    }
    ask(view()+"\nMisses "+(string)misses+"/6. Tried: "+guessed);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Beginner

Linked button message demo

Demonstrate communication between two prims in one linkset without chat listeners.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put a copy of this script in each of two linked prims. Owner-touch either scripted prim; each other scripted prim reports receiving a ping in owner chat.

Stop / restore: Remove both script copies. No stored visual setting is changed.

Only local link messages are used. A receiver never echoes a received message, avoiding message loops. Test with two prims before scaling.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer CODE = 7301;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llDetectedLinkNumber(0) != llGetLinkNumber()) return;
        llMessageLinked(LINK_ALL_OTHERS, CODE, "ping", NULL_KEY);
    }
    link_message(integer sender, integer number, string message, key data)
    {
        if (number == CODE && message == "ping")
        llOwnerSay("Prim " + (string)llGetLinkNumber() + " received ping from prim " + (string)sender + ".");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Linked switch with status reply

A button sends a toggle command to an indicator that replies with its state.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put this script in two linked prims. Name one panel_button and the other panel_indicator. Owner-touch the button.

Stop / restore: Turn off, then remove both copies. Indicator restores its original hover text when off.

Same code handles either role. Message code 7821 is private to the linkset, not secret from other scripts inside it. Replies never echo as commands.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer on;
list original;
default
{
    state_entry()
    {
        original=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetObjectName()!="panel_button"||llDetectedLinkNumber(0)!=llGetLinkNumber())return;
        llMessageLinked(LINK_ALL_OTHERS,7821,"toggle",NULL_KEY);
    }
    link_message(integer sender,integer code,string message,key data)
    {
        if(code!=7821)return;
        if(llGetObjectName()=="panel_indicator"&&llGetLinkName(sender)=="panel_button"&&message=="toggle")
        {
            on=!on;
            if(on)llSetText("Indicator ON",<0.5,1.0,0.7>,1.0);
            else llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+original);
            llMessageLinked(sender,7821,"status:"+(string)on,NULL_KEY);
        }
        else if(llGetObjectName()=="panel_button"&&llSubStringIndex(message,"status:")==0)llOwnerSay(message);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Live horizontal value slider

Map owner touches and drags to a configurable numeric range.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Set MINIMUM/MAXIMUM, then touch and drag horizontally. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Reports at most five updates per second; release always reports the final valid sample.

// Original Incoprea. MIT. Owner input only.
float MINIMUM=-10.0;
float MAXIMUM=30.0;
float nextReport;
report()
{
    vector uv=llDetectedTouchST(0);
    if(!usable(uv))return;
    float t=uv.x;
    if(t<0.0)t=0.0;
    if(t>1.0)t=1.0;
    llOwnerSay("Value="+(string)(MINIMUM+(MAXIMUM-MINIMUM)*t));
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        report();
        nextReport=llGetTime()+0.2;
    }
    touch(integer n)
    {
        if(!ownerTouch()||llGetTime()<nextReport)return;
        nextReport=llGetTime()+0.2;
        report();
    }
    touch_end(integer n)
    {
        if(ownerTouch())report();
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Live logarithmic range slider

Map a horizontal drag across several orders of magnitude.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Set positive MINIMUM and MAXIMUM greater than MINIMUM. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

A midpoint selects the geometric mean; invalid configuration is reported before calculating.

// Original Incoprea. MIT. Owner input only.
float MINIMUM=0.01;
float MAXIMUM=100.0;
float nextReport;
report()
{
    vector uv=llDetectedTouchST(0);
    if(!usable(uv))return;
    if(MINIMUM<=0.0||MAXIMUM<=MINIMUM)
    {
        llOwnerSay("Require0<minimum<maximum.");
        return;
    }
    float t=uv.x;
    if(t<0.0)t=0.0;
    if(t>1.0)t=1.0;
    llOwnerSay("Log value="+(string)(MINIMUM*llPow(MAXIMUM/MINIMUM,t)));
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(ownerTouch())
        {
            report();
            nextReport=llGetTime()+0.25;
        }
    }
    touch(integer n)
    {
        if(ownerTouch()&&llGetTime()>=nextReport)
        {
            nextReport=llGetTime()+0.25;
            report();
        }
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Lock a drag to its first dominant axis

Choose horizontal or vertical motion after the drag passes a threshold, then suppress the other axis.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press and drag on one face; release ends the gesture. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Axis choice remains fixed during the gesture to avoid jitter near diagonals.

// Original Incoprea. MIT. Owner input only.
integer active;
integer axis;
vector start;
integer face;
integer link;
float nextReport;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        start=uv;
        active=TRUE;
        axis=0;
        face=llDetectedTouchFace(0);
        link=llDetectedLinkNumber(0);
        nextReport=0.0;
    }
    touch(integer n)
    {
        if(!ownerTouch()||!active)return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv)||face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))return;
        vector delta=uv-start;
        if(axis==0&&llVecMag(delta)>0.05)
        {
            axis=1;
            if(llFabs(delta.y)>llFabs(delta.x))axis=2;
        }
        if(axis==1)delta.y=0.0;
        else if(axis==2)delta.x=0.0;
        if(axis&&llGetTime()>=nextReport)
        {
            nextReport=llGetTime()+0.2;
            llOwnerSay("Axis="+(string)axis+" constrained delta="+(string)delta);
        }
    }
    touch_end(integer n)
    {
        if(ownerTouch())active=FALSE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Beginner

Map location sign

Touch a sign to show a configured destination on the viewer’s map.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Replace DESTINATION_REGION and DESTINATION_POSITION with a real destination on the current grid. Put in a sign visitors can touch.

Stop / restore: Remove or disable. No prim setting is changed.

Opens a map rather than teleporting the toucher. Viewer and grid behavior can differ, especially for Hypergrid addresses; this example expects a local-grid region name.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string DESTINATION_REGION = "Your Region Name";
vector DESTINATION_POSITION = <128.0, 128.0, 30.0>;
default
{
    touch_start(integer count)
    {
        if (DESTINATION_REGION == "Your Region Name")
        {
            llOwnerSay("Set the destination region first.");
            return;
        }
        llMapDestination(DESTINATION_REGION, DESTINATION_POSITION, ZERO_VECTOR);
    }
}

MIT · original Incoprea example

API reference 1

Play & interact · Intermediate

Measure surface drag speed

Estimate instantaneousUV speed from successive drag events.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Hold and drag across one face. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Uses actual event elapsed time and reports at most four times per second. Simulator event timing is not raw mouse-device timing.

// Original Incoprea. MIT. Owner input only.
integer active;
vector last;
float lastTime;
float nextReport;
integer face;
integer link;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        last=uv;
        lastTime=llGetTime();
        nextReport=lastTime+0.25;
        face=llDetectedTouchFace(0);
        link=llDetectedLinkNumber(0);
        active=TRUE;
    }
    touch(integer n)
    {
        if(!ownerTouch()||!active)return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv)||face!=llDetectedTouchFace(0)||link!=llDetectedLinkNumber(0))return;
        float now=llGetTime();
        float dt=now-lastTime;
        if(dt>0.001&&now>=nextReport)
        {
            llOwnerSay("UV units/sec="+(string)(llVecDist(last,uv)/dt));
            nextReport=now+0.25;
        }
        last=uv;
        lastTime=now;
    }
    touch_end(integer n)
    {
        if(ownerTouch())active=FALSE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Measure the cadence of a held touch

Count touch events and report mean/min/max event spacing for one owner gesture.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press and hold or drag for several seconds, then release. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Cadence includes viewer and simulator scheduling; it is not an input latency benchmark.

// Original Incoprea. MIT. Owner input only.
integer active;
integer samples;
float previous;
float total;
float minimum;
float maximum;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        active=TRUE;
        samples=0;
        previous=llGetTime();
        total=0.0;
        minimum=1000000.0;
        maximum=0.0;
    }
    touch(integer n)
    {
        if(!ownerTouch()||!active)return;
        float now=llGetTime();
        float dt=now-previous;
        previous=now;
        ++samples;
        total+=dt;
        if(dt<minimum)minimum=dt;
        if(dt>maximum)maximum=dt;
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        active=FALSE;
        if(samples==0)
        {
            llOwnerSay("No intermediate touch events received.");
            return;
        }
        llOwnerSay("Events="+(string)samples+" mean spacing="+(string)(total/samples)+" min="+(string)minimum+" max="+(string)maximum);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Measure the traveled path of a surface drag

Accumulate world-space distance through owner drag event positions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press, drag across the object, then release. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Sampled path length underestimates motion between events and is not exact geodesic distance on the surface.

// Original Incoprea. MIT. Owner input only.
integer active;
vector last;
vector start;
float length;
integer samples;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch()||llDetectedTouchFace(0)<0)return;
        active=TRUE;
        start=llDetectedTouchPos(0);
        last=start;
        length=0.0;
        samples=1;
    }
    touch(integer n)
    {
        if(!ownerTouch()||!active||llDetectedTouchFace(0)<0)return;
        vector point=llDetectedTouchPos(0);
        length+=llVecDist(last,point);
        last=point;
        ++samples;
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        active=FALSE;
        if(llDetectedTouchFace(0)>=0)
        {
            vector point=llDetectedTouchPos(0);
            length+=llVecDist(last,point);
            last=point;
        }
        llOwnerSay("Traced metres="+(string)length+" endpoint metres="+(string)llVecDist(start,last)+" samples="+(string)samples);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Morse letter decoder

Look up one Morse letter from a dot-and-dash group.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch and enter one group such as .- or --..

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. A–Z lookup only; punctuation, procedural signals and numbers are intentionally excluded.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list codes=[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."];
start()
{
    ask("Enter one Morse letter using . and - (for example .-).");
}
answer(string s)
{
    integer p=llListFindList(codes,[s]);
    if(p<0)
    {
        ask("Not an A-Z Morse letter. Try one group without spaces.");
        return;
    }
    close();
    llOwnerSay(s+" = "+llGetSubString("ABCDEFGHIJKLMNOPQRSTUVWXYZ",p,p));
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Morse word encoder

Convert a short A–Z word into dot-and-dash groups.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch, then type up to 12 letters without spaces.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Uses international Morse A–Z only. Output is text, not audio or emergency signaling.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list codes=[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."];
start()
{
    ask("Enter 1-12 letters A-Z to encode as Morse.");
}
answer(string s)
{
    s=llToUpper(s);
    integer length=llStringLength(s);
    if(length<1||length>12)
    {
        ask("Use 1-12 letters.");
        return;
    }
    list out;
    integer i;
    for(i=0;i<length;++i)
    {
        integer p=llSubStringIndex("ABCDEFGHIJKLMNOPQRSTUVWXYZ",llGetSubString(s,i,i));
        if(p<0)
        {
            ask("Letters A-Z only.");
            return;
        }
        out+=[llList2String(codes,p)];
    }
    close();
    llOwnerSay(s+": "+llDumpList2String(out," "));
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Nine-light toggle puzzle

Switch a 3×3 grid off by toggling a cell and its orthogonal neighbors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch to start. Type a cell number 1–9; each move toggles a cross. The initial state is made from valid moves.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. A solvable Lights Out-style exercise. Symbols 1 and . indicate on and off; cell numbers run left-to-right by row.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
list board;
toggle(integer p)
{
    integer i;
    for(i=0;i<9;++i)if(i==p||llAbs(i/3-p/3)+llAbs(i%3-p%3)==1)board=llListReplaceList(board,[!llList2Integer(board,i)],i,i);
}
string view()
{
    string text="";
    integer i;
    for(i=0;i<9;++i)
    {
        if(llList2Integer(board,i))text+="1 ";
        else text+=". ";
        if(i%3==2)text+="\n";
    }
    return text;
}
start()
{
    board=[0,0,0,0,0,0,0,0,0];
    integer i;
    for(i=0;i<6;++i)toggle((integer)llFrand(9.0));
    ask(view()+"\nToggle a cell 1-9; switch all off.");
}
answer(string s)
{
    integer p=digit(s,1,9)-1;
    if(p<0)
    {
        ask(view()+"\nEnter 1-9.");
        return;
    }
    toggle(p);
    if(llListFindList(board,[1])<0)
    {
        close();
        llOwnerSay("All lights off. Solved!");
    }
    else ask(view()+"\nChoose 1-9.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Beginner

Nonrepeating prompt bag

Draw every creative challenge once before the bag is reshuffled.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim and edit the prompt list. Touch to draw the next item.

Stop / restore: Disable or remove and clear its text. Reset discards the current bag order.

Pseudorandom order for creative play. The last item of one bag can equal the first item of the next; no prizes or money are handled.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list prompts = ["Build something tiny", "Use only three colors", "Make a quiet machine", "Invent a new plant", "Design a doorway to nowhere"];
list bag;
default
{
    touch_start(integer count)
    {
        if (!llGetListLength(prompts)) return;
        if (!llGetListLength(bag)) bag = llListRandomize(prompts, 1);
        string prompt = llList2String(bag, 0);
        bag = llDeleteSubList(bag, 0, 0);
        llSetText(prompt + "\n" + (string)llGetListLength(bag) + " left in this bag", <0.9, 0.85, 0.7>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Notecard question and answer reveal

Read a notecard line containing a question and answer, revealing the answer on the next touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add quiz with one question|answer pair per line. Owner-touch alternates question and answer, then advances.

Stop / restore: Remove/disable; only owner chat is used.

Pairs are authored content. Malformed lines are reported and advanced one per touch; no unbounded skip loop is used. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer line;
integer reveal;
string answer;
key request;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||request!=NULL_KEY)return;
        if(reveal)
        {
            llOwnerSay("Answer: "+answer);
            reveal=FALSE;
            return;
        }
        if(llGetInventoryType("quiz")!=INVENTORY_NOTECARD)return;
        request=llGetNotecardLine("quiz",line);
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        if(data==EOF)
        {
            line=0;
            llOwnerSay("Quiz complete; next touch starts again.");
            return;
        }
        ++line;
        list pair=llParseStringKeepNulls(data,["|"],[]);
        if(llGetListLength(pair)!=2)
        {
            llOwnerSay("Expected question|answer on line "+(string)line);
            return;
        }
        answer=llGetSubString(llList2String(pair,1),0,800);
        reveal=TRUE;
        llOwnerSay("Question: "+llGetSubString(llList2String(pair,0),0,800)+" (touch to reveal)");
    }
    timer()
    {
        request=NULL_KEY;
        llSetTimerEvent(0.0);
    }
    changed(integer change)
    {
        if(change&CHANGED_INVENTORY)
        {
            request=NULL_KEY;
            line=0;
            reveal=FALSE;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Play & interact · Intermediate

One-stroke edge walk

Traverse a small graph without reusing any edge.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Vertices a,b,c,d. Start a. Enter next vertex; edges ab,bc,ca,ad,dc. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list edges;
list used;
string current;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    edges=["ab","bc","ac","ad","cd"];
    used=[];
    current="a";
}
string board()
{
    return "At "+current+" | used edges "+llList2CSV(used);
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Vertices a,b,c,d. Start a. Enter next vertex; edges ab,bc,ca,ad,dc. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==1&&llSubStringIndex("abcd",input)>=0)
            {
                string edge=current+input;
                if(llSubStringIndex("abcd",current)>llSubStringIndex("abcd",input))edge=input+current;
                if(llListFindList(edges,[edge])>=0&&llListFindList(used,[edge])<0)
                {
                    used+=[edge];
                    current=input;
                    if(llGetListLength(used)==5)llOwnerSay("Every edge crossed once!");
                }
                else llOwnerSay("Missing or already used edge.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Owner animation preview

Ask the owner for animation permission, then preview one inventory animation for five seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a licensed animation named preview_pose to this prim. Owner-touch and accept the animation permission dialog. Test while standing in a suitable space.

Stop / restore: Wait five seconds or touch again while playing. If interrupted, use the viewer’s Stop Animating Me command.

Never requests debit, camera, or controls permissions. Animation overrides may compete with the preview. Permissions can outlive the preview until reset or revoked.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string ANIMATION = "preview_pose";
integer pending;
integer playing;
stopPreview()
{
    if (playing && (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) && llGetPermissionsKey() == llGetOwner())
    llStopAnimation(ANIMATION);
    playing = FALSE;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (playing)
        {
            stopPreview();
            return;
        }
        if (pending) return;
        if (llGetInventoryType(ANIMATION) != INVENTORY_ANIMATION)
        {
            llOwnerSay("Add preview_pose animation.");
            return;
        }
        pending = TRUE;
        llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION);
    }
    run_time_permissions(integer permissions)
    {
        pending = FALSE;
        if ((permissions & PERMISSION_TRIGGER_ANIMATION) && llGetPermissionsKey() == llGetOwner())
        {
            if (llGetInventoryType(ANIMATION) != INVENTORY_ANIMATION) return;
            playing = TRUE;
            llStartAnimation(ANIMATION);
            llSetTimerEvent(5.0);
        }
    }
    timer()
    {
        stopPreview();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Owner description editor

Edit a prim’s description from an owner-only text box, with an original-value restore command.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the prim whose description you want to edit. Owner-touch and enter a short description or RESTORE.

Stop / restore: Enter RESTORE to recover the initial description before removing if desired. Edited descriptions otherwise persist.

The description is public object metadata, not a place for secrets. This limits entry to 100 characters; simulator byte limits can shorten non-ASCII text further.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string original;
integer channel;
integer handle;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    state_entry()
    {
        original = llGetObjectDesc();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llTextBox(llGetOwner(), "Enter a short public description (100 characters), or RESTORE.", channel);
        llSetTimerEvent(30.0);
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        close();
        if (llToUpper(llStringTrim(message, STRING_TRIM)) == "RESTORE") llSetObjectDesc(original);
        else if (llStringLength(message) > 100) llOwnerSay("Too long; use 100 characters or fewer.");
        else llSetObjectDesc(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Beginner

Owner lap stopwatch

Measure an elapsed interval in owner chat with a start and stop touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim. First owner touch starts; second reports elapsed seconds; the next starts a fresh interval.

Stop / restore: Disable or remove. No persistent prim settings are changed.

Measures script event timing, including network and simulator latency. Not appropriate for competitive adjudication.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer running;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        running = !running;
        if (running)
        {
            llResetTime();
            llOwnerSay("Stopwatch started. Touch to stop.");
        }
        else llOwnerSay("Elapsed: " + (string)llGetTime() + " seconds.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Owner pose menu

Choose one of three authored inventory poses after granting animation permission.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed animations pose_a, pose_b and pose_c. Owner-touch requests permission, then opens a menu.

Stop / restore: Choose Stop before removing or resetting. If interrupted, use the viewer Stop Animating Me command.

Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. Requests only animation permission. Stops only the animation it started, not every animation on the avatar. Viewer AO and animation priorities can compete.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer pending;
string current;
integer permitted()
{
    return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner();
}
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
stop()
{
    if(current!=""&&permitted())llStopAnimation(current);
    current="";
}
show()
{
    close();
    channel=-1000-(integer)llFrand(1000000.0);
    handle=llListen(channel,"",llGetOwner(),"");
    llDialog(llGetOwner(),"Preview a pose; Stop before removing.",["A","B","C","Stop"],channel);
    llSetTimerEvent(30.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||pending)return;
        if(permitted())show();
        else
        {
            pending=TRUE;
            llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
        }
    }
    run_time_permissions(integer p)
    {
        if(!pending)return;
        pending=FALSE;
        if(permitted())show();
    }
    listen(integer ch,string name,key id,string s)
    {
        if(!handle||ch!=channel||id!=llGetOwner()||!permitted())return;
        if(s=="Stop")
        {
            stop();
            close();
            return;
        }
        integer i=llListFindList(["A","B","C"],[s]);
        if(i<0)return;
        string animation=llList2String(["pose_a","pose_b","pose_c"],i);
        if(llGetInventoryType(animation)!=INVENTORY_ANIMATION)
        {
            llOwnerSay("Missing "+animation);
            return;
        }
        stop();
        current=animation;
        llStartAnimation(current);
        show();
    }
    timer()
    {
        stop();
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Owner seat pose controller

Play a custom pose only when the owner occupies this prim’s configured sit target.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare chair with a nonzero sit target already configured. Add seat_pose. Owner-touch arms, then sit normally.

Stop / restore: Owner-touch disarms and stops this pose; stand before removing. The pre-existing sit target is not changed.

Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. Does not force sitting, eject anyone, or stop the default sit animation. The custom pose asset needs an appropriate priority and can conflict with an AO.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer pending;
integer playing;
integer permitted()
{
    return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner();
}
stop()
{
    if(playing&&permitted())llStopAnimation("seat_pose");
    playing=FALSE;
}
check()
{
    if(!armed||llAvatarOnSitTarget()!=llGetOwner())
    {
        stop();
        return;
    }
    if(!playing&&!pending&&llGetInventoryType("seat_pose")==INVENTORY_ANIMATION)
    {
        pending=TRUE;
        llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
    }
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        check();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)
        {
            llResetScript();
            return;
        }
        if(change&CHANGED_LINK)check();
    }
    run_time_permissions(integer p)
    {
        if(!pending)return;
        pending=FALSE;
        if(armed&&llAvatarOnSitTarget()==llGetOwner()&&permitted()&&llGetInventoryType("seat_pose")==INVENTORY_ANIMATION)
        {
            playing=TRUE;
            llStartAnimation("seat_pose");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Owner XY pad with radial dead zone

Convert face coordinates into a bounded two-axis direction and magnitude.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Touch or drag relative to the face center. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

The radial dead zone avoids diagonal bias from separate per-axis dead zones; no avatar controls are requested.

// Original Incoprea. MIT. Owner input only.
float DEAD=0.15;
float nextReport;
report()
{
    vector uv=llDetectedTouchST(0);
    if(!usable(uv))return;
    if(DEAD<0.0||DEAD>=1.0)
    {
        llOwnerSay("Dead zone must be0..1 exclusive.");
        return;
    }
    vector p=<2.0*uv.x-1.0,2.0*uv.y-1.0,0.0>;
    float length=llVecMag(p);
    vector output=ZERO_VECTOR;
    if(length>DEAD)
    {
        float magnitude=length;
        if(magnitude>1.0)magnitude=1.0;
        output=llVecNorm(p)*((magnitude-DEAD)/(1.0-DEAD));
    }
    llOwnerSay("Pad="+(string)output);
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(ownerTouch())
        {
            report();
            nextReport=llGetTime()+0.2;
        }
    }
    touch(integer n)
    {
        if(ownerTouch()&&llGetTime()>=nextReport)
        {
            nextReport=llGetTime()+0.2;
            report();
        }
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Paired animation layer preview

Preview two purpose-built animation layers together for five seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add licensed animations upper_layer and lower_layer that were designed to affect different joints. Owner-touch grants permission.

Stop / restore: Touch while playing or wait five seconds. Stop Animating Me is the fallback after interruption.

Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. LSL does not change animation priority or joint masks; those must be authored in the assets. This is a compatibility preview, not a universal animation blender.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer pending;
integer playing;
integer permitted()
{
    return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner();
}
stop()
{
    if(playing&&permitted())
    {
        llStopAnimation("upper_layer");
        llStopAnimation("lower_layer");
    }
    playing=FALSE;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(playing)
        {
            stop();
            return;
        }
        if(pending)return;
        if(llGetInventoryType("upper_layer")!=INVENTORY_ANIMATION||llGetInventoryType("lower_layer")!=INVENTORY_ANIMATION)
        {
            llOwnerSay("Add upper_layer and lower_layer animations.");
            return;
        }
        pending=TRUE;
        llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
    }
    run_time_permissions(integer p)
    {
        if(!pending)return;
        pending=FALSE;
        if(!permitted())return;
        if(llGetInventoryType("upper_layer")!=INVENTORY_ANIMATION||llGetInventoryType("lower_layer")!=INVENTORY_ANIMATION)return;
        playing=TRUE;
        llStartAnimation("upper_layer");
        llStartAnimation("lower_layer");
        llSetTimerEvent(5.0);
    }
    timer()
    {
        stop();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Pocket maze

Navigate a tiny fixed maze from S to E using four direction buttons.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim and owner-touch to start a fresh maze. The dialog shows X for your location, # walls, and E for the exit.

Stop / restore: Stop responding and its listener closes after 60 seconds, or remove the script.

A private owner game using a fixed solvable map. Directions use the printed map, not world compass directions. No avatar is moved.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list rows = ["#######", "#S#..E#", "#.#.###", "#.....#", "#######"];
integer x = 1;
integer y = 1;
integer channel;
integer handle;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
show()
{
    string map = "";
    integer line;
    for (line = 0; line < llGetListLength(rows); ++line)
    {
        string row = llList2String(rows, line);
        if (line == y) row = llInsertString(llDeleteSubString(row, x, x), x, "X");
        map += row + "\n";
    }
    llDialog(llGetOwner(), map + "\nFind E. # is a wall.", ["North", "South", "East", "West"], channel);
    llSetTimerEvent(60.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        x = 1;
        y = 1;
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        show();
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        integer nx = x;
        integer ny = y;
        if (message == "North") --ny;
        else if (message == "South") ++ny;
        else if (message == "East") ++nx;
        else if (message == "West") --nx;
        else return;
        if (nx < 0 || nx >= 7 || ny < 0 || ny >= 5)
        {
            show();
            return;
        }
        string cell = llGetSubString(llList2String(rows, ny), nx, nx);
        if (cell != "#")
        {
            x = nx;
            y = ny;
        }
        if (cell == "E")
        {
            close();
            llOwnerSay("Exit found! Touch for another walk.");
        }
        else show();
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Pocket rock-paper-scissors

Play a quick owner-only round against a random computer choice.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim; owner-touch opens three choice buttons. The dialog listener closes after a choice or 20 seconds.

Stop / restore: Disable or remove. It changes no persistent visual settings.

For play only. The listener is restricted to the current owner and uses a random negative channel; it does not handle wagers or store identity history.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list choices = ["Rock", "Paper", "Scissors"];
integer channel;
integer handle;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llDialog(llGetOwner(), "Choose your move", choices, channel);
        llSetTimerEvent(20.0);
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        integer player = llListFindList(choices, [message]);
        if (player < 0) return;
        close();
        integer computer = (integer)llFrand(3.0);
        string result = "Draw";
        if (player != computer)
        {
            if ((player - computer + 3) % 3 == 1) result = "You win";
            else result = "Computer wins";
        }
        llOwnerSay("You: " + message + "; computer: " + llList2String(choices, computer) + ". " + result + ".");
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Reaction-time toy

Wait for a random GO cue, then touch to get an approximate reaction time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim. Owner-touch starts. Wait for green GO; touching early cancels the round.

Stop / restore: After a result, remove the script and clear its hover text. A round also times out after ten seconds at GO.

Network, viewer, and script lag contribute to the result; this is a toy, not a reliable human reaction-time measurement.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer phase;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (!phase)
        {
            phase = 1;
            llSetText("Wait...", <1.0, 0.7, 0.2>, 1.0);
            llSetTimerEvent(2.0 + llFrand(3.0));
        }
        else if (phase == 1)
        {
            phase = 0;
            llSetTimerEvent(0.0);
            llSetText("Too soon. Touch to retry.", <1.0, 0.5, 0.5>, 1.0);
        }
        else
        {
            phase = 0;
            llSetTimerEvent(0.0);
            llSetText((string)llGetTime() + " seconds (includes lag)\nTouch to retry", <0.7, 1.0, 0.8>, 1.0);
        }
    }
    timer()
    {
        if (phase == 1)
        {
            phase = 2;
            llResetTime();
            llSetText("GO!", <0.4, 1.0, 0.4>, 1.0);
            llSetTimerEvent(10.0);
        }
        else
        {
            phase = 0;
            llSetTimerEvent(0.0);
            llSetText("Round expired. Touch to retry.", <0.8, 0.8, 0.8>, 1.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Relative touch dial

Read an angular control value around the center of a face.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set FACE on a flat circular or square control pad. Owner-touch away from its center.

Stop / restore: Remove/disable. It changes no setting.

Returns degrees 0–360 measured counterclockwise from surface +S. The central dead zone avoids unstable angles.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer FACE=0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llDetectedTouchFace(0)!=FACE)return;
        vector p=llDetectedTouchST(0);
        if(p.x<0.0||p.y<0.0)return;
        p-=<0.5,0.5,0.0>;
        if(llVecMag(p)<0.1)return;
        float degrees=llAtan2(p.y,p.x)*RAD_TO_DEG;
        if(degrees<0.0)degrees+=360.0;
        llOwnerSay("Dial "+(string)llRound(degrees)+" degrees");
        llMessageLinked(LINK_ALL_OTHERS,7845,(string)degrees,NULL_KEY);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Remember the digit sequence

Memorize a four-digit sequence, then type it into a text box after it disappears.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a spare prim. The digits show for four seconds; a text box then asks for the same sequence.

Stop / restore: Wait for a result or owner-touch to restart; remove and clear text when done. Listener expires after 30 seconds.

The answer remains in viewer history only if the viewer records displayed text; this is a casual memory exercise, not a secure challenge.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string sequence;
integer channel;
integer handle;
integer phase;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        sequence = "";
        integer i;
        for (i = 0; i < 4; ++i) sequence += (string)((integer)llFrand(10.0));
        phase = 1;
        llSetText(sequence, <0.8, 1.0, 0.8>, 1.0);
        llSetTimerEvent(4.0);
    }
    timer()
    {
        if (phase == 1)
        {
            phase = 2;
            llSetText("What were the digits?", <0.8, 0.9, 1.0>, 1.0);
            channel = -1000 - (integer)llFrand(1000000.0);
            handle = llListen(channel, "", llGetOwner(), "");
            llTextBox(llGetOwner(), "Enter the four digits, including any leading zero.", channel);
            llSetTimerEvent(30.0);
        }
        else
        {
            close();
            phase = 0;
            llSetText("Time expired. Touch to retry.", <0.8, 0.8, 0.8>, 1.0);
        }
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner() || phase != 2) return;
        close();
        phase = 0;
        if (llStringTrim(message, STRING_TRIM) == sequence) llSetText("Correct! Touch for another.", <0.6, 1.0, 0.6>, 1.0);
        else llSetText("The sequence was " + sequence + ". Touch to retry.", <1.0, 0.8, 0.6>, 1.0);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Report face transitions during a drag

Track which link/face receives owner drag events and report only transitions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Hold a touch and move across accessible faces. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Viewers may terminate touch when leaving a surface; this reports actual received events rather than assuming continuous capture.

// Original Incoprea. MIT. Owner input only.
integer active;
integer lastFace=-1;
integer lastLink=-1;
integer changes;
sample()
{
    integer face=llDetectedTouchFace(0);
    integer link=llDetectedLinkNumber(0);
    if(face<0)return;
    if(face!=lastFace||link!=lastLink)
    {
        ++changes;
        lastFace=face;
        lastLink=link;
        llOwnerSay("Now link="+(string)link+" face="+(string)face);
    }
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        active=TRUE;
        changes=0;
        lastFace=-1;
        lastLink=-1;
        sample();
    }
    touch(integer n)
    {
        if(ownerTouch()&&active)sample();
    }
    touch_end(integer n)
    {
        if(!ownerTouch()||!active)return;
        sample();
        active=FALSE;
        llOwnerSay("Distinct transition events="+(string)changes);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Require a second tap near the first

Recognize an owner double-click only if time, link, face andUV distance all match.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Tap twice near the same point within0.6 seconds. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

A distant second tap starts a new candidate rather than confirming the old one.

// Original Incoprea. MIT. Owner input only.
integer armed;
integer face;
integer link;
vector first;
float deadline;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        float now=llGetTime();
        integer currentFace=llDetectedTouchFace(0);
        integer currentLink=llDetectedLinkNumber(0);
        if(armed&&now<=deadline&&face==currentFace&&link==currentLink&&llVecDist(first,uv)<=0.08)
        {
            armed=FALSE;
            llOwnerSay("Spatial double-click confirmed.");
        }
        else
        {
            armed=TRUE;
            first=uv;
            face=currentFace;
            link=currentLink;
            deadline=now+0.6;
            llOwnerSay("First tap recorded.");
        }
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

River crossing puzzle

Ferry the wolf, goat and cabbage without leaving an unsafe pair alone.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter alone, wolf, goat or cabbage to cross. Reset after a failed trip. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list banks;
integer lost;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    banks=[0,0,0,0];
    lost=FALSE;
}
string board()
{
    return "Banks (far=1): farmer,wolf,goat,cabbage "+llList2CSV(banks);
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter alone, wolf, goat or cabbage to cross. Reset after a failed trip. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(!lost)
            {
                integer cargo=llListFindList(["alone","wolf","goat","cabbage"],[input]);
                if(cargo>=0)
                {
                    integer farmer=llList2Integer(banks,0);
                    if(cargo==0||llList2Integer(banks,cargo)==farmer)
                    {
                        banks=llListReplaceList(banks,[1-farmer],0,0);
                        if(cargo)banks=llListReplaceList(banks,[1-farmer],cargo,cargo);
                        integer goat=llList2Integer(banks,2);
                        if(goat==farmer&&(llList2Integer(banks,1)==goat||llList2Integer(banks,3)==goat))
                        {
                            lost=TRUE;
                            llOwnerSay("Unsafe pair left alone. Reset to retry.");
                        }
                        else if(llList2CSV(banks)=="1, 1, 1, 1")llOwnerSay("Everyone crossed safely!");
                    }
                    else llOwnerSay("Cargo is on the other bank.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Route a touched grid cell to a named action

Map a3-by2 face grid to six fixed local command names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Touch different cells; labels are printed rather than executed. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Rows count from the bottom. Exactly-edge coordinates are clamped into the final cell.

// Original Incoprea. MIT. Owner input only.
list ACTIONS=["previous","play","next","quiet","help","home"];
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        integer column=llFloor(uv.x*3.0);
        integer row=llFloor(uv.y*2.0);
        if(column<0)column=0;
        if(column>2)column=2;
        if(row<0)row=0;
        if(row>1)row=1;
        llOwnerSay("Action="+llList2String(ACTIONS,row*3+column));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Sample a four-corner color palette by touch

Bilinearly blend four corner colors using the owner’s actual touch position.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Set color vectors BL/BR/TL/TR and touch the face. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Mixing is directly in supplied channel space; it does not automatically linearize sRGB.

// Original Incoprea. MIT. Owner input only.
vector BL=<0.1,0.2,0.4>;
vector BR=<0.8,0.3,0.1>;
vector TL=<0.2,0.8,0.5>;
vector TR=<0.9,0.9,0.7>;
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        vector uv=llDetectedTouchST(0);
        if(!usable(uv))return;
        float u=uv.x;
        float v=uv.y;
        if(u<0.0)u=0.0;
        if(u>1.0)u=1.0;
        if(v<0.0)v=0.0;
        if(v>1.0)v=1.0;
        vector bottom=BL+(BR-BL)*u;
        vector top=TL+(TR-TL)*u;
        llOwnerSay("Sample color="+(string)(bottom+(top-bottom)*v));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Beginner

Seat with owner stand-up button

Set a seat target and let its seated owner stand by touching the seat.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare seat prim. Adjust the nonzero sit offset for the chair. Sit normally using the viewer; the script never forces anyone to sit.

Stop / restore: Stand up, remove this script, then use Clear sit target to remove the persistent seat setting.

Only unsits the owner when the owner touches while seated on this prim’s sit target. It does not eject other sitters or animate an avatar.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    state_entry()
    {
        llSitTarget(<0.0, 0.0, 0.5>, ZERO_ROTATION);
    }
    touch_start(integer count)
    {
        key owner = llGetOwner();
        if (llDetectedKey(0) == owner && llAvatarOnSitTarget() == owner) llUnSit(owner);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Seven-hole peg solitaire

Jump neighboring pegs into empty holes to leave as few pegs as possible.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Holes 1-7. Enter from-to like 13 or 53; jump exactly two holes. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list pegs;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    pegs=[1,1,1,0,1,1,1];
}
string board()
{
    return "Holes1-7 (1=peg,0=empty): "+llList2CSV(pegs);
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Holes 1-7. Enter from-to like 13 or 53; jump exactly two holes. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==2)
            {
                integer a=llSubStringIndex("1234567",llGetSubString(input,0,0));
                integer b=llSubStringIndex("1234567",llGetSubString(input,1,1));
                integer middle=(a+b)/2;
                if(a>=0&&b>=0&&llAbs(a-b)==2&&llList2Integer(pegs,a)&&llList2Integer(pegs,middle)&&!llList2Integer(pegs,b))
                {
                    pegs=llListReplaceList(pegs,[0],a,a);
                    pegs=llListReplaceList(pegs,[0],middle,middle);
                    pegs=llListReplaceList(pegs,[1],b,b);
                }
                else llOwnerSay("Illegal jump.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Seven-letter word garden

Find words from a fixed authored list using a small shared letter set.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use letters a,c,e,l,p,r,t and include a. Enter a word; list is intentionally small. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list words;
list found;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    words=["ace","act","art","are","car","cat","cap","ear","eat","lap","pal","pat","pea","petal","place","plate","trace","crate","react","clear"];
    found=[];
}
string board()
{
    return "Found "+(string)llGetListLength(found)+"/"+(string)llGetListLength(words)+": "+llList2CSV(found);
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Use letters a,c,e,l,p,r,t and include a. Enter a word; list is intentionally small. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llListFindList(words,[input])>=0)
            {
                if(llListFindList(found,[input])<0)found+=[input];
                else llOwnerSay("Already found.");
            }
            else llOwnerSay("Not in this authored word list.");
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Short flashcard deck

Review question-and-answer cards with an explicit reveal step.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Enter SHOW to reveal an answer, then NEXT for the next card. Edit the alternating Q/A list for your topic.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Answers are a small authored deck, not generated factual claims. Every card is shown once in list order.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list cards=["Which prim is the linkset root?","The prim selected last when linking.","What stops stored particle emission?","Calling llParticleSystem with an empty list.","Does deleting a script undo every prim setting?","No. Some properties persist until changed."];
integer index;
integer revealed;
start()
{
    index=0;
    revealed=FALSE;
    ask(llList2String(cards,0)+"\nEnter SHOW.");
}
answer(string s)
{
    s=llToUpper(s);
    if(!revealed&&s=="SHOW")
    {
        revealed=TRUE;
        ask(llList2String(cards,index+1)+"\nEnter NEXT.");
        return;
    }
    if(revealed&&s=="NEXT")
    {
        index+=2;
        if(index>=llGetListLength(cards))
        {
            close();
            llOwnerSay("Deck complete.");
            return;
        }
        revealed=FALSE;
        ask(llList2String(cards,index)+"\nEnter SHOW.");
        return;
    }
    if(revealed)ask("Enter NEXT.");
    else ask("Enter SHOW.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Single-crate warehouse puzzle

Push a crate onto a goal without pulling it through walls.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter n,s,e,w. Grid: # wall, @ you, $ crate, . goal. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer player;
integer crate;
integer goal;
list walls;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    player=16;
    crate=12;
    goal=7;
    walls=[0,1,2,3,4,5,9,10,14,15,19,20,21,22,23,24];
}
string board()
{
    string s="";
    integer i;
    for(i=0;i<25;++i)
    {
        string ch=" ";
        if(llListFindList(walls,[i])>=0)ch="#";
        else if(i==player)ch="@";
        else if(i==crate)ch="$";
        else if(i==goal)ch=".";
        s+=ch;
        if(i%5==4)s+=" / ";
    }
    return s;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter n,s,e,w. Grid: # wall, @ you, $ crate, . goal. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            integer dir=llListFindList(["n","s","e","w"],[input]);
            if(dir>=0)
            {
                integer delta=llList2Integer([-5,5,1,-1],dir);
                integer next=player+delta;
                if(llListFindList(walls,[next])<0)
                {
                    if(next==crate)
                    {
                        integer beyond=crate+delta;
                        if(llListFindList(walls,[beyond])<0)
                        {
                            crate=beyond;
                            player=next;
                        }
                    }
                    else player=next;
                    if(crate==goal)llOwnerSay("Crate on goal!");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Sliding eight-tile puzzle

Reorder numbered tiles by sliding a tile adjacent to the blank.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch to generate a puzzle by valid random moves from a solved board. Enter the number of a tile next to the underscore.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. The scramble is always reachable from the solved state. A random walk can occasionally finish near or at solved; restart for another scramble.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
list board;
integer blank;
string view()
{
    return llDumpList2String(llList2List(board,0,2)," ")+"\n"+llDumpList2String(llList2List(board,3,5)," ")+"\n"+llDumpList2String(llList2List(board,6,8)," ");
}
integer adjacent(integer p)
{
    return llAbs(p/3-blank/3)+llAbs(p%3-blank%3)==1;
}
move(integer p)
{
    string value=llList2String(board,p);
    board=llListReplaceList(board,[value],blank,blank);
    board=llListReplaceList(board,["_"],p,p);
    blank=p;
}
start()
{
    board=["1","2","3","4","5","6","7","8","_"];
    blank=8;
    integer i;
    for(i=0;i<100;++i)
    {
        integer p=(integer)llFrand(9.0);
        if(adjacent(p))move(p);
    }
    ask(view()+"\nEnter adjacent tile 1-8.");
}
answer(string s)
{
    if(digit(s,1,8)<0)
    {
        ask(view()+"\nEnter a tile number 1-8.");
        return;
    }
    integer p=llListFindList(board,[s]);
    if(p<0||!adjacent(p))
    {
        ask(view()+"\nChoose a tile beside the blank.");
        return;
    }
    move(p);
    if(llDumpList2String(board,"")=="12345678_")
    {
        close();
        llOwnerSay("Puzzle solved.");
        return;
    }
    ask(view()+"\nSlide another tile.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Take-away stones

Take one to three stones per turn; the last stone wins.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch for a 15-stone game. Enter 1, 2, or 3; the computer then plays.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. The computer uses the simple multiples-of-four strategy where available. It is a teaching game with no wagering.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
integer stones;
start()
{
    stones=15;
    ask("15 stones. Take 1, 2, or 3. Last stone wins.");
}
answer(string s)
{
    integer take=digit(s,1,3);
    if(take<0||take>stones)
    {
        ask((string)stones+" stones. Take a legal amount 1-3.");
        return;
    }
    stones-=take;
    if(!stones)
    {
        close();
        llOwnerSay("You took the last stone. You win.");
        return;
    }
    integer computer=stones%4;
    if(!computer)computer=1;
    if(computer>stones)computer=stones;
    stones-=computer;
    if(!stones)
    {
        close();
        llOwnerSay("Computer took "+(string)computer+" and the last stone.");
        return;
    }
    ask("Computer took "+(string)computer+"; "+(string)stones+" remain. Your move.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Beginner

Tap counter

Count touches and show the tally above the prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim you can reset. Touch to increment.

Stop / restore: Reset or remove the script, then clear or replace its floating text.

Counts since the last script reset; it is not saved between resets.

// Original Incoprea example.
integer taps;
default
{
    state_entry()
    {
        taps = 0;
        llSetText("Taps: 0", <0.9, 0.9, 0.7>, 1.0);
    }
    touch_start(integer count)
    {
        taps += count;
        llSetText("Taps: " + (string)taps, <0.9, 0.9, 0.7>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1

Play & interact · Intermediate

Three-by-three hexapawn

Alternate two sides of chess pawns on a tiny board.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter source and target squares like a1a2. W starts at row1, B at row3. Move forward, capture diagonally. Promotion/elimination wins; agree to reset stalemates. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list cells;
integer turn;
integer done;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    cells=["W","W","W",".",".",".","B","B","B"];
    turn=0;
    done=FALSE;
}
string board()
{
    return "3 "+llDumpList2String(llList2List(cells,6,8),"")+" / 2 "+llDumpList2String(llList2List(cells,3,5),"")+" / 1 "+llDumpList2String(llList2List(cells,0,2),"")+" | turn "+(string)turn;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter source and target squares like a1a2. W starts at row1, B at row3. Move forward, capture diagonally. Promotion/elimination wins; agree to reset stalemates. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(!done&&llStringLength(input)==4)
            {
                integer x=llSubStringIndex("abc",llGetSubString(input,0,0));
                integer y=llSubStringIndex("123",llGetSubString(input,1,1));
                integer nx=llSubStringIndex("abc",llGetSubString(input,2,2));
                integer ny=llSubStringIndex("123",llGetSubString(input,3,3));
                if(x>=0&&y>=0&&nx>=0&&ny>=0)
                {
                    integer direction=1;
                    string own="W";
                    string other="B";
                    if(turn)
                    {
                        direction=-1;
                        own="B";
                        other="W";
                    }
                    integer a=y*3+x;
                    integer b=ny*3+nx;
                    string target=llList2String(cells,b);
                    if(llList2String(cells,a)==own&&ny-y==direction&&((nx==x&&target==".")||(llAbs(nx-x)==1&&target==other)))
                    {
                        cells=llListReplaceList(cells,["."],a,a);
                        cells=llListReplaceList(cells,[own],b,b);
                        if(ny==0||ny==2||llListFindList(cells,[other])<0)
                        {
                            done=TRUE;
                            llOwnerSay(own+" wins.");
                        }
                        turn=!turn;
                    }
                    else llOwnerSay("Illegal pawn move.");
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Three-choice touch menu

Open a tiny menu with three playful choices.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch the object. Choices arrive through the viewer dialog; a short-lived, per-avatar listener captures the reply.

Stop / restore: The listener times out after 30 seconds or closes after one answer.

Menus appear only for the toucher. Replies are matched to their avatar key. Works best with a viewer that accepts llDialog.

// Original Incoprea example. Dialog is private to the touching avatar.
integer listenHandle;
integer replyChannel;
key toucher;
default
{
    state_entry()
    {
        llSetTimerEvent(0.0);
    }
    touch_start(integer count)
    {
        if (listenHandle) llListenRemove(listenHandle);
        toucher = llDetectedKey(0);
        replyChannel = -1000 - (integer)llFrand(1000000.0);
        listenHandle = llListen(replyChannel, "", toucher, "");
        llDialog(toucher, "Choose a tiny adventure:", ["Moon", "Garden", "Return"],
        replyChannel);
        llSetTimerEvent(30.0);
    }
    listen(integer channel, string name, key id, string choice)
    {
        if (id == toucher)
        {
            llInstantMessage(toucher, "You chose: " + choice);
            llListenRemove(listenHandle);
            listenHandle = 0;
            llSetTimerEvent(0.0);
        }
    }
    timer()
    {
        if (listenHandle) llListenRemove(listenHandle);
        listenHandle = 0;
        llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Three-disk Hanoi table

Move three ordered disks between pegs without placing a larger disk on a smaller one.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter source and destination as ab, ac, ba, bc, ca or cb. Peg a starts full; goal c. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list positions;
integer moves;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    positions=[0,0,0];
    moves=0;
}
string board()
{
    return "Disk 1,2,3 peg indices (a=0,b=1,c=2): "+llList2CSV(positions)+" | moves "+(string)moves;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter source and destination as ab, ac, ba, bc, ca or cb. Peg a starts full; goal c. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(llStringLength(input)==2)
            {
                integer from=llSubStringIndex("abc",llGetSubString(input,0,0));
                integer to=llSubStringIndex("abc",llGetSubString(input,1,1));
                integer topFrom=-1;
                integer topTo=-1;
                integer i;
                for(i=2;i>=0;--i)
                {
                    if(llList2Integer(positions,i)==from)topFrom=i;
                    if(llList2Integer(positions,i)==to)topTo=i;
                }
                if(from>=0&&to>=0&&from!=to&&topFrom>=0&&(topTo<0||topFrom<topTo))
                {
                    positions=llListReplaceList(positions,[to],topFrom,topFrom);
                    ++moves;
                    if(llList2CSV(positions)=="2, 2, 2")llOwnerSay("All disks on c!");
                }
                else llOwnerSay("Illegal move.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Timed owner pose sequence

Preview three inventory poses in sequence with automatic cleanup.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add pose_a, pose_b and pose_c. Owner-touch grants permission; each pose lasts four seconds.

Stop / restore: Touch while active to stop. Wait for cleanup before removing; use Stop Animating Me if interrupted.

Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. Only the current sequence pose is stopped. No controls, camera or debit permissions are requested. Permission denial performs no animation.

// Original Incoprea. MIT. Not compiled or tested in-world.
list poses=["pose_a","pose_b","pose_c"];
integer index;
integer active;
integer pending;
string current;
integer permitted()
{
    return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner();
}
stop()
{
    if(current!=""&&permitted())llStopAnimation(current);
    current="";
    active=FALSE;
    llSetTimerEvent(0.0);
}
next()
{
    if(current!=""&&permitted())llStopAnimation(current);
    current="";
    if(!permitted()||index>=llGetListLength(poses))
    {
        stop();
        return;
    }
    string name=llList2String(poses,index++);
    if(llGetInventoryType(name)==INVENTORY_ANIMATION)
    {
        current=name;
        llStartAnimation(name);
    }
    else llOwnerSay("Missing "+name);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            stop();
            return;
        }
        if(pending)return;
        pending=TRUE;
        llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
    }
    run_time_permissions(integer p)
    {
        if(!pending)return;
        pending=FALSE;
        if(!permitted())return;
        active=TRUE;
        index=0;
        next();
        if(active)llSetTimerEvent(4.0);
    }
    timer()
    {
        if(active)next();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Tiny branching story

Explore a three-scene story by typing one of two choices at each step.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch and follow the choice words printed in the prompt.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. All story text is authored in the script. This is a local branching narrative, not an external model or chat service.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer scene;
start()
{
    scene=0;
    ask("A tiny lighthouse floats past. BOARD it or WATCH from shore?");
}
answer(string s)
{
    s=llToLower(s);
    if(scene==0)
    {
        if(s=="board")
        {
            scene=1;
            ask("Inside: a map and a sleeping compass. Read MAP or wake COMPASS?");
        }
        else if(s=="watch")
        {
            scene=2;
            ask("The light spells a word. WAVE or WRITE it down?");
        }
        else ask("Type BOARD or WATCH.");
        return;
    }
    if(scene==1)
    {
        if(s=="map")
        {
            close();
            llOwnerSay("The map shows tomorrow's shoreline. You keep the lighthouse company until dawn.");
        }
        else if(s=="compass")
        {
            close();
            llOwnerSay("The compass points toward an unmade friend. A small journey begins.");
        }
        else ask("Type MAP or COMPASS.");
        return;
    }
    if(s=="wave")
    {
        close();
        llOwnerSay("The lighthouse waves a little beam back. Some adventures are greetings.");
    }
    else if(s=="write")
    {
        close();
        llOwnerSay("The word is AGAIN. You leave a blank page for its return.");
    }
    else ask("Type WAVE or WRITE.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Tiny observatory escape

Solve a small authored sequence of inspect, collect and use actions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Commands: look, inspect desk, take lens, inspect chart, use lens, set 314, open dome. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer lens;
integer chart;
integer focused;
integer unlocked;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    lens=FALSE;
    chart=FALSE;
    focused=FALSE;
    unlocked=FALSE;
}
string board()
{
    return "Observatory: desk, chart, telescope, dome. Lens "+(string)lens+"; chart "+(string)chart+"; focused "+(string)focused;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Commands: look, inspect desk, take lens, inspect chart, use lens, set 314, open dome. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(input=="look")llOwnerSay("A loose lens rests on the desk. The chart is dusty.");
            else if(input=="inspect desk")llOwnerSay("The telescope is missing this lens.");
            else if(input=="take lens")lens=TRUE;
            else if(input=="inspect chart")
            {
                chart=TRUE;
                llOwnerSay("The chart marks three stars, then one, then four.");
            }
            else if(input=="use lens")
            {
                if(lens)
                {
                    focused=TRUE;
                    llOwnerSay("The telescope reveals a three-digit dome lock.");
                }
                else llOwnerSay("Find a lens.");
            }
            else if(input=="set 314")
            {
                if(chart&&focused)
                {
                    unlocked=TRUE;
                    llOwnerSay("Lock released.");
                }
                else llOwnerSay("You need the observations first.");
            }
            else if(input=="open dome")
            {
                if(unlocked)llOwnerSay("The dome opens onto a field of stars. Complete!");
                else llOwnerSay("Locked.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Tiny word ladder

Transform COLD into WARM by changing one letter at a time through a supplied dictionary.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch and enter a four-letter word. The allowed dictionary is printed in the prompt.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. A fixed educational dictionary ensures every accepted word is known. The COLD–CORD–CARD–WARD–WARM route is available.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list WORDS=["cold","cord","card","ward","warm","word","worm","wore","core","care"];
string current;
integer steps;
start()
{
    current="cold";
    steps=0;
    ask("COLD to WARM. Change one letter.\nAllowed: "+llDumpList2String(WORDS,", "));
}
answer(string s)
{
    s=llToLower(s);
    if(llListFindList(WORDS,[s])<0)
    {
        ask("Use the supplied dictionary. Current: "+current);
        return;
    }
    integer difference;
    integer i;
    for(i=0;i<4;++i)if(llGetSubString(s,i,i)!=llGetSubString(current,i,i))++difference;
    if(difference!=1)
    {
        ask("Change exactly one letter from "+current);
        return;
    }
    current=s;
    ++steps;
    if(current=="warm")
    {
        close();
        llOwnerSay("WARM reached in "+(string)steps+" steps.");
    }
    else ask("Current "+current+". Next word?");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Beginner

Touch XY control pad

Turn owner touches on a face into normalized two-axis controller values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a flat control-panel prim and set FACE. Owner-touch reports X/Y in owner chat and sends one link message with code 7402 and a vector string.

Stop / restore: Remove or disable. No object property is changed.

ST coordinates describe the touched surface, not texture transforms. Receivers are optional; this script works as an inspection pad by itself and does not send region chat.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llDetectedTouchFace(0) != FACE) return;
        vector st = llDetectedTouchST(0);
        if (st.x < 0.0 || st.x > 1.0 || st.y < 0.0 || st.y > 1.0) return;
        vector value = <st.x, st.y, 0.0>;
        llOwnerSay("XY: " + (string)value);
        llMessageLinked(LINK_ALL_OTHERS, 7402, (string)value, NULL_KEY);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Track a rotary drag across the angle seam

Accumulate signed angle changes while dragging around a face center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare ordinary cube owned by you. Press away from center, drag around it, then release. Surface mapping can differ on meshes; test one face first.

Stop / restore: Disable/remove; these controllers report privately and do not alter scene properties. Reset clears gesture/session state.

Crossings use shortest per-sample angular differences; extremely fast motion beyond180 degrees per event is ambiguous.

// Original Incoprea. MIT. Owner input only.
integer active;
float lastAngle;
float accumulated;
float nextReport;
sample()
{
    vector uv=llDetectedTouchST(0);
    if(!usable(uv))return;
    vector p=uv-<0.5,0.5,0.0>;
    if(llVecMag(p)<0.08)return;
    float angle=llAtan2(p.y,p.x);
    if(!active)
    {
        lastAngle=angle;
        active=TRUE;
        return;
    }
    float delta=angle-lastAngle;
    while(delta>PI)delta-=TWO_PI;
    while(delta< -PI)delta+=TWO_PI;
    accumulated+=delta;
    lastAngle=angle;
}
integer ownerTouch()
{
    return llDetectedKey(0)==llGetOwner();
}
integer usable(vector uv)
{
    return llDetectedTouchFace(0)>=0&&uv!=TOUCH_INVALID_TEXCOORD;
}
default
{
    touch_start(integer n)
    {
        if(!ownerTouch())return;
        active=FALSE;
        accumulated=0.0;
        sample();
        nextReport=llGetTime()+0.25;
    }
    touch(integer n)
    {
        if(!ownerTouch())return;
        sample();
        if(llGetTime()>=nextReport)
        {
            nextReport=llGetTime()+0.25;
            llOwnerSay("Accumulated degrees="+(string)(accumulated*RAD_TO_DEG));
        }
    }
    touch_end(integer n)
    {
        if(!ownerTouch())return;
        sample();
        llOwnerSay("Final degrees="+(string)(accumulated*RAD_TO_DEG));
        active=FALSE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Play & interact · Intermediate

Two-mark tic-tac-toe board

Play both sides of a small board to study winning lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch, then enter cell numbers 1–9. X and O alternate. Share a physical keyboard if playing together.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. This does not enroll or identify a second player. Board positions follow a printed 3×3 grid.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
integer digit(string text,integer min,integer max)
{
    if(llStringLength(text)!=1)return -1;
    integer n=llSubStringIndex("0123456789",text);
    if(n<min||n>max)return -1;
    return n;
}
list board;
integer turn;
string view()
{
    return llDumpList2String(llList2List(board,0,2)," ")+"\n"+llDumpList2String(llList2List(board,3,5)," ")+"\n"+llDumpList2String(llList2List(board,6,8)," ");
}
integer won()
{
    list lines=[0,1,2,3,4,5,6,7,8,0,3,6,1,4,7,2,5,8,0,4,8,2,4,6];
    integer i;
    for(i=0;i<24;i+=3)
    {
        string a=llList2String(board,llList2Integer(lines,i));
        if((a=="X"||a=="O")&&a==llList2String(board,llList2Integer(lines,i+1))&&a==llList2String(board,llList2Integer(lines,i+2)))return TRUE;
    }
    return FALSE;
}
start()
{
    board=["1","2","3","4","5","6","7","8","9"];
    turn=0;
    ask(view()+"\nX: choose 1-9.");
}
answer(string s)
{
    integer p=digit(s,1,9)-1;
    if(p<0)
    {
        ask(view()+"\nChoose 1-9.");
        return;
    }
    string old=llList2String(board,p);
    if(old=="X"||old=="O")
    {
        ask(view()+"\nThat cell is occupied.");
        return;
    }
    string mark="X";
    if(turn%2)mark="O";
    board=llListReplaceList(board,[mark],p,p);
    ++turn;
    if(won())
    {
        close();
        llOwnerSay(view()+"\n"+mark+" wins.");
        return;
    }
    if(turn==9)
    {
        close();
        llOwnerSay(view()+"\nDraw.");
        return;
    }
    mark="X";
    if(turn%2)mark="O";
    ask(view()+"\n"+mark+": choose 1-9.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Water jug puzzle

Measure exactly four liters using a three-liter and five-liter jug.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter fill3, fill5, empty3, empty5, 3to5 or 5to3. Owner-touch starts a fresh game; type reset to restart. Input times out after 90 seconds.

Stop / restore: Let the input timeout expire or remove the script. No world geometry, avatar or inventory is changed.

Original compact educational game. Owner-only local input; no scores or avatar identities are sent to a service. Output is short ASCII text. Not a competition authority.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer a;
integer b;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    a=0;
    b=0;
}
string board()
{
    return "3L jug: "+(string)a+" | 5L jug: "+(string)b;
}
show()
{
    llOwnerSay(board());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter fill3, fill5, empty3, empty5, 3to5 or 5to3. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string input)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        input=llToLower(llStringTrim(input,STRING_TRIM));
        if(input=="reset")start();
        else
        {
            if(input=="fill3")a=3;
            else if(input=="fill5")b=5;
            else if(input=="empty3")a=0;
            else if(input=="empty5")b=0;
            else if(input=="3to5")
            {
                integer amount=a;
                if(amount>5-b)amount=5-b;
                a-=amount;
                b+=amount;
            }
            else if(input=="5to3")
            {
                integer amount=b;
                if(amount>3-a)amount=3-a;
                b-=amount;
                a+=amount;
            }
            else llOwnerSay("Unknown move.");
            if(b==4)llOwnerSay("Exactly four liters!");
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Play & interact · Intermediate

Word rotation puzzle

Rotate a scrambled circular word back to its original spelling.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch. Submit the word you recognize; the letters have only been rotated, not randomly shuffled.

Stop / restore: Stop responding and the listener closes after 90 seconds, or remove/disable the script. Owner-touch restarts the exercise.

Owner-only local exercise; no prizes, visitor records, network service, or persistent scores. Useful for introducing circular indexing without a math-only example. ASCII vocabulary is editable.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
ask(string prompt)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),prompt,channel);
    llSetTimerEvent(90.0);
}
list words=["lantern","texture","sphere","workshop"];
string secret;
start()
{
    secret=llList2String(words,(integer)llFrand((float)llGetListLength(words)));
    integer shift=1+(integer)llFrand((float)(llStringLength(secret)-1));
    string rotated=llGetSubString(secret,shift,-1)+llGetSubString(secret,0,shift-1);
    ask("Rotate this word in your mind: "+rotated+"\nWhat is the word?");
}
answer(string s)
{
    if(llToLower(s)==secret)
    {
        close();
        llOwnerSay("Correct: "+secret);
    }
    else ask("Not yet. Same letters in a circular order; try again.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        answer(llStringTrim(message,STRING_TRIM));
    }
    timer()
    {
        close();
        llOwnerSay("Exercise paused. Touch to restart.");
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Play & interact · Intermediate

Word-scramble cabinet

Unscramble a short workshop-themed word using an owner-only text box.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim and owner-touch. Edit WORDS to change the vocabulary. Answer within 30 seconds.

Stop / restore: Listener closes after the answer or timeout. Remove the script when finished.

Uses simple ASCII words; scrambled order may occasionally be identical to the original. No visitor information or scores are stored.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list WORDS = ["shader", "script", "sphere", "texture", "canvas"];
string answer;
integer channel;
integer handle;
close()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        close();
        answer = llList2String(WORDS, (integer)llFrand((float)llGetListLength(WORDS)));
        list letters;
        integer i;
        for (i = 0; i < llStringLength(answer); ++i) letters += [llGetSubString(answer, i, i)];
        string scrambled = llDumpList2String(llListRandomize(letters, 1), " ");
        channel = -1000 - (integer)llFrand(1000000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llTextBox(llGetOwner(), "Unscramble: " + scrambled, channel);
        llSetTimerEvent(30.0);
    }
    listen(integer received, string name, key id, string message)
    {
        if (received != channel || id != llGetOwner()) return;
        close();
        if (llToLower(llStringTrim(message, STRING_TRIM)) == answer) llOwnerSay("Correct: " + answer);
        else llOwnerSay("This word was: " + answer);
    }
    timer()
    {
        close();
        llOwnerSay("Puzzle expired.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

NoveltiesCurious objects and tiny virtual-world inventions.40 scripts

Download this category (.zip)

Novelties · Intermediate

Balance beam placement lab

Place bounded integer weights at lever positions and inspect signed torque.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter position,weight using positions-5 through5 and weights0-9. Zero weight clears a position. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Ideal point weights on a massless static beam. It does not simulate flex, friction, acceleration or collision geometry.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list weights;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    weights=[];
    integer i;
    for(i=0;i<11;++i)weights+=[0];
}
string view()
{
    integer torque=0;
    integer total=0;
    integer i;
    for(i=0;i<11;++i)
    {
        integer mass=llList2Integer(weights,i);
        torque+=(i-5)*mass;
        total+=mass;
    }
    string result="Balanced";
    if(torque<0)result="Left-heavy";
    else if(torque>0)result="Right-heavy";
    return result+" | torque "+(string)torque+" total weight "+(string)total+" | positions -5..5 "+llList2CSV(weights);
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter position,weight using positions-5 through5 and weights0-9. Zero weight clears a position. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            list fields=llCSV2List(s);
            if(llGetListLength(fields)==2)
            {
                string ps=llStringTrim(llList2String(fields,0),STRING_TRIM);
                string ws=llStringTrim(llList2String(fields,1),STRING_TRIM);
                integer p=(integer)ps;
                integer w=(integer)ws;
                if((string)p==ps&&(string)w==ws&&p>=-5&&p<=5&&w>=0&&w<=9)weights=llListReplaceList(weights,[w],p+5,p+5);
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Bounded Koch rewrite lab

Expand a short turtle-drawing grammar without building geometry.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter grow to replace F with F+F--F+F. F=forward, plus/minus=60degree turns. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. A rewriting-system lesson. It emits instructions, not a visual fractal or a prim rezzer. The growth cap prevents runaway output.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
string word;
integer generation;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    word="F";
    generation=0;
}
string view()
{
    return "Generation "+(string)generation+": "+word;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter grow to replace F with F+F--F+F. F=forward, plus/minus=60degree turns. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="grow")
            {
                string next="";
                integer i;
                for(i=0;i<llStringLength(word);++i)
                {
                    string ch=llGetSubString(word,i,i);
                    if(ch=="F")next+="F+F--F+F";
                    else next+=ch;
                }
                if(llStringLength(next)<=240)
                {
                    word=next;
                    ++generation;
                }
                else llOwnerSay("240-character limit reached; reset to restart.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Bounded robot command lab

Rehearse turn and forward commands on a small text grid with a fuel budget.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter left,right,forward or refuel. Robot stays inside a5x5 grid. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. This exercises command state and boundary checks without moving any prim or avatar.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer x;
integer y;
integer direction;
integer fuel;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    x=2;
    y=2;
    direction=0;
    fuel=20;
}
string view()
{
    return "Robot x="+(string)x+" y="+(string)y+" heading "+llList2String(["N","E","S","W"],direction)+" fuel "+(string)fuel;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter left,right,forward or refuel. Robot stays inside a5x5 grid. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="left")direction=(direction+3)%4;
            else if(s=="right")direction=(direction+1)%4;
            else if(s=="refuel")fuel=20;
            else if(s=="forward"&&fuel>0)
            {
                integer nx=x;
                integer ny=y;
                if(direction==0)--ny;
                else if(direction==1)++nx;
                else if(direction==2)++ny;
                else --nx;
                if(nx>=0&&nx<5&&ny>=0&&ny<5)
                {
                    x=nx;
                    y=ny;
                    --fuel;
                }
                else llOwnerSay("Boundary: command rejected without fuel cost.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Beginner

Breathing lantern

A slow glow pulse for a tiny lantern, alien egg, or curious artifact.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a copy of a prim. Starts automatically and changes glow on every face, four times per second.

Stop / restore: Disable or remove the script, then set Glow to 0 in the prim’s texture/material controls.

Glow is a viewer effect, not a point light. Original glow values are not saved.

// Original Incoprea example. MIT.
default
{
    state_entry()
    {
        llResetTime();
        llSetTimerEvent(0.25);
    }
    timer()
    {
        float glow = 0.03 + 0.025 * llSin(llGetTime() * 0.7);
        llSetLinkPrimitiveParamsFast(LINK_THIS,
        [PRIM_GLOW, ALL_SIDES, glow]);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Novelties · Intermediate

Build theme caption board

Choose an authored design constraint to guide a workshop exercise.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit THEMES. Owner-touch selects one of six constraints; Restore reinstates the original hover text.

Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds.

Local owner-only control. Saved snapshots live in script memory and are lost on reset. A useful activity selector rather than a random fortune. It does not start tasks, record participants, or assess finished work.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
menu(string prompt,list buttons)
{
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llDialog(llGetOwner(),prompt,buttons,channel);
    llSetTimerEvent(45.0);
}
list THEMES=["Build using only circles","Make a readable sign","Design for a tiny avatar","Make movement feel slow","Use light without glare","Create an accessible sound cue"];
list saved;
init()
{
    saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
}
show()
{
    menu("Workshop constraint",["Circles","Sign","Tiny","Slow","Light","Sound","Restore"]);
}
choose(string s)
{
    if(s=="Restore")llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    else
    {
        integer i=llListFindList(["Circles","Sign","Tiny","Slow","Light","Sound"],[s]);
        if(i<0)return;
        llSetText(llList2String(THEMES,i),<0.9,0.9,0.7>,1.0);
    }
    show();
}
default
{
    state_entry()
    {
        init();
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        show();
    }
    listen(integer ch,string name,key id,string message)
    {
        if(!handle||ch!=channel||id!=llGetOwner())return;
        choose(message);
    }
    timer()
    {
        close();
    }
    changed(integer change)
    {
        if(change&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Damped spring state lab

Advance a small damped oscillator and inspect position, velocity and approximate energy.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step,ten,left or right. Left/right change the sample displacement by half a unit. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Fixed-step semi-implicit Euler with unit mass and stiffness. Approximate energy is diagnostic, not exact conservation. It moves no physical objects.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
float x;
float velocity;
integer steps;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    x=1.0;
    velocity=0.0;
    steps=0;
}
string view()
{
    return "Step "+(string)steps+" x="+(string)x+" v="+(string)velocity+" energy~"+(string)(0.5*x*x+0.5*velocity*velocity);
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step,ten,left or right. Left/right change the sample displacement by half a unit. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="left")
            {
                if(x>-5.0)x-=0.5;
            }
            else if(s=="right")
            {
                if(x<5.0)x+=0.5;
            }
            else
            {
                integer count=0;
                if(s=="step")count=1;
                else if(s=="ten")count=10;
                integer i;
                for(i=0;i<count;++i)
                {
                    velocity+=(-x-0.15*velocity)*0.1;
                    x+=velocity*0.1;
                    ++steps;
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Beginner

Eight-bit teaching counter

Show the same number in decimal and eight-bit binary, advancing on touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare teaching prim and touch to advance from 0 to 255, then wrap to 0.

Stop / restore: Disable or remove and clear its hover text. Reset starts the counter again.

An educational display; it does not record visitor identities or preserve the count across resets.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer value;
show()
{
    string bits = "";
    integer bit;
    for (bit = 7; bit >= 0; --bit)
    {
        if (value & (1 << bit)) bits += "1";
        else bits += "0";
    }
    llSetText((string)value + " decimal\n" + bits + " binary", <0.6, 1.0, 0.8>, 1.0);
}
default
{
    state_entry()
    {
        show();
    }
    touch_start(integer count)
    {
        value = (value + 1) % 256;
        show();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Novelties · Intermediate

Eight-thread weaving card

Compare plain, twill and basket interlacing as a compact text weave draft.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter plain,twill,basket or invert. X=warp above weft, dot=weft above warp. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. A structural interlacing diagram, not a loom controller or complete manufacturing draft. The script stores no material inventory.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer mode;
integer inverted;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    mode=0;
    inverted=FALSE;
}
string view()
{
    string text="";
    integer row;
    integer col;
    for(row=0;row<8;++row)
    {
        for(col=0;col<8;++col)
        {
            integer up=0;
            if(mode==0)up=(row+col)%2;
            else if(mode==1)up=((col-row+8)%4)<2;
            else up=((row/2)+(col/2))%2;
            if(inverted)up=!up;
            if(up)text+="X";
            else text+=".";
        }
        text+=" / ";
    }
    return text;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter plain,twill,basket or invert. X=warp above weft, dot=weft above warp. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="plain")mode=0;
            else if(s=="twill")mode=1;
            else if(s=="basket")mode=2;
            else if(s=="invert")inverted=!inverted;
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Fictional weather chain

Generate weather states from state-dependent transition probabilities.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step or ten. This creates fictional weather, not a forecast. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Probabilities are invented. Shows the difference between independent random selection and a process with state memory.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer weatherState;
list history;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    weatherState=0;
    history=["clear"];
}
string view()
{
    return "Recent fictional states: "+llDumpList2String(history," > ");
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step or ten. This creates fictional weather, not a forecast. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            integer count=0;
            if(s=="step")count=1;
            else if(s=="ten")count=10;
            integer i;
            for(i=0;i<count;++i)
            {
                float r=llFrand(1.0);
                if(weatherState==0)
                {
                    if(r<0.7)weatherState=0;
                    else weatherState=1;
                }
                else if(weatherState==1)
                {
                    if(r<0.3)weatherState=0;
                    else if(r<0.7)weatherState=1;
                    else weatherState=2;
                }
                else
                {
                    if(r<0.6)weatherState=2;
                    else weatherState=1;
                }
                history+=[llList2String(["clear","cloud","rain"],weatherState)];
                if(llGetListLength(history)>12)history=llDeleteSubList(history,0,0);
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Beginner

Firefly mood lamp

Touch to give your tiny lantern one of three hand-picked colors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a lantern-shaped prim. Touch to move between green, lilac, and amber.

Stop / restore: Disable the script and restore its original color in Edit.

Prim color only; it does not create light or modify permissions.

// Original Incoprea example.
integer mood;
list colors = [<0.55, 0.92, 0.62>, <0.76, 0.62, 1.0>, <1.0, 0.68, 0.36>];
default
{
    state_entry()
    {
        mood = 0;
    }
    touch_start(integer count)
    {
        mood = (mood + 1) % llGetListLength(colors);
        llSetColor(llList2Vector(colors, mood), ALL_SIDES);
    }
}

MIT · original Incoprea example

API reference 1

Novelties · Intermediate

Five-by-five Langton ant

Step an ant that turns according to the color of its current cell.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step or ten. Board wraps at edges; ant starts in center facing north. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. White cells turn right; black cells left. The finite torus differs from the usual infinite-plane ant.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list cells;
integer pos;
integer direction;
integer steps;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    cells=[];
    integer i;
    for(i=0;i<25;++i)cells+=[0];
    pos=12;
    direction=0;
    steps=0;
}
string view()
{
    string text="Step "+(string)steps+" direction "+(string)direction+": ";
    integer i;
    for(i=0;i<25;++i)
    {
        if(i==pos)text+="A";
        else if(llList2Integer(cells,i))text+="#";
        else text+=".";
        if(i%5==4)text+=" / ";
    }
    return text;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step or ten. Board wraps at edges; ant starts in center facing north. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            integer count=0;
            if(s=="step")count=1;
            else if(s=="ten")count=10;
            integer i;
            for(i=0;i<count;++i)
            {
                integer old=llList2Integer(cells,pos);
                if(old)direction=(direction+3)%4;
                else direction=(direction+1)%4;
                cells=llListReplaceList(cells,[!old],pos,pos);
                integer x=pos%5;
                integer y=pos/5;
                if(direction==0)y=(y+4)%5;
                else if(direction==1)x=(x+1)%5;
                else if(direction==2)y=(y+1)%5;
                else x=(x+4)%5;
                pos=y*5+x;
                ++steps;
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Five-cell diffusion lab

Spread a conserved scalar across five adjacent cells with reflecting boundaries.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step, or heat to add one unit at center. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Illustrates diffusion with a stable fixed coefficient; units are arbitrary. Floating-point rounding may cause small conservation errors.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list values;
integer steps;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    values=[0.0,0.0,10.0,0.0,0.0];
    steps=0;
}
string view()
{
    return "Step "+(string)steps+": "+llList2CSV(values);
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step, or heat to add one unit at center. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="heat")
            {
                float center=llList2Float(values,2);
                if(center<100.0)values=llListReplaceList(values,[center+1.0],2,2);
            }
            else if(s=="step")
            {
                list next=[];
                integer i;
                for(i=0;i<5;++i)
                {
                    float here=llList2Float(values,i);
                    float left=here;
                    float right=here;
                    if(i>0)left=llList2Float(values,i-1);
                    if(i<4)right=llList2Float(values,i+1);
                    next+=[here+0.25*(left+right-2.0*here)];
                }
                values=next;
                ++steps;
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Five-floor elevator simulator

Queue floor requests and move a simulated cabin one floor per step.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter0-4 to request a floor or step to move. Requests keep FIFO order without duplicates. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. A queue lesson only: does not move a platform, open a door, or transport avatars.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer floor;
list queue;
integer served;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    floor=0;
    queue=[];
    served=0;
}
string view()
{
    return "Cabin floor "+(string)floor+" | queue "+llList2CSV(queue)+" | served "+(string)served;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter0-4 to request a floor or step to move. Requests keep FIFO order without duplicates. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="step")
            {
                if(llGetListLength(queue))
                {
                    integer target=llList2Integer(queue,0);
                    if(floor<target)++floor;
                    else if(floor>target)--floor;
                    if(floor==target)
                    {
                        queue=llDeleteSubList(queue,0,0);
                        ++served;
                        llOwnerSay("Door cycle at floor "+(string)floor);
                    }
                }
            }
            else if(llStringLength(s)==1)
            {
                integer target=llSubStringIndex("01234",s);
                if(target>=0&&llListFindList(queue,[target])<0)queue+=[target];
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Four-by-four Life board

Edit live cells and advance a small Conway Life board one generation at a time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter1-16 to toggle a row-major cell or step to advance. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Cells outside the4x4 board are dead, not wrapped. No unbounded automatic generations.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list cells;
integer generation;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    cells=[0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0];
    generation=0;
}
string view()
{
    string text="Generation "+(string)generation+": ";
    integer i;
    for(i=0;i<16;++i)
    {
        if(llList2Integer(cells,i))text+="X";
        else text+=".";
        if(i%4==3)text+=" / ";
    }
    return text;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter1-16 to toggle a row-major cell or step to advance. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="step")
            {
                list next=[];
                integer i;
                for(i=0;i<16;++i)
                {
                    integer count=0;
                    integer dx;
                    integer dy;
                    for(dy=-1;dy<=1;++dy)for(dx=-1;dx<=1;++dx)
                    {
                        integer x=i%4+dx;
                        integer y=i/4+dy;
                        if((dx||dy)&&x>=0&&x<4&&y>=0&&y<4)count+=llList2Integer(cells,y*4+x);
                    }
                    integer alive=count==3||(count==2&&llList2Integer(cells,i));
                    next+=[alive];
                }
                cells=next;
                ++generation;
            }
            else
            {
                integer cell=(integer)s-1;
                if(cell>=0&&cell<16&&(string)(cell+1)==s)cells=llListReplaceList(cells,[!llList2Integer(cells,cell)],cell,cell);
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Gentle breathing display

Alternate a four-second In and six-second Out display with no breath-holding phase.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim. Owner-touch starts or stops the visual cue. Follow it only if comfortable; it is a decorative pacing aid.

Stop / restore: Touch to stop and restore the original hover text before deleting.

Not a medical tool. It neither tracks nor records anyone’s breathing, and uses no avatar animations.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active;
list original;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            llResetTime();
            llSetTimerEvent(0.25);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
        }
    }
    timer()
    {
        integer second = (integer)llGetTime() % 10;
        if (second < 4) llSetText("In  " + (string)(4 - second), <0.7, 0.9, 1.0>, 1.0);
        else llSetText("Out  " + (string)(10 - second), <0.7, 1.0, 0.8>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Beginner

Geometric firefly jar

Emit a few softly tinted sparkles from a small jar or crystal.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a copy of your object. The built-in particle texture is used. Nearby viewers see the effect.

Stop / restore: Run Stop particle effect below. Removing this script alone may leave the emitter settings set.

Particles are viewer effects; there is no physics or persistent inventory. Keep the rate low.

// Original Incoprea example. Low-rate particle effect.
default
{
    state_entry()
    {
        llParticleSystem([
        PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_INTERP_COLOR_MASK,
        PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
        PSYS_PART_START_COLOR, <0.72, 1.0, 0.63>,
        PSYS_PART_END_COLOR, <0.90, 0.75, 1.0>,
        PSYS_PART_START_ALPHA, 0.85,
        PSYS_PART_END_ALPHA, 0.0,
        PSYS_PART_START_SCALE, <0.08, 0.08, 0.0>,
        PSYS_PART_END_SCALE, <0.025, 0.025, 0.0>,
        PSYS_PART_MAX_AGE, 3.0,
        PSYS_SRC_BURST_PART_COUNT, 1,
        PSYS_SRC_BURST_RATE, 0.8,
        PSYS_SRC_BURST_RADIUS, 0.12,
        PSYS_SRC_BURST_SPEED_MIN, 0.04,
        PSYS_SRC_BURST_SPEED_MAX, 0.16,
        PSYS_SRC_ACCEL, <0.0, 0.0, 0.06>,
        PSYS_SRC_ANGLE_BEGIN, 0.0,
        PSYS_SRC_ANGLE_END, 0.55,
        PSYS_SRC_MAX_AGE, 0.0
        ]);
    }
}

MIT · original Incoprea example

API reference 1

Novelties · Intermediate

Intersection phase rehearsal

Step through a two-direction signal plan with explicit all-red intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step to advance phase or emergency for all red. Resume starts from first all-red phase. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Text-only safety illustration. Not suitable for controlling traffic or any real safety-critical system.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer phase;
integer emergency;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    phase=0;
    emergency=FALSE;
}
string view()
{
    if(emergency)return "ALL RED - rehearsal hold";
    return llList2String(["ALL RED","NS green / EW red","NS yellow / EW red","ALL RED","NS red / EW green","NS red / EW yellow"],phase);
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step to advance phase or emergency for all red. Resume starts from first all-red phase. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="emergency")emergency=TRUE;
            else if(s=="resume")
            {
                emergency=FALSE;
                phase=0;
            }
            else if(s=="step"&&!emergency)phase=(phase+1)%6;
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Manual reservoir valves

Experiment with inflow, drain and overflow in a bounded virtual tank.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter inlet, drain or step. Valve commands toggle; step advances one arbitrary time unit. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. The order is fill, drain, clamp. No fluid objects are created or real valves controlled.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer water;
integer inlet;
integer drain;
integer spilled;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    water=20;
    inlet=FALSE;
    drain=FALSE;
    spilled=0;
}
string view()
{
    return "Tank "+(string)water+"/100 | inlet "+(string)inlet+" drain "+(string)drain+" overflow "+(string)spilled;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter inlet, drain or step. Valve commands toggle; step advances one arbitrary time unit. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="inlet")inlet=!inlet;
            else if(s=="drain")drain=!drain;
            else if(s=="step")
            {
                if(inlet)water+=7;
                if(drain)water-=4;
                if(water<0)water=0;
                if(water>100)
                {
                    spilled+=water-100;
                    water=100;
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Morse-code teaching beacon

Blink the familiar three-short, three-long, three-short pattern for a Morse lesson.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim and set FACE. Owner-touch starts or stops. Uses half-second timing units and a low glow.

Stop / restore: Touch to restore the captured fullbright and glow values before removal or reset.

A teaching prop, not an emergency signaling system. Timer lag changes timing; use a modest display size and avoid intense glow.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
list units = [1,1,1,1,1,3,3,1,3,1,3,3,1,1,1,1,1,7];
integer index;
integer active;
integer fullbright;
float glow;
default
{
    state_entry()
    {
        list saved = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_FULLBRIGHT, FACE, PRIM_GLOW, FACE]);
        fullbright = llList2Integer(saved, 0);
        glow = llList2Float(saved, 1);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            index = 0;
            llSetTimerEvent(0.1);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_FULLBRIGHT, FACE, fullbright, PRIM_GLOW, FACE, glow]);
        }
    }
    timer()
    {
        integer on = !(index % 2);
        float value = 0.0;
        if (on) value = 0.08;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_FULLBRIGHT, FACE, on, PRIM_GLOW, FACE, value]);
        llSetTimerEvent(0.5 * llList2Integer(units, index));
        index = (index + 1) % llGetListLength(units);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Beginner

Museum of small mysteries

Cycle through curious exhibit labels on a little museum plinth.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a copy of a display object. Labels change every 20 seconds.

Stop / restore: Disable the script and clear the floating text.

The messages are public hover text and reset when the script resets.

// Original Incoprea example.
list labels = [
"Exhibit 1: a map of somewhere that almost existed.",
"Exhibit 2: the last thought of a forgetful moon.",
"Exhibit 3: a key with no known door.",
"Exhibit 4: a very small weather system."
];
showExhibit()
{
    integer pick = (integer)llFrand((float)llGetListLength(labels));
    llSetText(llList2String(labels, pick), <0.76, 0.88, 0.78>, 1.0);
}
default
{
    state_entry()
    {
        showExhibit();
        llSetTimerEvent(20.0);
    }
    timer()
    {
        showExhibit();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Museum quiet-reading mode

Toggle a prim between its normal label and a quiet-reading caption while silencing its attached audio.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a dedicated exhibit audio/label prim. Edit QUIET_CAPTION. Owner-touch activates quiet mode; touch again restores the original label.

Stop / restore: Turn quiet mode off to restore text before removing. Audio is stopped, not automatically restarted.

This is a manual exhibit affordance, not a sensor of someone’s accessibility needs. It affects only the prim containing the script. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
string QUIET_CAPTION="Quiet reading mode: please use the written exhibit description.";
list saved;
integer quiet;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        quiet=!quiet;
        if(quiet)
        {
            llStopSound();
            llSetText(QUIET_CAPTION,<0.9,0.95,1.0>,1.0);
        }
        else llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Novelties · Intermediate

NAND latch interactive lab

Explore set, clear, hold and the forbidden input combination of a latch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter set,clear,hold or forbidden. Active-low NAND-latch inputs are shown. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Abstract behavior model, not gate-delay simulation. The forbidden state intentionally remains indeterminate until an explicit valid set or clear.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer q;
integer unknown;
integer setInput;
integer resetInput;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    q=0;
    unknown=FALSE;
    setInput=1;
    resetInput=1;
}
string view()
{
    if(setInput==0&&resetInput==0)return "S=0 R=0: Q=1 and inverseQ=1 (forbidden). Release may be indeterminate.";
    string output=(string)q;
    if(unknown)output="indeterminate";
    return "Active-low S="+(string)setInput+" R="+(string)resetInput+" | Q "+output;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter set,clear,hold or forbidden. Active-low NAND-latch inputs are shown. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="set")
            {
                setInput=0;
                resetInput=1;
                q=1;
                unknown=FALSE;
            }
            else if(s=="clear")
            {
                setInput=1;
                resetInput=0;
                q=0;
                unknown=FALSE;
            }
            else if(s=="hold")
            {
                setInput=1;
                resetInput=1;
            }
            else if(s=="forbidden")
            {
                setInput=0;
                resetInput=0;
                unknown=TRUE;
                llOwnerSay("Forbidden combination; release can be indeterminate. Set or clear to establish state.");
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Beginner

Pocket oracle

Touch a small object for a quietly peculiar fortune above it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put this in a prim shaped like a pebble, shell, or mysterious machine. Touch to choose a message.

Stop / restore: Disable or remove it, then run Clear floating text in the same prim.

Messages are public hover text; it sends no chat messages and uses no external service.

// Original Incoprea example. MIT.
list fortunes = ["The moon has misplaced its keys.",
"Take the scenic teleport.", "A very small adventure is nearby.",
"Today, be the interesting rock."];
default
{
    state_entry()
    {
        llSetText("Touch for a small omen", <0.8, 0.9, 1.0>, 1.0);
    }
    touch_start(integer count)
    {
        integer choice = (integer)llFrand((float)llGetListLength(fortunes));
        llSetText(llList2String(fortunes, choice), <0.8, 0.9, 1.0>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Novelties · Beginner

Pocket weather report

Change a little weather report every 30 seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a copy of a sign. It cycles through fictional, gentle forecasts.

Stop / restore: Disable the script and clear the floating text.

These are invented fortunes, not region weather data.

// Original Incoprea example. Whimsical weather, not a real forecast.
list forecast = ["Chance of pocket-sized clouds.", "The wind may hum today.",
"A blue afternoon with one curious moon.", "Clear skies for tiny adventures."];
showForecast()
{
    integer pick = (integer)llFrand((float)llGetListLength(forecast));
    llSetText(llList2String(forecast, pick), <0.68, 0.86, 1.0>, 1.0);
}
default
{
    state_entry()
    {
        showForecast();
        llSetTimerEvent(30.0);
    }
    timer()
    {
        showForecast();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Push-your-luck point game

Choose whether to bank a temporary score or risk another die roll.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter roll or bank. Rolling1 loses the current unbanked score; other faces add points. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Local imaginary points only: no money, purchases, rewards, accounts or persistent leaderboard.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer roundPoints;
integer banked;
integer turns;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    roundPoints=0;
    banked=0;
    turns=0;
}
string view()
{
    return "Unbanked "+(string)roundPoints+" | banked "+(string)banked+" | rolls "+(string)turns;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter roll or bank. Rolling1 loses the current unbanked score; other faces add points. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="roll")
            {
                integer die=1+(integer)llFrand(6.0);
                ++turns;
                llOwnerSay("Rolled "+(string)die);
                if(die==1)roundPoints=0;
                else if(roundPoints<10000)roundPoints+=die;
            }
            else if(s=="bank")
            {
                if(banked+roundPoints<=1000000)
                {
                    banked+=roundPoints;
                    roundPoints=0;
                }
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Rule30 cellular strip

Evolve sixteen binary cells using the local three-cell Rule30 transition.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step or1-16 to toggle a cell. Ends wrap. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Only the current generation is retained. This is a1D cellular rule, not random-number security.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list cells;
integer generation;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    cells=[0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0];
    generation=0;
}
string view()
{
    return "Generation "+(string)generation+": "+llDumpList2String(cells,"");
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step or1-16 to toggle a cell. Ends wrap. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="step")
            {
                list next=[];
                integer i;
                for(i=0;i<16;++i)
                {
                    integer bits=llList2Integer(cells,(i+15)%16)*4+llList2Integer(cells,i)*2+llList2Integer(cells,(i+1)%16);
                    next+=[(30>>bits)&1];
                }
                cells=next;
                ++generation;
            }
            else
            {
                integer cell=(integer)s-1;
                if(cell>=0&&cell<16&&(string)(cell+1)==s)cells=llListReplaceList(cells,[!llList2Integer(cells,cell)],cell,cell);
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Short text marquee

Move a short message through an 18-character hover-text window.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare sign prim and edit MESSAGE. Owner-touch starts or stops the ticker.

Stop / restore: Touch to stop and restore the original hover text before removing or resetting.

Uses substring characters, not pixel measurement; proportional fonts and complex Unicode can appear uneven. No web or chat feed is connected.

// Original Incoprea example. MIT. Not compiled or tested in-world.
string MESSAGE = "Welcome to the little workshop";
string padded;
integer offset;
integer active;
list original;
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
        padded = "                  " + MESSAGE + "                  ";
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            offset = 0;
            llSetTimerEvent(0.35);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
        }
    }
    timer()
    {
        llSetText(llGetSubString(padded, offset, offset + 17), <0.8, 1.0, 0.8>, 1.0);
        ++offset;
        if (offset > llStringLength(padded) - 18) offset = 0;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Beginner

Slowly revealing sign

Reveal a short poetic message one character at a time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit MESSAGE before use. Put in a copy of a prim with floating text enabled.

Stop / restore: Disable the script and clear the floating text.

The public hover text updates once per second until the message is complete.

// Original Incoprea example.
string MESSAGE = "A small door remembers every visitor.";
integer shown;
default
{
    state_entry()
    {
        shown = 0;
        llSetText("", <0.8, 0.95, 0.75>, 1.0);
        llSetTimerEvent(1.0);
    }
    timer()
    {
        integer last = llStringLength(MESSAGE) - 1;
        if (shown > last)
        {
            llSetTimerEvent(0.0);
            return;
        }
        llSetText(llGetSubString(MESSAGE, 0, shown), <0.8, 0.95, 0.75>, 1.0);
        ++shown;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Beginner

Sun and shadow explainer

Estimate the horizontal shadow of a one-meter upright pole from the simulator sun direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a teaching prop. Owner-touch reports a ground-plane offset vector when the sun is above the horizon.

Stop / restore: Remove or disable. It does not alter the environment or a prim.

Assumes a flat horizontal ground plane and a one-meter pole. Viewer personal environment overrides may not match the simulator environment; it does not trace actual rendered shadows.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector sun = llGetSunDirection();
        if (sun.z <= 0.05)
        {
            llOwnerSay("Sun too low for a useful finite shadow estimate.");
            return;
        }
        vector shadow = <-sun.x / sun.z, -sun.y / sun.z, 0.0>;
        llOwnerSay("One-meter pole shadow offset in world meters: " + (string)shadow
        + " | length " + (string)llVecMag(shadow));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Novelties · Intermediate

Sun elevation and azimuth

Report the simulator sun’s elevation and compass azimuth for a lighting study.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a sundial or lighting-test prop.

Stop / restore: Remove/disable; the environment is read only.

Uses parcel sun direction and may differ from a viewer’s personal environment. Azimuth is undefined near directly overhead or below.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector sun=llVecNorm(llGetSunDirection());
        float z=sun.z;
        if(z>1.0)z=1.0;
        if(z< -1.0)z=-1.0;
        float elevation=llAsin(z)*RAD_TO_DEG;
        vector horizontal=<sun.x,sun.y,0.0>;
        string azimuth="undefined near vertical";
        if(llVecMag(horizontal)>0.001)
        {
            float a=llAtan2(sun.x,sun.y)*RAD_TO_DEG;
            if(a<0.0)a+=360.0;
            azimuth=(string)llRound(a)+" degrees";
        }
        llOwnerSay("Sun elevation "+(string)elevation+" degrees; azimuth "+azimuth);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Text hourglass

A one-minute visual timer with a ten-cell progress bar and a completion message.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Owner-touch starts; touching while running cancels and restores the original hover text.

Stop / restore: After completion touch once to restore the original text before removal. The next touch starts a new timer.

Tracks elapsed script time rather than counting timer events. Not intended for safety-critical timing; no sound required.

// Original Incoprea example. MIT. Not compiled or tested in-world.
float DURATION = 60.0;
integer active;
integer showing;
list original;
restore()
{
    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
}
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (active || showing)
        {
            active = FALSE;
            showing = FALSE;
            llSetTimerEvent(0.0);
            restore();
            return;
        }
        if (DURATION < 1.0) DURATION = 1.0;
        active = TRUE;
        showing = TRUE;
        llResetTime();
        llSetTimerEvent(0.5);
    }
    timer()
    {
        float elapsed = llGetTime();
        if (elapsed >= DURATION)
        {
            active = FALSE;
            llSetTimerEvent(0.0);
            llSetText("Time is up", <0.7, 1.0, 0.8>, 1.0);
            return;
        }
        integer filled = (integer)(10.0 * elapsed / DURATION);
        string bar = "";
        integer i;
        for (i = 0; i < 10; ++i)
        {
            if (i < filled) bar += "#";
            else bar += "-";
        }
        llSetText("[" + bar + "]\n" + (string)llCeil(DURATION - elapsed) + " seconds", <0.7, 1.0, 0.8>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Three-by-three sandpile

Add grains and manually relax unstable piles into their neighbors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter1-9 to add a grain, or step to topple each eligible cell once. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Sequential toppling pass; repeat step until stable. Grains leaving the finite boundary are counted and lost.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list piles;
integer lost;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    piles=[0,0,0,0,0,0,0,0,0];
    lost=0;
}
string view()
{
    return "Rows: "+llList2CSV(llList2List(piles,0,2))+" / "+llList2CSV(llList2List(piles,3,5))+" / "+llList2CSV(llList2List(piles,6,8))+" | boundary loss "+(string)lost;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter1-9 to add a grain, or step to topple each eligible cell once. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="step")
            {
                integer i;
                for(i=0;i<9;++i)if(llList2Integer(piles,i)>=4)
                {
                    piles=llListReplaceList(piles,[llList2Integer(piles,i)-4],i,i);
                    list neighbors=[];
                    if(i%3>0)neighbors+=[i-1];
                    else ++lost;
                    if(i%3<2)neighbors+=[i+1];
                    else ++lost;
                    if(i/3>0)neighbors+=[i-3];
                    else ++lost;
                    if(i/3<2)neighbors+=[i+3];
                    else ++lost;
                    integer j;
                    for(j=0;j<llGetListLength(neighbors);++j)
                    {
                        integer p=llList2Integer(neighbors,j);
                        piles=llListReplaceList(piles,[llList2Integer(piles,p)+1],p,p);
                    }
                }
            }
            else
            {
                integer cell=(integer)s-1;
                if(cell>=0&&cell<9&&(string)(cell+1)==s&&llList2Integer(piles,cell)<99)piles=llListReplaceList(piles,[llList2Integer(piles,cell)+1],cell,cell);
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Three-rod abacus trainer

Show decimal carry using three rods with a five-bead and four single-bead representation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter one,ten,hundred or down. Range0-999; down subtracts one. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Digits are represented separately; this is not an automatic representation of every physical abacus tradition.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer value;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    value=0;
}
string view()
{
    string text=(string)value+" | H T U rods: ";
    integer divisor=100;
    integer i;
    for(i=0;i<3;++i)
    {
        integer digit=(value/divisor)%10;
        text+="["+(string)(digit/5)+" five + "+(string)(digit%5)+" ones] ";
        divisor/=10;
    }
    return text;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter one,ten,hundred or down. Range0-999; down subtracts one. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            integer next=value;
            if(s=="one")++next;
            else if(s=="ten")next+=10;
            else if(s=="hundred")next+=100;
            else if(s=="down")--next;
            if(next>=0&&next<=999)value=next;
            else llOwnerSay("Outside three-rod range.");
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Three-station factory model

Move numbered jobs through three single-capacity stations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter add to queue a job or step to advance one pipeline tick. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Each tick completes station3, shifts stages, then loads one queued job. It creates no objects and controls no equipment.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
list pending;
list stations;
integer nextId;
integer complete;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    pending=[];
    stations=[0,0,0];
    nextId=1;
    complete=0;
}
string view()
{
    return "Waiting "+llList2CSV(pending)+" | stations "+llList2CSV(stations)+" | complete "+(string)complete;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter add to queue a job or step to advance one pipeline tick. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="add")
            {
                if(llGetListLength(pending)<8&&nextId<1000)pending+=[nextId++];
            }
            else if(s=="step")
            {
                if(llList2Integer(stations,2))++complete;
                integer first=0;
                if(llGetListLength(pending))
                {
                    first=llList2Integer(pending,0);
                    pending=llDeleteSubList(pending,0,0);
                }
                stations=[first,llList2Integer(stations,0),llList2Integer(stations,1)];
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

Tiny food-web model

Advance an explicitly simplified plant, herbivore and predator resource loop.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter step, rain to add plants, or seed to add one herbivore. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. Rules are invented for a teaching toy, not ecological prediction. All populations have explicit caps.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer plants;
integer herbivores;
integer predators;
integer turns;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    plants=30;
    herbivores=6;
    predators=2;
    turns=0;
}
string view()
{
    return "Turn "+(string)turns+" | plants "+(string)plants+" herbivores "+(string)herbivores+" predators "+(string)predators;
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter step, rain to add plants, or seed to add one herbivore. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="rain")
            {
                plants+=10;
                if(plants>100)plants=100;
            }
            else if(s=="seed")
            {
                if(herbivores<30)++herbivores;
            }
            else if(s=="step")
            {
                ++turns;
                plants+=5;
                if(plants>100)plants=100;
                if(plants>=herbivores)
                {
                    plants-=herbivores;
                    if(herbivores<30)++herbivores;
                }
                else
                {
                    plants=0;
                    if(herbivores>0)--herbivores;
                }
                integer eaten=predators;
                if(eaten>herbivores)eaten=herbivores;
                herbivores-=eaten;
                if(eaten==predators&&eaten>0&&turns%3==0&&predators<10)++predators;
                else if(eaten<predators&&predators>0)--predators;
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Beginner

Tiny story loom

Weave a miniature scene from three editable word lists.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare story object. Touch for a new scene. Replace the short lists to suit your world.

Stop / restore: Disable or remove, then use Clear floating text. This example replaces its prim’s hover text.

A local combinatorial writing toy with no external AI service, network call, or stored visitor data.

// Original Incoprea example. MIT. Not compiled or tested in-world.
list people = ["A clockmaker", "A lost robot", "A miniature dragon", "An absent-minded moon"];
list actions = ["borrowed a shadow", "planted a staircase", "found a tiny sea", "mailed a thunderstorm"];
list places = ["inside a teacup.", "beneath the last bridge.", "on a quiet asteroid.", "before breakfast."];
string pick(list words)
{
    return llList2String(words, (integer)llFrand((float)llGetListLength(words)));
}
default
{
    touch_start(integer count)
    {
        llSetText(pick(people) + "\n" + pick(actions) + "\n" + pick(places), <0.9, 0.8, 1.0>, 1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Two-flea tabletop race

Advance two fictional racers with alternate die rolls on a twenty-space track.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Enter roll. A and B alternate; first to reach20 wins. Owner-touch initializes; enter reset to restart. Text input closes after90seconds.

Stop / restore: Close or ignore the text box, or remove the script. It changes no world objects, avatar state or inventory.

Original bounded, manually stepped educational toy. Not a calibrated simulator, real-world control system, or live scientific measurement. A single owner operates both fictional racers. It is not network multiplayer or a betting system.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer channel;
integer handle;
integer a;
integer b;
integer turn;
integer done;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0.0);
}
start()
{
    a=0;
    b=0;
    turn=0;
    done=FALSE;
}
string view()
{
    return "A "+(string)a+"/20 | B "+(string)b+"/20 | next "+llList2String(["A","B"],turn);
}
show()
{
    llOwnerSay(view());
    if(!handle)
    {
        channel=-1000-(integer)llFrand(1000000.0);
        handle=llListen(channel,"",llGetOwner(),"");
    }
    llTextBox(llGetOwner(),"Enter roll. A and B alternate; first to reach20 wins. Type reset to restart.",channel);
    llSetTimerEvent(90.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        start();
        show();
    }
    listen(integer incomingChannel,string name,key id,string s)
    {
        if(!handle||incomingChannel!=channel||id!=llGetOwner())return;
        s=llToLower(llStringTrim(s,STRING_TRIM));
        if(s=="reset")start();
        else
        {
            if(s=="roll"&&!done)
            {
                integer die=1+(integer)llFrand(6.0);
                llOwnerSay("Rolled "+(string)die);
                if(turn)b+=die;
                else a+=die;
                if(a>=20||b>=20)
                {
                    done=TRUE;
                    llOwnerSay(llList2String(["A","B"],turn)+" wins.");
                }
                else turn=!turn;
            }
        }
        show();
    }
    timer()
    {
        close();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Novelties · Intermediate

UTC seasonal calendar

Display the UTC date with an illustrative northern-hemisphere season label.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare calendar prim. Updates once per minute. Season labels use meteorological month groups, not astronomical equinox calculations.

Stop / restore: Owner-touch stops and restores the original text; touch again restarts. Stop before removing.

UTC date may differ from your local date. Southern-hemisphere creators should edit or swap the season labels.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer active = TRUE;
list original;
show()
{
    string stamp = llGetTimestamp();
    integer month = (integer)llGetSubString(stamp, 5, 6);
    string season = "Winter";
    if (month >= 3 && month <= 5) season = "Spring";
    else if (month >= 6 && month <= 8) season = "Summer";
    else if (month >= 9 && month <= 11) season = "Autumn";
    llSetText(llGetSubString(stamp, 0, 9) + " UTC\n" + season + " (northern seasons)", <0.8, 0.95, 0.8>, 1.0);
}
default
{
    state_entry()
    {
        original = llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT]);
        show();
        llSetTimerEvent(60.0);
    }
    timer()
    {
        show();
    }
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        active = !active;
        if (active)
        {
            show();
            llSetTimerEvent(60.0);
        }
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_TEXT] + original);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Waterline clearance gauge

Report object-center height above simulator water and water depth above terrain.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a rezzed prop. Read the two measurements in owner chat.

Stop / restore: Remove/disable; this only reads environment data.

Measures simulator terrain/water at the object position, not a mesh pool or animated decorative water surface. Negative water depth means terrain is above water.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector p=llGetPos();
        float water=llWater(ZERO_VECTOR);
        float ground=llGround(ZERO_VECTOR);
        llOwnerSay("Center above water: "+(string)(p.z-water)+" m; water above terrain: "+(string)(water-ground)+" m.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Novelties · Intermediate

Wind bearing instrument

Report the simulator wind’s horizontal speed and destination bearing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a rezzed weather prop at the height of interest.

Stop / restore: Remove/disable; it makes no setting changes.

Bearing is where wind points toward, clockwise from north, not meteorological wind-from direction. Grid wind models can differ.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector wind=llWind(ZERO_VECTOR);
        wind.z=0.0;
        float speed=llVecMag(wind);
        if(speed<0.001)
        {
            llOwnerSay("Calm: no stable horizontal wind bearing.");
            return;
        }
        float bearing=llAtan2(wind.x,wind.y)*RAD_TO_DEG;
        if(bearing<0.0)bearing+=360.0;
        llOwnerSay("Wind toward "+(string)llRound(bearing)+" degrees; horizontal speed "+(string)speed+" m/s.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

SensingSimple sensing with explicit triggers and limits.22 scripts

Download this category (.zip)

Sensing · Intermediate

Nearby owned-object count

Count only the owner’s detected objects in a short-range scan.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch to scan a ten-meter sphere once.

Stop / restore: Remove/disable. Each touch performs one scan.

No avatar surveillance or visitor history. Sensors return capped subsets, not a complete parcel inventory. Agents are excluded explicitly.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer busy;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||busy)return;
        busy=TRUE;
        llSensor("",NULL_KEY,ACTIVE|PASSIVE,10.0,PI);
        llSetTimerEvent(10.0);
    }
    sensor(integer n)
    {
        integer count;
        integer i;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())++count;
        busy=FALSE;
        llSetTimerEvent(0.0);
        llOwnerSay("Detected owned objects: "+(string)count+" (sensor-limited subset).");
    }
    no_sensor()
    {
        busy=FALSE;
        llSetTimerEvent(0.0);
        llOwnerSay("No matching objects detected.");
    }
    timer()
    {
        busy=FALSE;
        llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Opt-in owner floorplan marker

Plot only the owner’s current region position onto an authored miniature map.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a nonphysical root and child owner_marker. Set world ORIGIN, map MAP_SCALE and map offset. Owner-touch arms; root XY should be your map plane.

Stop / restore: Owner-touch disarms and restores marker Home.

Use a spare modifiable build. Snapshot state is held only in script memory; restore before reset/removal. Do not relink during a preview. Reads only the owner after explicit arming, stores no travel history, and sends no data externally. Not GPS or a visitor tracker.

// Original Incoprea. MIT. Not compiled or tested in-world.
vector ORIGIN=<128.0,128.0,0.0>;
float MAP_SCALE=0.01;
vector OFFSET=<0.0,0.0,0.1>;
integer target;
vector home;
integer active;
integer valid=TRUE;
default
{
    state_entry()
    {
        integer i;
        integer count;
        for(i=2;i<=llGetObjectPrimCount(llGetKey());++i)if(llGetLinkName(i)=="owner_marker")
        {
            target=i;
            ++count;
        }
        if(count!=1)
        {
            valid=FALSE;
            return;
        }
        home=llList2Vector(llGetLinkPrimitiveParams(target,[PRIM_POS_LOCAL]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!valid)return;
        active=!active;
        if(active)llSetTimerEvent(2.0);
        else
        {
            llSetTimerEvent(0.0);
            llSetLinkPrimitiveParamsFast(target,[PRIM_POS_LOCAL,home]);
        }
    }
    timer()
    {
        if(llGetStatus(STATUS_PHYSICS)||!valid)
        {
            llSetTimerEvent(0.0);
            active=FALSE;
            return;
        }
        list data=llGetObjectDetails(llGetOwner(),[OBJECT_POS]);
        if(!llGetListLength(data))return;
        vector p=llList2Vector(data,0)-ORIGIN;
        p.z=0.0;
        p=p*MAP_SCALE+OFFSET;
        if(llVecMag(p)>5.0)return;
        llSetLinkPrimitiveParamsFast(target,[PRIM_POS_LOCAL,p]);
    }
    changed(integer change)
    {
        if(change&CHANGED_LINK)
        {
            active=FALSE;
            valid=FALSE;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Own child offset warning

Report a child moving more than twenty-five centimeters from its armed local pose.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a child and owner-touch. Move that child manually or with an existing controller.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Monitoring only, without automatic restoration. Root rotation does not count as local displacement. Rearm after relinking.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
vector reference;
integer displaced;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            reference=llGetLocalPos();
            displaced=FALSE;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        float d=llVecDist(llGetLocalPos(),reference);
        if(!displaced&&d>0.25)
        {
            displaced=TRUE;
            llOwnerSay("Child moved beyond 25 cm from its armed local pose.");
        }
        else if(displaced&&d<0.1)
        {
            displaced=FALSE;
            llOwnerSay("Child returned near its armed local pose.");
        }
    }
}

MIT · original Incoprea example

API reference 1

Sensing · Intermediate

Own-object altitude band monitor

Report transitions into low, middle and high altitude bands.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set LOW/HIGH in meters above region datum. Owner-touch arms.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Only this object’s band is retained; no position history or movement constraint.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float LOW=20.0;
float HIGH=40.0;
integer last=-1;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            last=-1;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        vector p=llGetPos();
        integer band=1;
        if(p.z<LOW)band=0;
        else if(p.z>HIGH)band=2;
        if(band!=last)
        {
            last=band;
            llOwnerSay("Altitude band: "+llList2String(["low","middle","high"],band));
        }
    }
}

MIT · original Incoprea example

API reference 1

Sensing · Intermediate

Own-object radius departure monitor

Report when this object leaves or returns near its armed position.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch captures center; then move this same object.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Three-meter exit and 2.5-meter return bands reduce chatter. Rearm after a region crossing.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
vector center;
integer outside;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            center=llGetPos();
            outside=FALSE;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        float distance=llVecDist(llGetPos(),center);
        if(!outside&&distance>3.0)
        {
            outside=TRUE;
            llOwnerSay("Object left its home radius.");
        }
        else if(outside&&distance<2.5)
        {
            outside=FALSE;
            llOwnerSay("Object returned near home.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object reversal cue

Detect a substantial reversal in object velocity direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch arms. Use an object already moving through its own mechanism.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Compares only this object above 0.2 m/s. Stopping clears the reference; no route is retained.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
vector previous;
float last;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            previous=ZERO_VECTOR;
            last=-10.0;
            llSetTimerEvent(0.5);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        vector v=llGetVel();
        if(llVecMag(v)<0.2)
        {
            previous=ZERO_VECTOR;
            return;
        }
        vector d=llVecNorm(v);
        if(llVecMag(previous)>0.5&&(d*previous)< -0.5&&llGetTime()-last>2.0)
        {
            last=llGetTime();
            llOwnerSay("Object reversed more than 120 degrees.");
        }
        previous=d;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object settling cue

Report when this object has remained nearly still for five seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch arms, then use the object’s existing movement mechanism.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Position jumps may not produce useful velocity. A new movement resets the settling interval.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float since;
integer quiet;
integer reported;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            since=llGetTime();
            quiet=FALSE;
            reported=FALSE;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        if(llVecMag(llGetVel())<0.03)
        {
            if(!quiet)
            {
                quiet=TRUE;
                since=llGetTime();
            }
            if(!reported&&llGetTime()-since>=5.0)
            {
                reported=TRUE;
                llOwnerSay("Nearly still for five seconds.");
            }
        }
        else
        {
            quiet=FALSE;
            reported=FALSE;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object speed-band indicator

Privately announce when object speed crosses a modest threshold.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch arms. Uses existing velocity and never drives or brakes.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Warns above 3 m/s and clears below 2.5 m/s. An exhibit indicator, not a safety device or region enforcement system.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer fast;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            fast=FALSE;
            llSetTimerEvent(0.5);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        float speed=llVecMag(llGetVel());
        if(!fast&&speed>3.0)
        {
            fast=TRUE;
            llOwnerSay("Object exceeds 3 m/s.");
        }
        else if(fast&&speed<2.5)
        {
            fast=FALSE;
            llOwnerSay("Object below 2.5 m/s.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object terrain-clearance monitor

Privately announce low center-to-terrain clearance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch arms a one-second check on a demonstration object.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Center clearance is not bottom clearance. Mesh floors are excluded; this does not stop a fall.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer low;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            low=FALSE;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        vector p=llGetPos();
        float c=p.z-llGround(ZERO_VECTOR);
        if(!low&&c<0.5)
        {
            low=TRUE;
            llOwnerSay("Object center is within 0.5 m of terrain.");
        }
        else if(low&&c>0.8)
        {
            low=FALSE;
            llOwnerSay("Terrain clearance recovered.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object upright monitor

Report when local up tilts more than forty-five degrees from world up.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch arms; rotate the object to test.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Uses local +Z, which may differ from a mesh’s modeled up. Recovery threshold is thirty-five degrees.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer tilted;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            tilted=FALSE;
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        vector up=llRot2Up(llGetRot());
        if(!tilted&&up.z<llCos(45.0*DEG_TO_RAD))
        {
            tilted=TRUE;
            llOwnerSay("Tilt beyond 45 degrees.");
        }
        else if(tilted&&up.z>llCos(35.0*DEG_TO_RAD))
        {
            tilted=FALSE;
            llOwnerSay("Object upright again.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Own-object waterline crossing cue

Play different short cues when this object crosses simulator water.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add optional enter_water and leave_water sounds; owner-touch arms.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Uses object center and a 0.1-meter dead band, not mesh-pool water. Sounds must be licensed and are audible nearby.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer underwater;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            vector p=llGetPos();
            underwater=p.z<llWater(ZERO_VECTOR);
            llSetTimerEvent(1.0);
            llOwnerSay("Monitor armed.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Monitor off.");
        }
    }
    timer()
    {
        if(!armed)return;
        vector p=llGetPos();
        float d=p.z-llWater(ZERO_VECTOR);
        string sound="";
        if(!underwater&&d< -0.1)
        {
            underwater=TRUE;
            sound="enter_water";
        }
        else if(underwater&&d>0.1)
        {
            underwater=FALSE;
            sound="leave_water";
        }
        if(sound!=""&&llGetInventoryType(sound)==INVENTORY_SOUND)llPlaySound(sound,0.2);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Owned beacon bearing

Report the nearest detected owned beacon’s distance and bearing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name a separate same-owner target workshop_beacon. Owner-touch scans twenty meters.

Stop / restore: Remove/disable. Scans only on owner touch.

No avatar surveillance or visitor history. Only owned object matches are used. Sensor caps and region borders can miss targets; no identity history is stored.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())llSensor("workshop_beacon",NULL_KEY,ACTIVE|PASSIVE,20.0,PI);
    }
    sensor(integer n)
    {
        integer i;
        float best=100000.0;
        vector offset;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())
        {
            vector d=llDetectedPos(i)-llGetPos();
            float length=llVecMag(d);
            if(length<best)
            {
                best=length;
                offset=d;
            }
        }
        if(best==100000.0)
        {
            llOwnerSay("No owned beacon in returned results.");
            return;
        }
        float bearing=llAtan2(offset.x,offset.y)*RAD_TO_DEG;
        if(bearing<0.0)bearing+=360.0;
        llOwnerSay("Owned beacon: "+(string)best+" m; bearing "+(string)llRound(bearing)+" degrees; height offset "+(string)offset.z+" m.");
    }
    no_sensor()
    {
        llOwnerSay("No beacon detected.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Owned docking-beacon lamp

Light face zero when a same-owner dock_beacon is within two meters.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name a separate target dock_beacon. Owner-touch arms five-second scans.

Stop / restore: Owner-touch to stop scanning and restore glow before removing.

No avatar surveillance or visitor history. Only present/absent is retained. A linkset cannot sense itself. Original glow is restored on disarm.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float saved;
show(integer found)
{
    float glow=saved;
    if(found)glow=0.1;
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_GLOW,0,glow]);
}
default
{
    state_entry()
    {
        saved=llList2Float(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_GLOW,0]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)llSensorRepeat("dock_beacon",NULL_KEY,ACTIVE|PASSIVE,2.0,PI,5.0);
        else
        {
            llSensorRemove();
            show(FALSE);
        }
    }
    sensor(integer n)
    {
        if(!armed)return;
        integer i;
        integer found;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())found=TRUE;
        show(found);
    }
    no_sensor()
    {
        if(armed)show(FALSE);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Owned practice-ball goal cue

Recognize a same-owner practice_ball contacting a goal.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name your ball practice_ball. Put in the goal; owner-touch arms. Add optional licensed success sound.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Not a competitive scoring server. No identifiers are stored; agents are excluded and repeated contacts have a two-second cooldown.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float last=-10.0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())armed=!armed;
    }
    collision_start(integer n)
    {
        if(!armed||llGetTime()-last<2.0)return;
        integer i;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner()&&llDetectedName(i)=="practice_ball")
        {
            last=llGetTime();
            llOwnerSay("Practice ball reached the goal.");
            if(llGetInventoryType("success")==INVENTORY_SOUND)llPlaySound("success",0.25);
            return;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Owned stage-prop count monitor

Report changes in the count of same-owner objects named stage_prop.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Name separate intended props stage_prop. Owner-touch arms five-second, ten-meter scans.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Only a count is kept, not names, keys or positions. Sensor limits make this a partial observation.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer previous=-1;
report(integer count)
{
    if(count!=previous)
    {
        previous=count;
        llOwnerSay("Detected owned stage props: "+(string)count+" (sensor-limited).");
    }
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            previous=-1;
            llSensorRepeat("stage_prop",NULL_KEY,ACTIVE|PASSIVE,10.0,PI,5.0);
        }
        else llSensorRemove();
    }
    sensor(integer n)
    {
        if(!armed)return;
        integer i;
        integer count;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())++count;
        report(count);
    }
    no_sensor()
    {
        if(armed)report(0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Owned-object contact counter

Count collision starts with same-owner objects while armed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a collision-capable exhibit prim. Owner-touch arms and resets; the next touch disarms and reports.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Excludes agents and foreign objects. Keeps only an integer count; simultaneous contacts count separately.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer total;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(armed)
        {
            total=0;
            llOwnerSay("Owned-object contact counter armed.");
        }
        else llOwnerSay("Owned-object contact starts: "+(string)total);
    }
    collision_start(integer n)
    {
        if(!armed)return;
        integer i;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())++total;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Owned-object forward cone check

Check a forward cone for the owner’s object centers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch; local +X is forward. Radius five meters, half-angle thirty degrees.

Stop / restore: Remove/disable. Scans only when touched.

No avatar surveillance or visitor history. A sensor cone is not a collision ray or proof of an unobstructed path. Only a count is reported.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())llSensor("",NULL_KEY,ACTIVE|PASSIVE,5.0,PI/6.0);
    }
    sensor(integer n)
    {
        integer i;
        integer count;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())++count;
        llOwnerSay("Owned object centers in forward cone: "+(string)count+" (limited results).");
    }
    no_sensor()
    {
        llOwnerSay("No object centers detected; not a collision-clearance guarantee.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Owned-object impact chime

Play a quiet chime on contact with another owned object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a short licensed impact sound. Owner-touch arms/disarms.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Agents and foreign objects are excluded. One-second cooldown limits chatter; no physics settings change.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float last=-10.0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(!armed)llStopSound();
    }
    collision_start(integer n)
    {
        if(!armed||llGetTime()-last<1.0)return;
        integer i;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())
        {
            last=llGetTime();
            if(llGetInventoryType("impact")==INVENTORY_SOUND)llPlaySound("impact",0.2);
            return;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Owned-object relative contact speed

Report approximate relative speed on contact with an owned object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a collision-capable exhibit and owner-touch to arm.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Uses event-time detected velocity minus this prim’s velocity. It is not force or energy; agents and foreign objects are excluded. Two-second cooldown.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float last=-10.0;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)==llGetOwner())armed=!armed;
    }
    collision_start(integer n)
    {
        if(!armed||llGetTime()-last<2.0)return;
        integer i;
        for(i=0;i<n;++i)if(!(llDetectedType(i)&AGENT)&&llDetectedOwner(i)==llGetOwner())
        {
            last=llGetTime();
            llOwnerSay("Approximate relative contact speed: "+(string)llVecMag(llDetectedVel(i)-llGetVel())+" m/s.");
            return;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Beginner

Quiet visitor bell

Let the owner know when an avatar is detected nearby.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the object, keep it in a region where scripts can run, and set SENSOR_RANGE for your needs.

Stop / restore: Disable or remove the script. It removes its sensor when the script stops.

Sensors are approximate, scan only a limited range, and may detect agents unexpectedly. This does not identify or message visitors.

// Original Incoprea example. Small range and slow scan.
float SENSOR_RANGE = 8.0;
default
{
    state_entry()
    {
        llSensorRepeat("", NULL_KEY, AGENT, SENSOR_RANGE, PI, 30.0);
    }
    sensor(integer found)
    {
        llOwnerSay("Someone is visiting nearby.");
    }
    no_sensor()
    {
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Sensing · Intermediate

Terrain contact lamp

Briefly light face-zero glow when the object contacts terrain.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in an already physical test object root. Owner-touch arms; this script never enables physics.

Stop / restore: Owner-touch to disarm and restore glow before removal.

No avatar surveillance or visitor history. Land events refer to terrain, not mesh floors. Restores captured glow after two seconds or on disarm.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
float saved;
restore()
{
    llSetTimerEvent(0.0);
    llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_GLOW,0,saved]);
}
default
{
    state_entry()
    {
        saved=llList2Float(llGetLinkPrimitiveParams(LINK_THIS,[PRIM_GLOW,0]),0);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        if(!armed)restore();
    }
    land_collision_start(vector position)
    {
        if(!armed)return;
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_GLOW,0,0.12]);
        llSetTimerEvent(2.0);
    }
    timer()
    {
        restore();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Sensing · Intermediate

Terrain hop displacement study

Compare height at terrain departure and the next terrain contact.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in an already physical test-object root. Owner-touch arms; use an existing safe movement mechanism.

Stop / restore: Owner-touch to disarm before removing. No physical status or movement is changed.

No avatar surveillance or visitor history. Reports endpoint height change, not maximum jump height or impact energy. Only this object’s events are used.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer armed;
integer airborne;
float departure;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        armed=!armed;
        airborne=FALSE;
    }
    land_collision_end(vector point)
    {
        if(!armed)return;
        vector p=llGetPos();
        departure=p.z;
        airborne=TRUE;
    }
    land_collision_start(vector point)
    {
        if(!armed||!airborne)return;
        vector p=llGetPos();
        airborne=FALSE;
        llOwnerSay("Terrain-contact endpoint height change: "+(string)(p.z-departure)+" m.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Tools & troubleshooting 6 categories
Project notebooksPrivate session notes, build plans, and manual test logs.20 scripts

Download this category (.zip)

Project notebooks · Intermediate

Choose a current focus task

Maintain a short list and select one task as the current private focus.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter add|task, focus|number, or list. Maximum ten tasks.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Selecting a focus does not complete or remove other tasks. The list exists only in script memory.

// Original Incoprea example. MIT.
list tasks;
integer focus=-1;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(tasks);++i)
        {
            string marker="  ";
            if(i==focus)marker="> ";
            llOwnerSay(marker+(string)(i+1)+" "+llList2String(tasks,i));
        }
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use add|task or focus|number.");
        return;
    }
    if(llList2String(p,0)=="add")
    {
        if(llList2String(p,1)=="" || llGetListLength(tasks)>=10)
        {
            llOwnerSay("Empty task or list full.");
            return;
        }
        tasks += [llList2String(p,1)];
        llOwnerSay("Task added.");
    }
    else if(llList2String(p,0)=="focus")
    {
        string number=llList2String(p,1);
        if(!positive(number) || (integer)number>llGetListLength(tasks))
        {
            llOwnerSay("Invalid task number.");
            return;
        }
        focus=(integer)number-1;
        llOwnerSay("Focus: "+llList2String(tasks,focus));
    }
    else llOwnerSay("Unknown command.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter add|task, focus|number, or list. Maximum ten tasks.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Curate a small tag set

Add normalized tags, remove tags, and print a reusable comma-separated tag line.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter add|tag, remove|tag, list, or clear. Up to 20 tags.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Tags are lowercased and trimmed. Commas and pipes are disallowed to preserve the output format.

// Original Incoprea example. MIT.
list tags;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="clear")
    {
        tags=[];
        llOwnerSay("Tags cleared.");
        return;
    }
    if(input=="list")
    {
        llOwnerSay(llDumpList2String(tags,", "));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use add|tag or remove|tag.");
        return;
    }
    string tag=llToLower(llStringTrim(llList2String(p,1),STRING_TRIM));
    if(tag=="" || llSubStringIndex(tag,",")!=-1)
    {
        llOwnerSay("Use one nonblank tag without commas.");
        return;
    }
    integer index=llListFindList(tags,[tag]);
    if(llList2String(p,0)=="add")
    {
        if(index==-1)
        {
            if(llGetListLength(tags)>=20)
            {
                llOwnerSay("Tag set full.");
                return;
            }
            tags += [tag];
        }
    }
    else if(llList2String(p,0)=="remove")
    {
        if(index!=-1)tags=llDeleteSubList(tags,index,index);
    }
    else
    {
        llOwnerSay("Unknown command.");
        return;
    }
    llOwnerSay(llDumpList2String(tags,", "));
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter add|tag, remove|tag, list, or clear. Up to 20 tags.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Draft an inventory sound playlist

Add existing sound names to an ordered draft and remove entries by number.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter add|soundName, remove|number, or list. Up to 12 cues.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Checks inventory type but does not play or transfer any sound. Repeated sounds are allowed because their order may matter.

// Original Incoprea example. MIT.
list cues;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(cues);++i)llOwnerSay((string)(i+1)+": "+llList2String(cues,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use add|sound or remove|number.");
        return;
    }
    string command=llList2String(p,0);
    string value=llList2String(p,1);
    if(command=="add")
    {
        if(llGetInventoryType(value)!=INVENTORY_SOUND || llGetListLength(cues)>=12)
        {
            llOwnerSay("Missing sound or playlist full.");
            return;
        }
        cues += [value];
        llOwnerSay("Cue appended.");
    }
    else if(command=="remove")
    {
        if(!positive(value) || (integer)value>llGetListLength(cues))
        {
            llOwnerSay("Invalid cue number.");
            return;
        }
        integer index=(integer)value-1;
        cues=llDeleteSubList(cues,index,index);
        llOwnerSay("Cue removed from draft.");
    }
    else llOwnerSay("Unknown command.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter add|soundName, remove|number, or list. Up to 12 cues.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Draft command aliases without executing them

Map short aliases to descriptive action text and inspect their expansion.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter alias|actionText, get|alias, or list. Maximum ten aliases.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. This stores and prints text only; expanded strings are never executed. The reserved words get and list cannot be alias names.

// Original Incoprea example. MIT.
list aliases;
list actions;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(aliases);++i)llOwnerSay(llList2String(aliases,i)+" => "+llList2String(actions,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use alias|action or get|alias.");
        return;
    }
    string alias=llToLower(llList2String(p,0));
    string action=llList2String(p,1);
    if(alias=="get")
    {
        integer index=llListFindList(aliases,[llToLower(action)]);
        if(index==-1)llOwnerSay("Unknown alias.");
        else llOwnerSay("Draft expansion: "+llList2String(actions,index));
        return;
    }
    if(alias=="" || alias=="list" || action=="")
    {
        llOwnerSay("Reserved/empty alias or empty action.");
        return;
    }
    integer index=llListFindList(aliases,[alias]);
    if(index==-1)
    {
        if(llGetListLength(aliases)>=10)
        {
            llOwnerSay("Alias table full.");
            return;
        }
        aliases += [alias];
        actions += [action];
    }
    else actions=llListReplaceList(actions,[action],index,index);
    llOwnerSay("Draft alias stored.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter alias|actionText, get|alias, or list. Maximum ten aliases.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Manual test result log

Record pass/fail test notes with a compact session summary.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter pass|note, fail|note, list, or summary. Keeps 20 results.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. These are your declared test results, not automatic compiler or simulator validation. Export owner-chat notes before resetting.

// Original Incoprea example. MIT.
list results;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="summary")
    {
        integer passed;
        integer failed;
        integer i;
        for(i=0;i<llGetListLength(results);i+=2)
        {
            if(llList2String(results,i)=="pass")++passed;
            else ++failed;
        }
        llOwnerSay("Manual results: "+(string)passed+" pass, "+(string)failed+" fail.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(results);i+=2)llOwnerSay(llList2String(results,i)+": "+llList2String(results,i+1));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,1)=="" || llListFindList(["pass","fail"],[llList2String(p,0)])==-1)
    {
        llOwnerSay("Use pass|note or fail|note.");
        return;
    }
    if(llGetListLength(results)>=40)
    {
        llOwnerSay("Result log full; export and reset.");
        return;
    }
    results += p;
    llOwnerSay("Manual result recorded.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter pass|note, fail|note, list, or summary. Keeps 20 results.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Named build position bookmarks

Capture this object’s current position under a short name and recall it privately.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter save|name, get|name, or list. Up to eight bookmarks.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Stores region name and position only; never teleports or moves an object. Useful for your own build notes, not tracking people.

// Original Incoprea example. MIT.
list names;
list places;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        llOwnerSay(llDumpList2String(names,", "));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,1)=="")
    {
        llOwnerSay("Use save|name or get|name.");
        return;
    }
    string name=llList2String(p,1);
    integer index=llListFindList(names,[name]);
    if(llList2String(p,0)=="get")
    {
        if(index==-1)llOwnerSay("Unknown bookmark.");
        else llOwnerSay(name+": "+llList2String(places,index));
        return;
    }
    if(llList2String(p,0)!="save")
    {
        llOwnerSay("Unknown command.");
        return;
    }
    string place=llGetRegionName()+" "+(string)llGetPos();
    if(index==-1)
    {
        if(llGetListLength(names)>=8)
        {
            llOwnerSay("Bookmark list full.");
            return;
        }
        names += [name];
        places += [place];
    }
    else places=llListReplaceList(places,[place],index,index);
    llOwnerSay("Position bookmarked.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter save|name, get|name, or list. Up to eight bookmarks.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Named measurement notebook

Record bounded decimal measurements with labels and print them later.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter label|number or list. Up to 12 values.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. A manual notebook; it does not measure avatars or geometry automatically. Restricts input to digits, sign, and decimal point before casting.

// Original Incoprea example. MIT.
list readings;
integer decimalOK(string v)
{
    integer n=llStringLength(v);
    if(n<1 || n>12)return FALSE;
    integer i;
    integer digits;
    integer dots;
    if(llGetSubString(v,0,0)=="-" || llGetSubString(v,0,0)=="+")i=1;
    for(;i<n;++i)
    {
        string c=llGetSubString(v,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(readings);i+=2)llOwnerSay(llList2String(readings,i)+": "+llList2String(readings,i+1));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,0)=="" || llGetListLength(readings)>=24)
    {
        llOwnerSay("Use label|number; maximum 12 readings.");
        return;
    }
    string number=llList2String(p,1);
    if(!decimalOK(number) || llFabs((float)number)>1000000)
    {
        llOwnerSay("Invalid or excessive number.");
        return;
    }
    readings += [llList2String(p,0),(float)number];
    llOwnerSay("Measurement recorded.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter label|number or list. Up to 12 values.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Personal build glossary

Store short definitions for terms and retrieve them by exact normalized key.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter term|definition, get|term, or list. Maximum ten terms.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Term matching is lowercase; definition spelling is preserved. No automatic claims about technical accuracy are made.

// Original Incoprea example. MIT.
list terms;
list definitions;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        llOwnerSay(llDumpList2String(terms,", "));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use term|definition or get|term.");
        return;
    }
    string term=llToLower(llStringTrim(llList2String(p,0),STRING_TRIM));
    string definition=llList2String(p,1);
    if(term=="get")
    {
        integer index=llListFindList(terms,[llToLower(definition)]);
        if(index==-1)llOwnerSay("Term not found.");
        else llOwnerSay(llList2String(definitions,index));
        return;
    }
    if(term=="" || definition=="")
    {
        llOwnerSay("Term and definition required.");
        return;
    }
    integer index=llListFindList(terms,[term]);
    if(index==-1)
    {
        if(llGetListLength(terms)>=10)
        {
            llOwnerSay("Glossary full.");
            return;
        }
        terms += [term];
        definitions += [definition];
    }
    else definitions=llListReplaceList(definitions,[definition],index,index);
    llOwnerSay("Definition stored for this session.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter term|definition, get|term, or list. Maximum ten terms.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Private build issue register

Add numbered issues and close them without renumbering the remaining records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter new|issue, close|ID, or list. Maximum 12 open issues.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. IDs increase within this session. Closing only removes the local note; it does not claim any external problem was fixed.

// Original Incoprea example. MIT.
list ids;
list notes;
integer serial;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(ids);++i)llOwnerSay((string)llList2Integer(ids,i)+": "+llList2String(notes,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use new|issue or close|ID.");
        return;
    }
    string command=llList2String(p,0);
    string value=llList2String(p,1);
    if(command=="new")
    {
        if(value=="" || llGetListLength(ids)>=12)
        {
            llOwnerSay("Empty issue or register full.");
            return;
        }
        ++serial;
        ids += [serial];
        notes += [value];
        llOwnerSay("Issue ID "+(string)serial);
    }
    else if(command=="close")
    {
        if(!positive(value))
        {
            llOwnerSay("Invalid ID.");
            return;
        }
        integer index=llListFindList(ids,[(integer)value]);
        if(index==-1)
        {
            llOwnerSay("Unknown ID.");
            return;
        }
        ids=llDeleteSubList(ids,index,index);
        notes=llDeleteSubList(notes,index,index);
        llOwnerSay("Local issue closed.");
    }
    else llOwnerSay("Unknown command.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter new|issue, close|ID, or list. Maximum 12 open issues.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Private material quantity ledger

Set and look up planned quantities for named build materials.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter material|quantity, list, or clear. Up to 12 material names.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Quantities are plans, not simulator inventory amounts. Names are exact and case-sensitive; later entries replace an earlier quantity.

// Original Incoprea example. MIT.
list names;
list quantities;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="clear")
    {
        names=[];
        quantities=[];
        llOwnerSay("Plan cleared.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(names);++i)llOwnerSay(llList2String(names,i)+": "+llList2String(quantities,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,0)=="" || !positive(llList2String(p,1)))
    {
        llOwnerSay("Use material|positive quantity.");
        return;
    }
    string name=llList2String(p,0);
    integer index=llListFindList(names,[name]);
    if(index==-1)
    {
        if(llGetListLength(names)>=12)
        {
            llOwnerSay("Ledger full.");
            return;
        }
        names += [name];
        quantities += [llList2Integer(p,1)];
    }
    else quantities=llListReplaceList(quantities,[llList2Integer(p,1)],index,index);
    llOwnerSay("Quantity recorded.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter material|quantity, list, or clear. Up to 12 material names.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Private session notebook

Keep the ten most recent short notes and print them on demand.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter a note, /list to read notes, or /clear to erase them.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Notes are private owner-chat output, never hover text. Do not treat volatile script memory as a durable archive.

// Original Incoprea example. MIT.
list notes;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="/clear")
    {
        notes=[];
        llOwnerSay("Session notes cleared.");
        return;
    }
    if(input=="/list")
    {
        integer i;
        for(i=0;i<llGetListLength(notes);++i)llOwnerSay((string)(i+1)+". "+llList2String(notes,i));
        return;
    }
    if(input=="")return;
    notes += [input];
    if(llGetListLength(notes)>10)notes=llDeleteSubList(notes,0,0);
    llOwnerSay("Note kept in this session.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter a note, /list to read notes, or /clear to erase them.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Private taskboard

Add tasks, mark one done by its number, and list remaining work.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter add|task, done|number, or list. Maximum 12 tasks.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Completing a task removes it and renumbers later tasks. This does not verify completion of any external work.

// Original Incoprea example. MIT.
list tasks;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(tasks);++i)llOwnerSay((string)(i+1)+". "+llList2String(tasks,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use add|task or done|number.");
        return;
    }
    string command=llList2String(p,0);
    string value=llList2String(p,1);
    if(command=="add")
    {
        if(value=="" || llGetListLength(tasks)>=12)
        {
            llOwnerSay("Empty task or taskboard full.");
            return;
        }
        tasks += [value];
        llOwnerSay("Task added.");
    }
    else if(command=="done")
    {
        if(!positive(value) || (integer)value>llGetListLength(tasks))
        {
            llOwnerSay("Invalid task number.");
            return;
        }
        integer index=(integer)value-1;
        llOwnerSay("Marked done: "+llList2String(tasks,index));
        tasks=llDeleteSubList(tasks,index,index);
    }
    else llOwnerSay("Unknown command.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter add|task, done|number, or list. Maximum 12 tasks.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Rate build options privately

Assign your own 1-5 rating to named design options and list results.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter option|rating or list. Maximum 12 options.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Records only owner input, not surveys or visitor preferences. Scores are personal notes and not objective quality measurements.

// Original Incoprea example. MIT.
list options;
list scores;
integer positive(string input)
{
    if(input=="" || llStringLength(input)>5)return FALSE;
    integer i;
    for(i=0;i<llStringLength(input);++i)if(llSubStringIndex("0123456789",llGetSubString(input,i,i))==-1)return FALSE;
    return (integer)input>0;
}
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(options);++i)llOwnerSay(llList2String(options,i)+": "+llList2String(scores,i)+"/5");
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,0)=="" || !positive(llList2String(p,1)) || llList2Integer(p,1)>5)
    {
        llOwnerSay("Use option|rating from 1 to 5.");
        return;
    }
    string option=llList2String(p,0);
    integer index=llListFindList(options,[option]);
    if(index==-1)
    {
        if(llGetListLength(options)>=12)
        {
            llOwnerSay("Option list full.");
            return;
        }
        options += [option];
        scores += [llList2Integer(p,1)];
    }
    else scores=llListReplaceList(scores,[llList2Integer(p,1)],index,index);
    llOwnerSay("Personal rating saved.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter option|rating or list. Maximum 12 options.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Record a build route manually

Capture this object’s position on command and measure consecutive segment lengths.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter mark, report, or clear. Up to 20 positions in one region.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Move your own object between marks. This does not track avatars or move anything; crossing regions requires clearing the route.

// Original Incoprea example. MIT.
list points;
string region;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="clear")
    {
        points=[];
        region="";
        llOwnerSay("Route notes cleared.");
        return;
    }
    if(input=="report")
    {
        float total;
        integer i;
        for(i=1;i<llGetListLength(points);++i)total+=llVecDist(llList2Vector(points,i-1),llList2Vector(points,i));
        llOwnerSay("Points: "+(string)llGetListLength(points)+"; polyline length: "+(string)total+" meters.");
        return;
    }
    if(input!="mark")
    {
        llOwnerSay("Use mark, report, or clear.");
        return;
    }
    if(llGetAttached())
    {
        llOwnerSay("Use a rezzed object.");
        return;
    }
    if(region!="" && region!=llGetRegionName())
    {
        llOwnerSay("Region changed; clear before recording more.");
        return;
    }
    if(llGetListLength(points)>=20)
    {
        llOwnerSay("Route full.");
        return;
    }
    region=llGetRegionName();
    points += [llGetPos()];
    llOwnerSay("Point recorded: "+(string)llGetPos());
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter mark, report, or clear. Up to 20 positions in one region.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Record before and after edit notes

Keep a short manual change ledger containing field, old value, and new value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter field|before|after, or list. Maximum 12 changes.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Records what you type and does not inspect or apply actual edits. Intended for rollback notes you export before reset.

// Original Incoprea example. MIT.
list changes;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(changes);i+=3)llOwnerSay(llList2String(changes,i)+": ["+llList2String(changes,i+1)+"] -> ["+llList2String(changes,i+2)+"]");
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=3 || llList2String(p,0)=="" || llGetListLength(changes)>=36)
    {
        llOwnerSay("Use field|before|after; maximum 12 records.");
        return;
    }
    changes += p;
    llOwnerSay("Change note recorded.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter field|before|after, or list. Maximum 12 changes.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Search this prim’s Contents

Search inventory names using a typed case-insensitive substring and report up to twenty matches.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter a search term. Use at most 200 inventory items in this prim.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. No assets are read, played, or transferred. Reports only names and type numbers to the owner.

// Original Incoprea example. MIT.
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="")
    {
        llOwnerSay("Enter a nonempty term.");
        return;
    }
    integer total=llGetInventoryNumber(INVENTORY_ALL);
    if(total>200)
    {
        llOwnerSay("Use a prim with at most 200 items.");
        return;
    }
    integer i;
    integer matches;
    string needle=llToLower(input);
    for(i=0;i<total;++i)
    {
        string name=llGetInventoryName(INVENTORY_ALL,i);
        if(llSubStringIndex(llToLower(name),needle)!=-1)
        {
            ++matches;
            if(matches<=20)llOwnerSay(name+" (type "+(string)llGetInventoryType(name)+")");
        }
    }
    llOwnerSay("Matches: "+(string)matches+"; at most 20 shown.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter a search term. Use at most 200 inventory items in this prim.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Session preferences with fixed keys

Set and read only a declared set of preference keys.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter key|value, get|key, or list. Keys: theme, mode, label.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Values are session-only and never applied to another script. The fixed schema rejects unknown keys and limits each value to 60 characters.

// Original Incoprea example. MIT.
list keys=["theme","mode","label"];
list values=["green","quiet","Workshop"];
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<3;++i)llOwnerSay(llList2String(keys,i)+"="+llList2String(values,i));
        return;
    }
    list p=llParseStringKeepNulls(input,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        llOwnerSay("Use key|value or get|key.");
        return;
    }
    string keyName=llList2String(p,0);
    string value=llList2String(p,1);
    if(keyName=="get")
    {
        integer index=llListFindList(keys,[value]);
        if(index==-1)llOwnerSay("Unknown key.");
        else llOwnerSay(value+"="+llList2String(values,index));
        return;
    }
    integer index=llListFindList(keys,[keyName]);
    if(index==-1 || llStringLength(value)>60)
    {
        llOwnerSay("Unknown key or value too long.");
        return;
    }
    values=llListReplaceList(values,[value],index,index);
    llOwnerSay("Session preference updated.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter key|value, get|key, or list. Keys: theme, mode, label.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Project notebooks · Intermediate

Work-session time ledger

Start and stop named work sessions and keep their elapsed durations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in your own object and touch. Enter start|label, stop, or list. Up to ten completed sessions.

Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds.

Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. Measures elapsed wall-clock seconds, not productive work. One session at a time; reset loses sessions and any active timer.

// Original Incoprea example. MIT.
list log;
string active;
integer started;
integer handle;
integer channel;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
respond(string input)
{
    input=llStringTrim(input,STRING_TRIM);
    if(llStringLength(input)>200)
    {
        llOwnerSay("Use at most 200 characters.");
        return;
    }
    if(input=="list")
    {
        integer i;
        for(i=0;i<llGetListLength(log);i+=2)llOwnerSay(llList2String(log,i)+": "+llList2String(log,i+1)+" seconds");
        if(active!="")llOwnerSay("Active: "+active);
        return;
    }
    if(input=="stop")
    {
        if(active=="")
        {
            llOwnerSay("No active session.");
            return;
        }
        if(llGetListLength(log)>=20)
        {
            llOwnerSay("Stopped "+active+": "+(string)(llGetUnixTime()-started)+" seconds. Log full, so this result was not stored.");
            active="";
            return;
        }
        log += [active,llGetUnixTime()-started];
        active="";
        llOwnerSay("Session recorded.");
        return;
    }
    if(llSubStringIndex(input,"start|")==0)
    {
        if(active!="")
        {
            llOwnerSay("Stop the current session first.");
            return;
        }
        active=llDeleteSubString(input,0,5);
        if(active=="")
        {
            llOwnerSay("Give the session a label.");
            return;
        }
        started=llGetUnixTime();
        llOwnerSay("Session started.");
        return;
    }
    llOwnerSay("Use start|label, stop, or list.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        closeInput();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(45);
        llTextBox(llGetOwner(),"Enter start|label, stop, or list. Up to ten completed sessions.",channel);
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner())return;
        closeInput();
        respond(input);
    }
    timer()
    {
        closeInput();
        llOwnerSay("Input closed.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Access & ownershipOwner controls and permission-aware patterns.28 scripts

Download this category (.zip)

Access & ownership · Intermediate

Check a pasted two-column mini table

Accept up to eight newline-separated key=value rows and reject duplicate keys before printing the parsed result.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch, paste a short table, and submit. The entire reply must fit 200 characters.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Splits only at the first equals sign and retains further equals signs in values. No data is applied to objects or stored beyond this response.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ask("Paste up to eight key=value rows, one per line.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        list rows=llParseStringKeepNulls(input,["\n"],[]);
        list keys;
        list values;
        integer valid=llGetListLength(rows)<=8;
        integer i;
        for(i=0;i<llGetListLength(rows) && valid;++i)
        {
            string row=llList2String(rows,i);
            integer at=llSubStringIndex(row,"=");
            if(at<1)valid=FALSE;
            else
            {
                string k=llStringTrim(llGetSubString(row,0,at-1),STRING_TRIM);
                string v="";
                if(at<llStringLength(row)-1)v=llGetSubString(row,at+1,-1);
                if(k=="" || llListFindList(keys,[k])!=-1)valid=FALSE;
                else
                {
                    keys += [k];
                    values += [v];
                }
            }
        }
        if(!valid)llOwnerSay("Rejected: malformed row, duplicate key, or more than eight rows.");
        else for(i=0;i<llGetListLength(keys);++i)llOwnerSay(llList2String(keys,i)+" => "+llList2String(values,i));
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Check a short caption against a word goal

Accept caption text and compare its whitespace-token count with a declared target range.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set MIN_WORDS and MAX_WORDS, then touch to enter a caption.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Punctuation is attached to tokens; this is not a linguistic word counter. It never uploads or publishes the caption.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer MIN_WORDS=8;
integer MAX_WORDS=20;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ask("Enter a short caption for a word-budget check.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        integer words=llGetListLength(llParseString2List(input,[" ","\n",llUnescapeURL("%09")],[]));
        if(MIN_WORDS<0 || MAX_WORDS<MIN_WORDS)llOwnerSay("Invalid goal range.");
        else
        {
            llOwnerSay("Words="+(string)words+"; target="+(string)MIN_WORDS+"–"+(string)MAX_WORDS);
            if(words<MIN_WORDS)llOwnerSay("Add a little more context.");
            else if(words>MAX_WORDS)llOwnerSay("Consider shortening the caption.");
            else llOwnerSay("Within the configured word range.");
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Check a typed draft against a UTF-8 budget

Measure the UTF-8 byte length of an owner-entered message before using it in a byte-limited field.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set BUDGET, then touch and enter a short draft.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Uses Base64 encoded length to count bytes. Reports only and does not truncate, transmit, or store the draft.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer BUDGET=127;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ask("Enter text to check against the configured byte budget.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        string b64=llStringToBase64(input);
        integer bytes=llStringLength(b64)/4*3;
        if(llGetSubString(b64,-1,-1)=="=")--bytes;
        if(llGetSubString(b64,-2,-2)=="=")--bytes;
        if(bytes<0)bytes=0;
        llOwnerSay("Characters="+(string)llStringLength(input)+" UTF-8 bytes="+(string)bytes+" budget="+(string)BUDGET);
        if(bytes>BUDGET)llOwnerSay("Draft exceeds the byte budget.");
        else llOwnerSay("Draft fits the configured budget.");
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Beginner

Check an item’s next-owner flags

Read the next-owner copy, modify, and transfer flags of one named inventory item.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set ITEM to an exact item name in this prim’s Contents. Touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Does not change any permissions. Flags describe simulator permissions, not licensing or permission to redistribute copyrighted content. Nested object contents may impose additional restrictions.

// Original Incoprea example. MIT.
string ITEM = "Example Object";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(ITEM) == INVENTORY_NONE)
        {
            llOwnerSay("Missing inventory item: " + ITEM);
            return;
        }
        integer mask = llGetInventoryPermMask(ITEM, MASK_NEXT);
        llOwnerSay(ITEM + " next owner: copy=" + (string)((mask & PERM_COPY) != 0)
        + ", modify=" + (string)((mask & PERM_MODIFY) != 0)
        + ", transfer=" + (string)((mask & PERM_TRANSFER) != 0));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Choose an inventory name from a numbered menu

Show up to eight inventory entries per dialog page and report the selected exact name privately.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch a prim with at most 80 inventory entries. Use numbered buttons, Next, and Back.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Numbers keep long inventory names out of dialog buttons. Selection only reports the name; it never transfers, runs, or plays the item. The initial name snapshot is used until the next touch.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
list names;
integer page;
showPage()
{
    integer n=llGetListLength(names);
    string prompt="Select a number:\n";
    list buttons;
    integer i;
    for(i=page;i<page+8 && i<n;++i)
    {
        prompt+=(string)(i-page+1)+": "+llGetSubString(llList2String(names,i),0,35)+"\n";
        buttons += [(string)(i-page+1)];
    }
    if(page>0)buttons += ["Back"];
    if(page+8<n)buttons += ["Next"];
    buttons += ["Close"];
    menu(prompt,buttons);
}
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        names=[];
        integer n=llGetInventoryNumber(INVENTORY_ALL);
        if(n>80)
        {
            llOwnerSay("Use at most 80 inventory items.");
        }
        else
        {
            integer i;
            for(i=0;i<n;++i)names += [llGetInventoryName(INVENTORY_ALL,i)];
            page=0;
            showPage();
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Next" && page+8<llGetListLength(names))
        {
            page+=8;
            showPage();
        }
        else if(input=="Back" && page>=8)
        {
            page-=8;
            showPage();
        }
        else if(llListFindList(["1","2","3","4","5","6","7","8"],[input])!=-1)
        {
            integer index=page+(integer)input-1;
            if(index<llGetListLength(names))llOwnerSay("Selected inventory name: "+llList2String(names,index));
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Collect an attribution in three guided steps

Ask for asset title, creator, and license/source, then print a combined private credit draft.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch and complete the three text prompts within each 45-second window.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. A structured writing aid, not proof of rights or license verification. Nothing is stored after reset or sent to anyone else.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer step;
string title;
string creator;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        step=1;
        title="";
        creator="";
        ask("Asset title?");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        input=llStringTrim(input,STRING_TRIM);
        if(input=="")
        {
            step=0;
            llOwnerSay("Empty answer; form cancelled.");
        }
        else if(step==1)
        {
            title=input;
            step=2;
            ask("Creator name?");
        }
        else if(step==2)
        {
            creator=input;
            step=3;
            ask("License and source reference?");
        }
        else if(step==3)
        {
            llOwnerSay("Credit draft: "+title+" — "+creator+"; "+input);
            step=0;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Compare design options head to head

Present option pairs and accumulate your own preferences in a private review session.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set two to six short unique OPTIONS, each at most 20 printable ASCII characters. Touch to begin.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. This is not a public vote or objective score. Buttons use Left/Right, preserving long option text in the prompt; ties give one point to both.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
list OPTIONS=["Green glass","Blue glass","Warm wood"];
list scores;
integer a;
integer b;
showPair()
{
    if(a>=llGetListLength(OPTIONS)-1)
    {
        integer i;
        for(i=0;i<llGetListLength(OPTIONS);++i)llOwnerSay(llList2String(OPTIONS,i)+": "+llList2String(scores,i));
    }
    else menu("Left: "+llList2String(OPTIONS,a)+"\nRight: "+llList2String(OPTIONS,b),["Left","Right","Tie","Cancel"]);
}
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(OPTIONS);
        if(n<2 || n>6)llOwnerSay("Use 2–6 options.");
        else
        {
            scores=[];
            integer i;
            for(i=0;i<n;++i)scores += [0];
            a=0;
            b=1;
            showPair();
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Left" || input=="Right" || input=="Tie")
        {
            if(input=="Left" || input=="Tie")scores=llListReplaceList(scores,[llList2Integer(scores,a)+1],a,a);
            if(input=="Right" || input=="Tie")scores=llListReplaceList(scores,[llList2Integer(scores,b)+1],b,b);
            ++b;
            if(b>=llGetListLength(OPTIONS))
            {
                ++a;
                b=a+1;
            }
            showPair();
        }
        else llOwnerSay("Option review cancelled.");
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Confirm an action with a deliberate hold

Require the owner to hold a touch for at least two seconds before reporting confirmation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Press and hold the prim, then release. A ten-second watchdog cancels a lost release event.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. The confirmed action is deliberately only a private message. Integrate real actions only after deciding which permissions and reversibility they require.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
float started;
integer deadline;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        started=llGetTime();
        deadline=llGetUnixTime()+10;
        active=TRUE;
        llOwnerSay("Hold two seconds, then release.");
        schedule();
    }
    touch_end(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            float duration=llGetTime()-started;
            if(duration>=2.0)llOwnerSay("Confirmed hold. Demo performs no external action.");
            else llOwnerSay("Released too soon; not confirmed.");
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=deadline)
        {
            active=FALSE;
            llOwnerSay("Hold confirmation expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Beginner

Creator and owner audit

Report the creator and current owner keys of the prim containing the script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the exact prim to inspect; touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

A creator UUID is useful metadata, not proof of rights to textures, meshes, code, or other included assets. Child prims may have different creators.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        key creator = llGetCreator();
        key owner = llGetOwner();
        llOwnerSay("Prim creator: " + (string)creator);
        llOwnerSay("Current owner: " + (string)owner);
        if (creator == owner) llOwnerSay("The current owner is this prim's creator.");
        else llOwnerSay("This prim's creator and owner differ.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Access & ownership · Intermediate

Generate a private human reference label

Create a short timestamp-and-random label for manually matching your own test notes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch to generate a new reference label in owner chat.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Not a password, authentication token, invitation, or cryptographically secure identifier. Collisions remain possible; do not use it to authorize access.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer serial;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ++serial;
        integer suffix=(integer)llFrand(1000000);
        llOwnerSay("Test reference: "+(string)llGetUnixTime()+"-"+(string)serial+"-"+(string)suffix);
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Measure your own touches in a short fixed window

Count only the owner’s touches for ten seconds and report the total once.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: The first touch starts the window and counts as one. Further owner touches increment until the deadline.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. No visitor identities or events are retained. Event delivery and input-device behavior affect the observed count.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer touchesInWindow;
integer due;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(!active)
        {
            active=TRUE;
            due=llGetUnixTime()+10;
            touchesInWindow=1;
            llOwnerSay("Ten-second owner touch window started.");
        }
        else if(llGetUnixTime()<due)++touchesInWindow;
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            active=FALSE;
            llOwnerSay("Owner touches in window: "+(string)touchesInWindow);
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Object permission matrix

Compare owner, next-owner, group, and everyone copy/modify/transfer flags.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in the inspected object.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Reads object permission masks, not a complete nested-content rights audit. Simulator flags do not grant copyright licenses.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list masks=[MASK_OWNER,MASK_NEXT,MASK_GROUP,MASK_EVERYONE];
        list labels=["owner","next owner","group","everyone"];
        integer i;
        for(i=0;i<4;++i)
        {
            integer flags=llGetObjectPermMask(llList2Integer(masks,i));
            llOwnerSay(llList2String(labels,i)+": copy="+(string)((flags & PERM_COPY)!=0)+", modify="+(string)((flags & PERM_MODIFY)!=0)+", transfer="+(string)((flags & PERM_TRANSFER)!=0));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Access & ownership · Intermediate

Owner object-name editor

Open a short-lived owner text box to update this prim’s name.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner, enter a short name, or enter /cancel.

Stop / restore: Listener expires after 30 seconds. Remove to disable; restore the original name in Edit if needed.

Changes the prim containing the script. Limits the new name to 40 printable ASCII characters for predictable metadata; no visitor can edit it.

// Original Incoprea example. MIT.
integer handle;
integer channel;
close()
{
    if(handle)llListenRemove(handle);
    handle=0;
    llSetTimerEvent(0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        close();
        channel=-10000-(integer)llFrand(1000000000);
        handle=llListen(channel,"",llGetOwner(),"");
        llSetTimerEvent(30);
        llTextBox(llGetOwner(),"New object name: 1-40 printable ASCII characters. /cancel keeps it.",channel);
    }
    listen(integer c,string name,key speaker,string text)
    {
        if(speaker!=llGetOwner() || c!=channel)return;
        close();
        if(text=="/cancel")return;
        text=llStringTrim(text,STRING_TRIM);
        if(llStringLength(text)<1 || llStringLength(text)>40)
        {
            llOwnerSay("Name must be 1-40 characters.");
            return;
        }
        integer i;
        for(i=0;i<llStringLength(text);++i)
        {
            integer code=llOrd(text,i);
            if(code<32 || code>126)
            {
                llOwnerSay("Printable ASCII only.");
                return;
            }
        }
        llSetObjectName(text);
        llOwnerSay("Name updated.");
    }
    timer()
    {
        close();
        llOwnerSay("Name input expired.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Access & ownership · Beginner

Owner-only touch switch

Respond only to the owner’s touch; ignore everyone else.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the controlled prim. Touch as owner; other avatars produce no response.

Stop / restore: Disable or remove the script. It changes no object permissions.

This checks the detected toucher’s key against the object owner. It is not a full permission system.

// Original Incoprea example. No object or inventory permissions changed.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) == llGetOwner())
        llOwnerSay("Your little switch is ready.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Access & ownership · Intermediate

Pause and resume a work countdown

Use a dialog to start, pause, resume, inspect, or clear an owner-only countdown.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set DURATION in seconds, then touch and choose Start.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Uses whole wall-clock seconds; pausing preserves remaining duration. Not a stopwatch or a guaranteed precision timer.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer DURATION=300;
integer remaining;
integer due;
integer paused;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        menu("Work countdown",["Start","Pause","Resume","Status","Clear"]);
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Start")
        {
            if(DURATION<5 || DURATION>3600)llOwnerSay("Use 5–3600 seconds.");
            else
            {
                remaining=DURATION;
                due=llGetUnixTime()+remaining;
                paused=FALSE;
                active=TRUE;
            }
        }
        else if(input=="Pause" && active)
        {
            remaining=due-llGetUnixTime();
            if(remaining<0)remaining=0;
            active=FALSE;
            paused=TRUE;
        }
        else if(input=="Resume" && paused && remaining>0)
        {
            due=llGetUnixTime()+remaining;
            paused=FALSE;
            active=TRUE;
        }
        else if(input=="Clear")
        {
            active=FALSE;
            paused=FALSE;
            remaining=0;
        }
        if(input=="Status")
        {
            integer left=remaining;
            if(active)left=due-llGetUnixTime();
            if(left<0)left=0;
            llOwnerSay("Remaining="+(string)left+" seconds; paused="+(string)paused);
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            active=FALSE;
            remaining=0;
            llOwnerSay("Work countdown complete.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Beginner

Private owner note

Send a diagnostic note to the object owner without public chat.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch the prim to send the owner a private note.

Stop / restore: Remove or disable the script. It sends nothing until touched.

Uses llOwnerSay, so nearby visitors do not receive the message.

// Original Incoprea example. No public chat.
default
{
    touch_start(integer count)
    {
        llOwnerSay("The observatory clock is awake.");
    }
}

MIT · original Incoprea example

API reference 1

Access & ownership · Intermediate

Record a private manual release-readiness review

Collect Yes/No answers about backup, rights review, testing, and stopping instructions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch to start the four-question review.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Manual answers are not verification, certification, or publication. Reports unanswered/cancelled reviews as incomplete and does not change permissions or publish anything.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
list QUESTIONS=["Have you saved a backup?","Have you reviewed asset rights?","Have you tested this version in-world?","Are stop/reset instructions included?"];
list answers;
integer step;
question()
{
    if(step>=llGetListLength(QUESTIONS))
    {
        integer yes;
        integer i;
        for(i=0;i<llGetListLength(answers);++i)if(llList2String(answers,i)=="Yes")++yes;
        llOwnerSay("Manual readiness answers: "+(string)yes+" / "+(string)llGetListLength(QUESTIONS)+" yes. Not independent verification.");
    }
    else menu(llList2String(QUESTIONS,step),["Yes","No","Cancel"]);
}
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        answers=[];
        step=0;
        question();
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Yes" || input=="No")
        {
            answers += [input];
            ++step;
            question();
        }
        else llOwnerSay("Readiness review incomplete.");
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Rehearse a sequence of private cue notes

Step through timed cue labels without playing media or moving anything.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set CUES as positive seconds/label pairs. Touch to begin or cancel.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Each duration begins after the previous cue was actually announced. This is a rehearsal aid, not a synchronization system for live performance.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
list CUES=[10,"Check lighting",15,"Read opening",10,"Inspect final position"];
integer index;
integer due;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            llOwnerSay("Rehearsal cancelled.");
        }
        else
        {
            integer valid=llGetListLength(CUES)>0 && llGetListLength(CUES)<=40 && !(llGetListLength(CUES)%2);
            integer i;
            for(i=0;i<llGetListLength(CUES);i+=2)if(llGetListEntryType(CUES,i)!=TYPE_INTEGER || llList2Integer(CUES,i)<1 || llList2Integer(CUES,i)>600)valid=FALSE;
            if(!valid)llOwnerSay("Use up to 20 positive 1–600 second/label pairs.");
            else
            {
                index=0;
                due=llGetUnixTime()+llList2Integer(CUES,0);
                active=TRUE;
                llOwnerSay("Cue: "+llList2String(CUES,1));
            }
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            index+=2;
            if(index>=llGetListLength(CUES))
            {
                active=FALSE;
                llOwnerSay("Rehearsal complete.");
            }
            else
            {
                due=llGetUnixTime()+llList2Integer(CUES,index);
                llOwnerSay("Cue: "+llList2String(CUES,index+1));
            }
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Remind yourself after a quiet work interval

Reset a private inactivity deadline every time you touch your tool object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set IDLE_SECONDS, then touch whenever you mark activity. A single nudge ends the run.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. This measures touches on this object only; it does not monitor avatar activity or infer whether you are actually idle.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer IDLE_SECONDS=120;
integer due;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(IDLE_SECONDS<10 || IDLE_SECONDS>3600)llOwnerSay("Use 10–3600 idle seconds.");
        else
        {
            due=llGetUnixTime()+IDLE_SECONDS;
            active=TRUE;
            llOwnerSay("Work-marker deadline refreshed.");
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            active=FALSE;
            llOwnerSay("No recent touch marker. Check your current work and save if needed.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Rename this prim with a preview and confirmation

Ask for a short name, show the old and proposed names, and apply only after explicit confirmation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own prim and touch. Enter a name and choose Apply.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Changes only this prim’s Name. Save the original first; removing the script does not restore it. Not suitable when another script depends on an exact inventory/object name.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer step;
string proposed;
string original;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        step=1;
        original=llGetObjectName();
        ask("Enter a new name, 1–40 printable ASCII characters.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(step==1)
        {
            integer valid=llStringLength(input)>=1 && llStringLength(input)<=40;
            integer i;
            for(i=0;i<llStringLength(input);++i)if(llOrd(input,i)<32 || llOrd(input,i)>126)valid=FALSE;
            if(!valid)
            {
                llOwnerSay("Invalid name.");
                step=0;
            }
            else
            {
                proposed=input;
                step=2;
                menu("Old: "+original+"\nNew: "+proposed,["Apply","Cancel"]);
            }
        }
        else if(step==2)
        {
            if(input=="Apply")
            {
                if(llGetObjectName()!=original)llOwnerSay("Name changed externally; restart to recheck.");
                else
                {
                    llSetObjectName(proposed);
                    llOwnerSay("Name updated. Original: "+original);
                }
            }
            step=0;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Request a small batch of numbered labels

Parse a prefix/count request and print numbered labels for copying into a build plan.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch and enter prefix|count, with count 1–12.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. No inventory or object names are changed. Prefix is capped at 30 characters and the count uses strict decimal digits.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
ask(string prompt)
{
    beginInput();
    llTextBox(llGetOwner(),prompt,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        ask("Enter prefix|count, for example Panel-|5.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        list p=llParseStringKeepNulls(input,["|"],[]);
        string prefix=llList2String(p,0);
        string countText=llList2String(p,1);
        integer valid=llGetListLength(p)==2 && prefix!="" && llStringLength(prefix)<=30 && llStringLength(countText)>=1 && llStringLength(countText)<=2;
        integer i;
        for(i=0;i<llStringLength(countText);++i)if(llSubStringIndex("0123456789",llGetSubString(countText,i,i))==-1)valid=FALSE;
        integer total=(integer)countText;
        if(!valid || total<1 || total>12)llOwnerSay("Use prefix|count with count 1–12.");
        else for(i=1;i<=total;++i)llOwnerSay(prefix+(string)i);
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Require a second touch inside a confirmation window

Arm on the first touch and accept a second touch only after a brief delay and before expiry.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch once, wait at least one second, and touch again within six seconds.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Only prints a confirmation; no destructive action is attached. This pattern avoids accidental immediate double events being accepted as deliberate confirmation.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer armedAt;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer now=llGetUnixTime();
        if(!active)
        {
            active=TRUE;
            armedAt=now;
            llOwnerSay("Armed: touch again in 1–6 seconds.");
        }
        else if(now-armedAt>=1 && now-armedAt<6)
        {
            active=FALSE;
            llOwnerSay("Second touch confirmed; demo only.");
        }
        else if(now-armedAt>=6)
        {
            active=FALSE;
            llOwnerSay("Window expired; touch again to arm.");
        }
        else llOwnerSay("Wait at least one second.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()-armedAt>=6)
        {
            active=FALSE;
            llOwnerSay("Confirmation window expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Beginner

Resolve the owner’s legacy name

Look up only the current owner’s legacy name and report it privately.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use an avatar-owned object; touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

This is not a display-name lookup. Group-owned objects are outside this example. Responses are matched by query key and time out after 20 seconds.

// Original Incoprea example. MIT.
key pending = NULL_KEY;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        pending = llRequestAgentData(llGetOwner(), DATA_NAME);
        llSetTimerEvent(20.0);
    }
    dataserver(key query, string data)
    {
        if (query != pending || pending == NULL_KEY) return;
        pending = NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Owner legacy name: " + data);
    }
    timer()
    {
        pending = NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Name request timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Access & ownership · Intermediate

Run a bounded work and break cycle

Alternate a configurable work phase and break phase for a finite number of rounds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit WORK, REST, and ROUNDS. Touch to start or cancel.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Only phase-change messages are emitted. A delayed timer starts the next phase when processed; it does not burst through missed notifications.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer WORK=300;
integer REST=60;
integer ROUNDS=3;
integer round;
integer phase;
integer due;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            llOwnerSay("Cycle cancelled.");
        }
        else if(WORK<5 || REST<5 || WORK>3600 || REST>3600 || ROUNDS<1 || ROUNDS>12)llOwnerSay("Invalid cycle limits.");
        else
        {
            round=1;
            phase=0;
            active=TRUE;
            due=llGetUnixTime()+WORK;
            llOwnerSay("Work round 1 begins.");
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            if(phase==0)
            {
                phase=1;
                due=llGetUnixTime()+REST;
                llOwnerSay("Break begins.");
            }
            else if(round>=ROUNDS)
            {
                active=FALSE;
                llOwnerSay("All work/break rounds complete.");
            }
            else
            {
                ++round;
                phase=0;
                due=llGetUnixTime()+WORK;
                llOwnerSay("Work round "+(string)round+" begins.");
            }
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Set a one-shot private reminder

Start one short countdown and send a single owner-chat reminder when it expires.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit SECONDS and MESSAGE. Touch to start; touch again before it fires to cancel.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. No public chat, sound, or offline delivery guarantee. Maximum one hour; reset loses the pending reminder.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer SECONDS=120;
string MESSAGE="Save a copy of the build.";
integer due;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            llOwnerSay("Reminder cancelled.");
        }
        else if(SECONDS>=5 && SECONDS<=3600)
        {
            due=llGetUnixTime()+SECONDS;
            active=TRUE;
            llOwnerSay("Reminder armed.");
        }
        else llOwnerSay("Use 5–3600 seconds.");
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            active=FALSE;
            llOwnerSay("Reminder: "+MESSAGE);
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Snooze a private review reminder

When a short timer expires, offer Done or Snooze through an owner-only dialog.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch to arm a 60-second review reminder. Snooze delays it another 60 seconds; touch while armed cancels.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. If the dialog expires there is no further notification until you touch to start again. Maximum three snoozes per run.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
integer due;
integer snoozes;
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(active)
        {
            active=FALSE;
            closeInput();
            llOwnerSay("Review reminder cancelled.");
        }
        else
        {
            closeInput();
            snoozes=0;
            active=TRUE;
            due=llGetUnixTime()+60;
            llOwnerSay("Review reminder in 60 seconds.");
        }
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Snooze" && snoozes<3)
        {
            ++snoozes;
            due=llGetUnixTime()+60;
            active=TRUE;
            llOwnerSay("Snoozed.");
        }
        else if(input=="Done")llOwnerSay("Review reminder dismissed.");
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        if(active && llGetUnixTime()>=due)
        {
            active=FALSE;
            if(snoozes<3)menu("Review your build now?",["Done","Snooze"]);
            else menu("Final reminder: review your build.",["Done"]);
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Access & ownership · Intermediate

Thirty-second owner console

Open a brief owner-only chat console for name, size, and close commands.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner, then use the chat channel printed privately. Type name, size, or close.

Stop / restore: Send close, wait thirty seconds, or remove the script. The listener is removed on timeout.

Only the avatar owner is accepted. This console does not move, delete, or transfer anything; channel secrecy is not used as authentication.

// Original Incoprea example. MIT.
integer channel;
integer handle;
closeConsole()
{
    if (handle) llListenRemove(handle);
    handle = 0;
    llSetTimerEvent(0.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        closeConsole();
        channel = 10000 + (integer)llFrand(900000.0);
        handle = llListen(channel, "", llGetOwner(), "");
        llSetTimerEvent(30.0);
        llOwnerSay("For 30 seconds, type /" + (string)channel + " name (or size, close).");
    }
    listen(integer heardChannel, string name, key speaker, string message)
    {
        if (speaker != llGetOwner() || heardChannel != channel) return;
        message = llToLower(llStringTrim(message, STRING_TRIM));
        if (message == "close")
        {
            closeConsole();
            llOwnerSay("Console closed.");
        }
        else if (message == "name") llOwnerSay(llGetObjectName());
        else if (message == "size") llOwnerSay((string)llGetScale());
        else llOwnerSay("Commands: name, size, close.");
    }
    timer()
    {
        closeConsole();
        llOwnerSay("Console expired.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Access & ownership · Intermediate

Walk through an ordered build checklist

Ask for a manual Done or Skip decision for each configured step and summarize skipped steps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set STEPS, then touch to start a fresh review.

Stop / restore: Remove, disable, or reset to stop timers and discard session state. Temporary input listeners expire after 45 seconds.

Only the current owner can control this example. Timing is approximate and can be delayed by simulator load. Manual declarations only; it cannot verify that a step was truly completed. The report is private and lost on reset.

// Original Incoprea example. MIT.
integer active;
integer handle;
integer channel;
integer expires;
list STEPS=["Check permissions","Check stop instructions","Save a backup","Test in a sandbox"];
integer index;
list skipped;
nextStep()
{
    if(index>=llGetListLength(STEPS))
    {
        llOwnerSay("Review complete. Skipped: "+llList2CSV(skipped));
    }
    else menu("Step "+(string)(index+1)+": "+llList2String(STEPS,index),["Done","Skip","Cancel"]);
}
closeInput()
{
    if(handle)llListenRemove(handle);
    handle=0;
}
schedule()
{
    if(active || handle)llSetTimerEvent(1.0);
    else llSetTimerEvent(0.0);
}
beginInput()
{
    closeInput();
    channel=-10000-(integer)llFrand(1000000000);
    handle=llListen(channel,"",llGetOwner(),"");
    expires=llGetUnixTime()+45;
    schedule();
}
menu(string prompt,list buttons)
{
    beginInput();
    llDialog(llGetOwner(),prompt,buttons,channel);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        index=0;
        skipped=[];
        nextStep();
        schedule();
    }
    listen(integer c,string name,key speaker,string input)
    {
        if(c!=channel || speaker!=llGetOwner() || !handle)return;
        closeInput();
        if(llStringLength(input)>200)
        {
            llOwnerSay("Reply is too long.");
            schedule();
            return;
        }
        if(input=="Done" || input=="Skip")
        {
            if(input=="Skip")skipped += [llList2String(STEPS,index)];
            ++index;
            nextStep();
        }
        else llOwnerSay("Review cancelled.");
        schedule();
    }
    timer()
    {
        if(handle && llGetUnixTime()>=expires)
        {
            closeInput();
            llOwnerSay("Input expired.");
        }
        schedule();
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Inventory & notecardsRead and work with an object’s contents.76 scripts

Download this category (.zip)

Inventory & notecards · Intermediate

Audit a build bill of materials

Check object-name/quantity rows and sum planned quantities.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use objectName|positiveIntegerQuantity. Add the referenced objects to the same prim. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Checks one inventory object entry exists for each name; an entry is not proof that enough transferable copies are available.

// Original Incoprea example. MIT.
integer numberOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
integer total;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Planned total component instances: "+(string)total);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2 || !numberOK(llList2String(p,1)))
    {
        issue("Expected objectName|quantity.");
        return;
    }
    integer quantity=llList2Integer(p,1);
    if(quantity<1 || quantity>1000)
    {
        issue("Quantity must be 1-1000.");
        return;
    }
    string name=llList2String(p,0);
    if(llGetInventoryType(name)!=INVENTORY_OBJECT)issue("Object asset missing: "+name);
    total+=quantity;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a configuration key namespace

Find config keys that begin with reserved underscore prefixes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use key=value lines. Keys beginning _ are reserved in this example. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. It does not validate values. Choose a reserved-prefix convention before handing configuration files to other builders.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    integer split=llSubStringIndex(data,"=");
    if(split<=0)
    {
        issue("Expected key=value.");
        return;
    }
    string keyName=llStringTrim(llGetSubString(data,0,split-1),STRING_TRIM);
    if(keyName=="")
    {
        issue("Empty key.");
        return;
    }
    if(llGetSubString(keyName,0,0)=="_")issue("Reserved internal key: "+keyName);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a daily UTC notice schedule

Validate HH:MM|message rows and detect duplicate times.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use 24-hour UTC times such as 09:30|Workshop opens. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Validates format only; it does not schedule broadcasts. Messages must fit a conservative 120-character limit.

// Original Incoprea example. MIT.
integer numberOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
list times;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        issue("Expected HH:MM|message.");
        return;
    }
    string time=llList2String(p,0);
    list clock=llParseStringKeepNulls(time,[":"],[]);
    if(llStringLength(time)!=5 || llGetListLength(clock)!=2 || !numberOK(llList2String(clock,0)) || !numberOK(llList2String(clock,1)) || llStringLength(llList2String(clock,0))!=2 || llStringLength(llList2String(clock,1))!=2 || llList2Integer(clock,0)>23 || llList2Integer(clock,1)>59)
    {
        issue("Invalid HH:MM time.");
        return;
    }
    string message=llList2String(p,1);
    if(message=="" || llStringLength(message)>120)issue("Message must be 1-120 characters.");
    if(llListFindList(times,[time])!=-1)issue("Duplicate scheduled time.");
    else times += [time];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a document’s internal anchor references

Find duplicate anchor declarations and references to missing anchors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use anchor|id and link|id rows. Other row kinds are rejected. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Checks your authored identifiers only; this is not an HTML parser or a web crawler. Empty identifiers are invalid.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list anchors;
    list links;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        string kind=llList2String(p,0);
        string id=llList2String(p,1);
        if(llGetListLength(p)!=2 || id=="")
        {
            llOwnerSay("Invalid anchor row.");
            return;
        }
        if(kind=="anchor")
        {
            if(llListFindList(anchors,[id])!=-1)llOwnerSay("Duplicate anchor: "+id);
            anchors += [id];
        }
        else if(kind=="link")links += [id];
        else
        {
            llOwnerSay("Use anchor or link.");
            return;
        }
    }
    for(i=0;i<llGetListLength(links);++i)if(llListFindList(anchors,[llList2String(links,i)])==-1)llOwnerSay("Broken internal reference: "+llList2String(links,i));
    llOwnerSay("Anchor audit complete.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a fallback inventory chain

Read ordered inventory names and report the first currently available item.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. One inventory item name per line, highest preference first. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. All inventory types are accepted; use the result only after checking the expected type in the consuming script. No asset is loaded, given, or played.

// Original Incoprea example. MIT.
string firstAvailable;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    if(firstAvailable=="")llOwnerSay("No available fallback item.");
    else llOwnerSay("First available candidate: "+firstAvailable);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    if(firstAvailable=="" && llGetInventoryType(data)!=INVENTORY_NONE)firstAvailable=data;
    else if(llGetInventoryType(data)==INVENTORY_NONE)llOwnerSay("Unavailable fallback candidate: "+data);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a named HEX palette

Validate unique color names paired with six-digit RGB codes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. One name|RRGGBB pair per line, for example Moss|74A068. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Names are case-sensitive. This does not apply colors or convert color spaces.

// Original Incoprea example. MIT.
integer hexOK(string value)
{
    integer i;
    if(llStringLength(value)!=6)return FALSE;
    value=llToLower(value);
    for(i=0;i<6;++i)if(llSubStringIndex("0123456789abcdef",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
list names;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        issue("Expected name|RRGGBB.");
        return;
    }
    string name=llList2String(p,0);
    if(name=="" || !hexOK(llList2String(p,1)))
    {
        issue("Empty name or invalid RGB code.");
        return;
    }
    if(llListFindList(names,[name])!=-1)issue("Duplicate color name: "+name);
    else names += [name];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit a small room-exit map

Find missing destination rooms and exits without a reverse connection.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use fromRoom|toRoom rows. Each named room must appear as a source somewhere to be considered declared. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. This analyzes your authored map only and does not inspect locations or people. One-way passages may be intentional; reports are warnings.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list from;
    list to;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2 || llList2String(p,0)=="" || llList2String(p,1)=="")
        {
            llOwnerSay("Malformed exit row.");
            return;
        }
        from += [llList2String(p,0)];
        to += [llList2String(p,1)];
    }
    for(i=0;i<llGetListLength(from);++i)
    {
        string a=llList2String(from,i);
        string b=llList2String(to,i);
        if(llListFindList(from,[b])==-1)llOwnerSay("Undeclared destination: "+b);
        integer j;
        integer reverse;
        for(j=0;j<llGetListLength(from);++j)if(llList2String(from,j)==b && llList2String(to,j)==a)reverse=TRUE;
        if(!reverse)llOwnerSay("No reverse exit: "+a+" -> "+b);
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit asset credit rows

Check asset|creatorCredit|licenseReference records are complete and point to an inventory item.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Write one attribution record per line; fields must not contain pipes. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Checks documentation presence, not legal validity. Creator-credit text is supplied by you and is not automatically verified against creator metadata.

// Original Incoprea example. MIT.
list assets;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=3)
    {
        issue("Expected asset|credit|license reference.");
        return;
    }
    integer i;
    for(i=0;i<3;++i)if(llStringTrim(llList2String(p,i),STRING_TRIM)=="")
    {
        issue("Incomplete credit row.");
        return;
    }
    string name=llList2String(p,0);
    if(llGetInventoryType(name)==INVENTORY_NONE)issue("Referenced inventory item missing: "+name);
    if(llListFindList(assets,[name])!=-1)issue("Duplicate asset credit row.");
    else assets += [name];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit dialog button labels

Check that a proposed dialog has at most twelve unique short ASCII labels.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. One button label per line. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Label limits here are conservative: 1-24 printable ASCII bytes. No dialog is opened, and button order is not changed.

// Original Incoprea example. MIT.
list labels;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    if(llStringLength(data)>24)
    {
        issue("Button exceeds 24 ASCII characters.");
        return;
    }
    integer i;
    for(i=0;i<llStringLength(data);++i)
    {
        integer c=llOrd(data,i);
        if(c<32 || c>126)
        {
            issue("Use printable ASCII labels.");
            return;
        }
    }
    if(llListFindList(labels,[data])!=-1)issue("Duplicate label.");
    else labels += [data];
    if(llGetListLength(labels)>12)issue("Dialog exceeds 12 distinct buttons.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit face-to-texture assignments

Check face numbers, duplicate assignments, and texture inventory names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use faceNumber|textureName, one assignment per line. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Validates against the prim containing the script. It neither changes textures nor verifies image content or licensing.

// Original Incoprea example. MIT.
integer numberOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
list faces;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2 || !numberOK(llList2String(p,0)))
    {
        issue("Expected faceNumber|textureName.");
        return;
    }
    integer face=llList2Integer(p,0);
    if(face>=llGetNumberOfSides())
    {
        issue("Face does not exist.");
        return;
    }
    if(llListFindList(faces,[face])!=-1)issue("Face assigned more than once.");
    else faces += [face];
    string name=llList2String(p,1);
    if(llGetInventoryType(name)!=INVENTORY_TEXTURE)issue("Texture missing: "+name);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit inventory media cues

Check timed sound/animation cues against this prim’s inventory.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use sound|name|seconds or animation|name|seconds. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Seconds must be a simple positive decimal up to 600. It does not play media or request animation permission.

// Original Incoprea example. MIT.
integer decimalOK(string value)
{
    integer n=llStringLength(value);
    if(n<1 || n>12)return FALSE;
    integer i;
    integer digits;
    integer dots;
    if(llGetSubString(value,0,0)=="-" || llGetSubString(value,0,0)=="+")i=1;
    for(;i<n;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
float total;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Duration of valid available cues: "+(string)total+" seconds.");
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=3)
    {
        issue("Expected type|name|seconds.");
        return;
    }
    string kind=llList2String(p,0);
    integer expected=INVENTORY_NONE;
    if(kind=="sound")expected=INVENTORY_SOUND;
    else if(kind=="animation")expected=INVENTORY_ANIMATION;
    else
    {
        issue("Type must be sound or animation.");
        return;
    }
    string duration=llList2String(p,2);
    if(!decimalOK(duration) || (float)duration<=0 || (float)duration>600)
    {
        issue("Invalid duration.");
        return;
    }
    string name=llList2String(p,1);
    if(llGetInventoryType(name)!=expected)issue("Missing or wrong-type asset: "+name);
    else total+=(float)duration;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit local waypoint triples

Validate x,y,z rows and report the total path length of accepted points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. One decimal x,y,z triple per line, without angle brackets. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. All coordinates must use the same local frame and lie within 4096 in magnitude. Invalid rows are excluded; no object moves.

// Original Incoprea example. MIT.
integer decimalOK(string value)
{
    integer n=llStringLength(value);
    if(n<1 || n>12)return FALSE;
    integer i;
    integer digits;
    integer dots;
    if(llGetSubString(value,0,0)=="-" || llGetSubString(value,0,0)=="+")i=1;
    for(;i<n;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
vector previous;
integer hasPoint;
float distance;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Accepted-segment path length: "+(string)distance+" meters.");
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,[","],[]);
    if(llGetListLength(p)!=3)
    {
        issue("Expected three components.");
        return;
    }
    integer i;
    for(i=0;i<3;++i)
    {
        string value=llStringTrim(llList2String(p,i),STRING_TRIM);
        if(!decimalOK(value) || llFabs((float)value)>4096)
        {
            issue("Invalid or out-of-range coordinate.");
            return;
        }
    }
    vector point=<llList2Float(p,0),llList2Float(p,1),llList2Float(p,2)>;
    if(hasPoint)distance+=llVecDist(previous,point);
    previous=point;
    hasPoint=TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit menu action routes

Check unique button labels mapped to a declared set of action names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use label|action rows. Edit ACTIONS in the script to your supported commands. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Does not execute any action. This catches stale labels and unknown action tokens before wiring a menu.

// Original Incoprea example. MIT.
list ACTIONS=["show","hide","help","close"];
list labels;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        issue("Expected label|action.");
        return;
    }
    string label=llList2String(p,0);
    string action=llList2String(p,1);
    if(label=="" || llStringLength(label)>24)issue("Label must be 1-24 characters.");
    if(llListFindList(labels,[label])!=-1)issue("Duplicate menu label.");
    else labels += [label];
    if(llListFindList(ACTIONS,[action])==-1)issue("Unknown action: "+action);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit named threshold bands

Validate ordered non-overlapping name|min|max ranges.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use decimal lower and upper bounds, such as Low|0|10. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Validates increasing intervals and overlap, not measurement semantics. Gaps are allowed and explicitly reported as informational.

// Original Incoprea example. MIT.
integer decimalOK(string value)
{
    integer n=llStringLength(value);
    if(n<1 || n>12)return FALSE;
    integer i;
    integer digits;
    integer dots;
    if(llGetSubString(value,0,0)=="-" || llGetSubString(value,0,0)=="+")i=1;
    for(;i<n;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
float lastHigh;
integer ready;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=3 || !decimalOK(llList2String(p,1)) || !decimalOK(llList2String(p,2)))
    {
        issue("Expected name|min|max.");
        return;
    }
    float low=llList2Float(p,1);
    float high=llList2Float(p,2);
    if(llList2String(p,0)=="" || high<=low)
    {
        issue("Empty name or invalid interval.");
        return;
    }
    if(ready)
    {
        if(low<lastHigh)issue("Overlaps prior band.");
        else if(low>lastHigh)llOwnerSay("Gap before "+llList2String(p,0));
    }
    lastHigh=high;
    ready=TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit non-overlapping subtitle cues

Validate start|end|text cues are ordered and do not overlap.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use decimal seconds from zero, for example 0|4.5|Welcome. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. No sound plays and no captions are displayed. Adjacent cues may touch at an endpoint; negative, inverted, or overlapping times are findings.

// Original Incoprea example. MIT.
integer decimalOK(string value)
{
    integer n=llStringLength(value);
    if(n<1 || n>12)return FALSE;
    integer i;
    integer digits;
    integer dots;
    if(llGetSubString(value,0,0)=="-" || llGetSubString(value,0,0)=="+")i=1;
    for(;i<n;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
float previousEnd;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=3 || !decimalOK(llList2String(p,0)) || !decimalOK(llList2String(p,1)))
    {
        issue("Expected start|end|text.");
        return;
    }
    float start=llList2Float(p,0);
    float end=llList2Float(p,1);
    if(start<0 || end<=start || end>86400)
    {
        issue("Invalid cue interval.");
        return;
    }
    if(start<previousEnd)issue("Overlaps or precedes the prior accepted cue.");
    if(llList2String(p,2)=="")issue("Empty caption.");
    previousEnd=end;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit paired language labels

Validate key|languageA|languageB rows for missing translations and repeated keys.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use a unique key followed by two short translations separated by pipes. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. No translation is performed or judged. Pipes inside translations are not supported; checks structural completeness only.

// Original Incoprea example. MIT.
list keys;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=3)
    {
        issue("Expected key|languageA|languageB.");
        return;
    }
    string name=llList2String(p,0);
    if(name=="" || llStringTrim(llList2String(p,1),STRING_TRIM)=="" || llStringTrim(llList2String(p,2),STRING_TRIM)=="")issue("Missing key or translation.");
    if(llListFindList(keys,[name])!=-1)issue("Duplicate translation key.");
    else keys += [name];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit resource reference schemes

Check resource-name|URI rows use an explicitly allowed URI prefix.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use name|https://... or name|secondlife://... rows. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Only checks an allowed prefix and rejects whitespace/control characters; it does not establish URL existence or safety and never opens a link.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2 || llList2String(p,0)=="")
    {
        issue("Expected name|URI.");
        return;
    }
    string uri=llList2String(p,1);
    string lower=llToLower(uri);
    if(llSubStringIndex(lower,"https://")!=0 && llSubStringIndex(lower,"secondlife://")!=0)
    {
        issue("Unsupported URI scheme.");
        return;
    }
    integer i;
    for(i=0;i<llStringLength(uri);++i)if(llOrd(uri,i)<=32)
    {
        issue("Whitespace/control character in URI.");
        return;
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit sprite-sheet specifications

Validate textureName|columns|rows|frames settings for a flipbook.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Place referenced textures in the same prim. Use positive integer grid sizes. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Frames cannot exceed grid cells. Does not inspect pixels to verify the claimed sprite sheet dimensions or start animation.

// Original Incoprea example. MIT.
integer numberOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=4)
    {
        issue("Expected texture|columns|rows|frames.");
        return;
    }
    integer i;
    for(i=1;i<4;++i)if(!numberOK(llList2String(p,i)))
    {
        issue("Grid values must be integers.");
        return;
    }
    integer cols=llList2Integer(p,1);
    integer rows=llList2Integer(p,2);
    integer frames=llList2Integer(p,3);
    if(cols<1 || rows<1 || cols>64 || rows>64 || frames<1 || frames>cols*rows)issue("Invalid grid or frame count.");
    if(llGetInventoryType(llList2String(p,0))!=INVENTORY_TEXTURE)issue("Referenced texture missing.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit tabular display widths

Check each pipe-delimited row against configured column character budgets.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Edit WIDTHS, then add pipe-separated rows with one field per column. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Character counts are not proportional-font pixel measurements. Empty cells are allowed; embedded pipes are unsupported.

// Original Incoprea example. MIT.
list WIDTHS=[16,10,6];
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=llGetListLength(WIDTHS))
    {
        issue("Wrong column count.");
        return;
    }
    integer i;
    for(i=0;i<llGetListLength(p);++i)if(llStringLength(llList2String(p,i))>llList2Integer(WIDTHS,i))issue("Column "+(string)(i+1)+" exceeds its width budget.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit unique ordered cue IDs

Check that positive cue IDs increase strictly while allowing numeric gaps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use integerID|description rows. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Increasing IDs make later insertions easier when gaps are left. This checks identifiers, not timing or event delivery.

// Original Incoprea example. MIT.
integer numberOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
integer previous;
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2 || !numberOK(llList2String(p,0)))
    {
        issue("Expected ID|description.");
        return;
    }
    integer id=llList2Integer(p,0);
    if(id<=0 || id<=previous)issue("ID must be positive and greater than prior ID.");
    if(llList2String(p,1)=="")issue("Empty cue description.");
    previous=id;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Audit UTF-8 message budgets

Check key|message records against a 240-byte UTF-8 display budget.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Use short message records with a unique key. Touch as owner; reset to scan again.

Stop / restore: Remove or disable. This auditor never changes object settings or inventory.

Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Byte count uses the returned notecard text; simulator truncation can hide the original full line length. Does not guarantee a later combined label fits.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
integer lineNumber;
integer scannedRows;
integer issues;
integer finished;
issue(string text)
{
    ++issues;
    llOwnerSay("Line "+(string)(lineNumber+1)+": "+text);
}
requestLine()
{
    pending=llGetNotecardLine("Config",lineNumber);
    llSetTimerEvent(20);
}
finish()
{
    pending=NULL_KEY;
    finished=TRUE;
    llSetTimerEvent(0);
    llOwnerSay("Audited rows: "+(string)scannedRows+"; findings: "+(string)issues);
}
check(string data)
{
    list p=llParseStringKeepNulls(data,["|"],[]);
    if(llGetListLength(p)!=2)
    {
        issue("Expected key|message.");
        return;
    }
    string text=llList2String(p,1);
    string encoded=llStringToBase64(text);
    integer size=llStringLength(encoded);
    integer bytes=(size/4)*3;
    if(size>0)
    {
        if(llGetSubString(encoded,-1,-1)=="=")--bytes;
        if(llGetSubString(encoded,-2,-2)=="=")--bytes;
    }
    if(bytes>240)issue("Message exceeds 240 UTF-8 bytes.");
    if(llList2String(p,0)=="")issue("Empty message key.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY || finished)
        {
            llOwnerSay("Reset before starting another audit.");
            return;
        }
        if(llGetInventoryType("Config")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Config notecard.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            finish();
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")
        {
            ++scannedRows;
            check(data);
        }
        ++lineNumber;
        if(lineNumber>=40)
        {
            llOwnerSay("40-line cap reached; report may be partial.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        finished=TRUE;
        llSetTimerEvent(0);
        llOwnerSay("Audit timed out; partial checks only. Reset to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Blend named numeric preset weights

Normalize nonnegative integer weights from a notecard and print percentages.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use label|integerWeight rows, weights 0–999999. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. A zero total is rejected. This computes a planned mix only; it does not apply colors, audio, physics, or probabilistic actions.

// Original Incoprea example. MIT.
integer whole(string s)
{
    if(s=="" || llStringLength(s)>6)return FALSE;
    integer i;
    for(i=0;i<llStringLength(s);++i)if(llSubStringIndex("0123456789",llGetSubString(s,i,i))==-1)return FALSE;
    return TRUE;
}
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list names;
    list weights;
    float total;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2 || llList2String(p,0)=="" || !whole(llList2String(p,1)))
        {
            llOwnerSay("Invalid weight row.");
            return;
        }
        if(llListFindList(names,[llList2String(p,0)])!=-1)
        {
            llOwnerSay("Duplicate preset label.");
            return;
        }
        names += [llList2String(p,0)];
        weights += [llList2Integer(p,1)];
        total+=(float)llList2Integer(p,1);
    }
    if(total<=0)
    {
        llOwnerSay("Weight total must be positive.");
        return;
    }
    for(i=0;i<llGetListLength(names);++i)llOwnerSay(llList2String(names,i)+" "+(string)(100.0*llList2Integer(weights,i)/total)+"%");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Browse a notecard glossary by prefix

Report entries whose term begins with a selected prefix.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use term|definition rows. Set PREFIX to a nonempty string. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Case-insensitive prefix search; emits at most ten matches and tells you how many matched in total. Definitions remain authored text, not verified facts.

// Original Incoprea example. MIT.
string PREFIX="rot";
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    string prefix=llToLower(PREFIX);
    if(prefix=="")
    {
        llOwnerSay("Set a nonempty prefix.");
        return;
    }
    integer i;
    integer matches;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2)
        {
            llOwnerSay("Use term|definition rows.");
            return;
        }
        if(llSubStringIndex(llToLower(llList2String(p,0)),prefix)==0)
        {
            ++matches;
            if(matches<=10)llOwnerSay(llList2String(p,0)+": "+llList2String(p,1));
        }
    }
    llOwnerSay("Matches: "+(string)matches+"; maximum ten shown.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Check a pipe table’s column counts

Find rows whose number of pipe-delimited columns differs from the first nonblank row.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Keeps empty cells. Quoted pipes are not supported; this is not CSV.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer expected;
integer rows;
integer issues;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Rows: "+(string)rows+", expected columns: "+(string)expected+", mismatches: "+(string)issues);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        if(llStringTrim(data,STRING_TRIM)!="")
        {
            integer columns=llGetListLength(llParseStringKeepNulls(data,["|"],[]));
            if(expected==0) expected=columns;
            else if(columns!=expected)
            {
                ++issues;
                llOwnerSay("Line "+(string)(lineNumber+1)+": "+(string)columns+" columns, expected "+(string)expected);
            }
            ++rows;
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Check installed package versions against requirements

Compare dependency minimums from a notecard to a configured local package manifest.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use package|minVersion rows. Edit INSTALLED package/version pairs in the script. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Both versions use three components 0–999. These are authored version labels, not an automatic security or compatibility guarantee.

// Original Incoprea example. MIT.
integer whole(string s)
{
    if(s=="" || llStringLength(s)>6)return FALSE;
    integer i;
    for(i=0;i<llStringLength(s);++i)if(llSubStringIndex("0123456789",llGetSubString(s,i,i))==-1)return FALSE;
    return TRUE;
}
integer validVersion(string s)
{
    list p=llParseStringKeepNulls(s,["."],[]);
    if(llGetListLength(p)!=3)return FALSE;
    integer i;
    for(i=0;i<3;++i)if(!whole(llList2String(p,i)) || llList2Integer(p,i)>999)return FALSE;
    return TRUE;
}
integer versionCode(string s)
{
    list p=llParseStringKeepNulls(s,["."],[]);
    return llList2Integer(p,0)*1000000+llList2Integer(p,1)*1000+llList2Integer(p,2);
}
list INSTALLED=["lighting","1.2.0","door","2.0.1"];
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    if(llGetListLength(INSTALLED)%2)
    {
        llOwnerSay("Installed manifest malformed.");
        return;
    }
    list keys;
    integer i;
    for(i=0;i<llGetListLength(INSTALLED);i+=2)
    {
        if(!validVersion(llList2String(INSTALLED,i+1)) || llListFindList(keys,[llList2String(INSTALLED,i)])!=-1)
        {
            llOwnerSay("Invalid or duplicate installed package.");
            return;
        }
        keys += [llList2String(INSTALLED,i)];
    }
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2 || !validVersion(llList2String(p,1)))
        {
            llOwnerSay("Invalid requirement.");
            return;
        }
        string name=llList2String(p,0);
        integer at=llListFindList(keys,[name]);
        if(at==-1)llOwnerSay("Missing package: "+name);
        else if(versionCode(llList2String(INSTALLED,at*2+1))<versionCode(llList2String(p,1)))llOwnerSay("Below required version: "+name);
        else llOwnerSay("Version meets declared minimum: "+name);
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Check language coverage for message identifiers

Find message keys missing from a configured set of languages.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use language|key|translation rows, for example en|hello|Hello. Set LANGUAGES. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Duplicate language/key rows are rejected; translations are not judged for correctness. Unlisted languages are allowed but do not satisfy required coverage.

// Original Incoprea example. MIT.
list LANGUAGES=["en","es","fr"];
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list keys;
    list pairs;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=3 || llList2String(p,0)=="" || llList2String(p,1)=="" || llList2String(p,2)=="")
        {
            llOwnerSay("Incomplete translation.");
            return;
        }
        string keyText=llList2String(p,1);
        string pair=llList2String(p,0)+"|"+keyText;
        if(llListFindList(pairs,[pair])!=-1)
        {
            llOwnerSay("Duplicate translation: "+pair);
            return;
        }
        pairs += [pair];
        if(llListFindList(keys,[keyText])==-1)keys += [keyText];
    }
    for(i=0;i<llGetListLength(keys);++i)
    {
        integer j;
        for(j=0;j<llGetListLength(LANGUAGES);++j)
        {
            string pair=llList2String(LANGUAGES,j)+"|"+llList2String(keys,i);
            if(llListFindList(pairs,[pair])==-1)llOwnerSay("Missing: "+pair);
        }
    }
    llOwnerSay("Language coverage audit complete.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Check local notecard include declarations

Verify that declared include targets exist as notecards in this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use include|Card Name lines; other lines are ignored. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Does not recursively load includes or execute configuration. Self-inclusion and repeated includes are reported as likely configuration mistakes.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list seen;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llList2String(p,0)=="include")
        {
            if(llGetListLength(p)!=2 || llList2String(p,1)=="")
            {
                llOwnerSay("Malformed include.");
                return;
            }
            string name=llList2String(p,1);
            if(name=="Data")llOwnerSay("Self include: "+name);
            if(llListFindList(seen,[name])!=-1)llOwnerSay("Repeated include: "+name);
            seen += [name];
            if(llGetInventoryType(name)!=INVENTORY_NOTECARD)llOwnerSay("Missing notecard: "+name);
            else llOwnerSay("Available include: "+name);
        }
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Check numbered instruction steps

Validate consecutive step prefixes such as 1. then 2. then 3.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Only lines beginning with digits followed by a dot are treated as steps. Number strings over six digits are rejected.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer expected=1;
integer issues;
integer steps;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Numbered steps: "+(string)steps+"; sequence findings: "+(string)issues);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        integer dot=llSubStringIndex(trimmed,".");
        if(dot>0 && dot<=6)
        {
            string digits=llGetSubString(trimmed,0,dot-1);
            integer valid=TRUE;
            integer i;
            for(i=0;i<llStringLength(digits);++i) if(llSubStringIndex("0123456789",llGetSubString(digits,i,i))==-1) valid=FALSE;
            if(valid)
            {
                integer number=(integer)digits;
                if(number!=expected)
                {
                    ++issues;
                    llOwnerSay("Line "+(string)(lineNumber+1)+": expected step "+(string)expected+", found "+digits);
                }
                expected=number+1;
                ++steps;
            }
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Check release notes are in version order

Validate simple three-integer versions and detect ordering mistakes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use major.minor.patch|release note rows in newest-first order. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Components are 0–999, with no prerelease/build suffixes. This is a deliberately smaller grammar than full Semantic Versioning.

// Original Incoprea example. MIT.
integer whole(string s)
{
    if(s=="" || llStringLength(s)>6)return FALSE;
    integer i;
    for(i=0;i<llStringLength(s);++i)if(llSubStringIndex("0123456789",llGetSubString(s,i,i))==-1)return FALSE;
    return TRUE;
}
integer validVersion(string s)
{
    list p=llParseStringKeepNulls(s,["."],[]);
    if(llGetListLength(p)!=3)return FALSE;
    integer i;
    for(i=0;i<3;++i)if(!whole(llList2String(p,i)) || llList2Integer(p,i)>999)return FALSE;
    return TRUE;
}
integer versionCode(string s)
{
    list p=llParseStringKeepNulls(s,["."],[]);
    return llList2Integer(p,0)*1000000+llList2Integer(p,1)*1000+llList2Integer(p,2);
}
// Components use whole-number validation.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    integer previous=1000000000;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        string value=llList2String(p,0);
        if(llGetListLength(p)!=2 || !validVersion(value))
        {
            llOwnerSay("Invalid version row.");
            return;
        }
        integer code=versionCode(value);
        if(code>=previous)llOwnerSay("Not strictly descending at "+value);
        previous=code;
    }
    llOwnerSay("Release order checked.");
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Beginner

Check required inventory assets

Check that named notecard, sound, and texture dependencies are present with the expected types.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the REQUIREMENTS list in type/name pairs to match your build. Touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Existence and type do not establish licensing, permissions, asset quality, or whether another script can use an asset successfully.

// Original Incoprea example. MIT.
list REQUIREMENTS = [INVENTORY_NOTECARD, "Config", INVENTORY_SOUND, "Chime", INVENTORY_TEXTURE, "Panel"];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer i;
        for (i = 0; i < llGetListLength(REQUIREMENTS); i += 2)
        {
            integer expected = llList2Integer(REQUIREMENTS, i);
            string name = llList2String(REQUIREMENTS, i + 1);
            integer actual = llGetInventoryType(name);
            if (actual == INVENTORY_NONE) llOwnerSay("MISSING: " + name);
            else if (actual != expected) llOwnerSay("WRONG TYPE: " + name);
            else llOwnerSay("PRESENT: " + name);
        }
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Common next-owner permission flags

Compute which copy/modify/transfer flags are shared by all items in this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner; audit a small delivery prim.

Stop / restore: Disable or remove the script. It makes no inventory changes.

A read-only planning aid, not a complete object packaging permission calculation or license determination. Includes the checker itself.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        integer common=PERM_COPY|PERM_MODIFY|PERM_TRANSFER;
        integer i;
        for(i=0;i<total;++i) common=common & llGetInventoryPermMask(llGetInventoryName(INVENTORY_ALL,i),MASK_NEXT);
        llOwnerSay("Flags shared by all inventory entries: copy="+(string)((common & PERM_COPY)!=0)+", modify="+(string)((common & PERM_MODIFY)!=0)+", transfer="+(string)((common & PERM_TRANSFER)!=0));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Compare a notecard manifest to actual asset types

Check declared texture, sound, animation, object, and notecard requirements against Contents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. One type|exact inventory name per row. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Reports mismatches without transferring or opening assets. Script requirements are deliberately excluded to avoid confusing this inspector with a required product script.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list types=["texture","sound","animation","object","notecard"];
    list codes=[INVENTORY_TEXTURE,INVENTORY_SOUND,INVENTORY_ANIMATION,INVENTORY_OBJECT,INVENTORY_NOTECARD];
    integer i;
    integer ok;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list row=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        integer type=llListFindList(types,[llList2String(row,0)]);
        if(llGetListLength(row)!=2 || type==-1 || llList2String(row,1)=="")
        {
            llOwnerSay("Invalid manifest row.");
            return;
        }
        string name=llList2String(row,1);
        if(llGetInventoryType(name)==llList2Integer(codes,type))++ok;
        else llOwnerSay("Missing or wrong type: "+name);
    }
    llOwnerSay("Matching requirements: "+(string)ok+" / "+(string)llGetListLength(lines));
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Compare a notecard property snapshot to this prim

Report differences between saved name/description/size fields and current values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use name|Expected name, description|Expected description, or size|the exact LSL vector string. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Size comparison here is textual against LSL vector formatting, not tolerant numeric matching. Does not restore properties or change the prim.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2)
        {
            llOwnerSay("Use field|expected.");
            return;
        }
        string name=llList2String(p,0);
        string actual;
        if(name=="name")actual=llGetObjectName();
        else if(name=="description")actual=llGetObjectDesc();
        else if(name=="size")actual=(string)llGetScale();
        else
        {
            llOwnerSay("Unsupported field: "+name);
            return;
        }
        if(actual!=llList2String(p,1))llOwnerSay(name+" differs; current="+actual);
        else llOwnerSay(name+" matches.");
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Compare Contents against a snapshot

First touch records item names; later touches report added and removed names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch once as owner, edit Contents, then touch again.

Stop / restore: Disable or remove the script. It makes no inventory changes.

In-memory snapshot is lost on reset. Inventory changes do not reset it. Names are compared, so an asset replacement with the same name is not detected.

// Original Incoprea example. MIT.
list snapshot;
integer hasSnapshot;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        list current=[];
        integer i;
        for(i=0;i<total;++i) current += [llGetInventoryName(INVENTORY_ALL,i)];
        if(!hasSnapshot)
        {
            snapshot=current;
            hasSnapshot=TRUE;
            llOwnerSay("Baseline recorded.");
            return;
        }
        for(i=0;i<llGetListLength(current);++i) if(llListFindList(snapshot,[llList2String(current,i)])==-1) llOwnerSay("Added: "+llList2String(current,i));
        for(i=0;i<llGetListLength(snapshot);++i) if(llListFindList(current,[llList2String(snapshot,i)])==-1) llOwnerSay("Removed: "+llList2String(snapshot,i));
        snapshot=current;
        llOwnerSay("Comparison finished; baseline advanced.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Beginner

Contents by asset type

Count common asset types in the current prim’s Contents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner; no assets need to be added.

Stop / restore: Remove or disable the script. It does not change the build.

Counts only this prim’s inventory, not nested object contents or neighboring linked prims. The total may include additional types beyond the listed categories.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Total items: " + (string)llGetInventoryNumber(INVENTORY_ALL));
        llOwnerSay("Scripts: " + (string)llGetInventoryNumber(INVENTORY_SCRIPT)
        + ", objects: " + (string)llGetInventoryNumber(INVENTORY_OBJECT)
        + ", notecards: " + (string)llGetInventoryNumber(INVENTORY_NOTECARD));
        llOwnerSay("Sounds: " + (string)llGetInventoryNumber(INVENTORY_SOUND)
        + ", textures: " + (string)llGetInventoryNumber(INVENTORY_TEXTURE)
        + ", animations: " + (string)llGetInventoryNumber(INVENTORY_ANIMATION));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Copy-only owner handout

Offer the owner a copy of one configured inventory handout without moving a no-copy original.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a notecard named handout. Owner-touch offers it to the owner’s inventory.

Stop / restore: Remove/disable. No-copy handouts are refused; existing delivered copies remain in inventory.

Checks current-owner COPY permission before giving. Inventory offers have no delivery receipt, so the script says offered rather than received. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string item="handout";
        if(llGetInventoryType(item)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add handout notecard.");
            return;
        }
        if(!(llGetInventoryPermMask(item,MASK_OWNER)&PERM_COPY))
        {
            llOwnerSay("Refusing to move a no-copy original.");
            return;
        }
        llGiveInventory(llGetOwner(),item);
        llOwnerSay("Handout offered to your inventory.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Beginner

Count notecard lines

Request the line count of one saved notecard without printing its content.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

A new unsaved notecard may not yet have an asset. Embedded inventory can invalidate the response. Requests time out after twenty seconds.

// Original Incoprea example. MIT.
string CARD = "Notes";
key pending = NULL_KEY;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(CARD) != INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved notecard named " + CARD);
            return;
        }
        pending = llGetNumberOfNotecardLines(CARD);
        llSetTimerEvent(20.0);
    }
    dataserver(key query, string data)
    {
        if (query != pending || pending == NULL_KEY) return;
        pending = NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay(CARD + " line-count response: " + data);
    }
    timer()
    {
        pending = NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Line-count request timed out.");
    }
    changed(integer flags)
    {
        if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Count TODO checklist states

Count [ ] open and [x] completed items in a plain-text checklist.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Matching is case-insensitive at the start of a trimmed line. Other lines are ignored.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer openItems;
integer doneItems;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Open: "+(string)openItems+"; completed: "+(string)doneItems);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llToLower(llStringTrim(data,STRING_TRIM));
        if(llSubStringIndex(trimmed,"[ ]")==0) ++openItems;
        else if(llSubStringIndex(trimmed,"[x]")==0) ++doneItems;
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Detect overlapping two-condition rules

Check whether two wildcard decision rules could both match the same input.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use conditionA|conditionB|result rows. An asterisk means any value. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Reports ambiguity when overlapping conditions produce different result strings. This is a static consistency check, not a rules executor.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list rows;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=3)
        {
            llOwnerSay("Expected three fields.");
            return;
        }
        rows += p;
    }
    for(i=0;i<llGetListLength(rows);i+=3)
    {
        integer j;
        for(j=i+3;j<llGetListLength(rows);j+=3)
        {
            string a=llList2String(rows,i);
            string b=llList2String(rows,i+1);
            string c=llList2String(rows,j);
            string d=llList2String(rows,j+1);
            if((a==c || a=="*" || c=="*") && (b==d || b=="*" || d=="*") && llList2String(rows,i+2)!=llList2String(rows,j+2))llOwnerSay("Conflicting overlapping rules "+(string)(i/3+1)+" and "+(string)(j/3+1));
        }
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Export a named inventory group

Emit pipe-delimited name/type rows for items matching a configured prefix.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set PREFIX and touch as owner.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Prefix matching is case-sensitive. Names containing pipes are skipped because they would break the simple output format; no assets are transferred.

// Original Incoprea example. MIT.
string PREFIX="Garden-";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        integer i;
        integer exported;
        if(PREFIX=="")
        {
            llOwnerSay("Set a nonempty prefix.");
            return;
        }
        for(i=0;i<total;++i)
        {
            string name=llGetInventoryName(INVENTORY_ALL,i);
            if(llSubStringIndex(name,PREFIX)==0)
            {
                if(llSubStringIndex(name,"|")==-1)
                {
                    llOwnerSay(name+"|"+(string)llGetInventoryType(name));
                    ++exported;
                }
                else llOwnerSay("Skipped delimiter in name: "+name);
            }
        }
        llOwnerSay("Rows exported: "+(string)exported);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Fill a private template from notecard variables

Substitute declared {{name}} placeholders once without rescanning inserted values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use unique name|value lines. Edit TEMPLATE in the script. Values may not contain pipe. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Unknown or unclosed placeholders reject the preview. Literal braces outside {{...}} are preserved. Output is clipped by a conservative 800-character guard.

// Original Incoprea example. MIT.
string TEMPLATE="Welcome to {{place}}, made by {{creator}}.";
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list keys;
    list values;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2 || llList2String(p,0)=="" || llListFindList(keys,[llList2String(p,0)])!=-1)
        {
            llOwnerSay("Bad or duplicate variable row.");
            return;
        }
        keys += [llList2String(p,0)];
        values += [llList2String(p,1)];
    }
    string out="";
    integer pos;
    while(pos<llStringLength(TEMPLATE))
    {
        if(llGetSubString(TEMPLATE,pos,pos+1)=="{{")
        {
            integer start=pos+2;
            string tail="";
            if(start<llStringLength(TEMPLATE))tail=llGetSubString(TEMPLATE,start,-1);
            integer end=llSubStringIndex(tail,"}}");
            if(end<=0)
            {
                llOwnerSay("Unclosed or empty placeholder.");
                return;
            }
            string name=llGetSubString(tail,0,end-1);
            integer at=llListFindList(keys,[name]);
            if(at==-1)
            {
                llOwnerSay("Unknown variable: "+name);
                return;
            }
            out+=llList2String(values,at);
            pos=start+end+2;
        }
        else
        {
            out+=llGetSubString(TEMPLATE,pos,pos);
            ++pos;
        }
        if(llStringLength(out)>800)
        {
            llOwnerSay("Expanded text too long.");
            return;
        }
    }
    llOwnerSay(out);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Find duplicate configuration keys

Report repeated key names in a key=value configuration file.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Keys are case-sensitive after trimming. Comments beginning # and empty keys are ignored. Stores at most 100 short key names.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
list keys;
integer duplicates;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Distinct keys: "+(string)llGetListLength(keys)+"; duplicate occurrences: "+(string)duplicates);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        integer split=llSubStringIndex(trimmed,"=");
        if(split>0 && llGetSubString(trimmed,0,0)!="#")
        {
            string name=llStringTrim(llGetSubString(trimmed,0,split-1),STRING_TRIM);
            if(name!="")
            {
                if(llListFindList(keys,[name])!=-1)
                {
                    ++duplicates;
                    llOwnerSay("Duplicate key at line "+(string)(lineNumber+1)+": "+name);
                }
                else keys += [name];
            }
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Find long notecard lines

Report lines longer than a configured character threshold and the longest returned line.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines. Set LIMIT to your display budget.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Measures returned string characters, not original file bytes. A truncated dataserver response cannot reveal the original full line length.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer LIMIT=80;
integer longest;
integer longestLine;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Longest returned line: "+(string)longestLine+" at "+(string)longest+" characters.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        integer length=llStringLength(data);
        if(length>longest)
        {
            longest=length;
            longestLine=lineNumber+1;
        }
        if(length>LIMIT) llOwnerSay("Long line "+(string)(lineNumber+1)+": "+(string)length+" returned characters.");
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Find repeated exposed asset keys

Find different inventory names that expose the same nonzero asset identifier.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner; full-permission assets make this check more useful.

Stop / restore: Disable or remove the script. It makes no inventory changes.

NULL_KEY entries are skipped and counted. Object/script identifiers may be pseudo-keys. Matching identifiers do not grant redistribution rights.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        list keys=[];
        list names=[];
        integer skipped;
        integer i;
        for(i=0;i<total;++i)
        {
            string name=llGetInventoryName(INVENTORY_ALL,i);
            key asset=llGetInventoryKey(name);
            if(asset==NULL_KEY) ++skipped;
            else
            {
                integer index=llListFindList(keys,[asset]);
                if(index!=-1) llOwnerSay("Same exposed key: "+llList2String(names,index)+" / "+name);
                else
                {
                    keys += [asset];
                    names += [name];
                }
            }
        }
        llOwnerSay("Unavailable identifiers skipped: "+(string)skipped);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Fingerprint normalized notecard content

Create an MD5 change-detection fingerprint of the loaded content lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Any short plain-text content; blank lines and # comments are omitted and edges trimmed. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. This is not a security signature or proof of authorship. Formatting removed by the loader does not change the fingerprint; embedded inventory content is unsupported.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    string canonical=llDumpList2String(lines,"\n");
    llOwnerSay("Normalized line count="+(string)llGetListLength(lines)+" fingerprint="+llMD5String(canonical,0));
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Format an asset credit list from a notecard

Produce consistent readable credit lines for named assets.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use title|creator|license|source rows. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. All four fields are required, but this script cannot verify rights, provenance, or license compatibility. It does not publish or distribute the assets.

// Original Incoprea example. MIT.
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=4)
        {
            llOwnerSay("Expected four credit fields.");
            return;
        }
        integer j;
        for(j=0;j<4;++j)if(llList2String(p,j)=="")
        {
            llOwnerSay("Missing credit field.");
            return;
        }
        llOwnerSay(llList2String(p,0)+" — "+llList2String(p,1)+"; "+llList2String(p,2)+"; source: "+llList2String(p,3));
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Four-line notecard pages

Collect up to four short lines and report them as one owner-readable page.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a notecard named pages. Owner-touch loads the next page; each line should be under 160 characters.

Stop / restore: Remove/disable; no prim property is changed.

Reads sequentially with request correlation and a timeout. Each completed page is bounded, and EOF returns the reader to page one. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer line;
integer loaded;
string page;
key request;
fetch()
{
    request=llGetNotecardLine("pages",line);
    llSetTimerEvent(15.0);
}
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||request!=NULL_KEY)return;
        if(llGetInventoryType("pages")!=INVENTORY_NOTECARD)return;
        loaded=0;
        page="";
        fetch();
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        request=NULL_KEY;
        if(data==EOF)
        {
            line=0;
            llSetTimerEvent(0.0);
            if(page!="")llOwnerSay(page);
            llOwnerSay("End of pages.");
            return;
        }
        page+=llGetSubString(data,0,159)+"\n";
        ++line;
        ++loaded;
        if(loaded<4)fetch();
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay(page);
        }
    }
    timer()
    {
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Page read timed out.");
    }
    changed(integer change)
    {
        if(change&CHANGED_INVENTORY)
        {
            request=NULL_KEY;
            line=0;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Index link-only notecard lines

Report line numbers containing a whole line that begins with https:// or http://.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Does not fetch or open any URL and does not claim the destination is safe or still valid.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer links;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Link-prefixed lines: "+(string)links);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        string lower=llToLower(trimmed);
        if(llSubStringIndex(lower,"https://")==0 || llSubStringIndex(lower,"http://")==0)
        {
            ++links;
            llOwnerSay("Link at line "+(string)(lineNumber+1)+": "+trimmed);
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Index notecard section headings

Report line numbers for headings enclosed in square brackets.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. A heading must occupy the entire trimmed line.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer headings;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Section headings: "+(string)headings);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        if(llStringLength(trimmed)>2 && llGetSubString(trimmed,0,0)=="[" && llGetSubString(trimmed,-1,-1)=="]")
        {
            ++headings;
            llOwnerSay("Line "+(string)(lineNumber+1)+": "+trimmed);
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Beginner

Inspect an inventory asset key

Read the asset identifier exposed for a named inventory entry and explain an unavailable result.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set ITEM to an exact Contents item name and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Second Life generally exposes keys only for full-permission items. New unsaved notecards can also return NULL_KEY; object/script keys may be pseudo-identifiers. An identifier grants no reuse rights.

// Original Incoprea example. MIT.
string ITEM = "Panel";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(ITEM) == INVENTORY_NONE)
        {
            llOwnerSay("No inventory item named " + ITEM);
            return;
        }
        key asset = llGetInventoryKey(ITEM);
        if (asset == NULL_KEY)
        llOwnerSay("Item exists but its asset key is unavailable. Check permissions and whether it has been saved.");
        else llOwnerSay(ITEM + " asset identifier: " + (string)asset);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Beginner

Inspect an item’s creator

Read creator metadata for a specific item inside this prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set ITEM to an exact Contents item name and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Creator metadata is not a complete provenance record or license. Included textures, sounds, meshes, or nested assets can have different authors and terms.

// Original Incoprea example. MIT.
string ITEM = "Panel";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetInventoryType(ITEM) == INVENTORY_NONE)
        {
            llOwnerSay("Missing item: " + ITEM);
            return;
        }
        key creator = llGetInventoryCreator(ITEM);
        if (creator == NULL_KEY) llOwnerSay("Creator data unavailable.");
        else llOwnerSay(ITEM + " creator: " + (string)creator);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Inventory name hygiene

Find leading/trailing whitespace and delimiter characters that make exact-name configuration fragile.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in a prim with at most 100 Contents items.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Only reports suspect names; it does not rename anything. A flagged name may be intentional.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        integer i;
        integer found;
        for(i=0;i<total;++i)
        {
            string name=llGetInventoryName(INVENTORY_ALL,i);
            if(name!=llStringTrim(name,STRING_TRIM) || llSubStringIndex(name,"|")!=-1 || llSubStringIndex(name,"=")!=-1)
            {
                ++found;
                llOwnerSay("Review name: ["+name+"]");
            }
        }
        llOwnerSay((string)found+" names need review.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Landmark distance preview

Read the first inventory landmark and report its horizontal distance from this object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a landmark to the script prim. Owner-touch requests its location data.

Stop / restore: Remove/disable; no teleport or inventory offer occurs.

A landmark location is returned relative to this region origin, including cross-region offsets on compatible grids. Hypergrid behavior is grid-specific. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
key request;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||request!=NULL_KEY)return;
        if(!llGetInventoryNumber(INVENTORY_LANDMARK))
        {
            llOwnerSay("Add a landmark.");
            return;
        }
        request=llRequestInventoryData(llGetInventoryName(INVENTORY_LANDMARK,0));
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        vector target=(vector)data;
        vector origin=llGetPos();
        target.z=0.0;
        origin.z=0.0;
        llOwnerSay("Horizontal landmark distance: "+(string)llVecDist(target,origin)+" meters.");
    }
    timer()
    {
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Landmark lookup timed out.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Look up assets by a declared tag

Read asset|comma-separated-tags rows and report assets containing a configured tag.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Example: Lamp|garden,light,green. Edit SEARCH_TAG. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Tag matching trims spaces and ignores ASCII case. It searches your authored catalog only, not visitors or world objects.

// Original Incoprea example. MIT.
string SEARCH_TAG="garden";
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    string target=llToLower(llStringTrim(SEARCH_TAG,STRING_TRIM));
    if(target=="")
    {
        llOwnerSay("Set SEARCH_TAG.");
        return;
    }
    integer i;
    integer found;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        if(llGetListLength(p)!=2)
        {
            llOwnerSay("Invalid catalog row.");
            return;
        }
        list tags=llParseStringKeepNulls(llList2String(p,1),[","],[]);
        integer j;
        integer matches;
        for(j=0;j<llGetListLength(tags);++j)if(llToLower(llStringTrim(llList2String(tags,j),STRING_TRIM))==target)matches=TRUE;
        if(matches)
        {
            ++found;
            llOwnerSay(llList2String(p,0));
        }
    }
    llOwnerSay("Matching catalog assets: "+(string)found);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Names that differ only by case

Find case-insensitive name collisions before writing a case-insensitive lookup tool.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in a prim with at most 100 items.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Exact names remain distinct. This performs small bounded local searches and never modifies inventory.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        list seen=[];
        list originals=[];
        integer i;
        for(i=0;i<total;++i)
        {
            string name=llGetInventoryName(INVENTORY_ALL,i);
            string lower=llToLower(name);
            integer index=llListFindList(seen,[lower]);
            if(index!=-1) llOwnerSay("Case collision: "+llList2String(originals,index)+" / "+name);
            else
            {
                seen += [lower];
                originals += [name];
            }
        }
        llOwnerSay("Name comparison complete.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Notecard content profile

Count blank lines, # comment lines, and content lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Comments mean lines whose first non-space character is #.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
integer blank;
integer comments;
integer content;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("Blank: "+(string)blank+", comments: "+(string)comments+", content: "+(string)content);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        if(trimmed=="") ++blank;
        else if(llGetSubString(trimmed,0,0)=="#") ++comments;
        else ++content;
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Notecard reading stand

Read one notecard line per touch with an explicit end-of-card reset.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a notecard named exhibit with one short paragraph per line. Owner-touch advances.

Stop / restore: Remove/disable; this reports to owner chat and changes no prim text.

Only one outstanding request is allowed. An inventory edit resets the reading index and invalidates a pending response. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
integer line;
key request;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||request!=NULL_KEY)return;
        if(llGetInventoryType("exhibit")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add exhibit notecard.");
            return;
        }
        request=llGetNotecardLine("exhibit",line);
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        if(data==EOF)
        {
            line=0;
            llOwnerSay("End of exhibit. Next touch starts again.");
        }
        else
        {
            ++line;
            llOwnerSay((string)line+": "+llGetSubString(data,0,900));
        }
    }
    timer()
    {
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer change)
    {
        if(change&CHANGED_INVENTORY)
        {
            request=NULL_KEY;
            line=0;
            llSetTimerEvent(0.0);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Owner resource folder offer

Offer a bounded folder of copyable notecards and landmarks as an exhibit kit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add the intended notecards and landmarks to this prim. Owner-touch offers up to twelve COPY-permitted items in a folder.

Stop / restore: Remove/disable. Offered copies remain with the recipient; source items are retained.

Skips all scripts, objects, textures, sounds and no-copy items. Permission checks are per item. No automatic offers to visitors occur. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list items;
        integer i;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        for(i=0;i<total&&llGetListLength(items)<12;++i)
        {
            string name=llGetInventoryName(INVENTORY_ALL,i);
            integer type=llGetInventoryType(name);
            if((type==INVENTORY_NOTECARD||type==INVENTORY_LANDMARK)&&(llGetInventoryPermMask(name,MASK_OWNER)&PERM_COPY))items+=[name];
        }
        if(!llGetListLength(items))
        {
            llOwnerSay("No copyable notecards or landmarks.");
            return;
        }
        llGiveInventoryList(llGetOwner(),"Exhibit resources",items);
        llOwnerSay("Resource folder offered.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Pack content lines into bounded sign pages

Group whole notecard lines into private page previews without splitting lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use short text lines; set PAGE_BUDGET to a character limit. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Budget counts characters, not UTF-8 bytes or rendered width. This only previews pages in chat and does not modify hover text.

// Original Incoprea example. MIT.
integer PAGE_BUDGET=160;
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    if(PAGE_BUDGET<20 || PAGE_BUDGET>700)
    {
        llOwnerSay("Budget must be 20–700.");
        return;
    }
    string page="";
    integer number=1;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        string line=llList2String(lines,i);
        if(llStringLength(line)>PAGE_BUDGET)
        {
            llOwnerSay("A line exceeds the page budget.");
            return;
        }
    }
    for(i=0;i<llGetListLength(lines);++i)
    {
        string line=llList2String(lines,i);
        integer needed=llStringLength(line);
        if(page!="")++needed;
        if(llStringLength(page)+needed>PAGE_BUDGET)
        {
            llOwnerSay("PAGE "+(string)number+"\n"+page);
            ++number;
            page="";
        }
        if(page!="")page+="\n";
        page+=line;
    }
    if(page!="")llOwnerSay("PAGE "+(string)number+"\n"+page);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Beginner

Paged Contents directory

Show up to eight item names per owner touch from this prim’s inventory.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim you want to inspect. Touch repeatedly for successive pages.

Stop / restore: Remove or disable the script. It does not change the build.

Includes the directory script itself. Linked prims have separate inventories. The order follows the simulator inventory enumeration.

// Original Incoprea example. MIT.
integer cursor;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetInventoryNumber(INVENTORY_ALL);
        if (total == 0)
        {
            llOwnerSay("Contents are empty.");
            return;
        }
        if (cursor >= total) cursor = 0;
        integer last = cursor + 7;
        if (last >= total) last = total - 1;
        integer i;
        for (i = cursor; i <= last; ++i)
        llOwnerSay((string)(i + 1) + "/" + (string)total + " " + llGetInventoryName(INVENTORY_ALL, i));
        cursor = last + 1;
    }
    changed(integer flags)
    {
        if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Parse a configuration notecard

Read key=value settings while skipping blank lines and # comments.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Config. Try label=Garden and interval=30 on separate lines; touch as owner.

Stop / restore: Remove or disable. Editing Contents cancels the read and resets stored settings.

This demonstration reports settings without applying them. First equals sign separates key from value; duplicate keys replace earlier values. Limits reading to 50 lines and 20 settings.

// Original Incoprea example. MIT.
string CARD = "Config";
key pending = NULL_KEY;
integer lineNumber;
list settings;
finish()
{
    pending = NULL_KEY;
    llSetTimerEvent(0.0);
    integer i;
    for (i = 0; i < llGetListLength(settings); i += 2)
    llOwnerSay(llList2String(settings, i) + " = " + llList2String(settings, i + 1));
    llOwnerSay("Read complete; " + (string)(llGetListLength(settings) / 2) + " settings.");
}
requestLine()
{
    pending = llGetNotecardLine(CARD, lineNumber);
    llSetTimerEvent(20.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (pending != NULL_KEY) return;
        if (llGetInventoryType(CARD) != INVENTORY_NOTECARD)
        {
            llOwnerSay("Add the Config notecard first.");
            return;
        }
        settings = [];
        lineNumber = 0;
        requestLine();
    }
    dataserver(key query, string data)
    {
        if (query != pending || pending == NULL_KEY) return;
        if (data == EOF)
        {
            finish();
            return;
        }
        data = llStringTrim(data, STRING_TRIM);
        integer split = llSubStringIndex(data, "=");
        if (data != "" && llGetSubString(data, 0, 0) != "#" && split > 0)
        {
            string name = llStringTrim(llGetSubString(data, 0, split - 1), STRING_TRIM);
            string value = "";
            if (split < llStringLength(data) - 1)
            value = llStringTrim(llGetSubString(data, split + 1, -1), STRING_TRIM);
            integer found = -1;
            integer i;
            for (i = 0; i < llGetListLength(settings); i += 2)
            if (llList2String(settings, i) == name) found = i;
            if (name != "")
            {
                if (found != -1) settings = llListReplaceList(settings, [name, value], found, found + 1);
                else if (llGetListLength(settings) < 40) settings += [name, value];
                else llOwnerSay("Skipped setting beyond the 20-setting limit: " + name);
            }
        }
        ++lineNumber;
        if (lineNumber >= 50)
        {
            llOwnerSay("Stopped at the 50-line limit.");
            finish();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending = NULL_KEY;
        llSetTimerEvent(0.0);
        settings = [];
        llOwnerSay("Timed out; partial settings discarded. Touch to retry.");
    }
    changed(integer flags)
    {
        if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Inventory & notecards · Intermediate

Random authored exhibit fact

Pick a random line from a notecard and show it temporarily as an exhibit fact.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a plain notecard named facts, one short authored fact per line. Owner-touch reads a random line.

Stop / restore: Wait for the 15-second display to restore the original text. Removing mid-display leaves that text set.

Count and line requests are correlated by keys. This displays authored content, not verified research or an external generator. Keep the notecard modest. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated.

// Original Incoprea. MIT. Not compiled or tested in-world.
key request;
integer phase;
list saved;
default
{
    state_entry()
    {
        saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]);
    }
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||phase)return;
        if(llGetInventoryType("facts")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add facts notecard.");
            return;
        }
        phase=1;
        request=llGetNumberOfNotecardLines("facts");
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request)return;
        if(phase==1)
        {
            integer count=(integer)data;
            if(count<1)
            {
                phase=0;
                llSetTimerEvent(0.0);
                return;
            }
            phase=2;
            request=llGetNotecardLine("facts",(integer)llFrand((float)count));
        }
        else if(phase==2)
        {
            request=NULL_KEY;
            phase=3;
            if(data!=EOF)llSetText(llGetSubString(data,0,220),<0.9,0.95,0.8>,1.0);
            llSetTimerEvent(15.0);
        }
    }
    timer()
    {
        request=NULL_KEY;
        phase=0;
        llSetTimerEvent(0.0);
        llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Inventory & notecards · Intermediate

Read a notecard handbook one short page at a time

Cache the card and show four content lines per owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. One short handbook line per row. Blank/comment lines are omitted. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Cycles to the first page after the last one. Text is sent only to owner chat, not hover text.

// Original Incoprea example. MIT.
integer page;
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    if(llGetListLength(lines)==0)
    {
        llOwnerSay("No content lines.");
        return;
    }
    integer total=llGetListLength(lines);
    if(page>=total)page=0;
    integer last=page+4;
    if(last>total)last=total;
    llOwnerSay("Lines "+(string)(page+1)+"–"+(string)last+" of "+(string)total);
    integer i;
    for(i=page;i<page+4 && i<total;++i)llOwnerSay(llList2String(lines,i));
    page+=4;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Read a short notecard safely

Read up to forty notecard lines in sequence, matching responses and timing out stalled requests.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes to this prim. Touch as owner to read it.

Stop / restore: Remove or disable the script. Editing Contents cancels the current read; touch to begin again.

Outputs only to owner chat. Lines may be truncated by the simulator; use short plain-text lines and no embedded inventory. It stops at forty lines to avoid runaway output.

// Original Incoprea example. MIT.
string CARD = "Notes";
integer lineNumber;
integer MAX_LINES = 40;
key pending = NULL_KEY;
finish(string message)
{
    pending = NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay(message);
}
requestLine()
{
    pending = llGetNotecardLine(CARD, lineNumber);
    llSetTimerEvent(20.0);
}
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (pending != NULL_KEY)
        {
            llOwnerSay("A read is already in progress.");
            return;
        }
        if (llGetInventoryType(CARD) != INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved notecard named " + CARD);
            return;
        }
        lineNumber = 0;
        requestLine();
    }
    dataserver(key query, string data)
    {
        if (query != pending || pending == NULL_KEY) return;
        if (data == EOF)
        {
            finish("End of notecard.");
            return;
        }
        llOwnerSay((string)(lineNumber + 1) + ": " + data);
        ++lineNumber;
        if (lineNumber >= MAX_LINES)
        {
            finish("Stopped at the 40-line limit.");
            return;
        }
        requestLine();
    }
    timer()
    {
        finish("Read timed out. Check the card and touch to retry.");
    }
    changed(integer flags)
    {
        if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Inventory & notecards · Intermediate

Read the first notecard paragraph

Collect up to 500 characters from the first nonblank paragraph.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Stops collecting after a blank line following the paragraph; the bounded scan still completes.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
string paragraph;
integer started;
integer ended;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    llOwnerSay("First paragraph: "+paragraph);
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        if(!ended)
        {
            if(trimmed=="")
            {
                if(started) ended=TRUE;
            }
            else
            {
                if(started) paragraph += " ";
                paragraph += trimmed;
                started=TRUE;
                if(llStringLength(paragraph)>500)
                {
                    paragraph=llGetSubString(paragraph,0,499);
                    ended=TRUE;
                }
            }
        }
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Release package checklist

Check a configured release package for its object, README, and LICENSE inventory entries.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Adjust REQUIRED type/name pairs and touch as owner.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Checks presence, type, and current-owner transfer flags; does not transfer anything or validate license text. Nested object permissions may differ.

// Original Incoprea example. MIT.
list REQUIRED=[INVENTORY_OBJECT,"Product",INVENTORY_NOTECARD,"README",INVENTORY_NOTECARD,"LICENSE"];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer failures;
        integer i;
        for(i=0;i<llGetListLength(REQUIRED);i+=2)
        {
            integer expected=llList2Integer(REQUIRED,i);
            string name=llList2String(REQUIRED,i+1);
            if(llGetInventoryType(name)!=expected)
            {
                ++failures;
                llOwnerSay("Missing or wrong type: "+name);
            }
            else if(!(llGetInventoryPermMask(name,MASK_OWNER) & PERM_TRANSFER))
            {
                ++failures;
                llOwnerSay("Current owner cannot transfer: "+name);
            }
            else llOwnerSay("Present and transfer flag set: "+name);
        }
        llOwnerSay("Checklist findings: "+(string)failures);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Resolve a filename using the longest suffix rule

Choose the most specific matching filename suffix from a notecard mapping.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use suffix|handlerLabel rows, for example .tar.gz|archive and .gz|compressed. Edit FILENAME. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Case-insensitive suffix matching. Equal-length conflicting matches are rejected. The result is a label only and never launches or opens files.

// Original Incoprea example. MIT.
string FILENAME="library.tar.gz";
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    string file=llToLower(FILENAME);
    integer best=-1;
    string result;
    integer i;
    for(i=0;i<llGetListLength(lines);++i)
    {
        list p=llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
        string suffix=llToLower(llList2String(p,0));
        integer length=llStringLength(suffix);
        if(llGetListLength(p)!=2 || length==0)
        {
            llOwnerSay("Malformed suffix rule.");
            return;
        }
        if(length<=llStringLength(file) && llGetSubString(file,-length,-1)==suffix)
        {
            string label=llList2String(p,1);
            if(length==best && result!=label)
            {
                llOwnerSay("Conflicting suffix rules.");
                return;
            }
            if(length>best)
            {
                best=length;
                result=label;
            }
        }
    }
    if(best==-1)llOwnerSay("No suffix rule.");
    else llOwnerSay("Route label: "+result);
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Resolve a named INI-style profile

Merge a default section and one selected profile into a private preview.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. Use [default] then key=value lines, plus [garden] for overrides. Set PROFILE in the script. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Only simple sections and first-equals splitting are supported. Later keys replace earlier keys within an applicable section; unrelated sections are ignored.

// Original Incoprea example. MIT.
string PROFILE="garden";
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    list keys;
    list values;
    integer pass;
    for(pass=0;pass<2;++pass)
    {
        string section="";
        integer i;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            if(llGetSubString(line,0,0)=="[" && llGetSubString(line,-1,-1)=="]")
            {
                if(llStringLength(line)<3)
                {
                    llOwnerSay("Empty section.");
                    return;
                }
                section=llGetSubString(line,1,-2);
            }
            else if((pass==0 && section=="default") || (pass==1 && section==PROFILE))
            {
                integer at=llSubStringIndex(line,"=");
                if(at<1)
                {
                    llOwnerSay("Malformed key=value.");
                    return;
                }
                string name=llStringTrim(llGetSubString(line,0,at-1),STRING_TRIM);
                string value="";
                if(at<llStringLength(line)-1)value=llStringTrim(llGetSubString(line,at+1,-1),STRING_TRIM);
                if(name=="")
                {
                    llOwnerSay("Empty key.");
                    return;
                }
                integer k=llListFindList(keys,[name]);
                if(k==-1)
                {
                    keys += [name];
                    values += [value];
                }
                else values=llListReplaceList(values,[value],k,k);
            }
        }
    }
    integer j;
    for(j=0;j<llGetListLength(keys);++j)llOwnerSay(llList2String(keys,j)+"="+llList2String(values,j));
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Saved notecard readiness check

Distinguish a missing/wrong-type notecard from a present card whose asset key is unavailable.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set CARD and touch as owner.

Stop / restore: Disable or remove the script. It makes no inventory changes.

NULL_KEY does not prove a card is unsaved: restricted permissions can also hide the key. The script deliberately reports that ambiguity.

// Original Incoprea example. MIT.
string CARD="Notes";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer kind=llGetInventoryType(CARD);
        if(kind==INVENTORY_NONE)
        {
            llOwnerSay("Notecard missing.");
            return;
        }
        if(kind!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Name exists, but is not a notecard.");
            return;
        }
        key asset=llGetInventoryKey(CARD);
        if(asset!=NULL_KEY) llOwnerSay("Notecard has an exposed asset key; ready to attempt an asynchronous read.");
        else llOwnerSay("Present, but no exposed key. It may be unsaved or permission-restricted; a key check alone cannot decide.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Inventory & notecards · Intermediate

Unique inventory creator roster

List each distinct nonzero creator key found in this prim’s inventory.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in a small delivery prim.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Useful when preparing attribution notes, but metadata is not proof of licensing or full provenance. No names are looked up and no external messages sent.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total=llGetInventoryNumber(INVENTORY_ALL);
        if(total>100)
        {
            llOwnerSay("Use a prim with at most 100 inventory items.");
            return;
        }
        list creators=[];
        integer i;
        for(i=0;i<total;++i)
        {
            key creator=llGetInventoryCreator(llGetInventoryName(INVENTORY_ALL,i));
            if(creator!=NULL_KEY && llListFindList(creators,[creator])==-1) creators += [creator];
        }
        for(i=0;i<llGetListLength(creators);++i) llOwnerSay("Creator: "+llList2String(creators,i));
        llOwnerSay((string)llGetListLength(creators)+" unique creator keys.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Use a private notecard flashcard deck

Alternate question and answer on owner touches, then advance to the next card.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Create a saved plain-text notecard named Data. One question|answer pair per row. Touch as owner to load it; touch again to use the cached content.

Stop / restore: Remove or disable. Reset or an inventory change discards the cache. No notecards are changed.

At most 60 lines, 300 characters per line, and 6000 total characters; blank lines and # comments are omitted. Incomplete reads are rejected. Not a graded test and never records visitor data. Cards cycle in source order; only one short question or answer is output per touch.

// Original Incoprea example. MIT.
integer index;
integer showAnswer;
list lines;
integer lineNumber;
integer characters;
integer loaded;
key pending=NULL_KEY;
request()
{
    pending=llGetNotecardLine("Data",lineNumber);
    llSetTimerEvent(20);
}
run()
{
    integer n=llGetListLength(lines);
    if(n==0)
    {
        llOwnerSay("Deck is empty.");
        return;
    }
    integer i;
    for(i=0;i<n;++i)if(llGetListLength(llParseStringKeepNulls(llList2String(lines,i),["|"],[]))!=2)
    {
        llOwnerSay("Every row needs question|answer.");
        return;
    }
    if(index>=n)index=0;
    list row=llParseStringKeepNulls(llList2String(lines,index),["|"],[]);
    if(showAnswer)
    {
        llOwnerSay("Answer: "+llList2String(row,1));
        ++index;
        showAnswer=FALSE;
    }
    else
    {
        llOwnerSay("Question: "+llList2String(row,0));
        showAnswer=TRUE;
    }
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Still loading.");
            return;
        }
        if(loaded)
        {
            run();
            return;
        }
        if(llGetInventoryType("Data")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Data notecard.");
            return;
        }
        lines=[];
        lineNumber=0;
        characters=0;
        request();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        if(data==EOF)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            loaded=TRUE;
            run();
            return;
        }
        characters+=llStringLength(data);
        if(lineNumber>=60 || llStringLength(data)>300 || characters>6000)
        {
            pending=NULL_KEY;
            llSetTimerEvent(0);
            lines=[];
            llOwnerSay("Read rejected: card exceeds bounds.");
            return;
        }
        data=llStringTrim(data,STRING_TRIM);
        if(data!="" && llGetSubString(data,0,0)!="#")lines += [data];
        ++lineNumber;
        request();
    }
    timer()
    {
        pending=NULL_KEY;
        lines=[];
        llSetTimerEvent(0);
        llOwnerSay("Read timed out; touch to retry.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Inventory & notecards · Intermediate

Validate a scripted dependency name

Reject blank and whitespace-padded dependency names before looking them up.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit REQUESTED and touch as owner.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Exact inventory lookup is case-sensitive. This validation refuses to silently trim a configured name, because spaces may be intentional.

// Original Incoprea example. MIT.
string REQUESTED="Config";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if(REQUESTED=="" || llStringTrim(REQUESTED,STRING_TRIM)=="")
        {
            llOwnerSay("Dependency name is blank.");
            return;
        }
        if(REQUESTED!=llStringTrim(REQUESTED,STRING_TRIM))
        {
            llOwnerSay("Dependency name has outer whitespace; confirm its exact spelling.");
            return;
        }
        integer kind=llGetInventoryType(REQUESTED);
        if(kind==INVENTORY_NONE) llOwnerSay("No exact inventory match.");
        else llOwnerSay("Exact match found with inventory type "+(string)kind);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Inventory & notecards · Intermediate

Validate required notecard sections

Check that [About], [Setup], and [License] headings exist in a delivery note.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text notecard named Notes. Touch as owner to scan once; reset to scan again. Reads at most 100 lines. Edit REQUIRED to your documentation standard.

Stop / restore: Disable or remove the script. It makes no inventory changes.

Line requests time out after 20 seconds. Lines may be truncated by the simulator; use short lines without embedded inventory. Editing Contents resets the scan. Reports only to the owner. Heading matching is exact after trimming. This checks structure, not the truth or completeness of the contents.

// Original Incoprea example. MIT.
string CARD="Notes";
integer lineNumber;
key pending=NULL_KEY;
list REQUIRED=["[About]","[Setup]","[License]"];
list found;
requestLine()
{
    pending=llGetNotecardLine(CARD,lineNumber);
    llSetTimerEvent(20.0);
}
complete()
{
    pending=NULL_KEY;
    llSetTimerEvent(0.0);
    integer i;
    for(i=0;i<llGetListLength(REQUIRED);++i)
    {
        string heading=llList2String(REQUIRED,i);
        if(llListFindList(found,[heading])==-1) llOwnerSay("Missing heading: "+heading);
    }
    llOwnerSay("Found "+(string)llGetListLength(found)+" of "+(string)llGetListLength(REQUIRED)+" required headings.");
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(pending!=NULL_KEY)
        {
            llOwnerSay("Read in progress.");
            return;
        }
        if(lineNumber>0)
        {
            llOwnerSay("Reset this script to scan again.");
            return;
        }
        if(llGetInventoryType(CARD)!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved plain-text notecard named Notes.");
            return;
        }
        requestLine();
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY) return;
        if(data==EOF)
        {
            complete();
            return;
        }
        string trimmed=llStringTrim(data,STRING_TRIM);
        if(llListFindList(REQUIRED,[trimmed])!=-1 && llListFindList(found,[trimmed])==-1) found += [trimmed];
        ++lineNumber;
        if(lineNumber>=100)
        {
            llOwnerSay("Stopped at 100 input lines; results may be partial.");
            complete();
            return;
        }
        requestLine();
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Timed out; reset before retrying. Partial values were not reported.");
        lineNumber=100;
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_INVENTORY|CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & listsPractical building blocks for your own scripts.178 scripts

Download this category (.zip)

Data & lists · Intermediate

Add a bounded number of weekdays

Advance a date by a positive count of Monday-through-Friday days.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. The starting date does not consume a day. No holidays are considered; a result beyond the supported range is rejected.

// Original Incoprea example. MIT.
string DATE="2026-09-25";
integer COUNT=5;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(COUNT<0 || COUNT>260)
        {
            llOwnerSay("Use 0-260 working days.");
            return;
        }
        integer serial=dateSerial(date);
        integer left=COUNT;
        while(left>0)
        {
            ++serial;
            if(weekday(serial)!=0 && weekday(serial)!=6)--left;
        }
        llOwnerSay(dateText(fromSerial(serial)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Add line numbers to a short snippet

Print each logical line with a one-based line number, preserving blank lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Useful for discussing a short code or config excerpt. The numbering is reported separately and should not be pasted back as executable LSL.

// Original Incoprea example. MIT.
string TEXT="default\n{\n\n    state_entry() {}\n}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        integer i;
        for(i=0;i<llGetListLength(lines);++i)llOwnerSay((string)(i+1)+" | "+llList2String(lines,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Add or subtract calendar days

Shift a date by a bounded whole-day offset across month and year boundaries.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Rejects results outside the supported year range and offsets over 3660 days in magnitude.

// Original Incoprea example. MIT.
string DATE="2028-02-27";
integer OFFSET=3;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(OFFSET < -3660 || OFFSET>3660)
        {
            llOwnerSay("Offset exceeds ten-year planning bound.");
            return;
        }
        list result=fromSerial(dateSerial(date)+OFFSET);
        llOwnerSay(dateText(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Align a compact name/value report

Pad short field names to a chosen character width before displaying their values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Owner chat may use proportional fonts, so character padding is not guaranteed pixel-perfect. Overlong names are preserved rather than cut.

// Original Incoprea example. MIT.
list RECORD=["Title","Lamp","Version","1.0","Color","Green"];
integer WIDTH=10;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2 || WIDTH<1 || WIDTH>40)
        {
            llOwnerSay("Invalid record or width.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string name=llList2String(RECORD,i);
            while(llStringLength(name)<WIDTH)name+=" ";
            llOwnerSay(name+" : "+llList2String(RECORD,i+1));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Angle between two directions

Find the smaller angle between two nonzero direction vectors.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit A and B, then touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

The result is unsigned, from zero through 180 degrees. Zero vectors are rejected, and the dot product is clamped to prevent floating-point rounding from breaking acos.

// Original Incoprea example. MIT.
vector A = <1.0, 0.0, 0.0>;
vector B = <1.0, 1.0, 0.0>;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llVecMag(A) < 0.00001 || llVecMag(B) < 0.00001)
        {
            llOwnerSay("Both direction vectors must be nonzero.");
            return;
        }
        float dot = llVecNorm(A) * llVecNorm(B);
        if (dot > 1.0) dot = 1.0;
        if (dot < -1.0) dot = -1.0;
        llOwnerSay("Angle: " + (string)(llAcos(dot) * RAD_TO_DEG) + " degrees.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Append to a bounded JSON list

Append one string to a JSON array only when it has room.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT, VALUE, and LIMIT; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Requires JSON support. String encoding is explicit so numeric-looking values remain strings. No persistent storage or external request is involved.

// Original Incoprea example. MIT.
string DOCUMENT="[\"lamp\",\"cup\"]";
string VALUE="003";
integer LIMIT=5;
string quoteJson(string value)
{
    string output="\"";
    string digits="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer code=llOrd(value,i);
        if(c=="\"" || c=="\\") output+="\\"+c;
        else if(code<32) output+="\\u00"+llGetSubString(digits,code/16,code/16)+llGetSubString(digits,code%16,code%16);
        else output+=c;
    }
    return output+"\"";
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected an array.");
            return;
        }
        integer itemCount=llGetListLength(llJson2List(DOCUMENT));
        if(LIMIT<1 || LIMIT>50 || itemCount>=LIMIT)
        {
            llOwnerSay("Invalid limit or list full.");
            return;
        }
        string encoded=quoteJson(VALUE);
        llOwnerSay(llJsonSetValue(DOCUMENT,[JSON_APPEND],encoded));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Apply a noncascading character map

Replace source characters using a map without rescanning the replacement text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Each map key must be exactly one character. First matching map entry wins; generated replacements are never mapped again.

// Original Incoprea example. MIT.
string TEXT="A&B<C";
list MAP=["&","and","<"," before "];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(MAP)%2)
        {
            llOwnerSay("Incomplete map.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(MAP);i+=2)if(llStringLength(llList2String(MAP,i))!=1)
        {
            llOwnerSay("Map keys must be single characters.");
            return;
        }
        string result="";
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            integer j;
            integer found;
            for(j=0;j<llGetListLength(MAP);j+=2)if(!found && llList2String(MAP,j)==c)
            {
                result+=llList2String(MAP,j+1);
                found=TRUE;
            }
            if(!found)result+=c;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Apply a preview patch only if every old value matches

Validate field/expected/new triples before replacing any value in a local preview.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Record field names and patch field names must be unique. A failed precondition leaves the original record and proposed output unchanged.

// Original Incoprea example. MIT.
list RECORD=["color","green","size","small"];
list PATCH=["color","green","blue","size","small","large"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2 || llGetListLength(PATCH)%3)
        {
            llOwnerSay("Malformed record/patch.");
            return;
        }
        list keys;
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string name=llList2String(RECORD,i);
            if(llListFindList(keys,[name])!=-1)
            {
                llOwnerSay("Duplicate record key.");
                return;
            }
            keys += [name];
        }
        list touched;
        for(i=0;i<llGetListLength(PATCH);i+=3)
        {
            string name=llList2String(PATCH,i);
            integer index=llListFindList(keys,[name]);
            if(index==-1 || llListFindList(touched,[name])!=-1)
            {
                llOwnerSay("Unknown or repeated patch key.");
                return;
            }
            if(llList2String(RECORD,index*2+1)!=llList2String(PATCH,i+1))
            {
                llOwnerSay("Precondition failed for "+name);
                return;
            }
            touched += [name];
        }
        list result=RECORD;
        for(i=0;i<llGetListLength(PATCH);i+=3)
        {
            integer index=llListFindList(keys,[llList2String(PATCH,i)])*2+1;
            result=llListReplaceList(result,[llList2String(PATCH,i+2)],index,index);
        }
        llOwnerSay("Proposed record: "+llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Audit required JSON fields

Check that required fields exist and are not JSON null.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and REQUIRED; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Requires JSON support. This checks presence only; a production schema should also constrain individual value types and lengths.

// Original Incoprea example. MIT.
string DOCUMENT="{\"title\":\"Lamp\",\"author\":null}";
list REQUIRED=["title","author","version"];
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_OBJECT)
        {
            llOwnerSay("Expected a JSON object.");
            return;
        }
        integer i;
        integer issues;
        for(i=0;i<llGetListLength(REQUIRED);++i)
        {
            string field=llList2String(REQUIRED,i);
            string kind=llJsonValueType(DOCUMENT,[field]);
            if(kind==JSON_INVALID || kind==JSON_NULL)
            {
                ++issues;
                llOwnerSay("Missing or null: "+field);
            }
        }
        llOwnerSay("Required-field findings: "+(string)issues);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Beginner

Base64 round trip

Convert a short text value to Base64 and restore it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit MESSAGE and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Base64 is an encoding, not a secret or password protection. This sends no network traffic.

// Original Incoprea example. MIT.
string MESSAGE = "A small world in a bottle.";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string encoded = llStringToBase64(MESSAGE);
        llOwnerSay("Base64: " + encoded);
        llOwnerSay("Restored: " + llBase64ToString(encoded));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Build an encoded query string

Encode both keys and values from a flat pair list and join them with ampersands.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Does not open or fetch the resulting URL. Duplicate keys are preserved; values are encoded separately so reserved characters remain data.

// Original Incoprea example. MIT.
list PAIRS=["q","blue glass","category","garden & light","empty",""];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(PAIRS)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list encoded=[];
        integer i;
        for(i=0;i<llGetListLength(PAIRS);i+=2)encoded += [llEscapeURL(llList2String(PAIRS,i))+"="+llEscapeURL(llList2String(PAIRS,i+1))];
        llOwnerSay(llDumpList2String(encoded,"&"));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Build an inverse lookup report

For each distinct value, list all record keys pointing to it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD key/value pairs; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Useful for finding aliases or shared settings. Values are exact strings and keys are not assumed unique.

// Original Incoprea example. MIT.
list RECORD=["lamp","green","plant","green","cup","blue"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list values=[];
        integer i;
        integer j;
        for(i=1;i<llGetListLength(RECORD);i+=2)
        {
            string value=llList2String(RECORD,i);
            if(llListFindList(values,[value])==-1)values+=[value];
        }
        for(i=0;i<llGetListLength(values);++i)
        {
            string value=llList2String(values,i);
            list keys=[];
            for(j=0;j<llGetListLength(RECORD);j+=2)if(llList2String(RECORD,j+1)==value)keys+=[llList2String(RECORD,j)];
            llOwnerSay("["+value+"] <- "+llDumpList2String(keys,", "));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Build summary as JSON

Create a small structured JSON record describing the current prim.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Copy the owner-chat result into your own notes or tool.

Stop / restore: Remove or disable the script. It does not change the build.

Output is sent only to the owner, never to a web service. Scale is intentionally stored as a vector string. JSON support varies across simulators.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string result = llList2Json(JSON_OBJECT, [
        "name", llGetObjectName(),
        "region", llGetRegionName(),
        "scale", (string)llGetScale(),
        "faces", llGetNumberOfSides()
        ]);
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Calculate a build note’s calendar age

Compare a configured creation date with the simulator’s current UTC date.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Calendar days are not exact 24-hour intervals. A future creation date is reported explicitly rather than as a negative age.

// Original Incoprea example. MIT.
string DATE="2026-09-01";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        list today=parseDate(llGetDate());
        if(llGetListLength(today)!=3)
        {
            llOwnerSay("Current date outside supported years.");
            return;
        }
        integer age=dateSerial(today)-dateSerial(date);
        if(age<0)llOwnerSay("Creation date is in the future by "+(string)(-age)+" days.");
        else llOwnerSay("Note age: "+(string)age+" calendar days.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Calculate a local stock movement ledger

Apply signed quantity adjustments to an initial amount and flag a negative running balance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit START and MOVES as note/integer delta pairs; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Illustrative planning arithmetic only. It never delivers, sells, or counts actual inventory assets; values must be configured integers.

// Original Incoprea example. MIT.
integer START=10;
list MOVES=["Added",5,"Reserved",-4,"Used",-3,"Planned",-12];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(START<0 || llGetListLength(MOVES)%2)
        {
            llOwnerSay("Invalid start or movement records.");
            return;
        }
        integer balance=START;
        integer i;
        for(i=0;i<llGetListLength(MOVES);i+=2)
        {
            balance+=llList2Integer(MOVES,i+1);
            llOwnerSay(llList2String(MOVES,i)+": balance "+(string)balance);
            if(balance<0)llOwnerSay("Finding: balance below zero at this step.");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Characters versus UTF-8 bytes

Compare string length with its UTF-8 byte count using Base64 padding.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Many LSL message limits are byte limits, so non-ASCII text can use more room than expected. This is a short-text calculation, not a memory profiler.

// Original Incoprea example. MIT.
string TEXT = "Café garden";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string encoded = llStringToBase64(TEXT);
        integer length = llStringLength(encoded);
        integer bytes = (length / 4) * 3;
        if (length > 0)
        {
            if (llGetSubString(encoded, -1, -1) == "=") --bytes;
            if (llGetSubString(encoded, -2, -2) == "=") --bytes;
        }
        llOwnerSay("String length: " + (string)llStringLength(TEXT) + "; UTF-8 bytes: " + (string)bytes);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Check a JSON document size and item budget

Reject malformed JSON, excessive UTF-8 size, and oversized top-level collections before use.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

An input-size guard is not a complete defense against deeply nested or expensive content. Use small trusted configuration sources and validate application fields too.

// Original Incoprea example. MIT.
string DOCUMENT="{\"title\":\"Lamp\",\"tags\":[\"garden\",\"light\"]}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string kind=llJsonValueType(DOCUMENT,[]);
        if(kind==JSON_INVALID)
        {
            llOwnerSay("Invalid JSON.");
            return;
        }
        string encoded=llStringToBase64(DOCUMENT);
        integer size=llStringLength(encoded);
        integer bytes=(size/4)*3;
        if(size>0)
        {
            if(llGetSubString(encoded,-1,-1)=="=")--bytes;
            if(llGetSubString(encoded,-2,-2)=="=")--bytes;
        }
        if(bytes>2048)
        {
            llOwnerSay("JSON exceeds 2048-byte budget.");
            return;
        }
        integer items=0;
        if(kind==JSON_ARRAY)items=llGetListLength(llJson2List(DOCUMENT));
        else if(kind==JSON_OBJECT)items=llGetListLength(llJson2List(DOCUMENT))/2;
        if(items>40)
        {
            llOwnerSay("Collection exceeds 40 items.");
            return;
        }
        llOwnerSay("Within document budgets: "+(string)bytes+" bytes, "+(string)items+" top-level items.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check a nested display schema

Validate display.title, display.enabled, and display.scale as specific JSON types.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Reports schema findings only. A JSON boolean is distinguished from the strings true and false.

// Original Incoprea example. MIT.
string DOCUMENT="{\"display\":{\"title\":\"Lamp\",\"enabled\":true,\"scale\":1.5}}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer findings;
        if(llJsonValueType(DOCUMENT,["display"])!=JSON_OBJECT)
        {
            llOwnerSay("display must be an object.");
            return;
        }
        if(llJsonValueType(DOCUMENT,["display","title"])!=JSON_STRING)
        {
            ++findings;
            llOwnerSay("title must be a string.");
        }
        string enabled=llJsonValueType(DOCUMENT,["display","enabled"]);
        if(enabled!=JSON_TRUE && enabled!=JSON_FALSE)
        {
            ++findings;
            llOwnerSay("enabled must be boolean.");
        }
        if(llJsonValueType(DOCUMENT,["display","scale"])!=JSON_NUMBER)
        {
            ++findings;
            llOwnerSay("scale must be numeric.");
        }
        llOwnerSay("Nested schema findings: "+(string)findings);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check inventory references in JSON products

Validate each name/type entry resolves to the declared texture or sound inventory type.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Checks this prim’s inventory only and does not play, reveal, or transfer assets. Only the declared two media types are accepted.

// Original Incoprea example. MIT.
string DOCUMENT="[{\"name\":\"Panel\",\"type\":\"texture\"},{\"name\":\"Chime\",\"type\":\"sound\"}]";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>30)
        {
            llOwnerSay("Maximum 30 dependencies.");
            return;
        }
        integer i;
        for(i=0;i<total;++i)
        {
            if(llJsonValueType(DOCUMENT,[i,"name"])!=JSON_STRING || llJsonValueType(DOCUMENT,[i,"type"])!=JSON_STRING)
            {
                llOwnerSay("Invalid dependency record.");
                return;
            }
            string name=llJsonGetValue(DOCUMENT,[i,"name"]);
            string kind=llJsonGetValue(DOCUMENT,[i,"type"]);
            integer expected=INVENTORY_NONE;
            if(kind=="texture")expected=INVENTORY_TEXTURE;
            else if(kind=="sound")expected=INVENTORY_SOUND;
            else
            {
                llOwnerSay("Unsupported dependency type.");
                return;
            }
            if(llGetInventoryType(name)==expected)llOwnerSay("Present: "+name);
            else llOwnerSay("Missing/wrong type: "+name);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check quoted-string closure in a line

Walk double-quoted strings with backslash escapes and report whether the line ends inside a string.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Does not parse comments or a complete programming language. It is useful as one small diagnostic for pasted configuration lines.

// Original Incoprea example. MIT.
string LINE="label=\"A \\\"small\\\" lamp\"";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer quoted;
        integer escaped;
        integer opened;
        integer i;
        for(i=0;i<llStringLength(LINE);++i)
        {
            string c=llGetSubString(LINE,i,i);
            if(quoted)
            {
                if(escaped)escaped=FALSE;
                else if(c=="\\")escaped=TRUE;
                else if(c=="\"")quoted=FALSE;
            }
            else if(c=="\"")
            {
                quoted=TRUE;
                opened=i;
            }
        }
        if(quoted)llOwnerSay("Unclosed quote opened at character "+(string)opened);
        else llOwnerSay("Quoted strings are closed on this line.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check required option coverage

Find missing allowed options and unexpected values in a sample record column.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Counts repeat use of valid options and prints missing options. Matching is exact and case-sensitive.

// Original Incoprea example. MIT.
list ALLOWED=["draft","review","ready"];
list VALUES=["draft","ready","ready","archived"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        for(i=0;i<llGetListLength(ALLOWED);++i)
        {
            string option=llList2String(ALLOWED,i);
            integer count;
            integer j;
            for(j=0;j<llGetListLength(VALUES);++j)if(llList2String(VALUES,j)==option)++count;
            llOwnerSay(option+" count="+(string)count);
        }
        for(i=0;i<llGetListLength(VALUES);++i)if(llListFindList(ALLOWED,[llList2String(VALUES,i)])==-1)llOwnerSay("Unexpected: "+llList2String(VALUES,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check two-column uniqueness

Detect repeated category/name combinations in three-field catalog records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS as category,name,value triples; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Fields are compared separately, so embedded delimiters cannot create accidental combined-key collisions.

// Original Incoprea example. MIT.
list ROWS=["Lights","Lamp","blue","Seats","Lamp","small","Lights","Lamp","red"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%3)
        {
            llOwnerSay("Incomplete triple.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<llGetListLength(ROWS);i+=3)for(j=0;j<i;j+=3)if(llList2String(ROWS,i)==llList2String(ROWS,j) && llList2String(ROWS,i+1)==llList2String(ROWS,j+1))llOwnerSay("Repeated category/name at rows "+(string)(j/3)+" and "+(string)(i/3));
        llOwnerSay("Composite-key check complete.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Check UUID text structure

Validate the canonical 8-4-4-4-12 hexadecimal shape of an identifier.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit VALUE and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Structure alone does not prove that an avatar, object, or asset exists. Rejects the all-zero UUID separately; no lookup occurs.

// Original Incoprea example. MIT.
string VALUE="12345678-1234-1234-1234-123456789abc";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string value=llToLower(VALUE);
        if(llStringLength(value)!=36)
        {
            llOwnerSay("Expected 36 characters.");
            return;
        }
        integer i;
        for(i=0;i<36;++i)
        {
            string c=llGetSubString(value,i,i);
            if(i==8 || i==13 || i==18 || i==23)
            {
                if(c!="-")
                {
                    llOwnerSay("Missing UUID hyphen.");
                    return;
                }
            }
            else if(llSubStringIndex("0123456789abcdef",c)==-1)
            {
                llOwnerSay("Non-hexadecimal UUID character.");
                return;
            }
        }
        if(value==(string)NULL_KEY)
        {
            llOwnerSay("Null UUID is not an identity.");
            return;
        }
        llOwnerSay("Canonical UUID shape accepted; existence unverified.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Check whether a delimiter is safe for export

Find fields that would be ambiguous in an unquoted delimited export.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit FIELDS and SEPARATOR; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Rejects delimiter characters and line breaks in fields. It recommends quoting or another format instead of silently losing information.

// Original Incoprea example. MIT.
list FIELDS=["Lamp","blue|green","small"];
string SEPARATOR="|";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SEPARATOR=="")
        {
            llOwnerSay("Choose a nonempty separator.");
            return;
        }
        integer i;
        integer issues;
        for(i=0;i<llGetListLength(FIELDS);++i)
        {
            string value=llList2String(FIELDS,i);
            if(llSubStringIndex(value,SEPARATOR)!=-1 || llSubStringIndex(value,"\n")!=-1 || llSubStringIndex(value,llUnescapeURL("%0D"))!=-1)
            {
                ++issues;
                llOwnerSay("Field "+(string)i+" needs quoting or another export format.");
            }
        }
        if(!issues)llOwnerSay("Unquoted export: "+llDumpList2String(FIELDS,SEPARATOR));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Choose an unused component name

Try a base name, then bounded numbered suffixes against an existing name list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

This only previews a name. Concurrent changes can invalidate the result; recheck before applying it to a real inventory or linkset.

// Original Incoprea example. MIT.
string BASE="Lamp";
list EXISTING=["Lamp","Lamp-2","Lamp-3","Bench"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(BASE=="")
        {
            llOwnerSay("Set a base name.");
            return;
        }
        if(llListFindList(EXISTING,[BASE])==-1)
        {
            llOwnerSay(BASE);
            return;
        }
        integer n;
        for(n=2;n<=100;++n)
        {
            string candidate=BASE+"-"+(string)n;
            if(llListFindList(EXISTING,[candidate])==-1)
            {
                llOwnerSay(candidate);
                return;
            }
        }
        llOwnerSay("No free name within the 100-name search bound.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Classify record fields by schema role

Identify fields as mandatory, optional, or unknown and report absent mandatory fields.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD, MANDATORY, and OPTIONAL; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

This examines field names, not whether their values are valid. Requires complete record pairs; no persistence is changed.

// Original Incoprea example. MIT.
list RECORD=["title","Lamp","debug","yes","color","green"];
list MANDATORY=["title","version"];
list OPTIONAL=["color","description"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Incomplete record.");
            return;
        }
        list present=[];
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string field=llList2String(RECORD,i);
            present+=[field];
            string role="UNKNOWN";
            if(llListFindList(MANDATORY,[field])!=-1)role="mandatory";
            else if(llListFindList(OPTIONAL,[field])!=-1)role="optional";
            llOwnerSay(field+": "+role);
        }
        for(i=0;i<llGetListLength(MANDATORY);++i)if(llListFindList(present,[llList2String(MANDATORY,i)])==-1)llOwnerSay("Missing mandatory: "+llList2String(MANDATORY,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Clean up a tag list

Trim whitespace, lowercase tags, discard blanks, and remove duplicates while retaining first-seen order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Uses comma-separated simple tags; commas cannot be embedded inside a tag. Case normalization is deliberate.

// Original Incoprea example. MIT.
string INPUT = " Light, water,light,  ,Plants,WATER ";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list raw = llParseString2List(INPUT, [","], []);
        list clean = [];
        integer i;
        for (i = 0; i < llGetListLength(raw); ++i)
        {
            string tag = llToLower(llStringTrim(llList2String(raw, i), STRING_TRIM));
            if (tag != "" && llListFindList(clean, [tag]) == -1) clean += [tag];
        }
        llOwnerSay(llDumpList2String(clean, ", "));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Clip text to a UTF-8 byte budget

Append whole string characters until the UTF-8 byte budget would be exceeded.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and BUDGET; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Uses Base64 length to count UTF-8 bytes and never cuts encoded bytes directly. Combining characters may still be separated visually. Keep source text short for efficiency.

// Original Incoprea example. MIT.
string TEXT="Café lanterns beside the water";
integer BUDGET=15;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(BUDGET<0 || BUDGET>900)
        {
            llOwnerSay("Budget must be 0-900 bytes.");
            return;
        }
        string result="";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string candidate=result+llGetSubString(TEXT,i,i);
            string encoded=llStringToBase64(candidate);
            integer bytes=(llStringLength(encoded)/4)*3;
            if(llGetSubString(encoded,-1,-1)=="=") --bytes;
            if(llGetSubString(encoded,-2,-2)=="=") --bytes;
            if(bytes>BUDGET)
            {
                llOwnerSay("Clipped: "+result);
                return;
            }
            result=candidate;
        }
        llOwnerSay("Fits: "+result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Compare three-part release versions

Compare numeric major.minor.patch versions without mistaking 1.10 for 1.1.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit A and B; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Only exactly three nonnegative numeric components, each up to six digits. Prerelease/build suffixes are intentionally unsupported.

// Original Incoprea example. MIT.
string A="1.10.2";
string B="1.9.12";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list left=llParseStringKeepNulls(A,["."],[]);
        list right=llParseStringKeepNulls(B,["."],[]);
        if(llGetListLength(left)!=3 || llGetListLength(right)!=3)
        {
            llOwnerSay("Use three numeric components.");
            return;
        }
        list all=left+right;
        integer i;
        for(i=0;i<6;++i)
        {
            string part=llList2String(all,i);
            integer j;
            if(part=="" || llStringLength(part)>6)
            {
                llOwnerSay("Invalid component length.");
                return;
            }
            for(j=0;j<llStringLength(part);++j) if(llSubStringIndex("0123456789",llGetSubString(part,j,j))==-1)
            {
                llOwnerSay("Numeric components only.");
                return;
            }
        }
        integer relation=0;
        for(i=0;i<3;++i) if(relation==0)
        {
            integer a=llList2Integer(left,i);
            integer b=llList2Integer(right,i);
            if(a<b) relation=-1;
            else if(a>b) relation=1;
        }
        llOwnerSay("Comparison (-1 older, 0 equal, 1 newer): "+(string)relation);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Compare two configuration schemas

Report required keys missing from supplied keys and supplied keys unknown to the schema.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit REQUIRED and PROVIDED; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Works on names only and does not inspect values. Duplicate input keys are outside this simple set comparison; use the record-key validator first.

// Original Incoprea example. MIT.
list REQUIRED=["title","version","color"];
list PROVIDED=["title","colour","debug"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        for(i=0;i<llGetListLength(REQUIRED);++i)
        {
            string field=llList2String(REQUIRED,i);
            if(llListFindList(PROVIDED,[field])==-1)llOwnerSay("Missing required key: "+field);
        }
        for(i=0;i<llGetListLength(PROVIDED);++i)
        {
            string field=llList2String(PROVIDED,i);
            if(llListFindList(REQUIRED,[field])==-1)llOwnerSay("Unknown supplied key: "+field);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Compare two key/value records

Report fields added, removed, or changed between two flat records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit OLD and NEW as alternating unique key/value strings; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

This sample expects valid unique-key pairs. It compares exact strings and reports to the owner without updating either record.

// Original Incoprea example. MIT.
list OLD=["name","Lamp","color","blue","stock","4"];
list NEW=["name","Lamp","color","green","size","small"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(OLD)%2 || llGetListLength(NEW)%2)
        {
            llOwnerSay("Incomplete key/value record.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<llGetListLength(OLD);i+=2)
        {
            string name=llList2String(OLD,i);
            integer found=-1;
            for(j=0;j<llGetListLength(NEW);j+=2)if(llList2String(NEW,j)==name)found=j;
            if(found==-1)llOwnerSay("Removed: "+name);
            else if(llList2String(OLD,i+1)!=llList2String(NEW,found+1))llOwnerSay("Changed "+name+": "+llList2String(OLD,i+1)+" -> "+llList2String(NEW,found+1));
        }
        for(i=0;i<llGetListLength(NEW);i+=2)
        {
            integer found=FALSE;
            for(j=0;j<llGetListLength(OLD);j+=2)if(llList2String(OLD,j)==llList2String(NEW,i))found=TRUE;
            if(!found)llOwnerSay("Added: "+llList2String(NEW,i));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Convert a simple identifier style

Convert between lowerCamel and snake_case using an explicit mode.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Restricted to ASCII letters, digits, and underscore. Acronym runs are split mechanically and are not inferred as words.

// Original Incoprea example. MIT.
string INPUT="gardenLampCount";
string MODE="snake";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer i;
        integer upperNext;
        for(i=0;i<llStringLength(INPUT);++i)
        {
            string c=llGetSubString(INPUT,i,i);
            integer code=llOrd(c,0);
            if(llSubStringIndex("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_",c)==-1)
            {
                llOwnerSay("Unsupported identifier character.");
                return;
            }
            if(MODE=="snake")
            {
                if(code>=65 && code<=90)
                {
                    if(i>0)result+="_";
                    result+=llToLower(c);
                }
                else result+=c;
            }
            else if(MODE=="camel")
            {
                if(c=="_")upperNext=TRUE;
                else
                {
                    if(upperNext)c=llToUpper(c);
                    else if(result=="")c=llToLower(c);
                    result+=c;
                    upperNext=FALSE;
                }
            }
            else
            {
                llOwnerSay("Mode must be snake or camel.");
                return;
            }
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Copy approved JSON fields

Build a new JSON object containing only approved string fields from an input object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and ALLOWED; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Ignores unknown keys and rejects non-string approved fields. This is local data selection, not encryption or an external upload.

// Original Incoprea example. MIT.
string INPUT="{\"title\":\"Lamp\",\"version\":\"1.0\",\"internal\":\"omit\"}";
list ALLOWED=["title","version"];
string quoteJson(string value)
{
    string output="\"";
    string digits="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer code=llOrd(value,i);
        if(c=="\"" || c=="\\") output+="\\"+c;
        else if(code<32) output+="\\u00"+llGetSubString(digits,code/16,code/16)+llGetSubString(digits,code%16,code%16);
        else output+=c;
    }
    return output+"\"";
}
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llJsonValueType(INPUT,[])!=JSON_OBJECT)
        {
            llOwnerSay("Expected an object.");
            return;
        }
        string result="{}";
        integer i;
        for(i=0;i<llGetListLength(ALLOWED);++i)
        {
            string field=llList2String(ALLOWED,i);
            string kind=llJsonValueType(INPUT,[field]);
            if(kind!=JSON_INVALID)
            {
                if(kind!=JSON_STRING)
                {
                    llOwnerSay("Approved field is not a string: "+field);
                    return;
                }
                string encoded=quoteJson(llJsonGetValue(INPUT,[field]));
                result=llJsonSetValue(result,[field],encoded);
            }
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Count adjacent word pairs

Build counts for adjacent word pairs in a short whitespace-tokenized note.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Lowercases words but leaves punctuation attached. Caps input at 50 words; this is a text-pattern aid, not a language model.

// Original Incoprea example. MIT.
string TEXT="blue glass green glass blue glass";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list words=llParseString2List(llToLower(TEXT),[" ","\n",llUnescapeURL("%09")],[]);
        if(llGetListLength(words)>50)
        {
            llOwnerSay("Use at most 50 words.");
            return;
        }
        list pairs=[];
        list counts=[];
        integer i;
        for(i=1;i<llGetListLength(words);++i)
        {
            string pair=llList2String(words,i-1)+" "+llList2String(words,i);
            integer at=llListFindList(pairs,[pair]);
            if(at==-1)
            {
                pairs += [pair];
                counts += [1];
            }
            else counts=llListReplaceList(counts,[llList2Integer(counts,at)+1],at,at);
        }
        for(i=0;i<llGetListLength(pairs);++i)llOwnerSay(llList2String(pairs,i)+": "+llList2String(counts,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Count ASCII word tokens

Count runs of letters or digits as words while treating punctuation as separators.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

A deliberately simple ASCII tokenizer; it is not suitable for all writing systems or linguistic word counts.

// Original Incoprea example. MIT.
string TEXT="Garden-lamp #2: brass & glass.";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer words;
        integer inside;
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llToLower(llGetSubString(TEXT,i,i));
            integer wordChar=llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789",c)!=-1;
            if(wordChar && !inside)++words;
            inside=wordChar;
        }
        llOwnerSay("ASCII word tokens: "+(string)words);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Count days between two dates

Subtract date serials to obtain signed whole-calendar-day distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Returns zero for the same date. The endpoint day is not counted inclusively; no elapsed-hour claim is made.

// Original Incoprea example. MIT.
string FROM="2028-02-27";
string TO="2028-03-02";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list first=parseDate(FROM);
        list last=parseDate(TO);
        if(llGetListLength(first)!=3 || llGetListLength(last)!=3)
        {
            llOwnerSay("Invalid dates.");
            return;
        }
        llOwnerSay("Calendar-day difference: "+(string)(dateSerial(last)-dateSerial(first)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Count nonoverlapping text occurrences

Count exact occurrences while advancing past each full match.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Empty search text is rejected. Overlapping matches are intentionally not counted, which is useful for replacement planning.

// Original Incoprea example. MIT.
string TEXT="aaaaa";
string NEEDLE="aa";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(NEEDLE=="")
        {
            llOwnerSay("Set a nonempty search string.");
            return;
        }
        string rest=TEXT;
        integer matches;
        integer at=llSubStringIndex(rest,NEEDLE);
        while(at!=-1)
        {
            ++matches;
            rest=llDeleteSubString(rest,0,at+llStringLength(NEEDLE)-1);
            at=llSubStringIndex(rest,NEEDLE);
        }
        llOwnerSay("Nonoverlapping occurrences: "+(string)matches);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Count weekdays in a date interval

Count Monday-through-Friday dates from the start through the day before the end.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Half-open interval: start included, end excluded. No holidays; intervals are capped at 366 days.

// Original Incoprea example. MIT.
string FROM="2026-09-21";
string TO="2026-09-28";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list first=parseDate(FROM);
        list last=parseDate(TO);
        if(llGetListLength(first)!=3 || llGetListLength(last)!=3)
        {
            llOwnerSay("Invalid dates.");
            return;
        }
        integer a=dateSerial(first);
        integer b=dateSerial(last);
        if(b<a || b-a>366)
        {
            llOwnerSay("Use an ascending interval of at most 366 days.");
            return;
        }
        integer count;
        integer day;
        for(day=a;day<b;++day)if(weekday(day)!=0 && weekday(day)!=6)++count;
        llOwnerSay("Weekdays in interval: "+(string)count);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Create a short collection abbreviation

Take the first character of each whitespace-separated word to form initials.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

A display abbreviation only; it is not guaranteed unique. Limit the source to short labels and review the result for ambiguity.

// Original Incoprea example. MIT.
string TEXT="Garden Light Workshop";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list words=llParseString2List(TEXT,[" ","\n",llUnescapeURL("%09")],[]);
        string initials="";
        integer i;
        for(i=0;i<llGetListLength(words) && i<8;++i)initials+=llToUpper(llGetSubString(llList2String(words,i),0,0));
        llOwnerSay("Abbreviation: "+initials);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Decode a small declared escape syntax

Decode backslash-n, escaped backslash, and escaped quote in a short configuration value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Rejects unknown escapes and a trailing backslash. This is not an LSL parser or a general Unicode escape decoder.

// Original Incoprea example. MIT.
string INPUT="Garden\\nLamp";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer escaped;
        integer i;
        for(i=0;i<llStringLength(INPUT);++i)
        {
            string c=llGetSubString(INPUT,i,i);
            if(escaped)
            {
                if(c=="n")result+="\n";
                else if(c=="\\" || c=="\"")result+=c;
                else
                {
                    llOwnerSay("Unsupported escape at "+(string)i);
                    return;
                }
                escaped=FALSE;
            }
            else if(c=="\\")escaped=TRUE;
            else result+=c;
        }
        if(escaped)
        {
            llOwnerSay("Trailing backslash.");
            return;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Decode a URL query string

Split a query string into name/value pairs, decoding percent escapes and form-style plus signs.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit QUERY without the leading question mark; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Uses the first equals sign as separator. Repeated keys are preserved as separate reports. This opens no URL and sends no data externally.

// Original Incoprea example. MIT.
string QUERY="label=Blue+Glass&tags=garden%2Clight&empty=";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list pairs=llParseStringKeepNulls(QUERY,["&"],[]);
        integer i;
        for(i=0;i<llGetListLength(pairs);++i)
        {
            string pair=llList2String(pairs,i);
            integer split=llSubStringIndex(pair,"=");
            string name=pair;
            string value="";
            if(split==0) name="";
            else if(split>0) name=llGetSubString(pair,0,split-1);
            if(split!=-1 && split<llStringLength(pair)-1) value=llGetSubString(pair,split+1,-1);
            name=llDumpList2String(llParseStringKeepNulls(name,["+"],[])," ");
            value=llDumpList2String(llParseStringKeepNulls(value,["+"],[])," ");
            llOwnerSay("["+llUnescapeURL(name)+"] = ["+llUnescapeURL(value)+"]");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Decode character-counted string records

Parse length-prefixed strings with strict length digits and remaining-input checks.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Accepts at most 20 records and 800 input characters. An incomplete prefix or value rejects the entire decoded preview.

// Original Incoprea example. MIT.
string INPUT="10:Lamp:green0:10:Bench|wide";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llStringLength(INPUT)>800)
        {
            llOwnerSay("Input too long.");
            return;
        }
        integer pos;
        integer total=llStringLength(INPUT);
        list result;
        while(pos<total)
        {
            if(llGetListLength(result)>=20)
            {
                llOwnerSay("Too many records.");
                return;
            }
            string tail=llGetSubString(INPUT,pos,-1);
            integer colon=llSubStringIndex(tail,":");
            if(colon<1 || colon>3)
            {
                llOwnerSay("Invalid length prefix.");
                return;
            }
            string digits=llGetSubString(tail,0,colon-1);
            integer i;
            for(i=0;i<llStringLength(digits);++i)if(llSubStringIndex("0123456789",llGetSubString(digits,i,i))==-1)
            {
                llOwnerSay("Non-digit length.");
                return;
            }
            integer length=(integer)digits;
            pos+=colon+1;
            if(pos+length>total)
            {
                llOwnerSay("Truncated value.");
                return;
            }
            string value="";
            if(length>0)value=llGetSubString(INPUT,pos,pos+length-1);
            result += [value];
            pos+=length;
        }
        llOwnerSay("Decoded: "+llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Detect conflicts in a three-way field merge

Compare base, local, and remote values for the same ordered field set.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

An unchanged side yields to the changed side; identical edits merge. Conflicting edits are reported without choosing a winner. Lists must align by field.

// Original Incoprea example. MIT.
list FIELDS=["color","size","label"];
list BASE=["green","small","Lamp"];
list LOCAL=["blue","small","Garden Lamp"];
list REMOTE=["green","large","Display Lamp"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(FIELDS);
        if(llGetListLength(BASE)!=n || llGetListLength(LOCAL)!=n || llGetListLength(REMOTE)!=n)
        {
            llOwnerSay("Lists must align.");
            return;
        }
        integer i;
        for(i=0;i<n;++i)
        {
            string b=llList2String(BASE,i);
            string l=llList2String(LOCAL,i);
            string r=llList2String(REMOTE,i);
            string value;
            if(l==r)value=l;
            else if(l==b)value=r;
            else if(r==b)value=l;
            else
            {
                llOwnerSay("CONFLICT "+llList2String(FIELDS,i)+" local="+l+" remote="+r);
                value="[unresolved]";
            }
            llOwnerSay(llList2String(FIELDS,i)+" => "+value);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Detect keys that collide after normalization

Report distinct identifiers that become equal after trimming and lowercasing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Does not remove accents or perform Unicode normalization. Exact duplicates are also reported because they would occupy the same normalized slot.

// Original Incoprea example. MIT.
list KEYS=["Lamp"," lamp ","Bench","BENCH","Door"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list canonical;
        list original;
        integer i;
        for(i=0;i<llGetListLength(KEYS);++i)
        {
            string keyText=llList2String(KEYS,i);
            string normalized=llToLower(llStringTrim(keyText,STRING_TRIM));
            integer at=llListFindList(canonical,[normalized]);
            if(at!=-1)llOwnerSay("Collision: ["+llList2String(original,at)+"] with ["+keyText+"]");
            else
            {
                canonical += [normalized];
                original += [keyText];
            }
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Detect schema field-order drift

Compare two key/value records for matching field order independent of their values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit A and B; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

A differing order is informational unless your serialization format depends on it. Missing trailing keys are explicitly reported.

// Original Incoprea example. MIT.
list A=["title","Lamp","color","green"];
list B=["color","blue","title","Lamp","size","small"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(A)%2 || llGetListLength(B)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        integer total=llGetListLength(A);
        if(llGetListLength(B)>total)total=llGetListLength(B);
        integer i;
        for(i=0;i<total;i+=2)
        {
            string left="[absent]";
            string right="[absent]";
            if(i<llGetListLength(A))left=llList2String(A,i);
            if(i<llGetListLength(B))right=llList2String(B,i);
            if(left!=right)llOwnerSay("Field slot "+(string)(i/2)+": "+left+" -> "+right);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Distinguish a missing field from explicit null

Report absent, null, empty-string, and other present states separately.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

These states can have different configuration meanings. This example reports the distinction without choosing a fallback automatically.

// Original Incoprea example. MIT.
string DOCUMENT="{\"label\":\"\",\"subtitle\":null}";
string FIELD="label";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string kind=llJsonValueType(DOCUMENT,[FIELD]);
        if(kind==JSON_INVALID)llOwnerSay("Field absent.");
        else if(kind==JSON_NULL)llOwnerSay("Field explicitly null.");
        else if(kind==JSON_STRING && llJsonGetValue(DOCUMENT,[FIELD])=="")llOwnerSay("Field is an intentional empty string.");
        else llOwnerSay("Field exists with a non-null value.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Distinguish moved records from changed values

Compare two unique-key lists and identify added, removed, moved, or value-changed records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Pairs are key/value. Index changes indicate an ordering difference, not necessarily a deliberate individual move.

// Original Incoprea example. MIT.
list BEFORE=["a","green","b","small","c","Lamp"];
list AFTER=["c","Lamp","a","blue","d","new"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(BEFORE)%2 || llGetListLength(AFTER)%2)
        {
            llOwnerSay("Use key/value pairs.");
            return;
        }
        list a;
        list b;
        integer i;
        for(i=0;i<llGetListLength(BEFORE);i+=2)
        {
            string keyText=llList2String(BEFORE,i);
            if(llListFindList(a,[keyText])!=-1)
            {
                llOwnerSay("Duplicate old key.");
                return;
            }
            a += [keyText];
        }
        for(i=0;i<llGetListLength(AFTER);i+=2)
        {
            string keyText=llList2String(AFTER,i);
            if(llListFindList(b,[keyText])!=-1)
            {
                llOwnerSay("Duplicate new key.");
                return;
            }
            b += [keyText];
        }
        for(i=0;i<llGetListLength(a);++i)
        {
            string keyText=llList2String(a,i);
            integer at=llListFindList(b,[keyText]);
            if(at==-1)llOwnerSay("Removed "+keyText);
            else
            {
                if(at!=i)llOwnerSay("Order changed "+keyText);
                if(llList2String(BEFORE,i*2+1)!=llList2String(AFTER,at*2+1))llOwnerSay("Value changed "+keyText);
            }
        }
        for(i=0;i<llGetListLength(b);++i)if(llListFindList(a,[llList2String(b,i)])==-1)llOwnerSay("Added "+llList2String(b,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Encode a URL parameter

Demonstrate encoding one text value for a URL query parameter and decoding it again.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit VALUE and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Only encodes text locally; no browser or network request opens. Escape a parameter value rather than an entire URL. Encoding is not encryption.

// Original Incoprea example. MIT.
string VALUE = "blue glass & brass";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string encoded = llEscapeURL(VALUE);
        llOwnerSay("Encoded: " + encoded);
        llOwnerSay("Decoded: " + llUnescapeURL(encoded));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Encode strings without a delimiter restriction

Serialize a short list as character-count colon value records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Lengths count LSL characters, not UTF-8 bytes. The format preserves empty strings and colons inside values; it is a local example format, not a network standard.

// Original Incoprea example. MIT.
list VALUES=["Lamp:green","","Bench|wide"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer i;
        for(i=0;i<llGetListLength(VALUES);++i)
        {
            string value=llList2String(VALUES,i);
            result+=(string)llStringLength(value)+":"+value;
        }
        if(llStringLength(result)>800)
        {
            llOwnerSay("Use shorter values for this owner-chat demo.");
            return;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Escape Markdown inline punctuation

Prefix common Markdown punctuation with a backslash for a plain inline label.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

This is a conservative inline-label formatter, not a complete Markdown parser. Newlines and HTML contexts require separate handling.

// Original Incoprea example. MIT.
string TEXT="[Garden] *Lamp* #1";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            if(llSubStringIndex("\\*_{}[]()#+-.!|>",c)!=-1 || llOrd(c,0)==96)result+="\\";
            result+=c;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Escape plain text for HTML

Replace markup-significant characters with HTML entities for a text-node export.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Produces escaped text, not a complete HTML sanitizer. Never use it to validate a URL, script, CSS, or arbitrary HTML context.

// Original Incoprea example. MIT.
string TEXT="Garden <Lamp> & Glass";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            if(c=="&")result+="&amp;";
            else if(c=="<")result+="&lt;";
            else if(c==">")result+="&gt;";
            else if(c=="\"")result+="&quot;";
            else if(c=="'")result+="&#39;";
            else result+=c;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Expand a short numbered selection

Expand comma-separated integers and ascending ranges into a unique selection list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT, for example 1-3,6,8-9; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Accepts values 0-100 and at most 50 output entries. Rejects descending ranges, negative values, and empty tokens. No object links are manipulated.

// Original Incoprea example. MIT.
string INPUT="1-3,6,8-9,2";
integer digitsOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list tokens=llParseStringKeepNulls(INPUT,[","],[]);
        list result=[];
        integer i;
        for(i=0;i<llGetListLength(tokens);++i)
        {
            list ends=llParseStringKeepNulls(llStringTrim(llList2String(tokens,i),STRING_TRIM),["-"],[]);
            integer size=llGetListLength(ends);
            if(size<1 || size>2)
            {
                llOwnerSay("Invalid range.");
                return;
            }
            if(!digitsOK(llList2String(ends,0)))
            {
                llOwnerSay("Invalid start.");
                return;
            }
            integer first=llList2Integer(ends,0);
            integer last=first;
            if(size==2)
            {
                if(!digitsOK(llList2String(ends,1)))
                {
                    llOwnerSay("Invalid end.");
                    return;
                }
                last=llList2Integer(ends,1);
            }
            if(first>last || last>100)
            {
                llOwnerSay("Range must ascend within 0-100.");
                return;
            }
            integer n;
            for(n=first;n<=last;++n)
            {
                if(llListFindList(result,[n])==-1)result += [n];
                if(llGetListLength(result)>50)
                {
                    llOwnerSay("Selection exceeds 50 entries.");
                    return;
                }
            }
        }
        llOwnerSay(llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Expand components with several material options

Join each component to every matching material option while preserving source order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Components are name/category pairs; options are category/material pairs. Output is bounded to 30 rows and duplicates are retained intentionally.

// Original Incoprea example. MIT.
list PARTS=["Seat","fabric","Leg","wood"];
list OPTIONS=["fabric","linen","wood","oak","fabric","velvet"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(PARTS)%2 || llGetListLength(OPTIONS)%2)
        {
            llOwnerSay("Use complete pairs.");
            return;
        }
        integer i;
        integer j;
        integer rows;
        for(i=0;i<llGetListLength(PARTS);i+=2)for(j=0;j<llGetListLength(OPTIONS);j+=2)if(llList2String(PARTS,i+1)==llList2String(OPTIONS,j))
        {
            if(rows>=30)
            {
                llOwnerSay("Output limit reached.");
                return;
            }
            ++rows;
            llOwnerSay(llList2String(PARTS,i)+" / "+llList2String(OPTIONS,j+1));
        }
        llOwnerSay("Expanded rows: "+(string)rows);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Expand real tabs to tab stops

Replace actual tab characters with spaces to reach the next fixed-width tab stop.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Uses character columns rather than rendered pixel widths. Newlines reset the column; a literal tab is generated with URL decoding for portability.

// Original Incoprea example. MIT.
integer WIDTH=4;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<1 || WIDTH>16)
        {
            llOwnerSay("Tab width must be 1-16.");
            return;
        }
        string text="A"+llUnescapeURL("%09")+"B\nLong"+llUnescapeURL("%09")+"C";
        string result="";
        integer column;
        integer i;
        for(i=0;i<llStringLength(text);++i)
        {
            string c=llGetSubString(text,i,i);
            if(c==llUnescapeURL("%09"))
            {
                integer spaces=WIDTH-(column%WIDTH);
                integer j;
                for(j=0;j<spaces;++j)result+=" ";
                column+=spaces;
            }
            else
            {
                result+=c;
                if(c=="\n")column=0;
                else ++column;
            }
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Export a vector as numeric JSON components

Represent a vector using a numeric JSON array instead of an ambiguous angle-bracket string.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

The configured vector is not applied to any object. Consumers must agree on coordinate system and units separately.

// Original Incoprea example. MIT.
vector POINT=<1.25,-2.0,3.5>;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result=llList2Json(JSON_ARRAY,[POINT.x,POINT.y,POINT.z]);
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Export text as an LSL string literal

Escape quotes, backslashes, and newlines so short text can be pasted into source.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Unsupported control characters are rejected. The returned quoted string is source text only and is not executed.

// Original Incoprea example. MIT.
string TEXT="A \"small\" garden\nSecond line";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="\"";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            integer n=llOrd(TEXT,i);
            if(c=="\"" || c=="\\")result+="\\"+c;
            else if(c=="\n")result+="\\n";
            else if(n<32 || n==127)
            {
                llOwnerSay("Unsupported control character at "+(string)i);
                return;
            }
            else result+=c;
        }
        result+="\"";
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Extract a column from records

Pull one selected column from a fixed-width list of records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS, STRIDE, and COLUMN; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Column numbers start at zero. Rejects incomplete rows and invalid stride/column settings. This copies data without changing the source list.

// Original Incoprea example. MIT.
list ROWS=["Lamp",12,"brass","Cup",3,"clay","Bench",20,"wood"];
integer STRIDE=3;
integer COLUMN=2;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(STRIDE<1 || COLUMN<0 || COLUMN>=STRIDE || llGetListLength(ROWS)%STRIDE!=0)
        {
            llOwnerSay("Invalid stride, column, or incomplete row.");
            return;
        }
        list result=[];
        integer i;
        for(i=COLUMN;i<llGetListLength(ROWS);i+=STRIDE) result+=llList2List(ROWS,i,i);
        llOwnerSay(llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Extract a configuration namespace

Select keys beginning with a namespace prefix and remove that prefix from the preview.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD and PREFIX; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Prefix must be nonempty; resulting empty names are rejected. Useful for separating display.* from audio.* configuration without applying either.

// Original Incoprea example. MIT.
list RECORD=["display.title","Lamp","audio.volume","0.2","display.color","green"];
string PREFIX="display.";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PREFIX=="" || llGetListLength(RECORD)%2)
        {
            llOwnerSay("Invalid prefix or record.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string name=llList2String(RECORD,i);
            if(llSubStringIndex(name,PREFIX)==0)
            {
                string shortName=llDeleteSubString(name,0,llStringLength(PREFIX)-1);
                if(shortName=="")
                {
                    llOwnerSay("Namespace entry has no field name.");
                    return;
                }
                llOwnerSay(shortName+"="+llList2String(RECORD,i+1));
            }
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Extract a marked text block

Read the first section between literal opening and closing markers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT, OPEN, and CLOSE; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Markers must be nonempty. Nested sections are not supported; the first closing marker after the opener ends the block. No code or markup is executed.

// Original Incoprea example. MIT.
string TEXT="Before [note]Use a spare prim.[/note] After";
string OPEN="[note]";
string CLOSE="[/note]";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(OPEN=="" || CLOSE=="")
        {
            llOwnerSay("Markers must be nonempty.");
            return;
        }
        integer start=llSubStringIndex(TEXT,OPEN);
        if(start==-1)
        {
            llOwnerSay("Opening marker absent.");
            return;
        }
        string tail=llDeleteSubString(TEXT,0,start+llStringLength(OPEN)-1);
        integer end=llSubStringIndex(tail,CLOSE);
        if(end==-1)
        {
            llOwnerSay("Closing marker absent.");
            return;
        }
        string block="";
        if(end>0) block=llGetSubString(tail,0,end-1);
        llOwnerSay("Marked block: ["+block+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Extract a numbered line span

Print a selected inclusive one-based range from a multiline snippet.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Rejects missing or reversed lines. Blank lines are preserved; this is source inspection, not execution.

// Original Incoprea example. MIT.
string TEXT="Header\nSetup\n\nNotes\nLicense";
integer FIRST=2;
integer LAST=4;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        if(FIRST<1 || LAST<FIRST || LAST>llGetListLength(lines))
        {
            llOwnerSay("Invalid line span.");
            return;
        }
        integer i;
        for(i=FIRST-1;i<LAST;++i)llOwnerSay((string)(i+1)+": "+llList2String(lines,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Extract a simple HTTPS host

Extract a host from a basic HTTPS URL while rejecting credentials and unusual authority syntax.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit URL and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Accepts a hostname with optional numeric port, but not IPv6 literals, userinfo, or arbitrary schemes. Parsing is not destination validation and makes no request.

// Original Incoprea example. MIT.
string URL="https://example.org:443/library?q=lamp";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llSubStringIndex(llToLower(URL),"https://")!=0)
        {
            llOwnerSay("HTTPS URL required.");
            return;
        }
        string rest=llGetSubString(URL,8,-1);
        list parts=llParseStringKeepNulls(rest,["/","?","#"],[]);
        string authority=llList2String(parts,0);
        if(authority=="" || llSubStringIndex(authority,"@")!=-1 || llSubStringIndex(authority,"[")!=-1 || llSubStringIndex(authority," ")!=-1)
        {
            llOwnerSay("Unsupported or empty authority.");
            return;
        }
        list hostport=llParseStringKeepNulls(authority,[":"],[]);
        if(llGetListLength(hostport)>2)
        {
            llOwnerSay("Unsupported authority.");
            return;
        }
        string host=llToLower(llList2String(hostport,0));
        if(host=="")
        {
            llOwnerSay("Empty hostname.");
            return;
        }
        if(llGetListLength(hostport)==2)
        {
            string port=llList2String(hostport,1);
            integer j;
            if(port=="" || llStringLength(port)>5)
            {
                llOwnerSay("Invalid port.");
                return;
            }
            for(j=0;j<llStringLength(port);++j) if(llSubStringIndex("0123456789",llGetSubString(port,j,j))==-1)
            {
                llOwnerSay("Port must be numeric.");
                return;
            }
            if((integer)port<1 || (integer)port>65535)
            {
                llOwnerSay("Port out of range.");
                return;
            }
        }
        llOwnerSay("Host: "+host);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Extract labels from JSON objects

Build a JSON string array from each product’s title field.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Rejects missing or non-string titles. Explicit escaping preserves values such as true, null, quotes, and surrounding whitespace as strings.

// Original Incoprea example. MIT.
string DOCUMENT="[{\"title\":\"Lamp\",\"size\":2},{\"title\":\"true\",\"size\":1}]";
string quoteJson(string value)
{
    string result="\"";
    string hex="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer n=llOrd(value,i);
        if(c=="\"" || c=="\\")result+="\\"+c;
        else if(n<32)result+="\\u00"+llGetSubString(hex,n/16,n/16)+llGetSubString(hex,n%16,n%16);
        else result+=c;
    }
    return result+"\"";
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>40)
        {
            llOwnerSay("Too many products.");
            return;
        }
        string result="[]";
        integer i;
        for(i=0;i<total;++i)
        {
            if(llJsonValueType(DOCUMENT,[i,"title"])!=JSON_STRING)
            {
                llOwnerSay("Invalid title at "+(string)i);
                return;
            }
            result=llJsonSetValue(result,[JSON_APPEND],quoteJson(llJsonGetValue(DOCUMENT,[i,"title"])));
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Extract quoted labels from prose

Collect double-quoted phrases while honoring escaped quotes and backslashes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Only reports quoted segments and rejects unsupported escapes or an unclosed quote. This is not a complete source-code parser.

// Original Incoprea example. MIT.
string TEXT="Use \"Garden Lamp\" with \"Blue Glass\".";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list labels=[];
        string label="";
        integer inside;
        integer escaped;
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            if(inside)
            {
                if(escaped)
                {
                    if(c!="\"" && c!="\\")
                    {
                        llOwnerSay("Unsupported escape inside label.");
                        return;
                    }
                    label+=c;
                    escaped=FALSE;
                }
                else if(c=="\\")escaped=TRUE;
                else if(c=="\"")
                {
                    labels += [label];
                    label="";
                    inside=FALSE;
                }
                else label+=c;
            }
            else if(c=="\"")inside=TRUE;
        }
        if(inside)
        {
            llOwnerSay("Unclosed quoted label.");
            return;
        }
        for(i=0;i<llGetListLength(labels);++i)llOwnerSay(llList2String(labels,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Fill missing optional fields

Build a record from defaults plus explicit supplied values, preserving intentional empty strings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DEFAULTS and INPUT as unique key/value pairs; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Only missing keys receive defaults. An empty supplied value is considered present and is not replaced.

// Original Incoprea example. MIT.
list DEFAULTS=["color","green","label","Untitled","mode","quiet"];
list INPUT=["label","","color","blue"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(DEFAULTS)%2 || llGetListLength(INPUT)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list result=INPUT;
        integer i;
        integer j;
        for(i=0;i<llGetListLength(DEFAULTS);i+=2)
        {
            string name=llList2String(DEFAULTS,i);
            integer found;
            for(j=0;j<llGetListLength(INPUT);j+=2)if(llList2String(INPUT,j)==name)found=TRUE;
            if(!found)result+=llList2List(DEFAULTS,i,i+1);
        }
        for(i=0;i<llGetListLength(result);i+=2)llOwnerSay(llList2String(result,i)+"=["+llList2String(result,i+1)+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Filter JSON product objects

Select product objects whose category field matches an exact configured value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Requires every input element to be an object with a string category. Selected objects retain their other fields; no external catalog is changed.

// Original Incoprea example. MIT.
string DOCUMENT="[{\"title\":\"Lamp\",\"category\":\"Light\"},{\"title\":\"Bench\",\"category\":\"Seat\"},{\"title\":\"Lantern\",\"category\":\"Light\"}]";
string CATEGORY="Light";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected an array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>40)
        {
            llOwnerSay("Maximum 40 objects.");
            return;
        }
        string result="[]";
        integer i;
        for(i=0;i<total;++i)
        {
            if(llJsonValueType(DOCUMENT,[i])!=JSON_OBJECT || llJsonValueType(DOCUMENT,[i,"category"])!=JSON_STRING)
            {
                llOwnerSay("Invalid product at "+(string)i);
                return;
            }
            if(llJsonGetValue(DOCUMENT,[i,"category"])==CATEGORY)result=llJsonSetValue(result,[JSON_APPEND],llJsonGetValue(DOCUMENT,[i]));
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a collection name prefix

Find the longest character prefix shared by a list of names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit NAMES and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Comparison is case-sensitive. This does not infer words or rename inventory. Empty input produces an empty result.

// Original Incoprea example. MIT.
list NAMES=["Garden Lamp","Garden Bench","Garden Gate"];
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetListLength(NAMES)==0)
        {
            llOwnerSay("No names.");
            return;
        }
        string prefix=llList2String(NAMES,0);
        integer i;
        for(i=1;i<llGetListLength(NAMES);++i)
        {
            string name=llList2String(NAMES,i);
            integer common=0;
            integer limit=llStringLength(prefix);
            if(llStringLength(name)<limit) limit=llStringLength(name);
            while(common<limit && llGetSubString(prefix,common,common)==llGetSubString(name,common,common)) ++common;
            if(common==0) prefix="";
            else prefix=llGetSubString(prefix,0,common-1);
        }
        llOwnerSay("Common prefix: ["+prefix+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Find a configured date’s weekday

Resolve an arbitrary accepted date to its weekday name.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Uses January 1, 2000 as the Saturday anchor; no simulator local clock is consulted.

// Original Incoprea example. MIT.
string DATE="2026-09-26";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        list names=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
        llOwnerSay(DATE+" is "+llList2String(names,weekday(dateSerial(date))));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a date’s day of year

Calculate the one-based ordinal day, accounting for leap years.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. January 1 is day one. This is a date calculation rather than elapsed seconds.

// Original Incoprea example. MIT.
string DATE="2028-03-01";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        integer y=llList2Integer(date,0);
        integer ordinal=dateSerial(date)-dateSerial([y,1,1])+1;
        llOwnerSay("Day of year: "+(string)ordinal+" of "+(string)(365+leap(y)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a fiscal quarter

Classify a date relative to a configurable fiscal-year starting month.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Reports the year in which the fiscal year begins, not an organization-specific financial label. No financial advice or reporting is implied.

// Original Incoprea example. MIT.
string DATE="2026-09-26";
integer START_MONTH=7;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(START_MONTH<1 || START_MONTH>12)
        {
            llOwnerSay("Start month must be 1-12.");
            return;
        }
        integer y=llList2Integer(date,0);
        integer m=llList2Integer(date,1);
        integer position=(m-START_MONTH+12)%12;
        integer fiscalYear=y;
        if(m<START_MONTH)--fiscalYear;
        llOwnerSay("Fiscal year beginning "+(string)fiscalYear+", quarter "+(string)(position/3+1));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a month’s last chosen weekday

Calculate the last occurrence of a weekday in a configured month.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Weekday numbers use Sunday=0 through Saturday=6. This is useful for recurring workshop planning, but creates no reminder.

// Original Incoprea example. MIT.
integer YEAR=2026;
integer MONTH=10;
integer WEEKDAY=5;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(YEAR<2000 || YEAR>2099 || MONTH<1 || MONTH>12 || WEEKDAY<0 || WEEKDAY>6)
        {
            llOwnerSay("Invalid parameters.");
            return;
        }
        integer last=monthDays(YEAR,MONTH);
        integer actual=weekday(dateSerial([YEAR,MONTH,last]));
        integer day=last-(actual-WEEKDAY+7)%7;
        llOwnerSay(dateText([YEAR,MONTH,day]));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a next calendar anniversary

Find this year’s or next year’s month/day occurrence relative to a reference date.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. February 29 is observed on February 28 in a non-leap year. Today counts as the next occurrence. That policy may differ from your event requirements.

// Original Incoprea example. MIT.
string DATE="2026-09-26";
integer MONTH=2;
integer DAY=29;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(MONTH<1 || MONTH>12 || DAY<1 || DAY>monthDays(2000,MONTH))
        {
            llOwnerSay("Invalid anniversary month/day.");
            return;
        }
        integer year=llList2Integer(date,0);
        integer day=DAY;
        if(day>monthDays(year,MONTH))day=monthDays(year,MONTH);
        list candidate=[year,MONTH,day];
        if(dateSerial(candidate)<dateSerial(date))
        {
            ++year;
            day=DAY;
            if(day>monthDays(year,MONTH))day=monthDays(year,MONTH);
            candidate=[year,MONTH,day];
        }
        if(year>2099)
        {
            llOwnerSay("Next occurrence outside supported range.");
            return;
        }
        llOwnerSay(dateText(candidate));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find a whole ASCII word

Find a keyword only when adjacent characters are not ASCII letters, digits, or underscore.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and WORD; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Case-insensitive ASCII word-boundary rule; punctuation separates words. This is not a general Unicode linguistic tokenizer.

// Original Incoprea example. MIT.
string TEXT="A lamp, lampshade, and LAMP.";
string WORD="lamp";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string text=llToLower(TEXT);
        string word=llToLower(WORD);
        if(word=="")
        {
            llOwnerSay("Set a word.");
            return;
        }
        integer found;
        integer i;
        for(i=0;i<=llStringLength(text)-llStringLength(word);++i)
        {
            if(llGetSubString(text,i,i+llStringLength(word)-1)==word)
            {
                integer left=TRUE;
                integer right=TRUE;
                if(i>0)left=llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789_",llGetSubString(text,i-1,i-1))==-1;
                integer after=i+llStringLength(word);
                if(after<llStringLength(text))right=llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789_",llGetSubString(text,after,after))==-1;
                if(left && right)
                {
                    ++found;
                    llOwnerSay("Whole-word match at "+(string)i);
                }
            }
        }
        llOwnerSay("Matches: "+(string)found);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Find an nth weekday of a month

Find a date such as the second Tuesday, or report that it does not exist.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Weekday numbers use Sunday=0 through Saturday=6. NTH must be 1-5; a fifth occurrence is not guaranteed.

// Original Incoprea example. MIT.
integer YEAR=2026;
integer MONTH=10;
integer WEEKDAY=2;
integer NTH=2;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(YEAR<2000 || YEAR>2099 || MONTH<1 || MONTH>12 || WEEKDAY<0 || WEEKDAY>6 || NTH<1 || NTH>5)
        {
            llOwnerSay("Invalid planning parameters.");
            return;
        }
        integer first=weekday(dateSerial([YEAR,MONTH,1]));
        integer day=1+(WEEKDAY-first+7)%7+7*(NTH-1);
        if(day>monthDays(YEAR,MONTH))llOwnerSay("That occurrence does not exist.");
        else llOwnerSay(dateText([YEAR,MONTH,day]));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find duplicate full records

Identify repeated two-field records while distinguishing shared keys with different values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS as pairs and touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Exact field comparison; does not silently deduplicate. Record width is fixed at two in this example.

// Original Incoprea example. MIT.
list ROWS=["Lamp","Green","Cup","Blue","Lamp","Green","Lamp","Red"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        integer i;
        integer j;
        integer matches;
        for(i=0;i<llGetListLength(ROWS);i+=2)for(j=0;j<i;j+=2)if(llList2String(ROWS,i)==llList2String(ROWS,j) && llList2String(ROWS,i+1)==llList2String(ROWS,j+1))
        {
            ++matches;
            llOwnerSay("Duplicate record positions "+(string)(j/2)+" and "+(string)(i/2));
        }
        llOwnerSay("Duplicate record pairs: "+(string)matches);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find invisible control characters

Report the index and numeric code of control characters in short pasted text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT, or leave it empty for a generated tab/newline sample. Touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Tabs and newlines are reported because they may be intentional but matter in single-line metadata. Unicode formatting characters above 127 are not covered by this basic audit.

// Original Incoprea example. MIT.
string TEXT="";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TEXT=="")TEXT="Garden"+llUnescapeURL("%09")+"Lamp\nBlue";
        integer findings;
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            integer code=llOrd(TEXT,i);
            if(code<32 || code==127)
            {
                ++findings;
                llOwnerSay("Control code "+(string)code+" at index "+(string)i);
            }
        }
        llOwnerSay("Control-character findings: "+(string)findings);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Find malformed URL escapes

Verify that every percent sign is followed by two hexadecimal digits.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Valid escape syntax does not guarantee valid UTF-8 or a safe URL. The script does not decode, fetch, or open the address.

// Original Incoprea example. MIT.
string TEXT="blue%20glass%2Fbrass";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        integer escapes;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            if(llGetSubString(TEXT,i,i)=="%")
            {
                if(i+2>=llStringLength(TEXT))
                {
                    llOwnerSay("Incomplete escape at "+(string)i);
                    return;
                }
                string pair=llToLower(llGetSubString(TEXT,i+1,i+2));
                if(llSubStringIndex("0123456789abcdef",llGetSubString(pair,0,0))==-1 || llSubStringIndex("0123456789abcdef",llGetSubString(pair,1,1))==-1)
                {
                    llOwnerSay("Invalid hex escape at "+(string)i);
                    return;
                }
                ++escapes;
                i+=2;
            }
        }
        llOwnerSay("Well-formed percent escapes: "+(string)escapes);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Find missing referenced assets

Validate that every record refers to a key in a declared asset registry.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Records use item/reference pairs; registry keys are exact strings. This validates names, not actual simulator inventory.

// Original Incoprea example. MIT.
list REGISTRY=["glass","wood","metal"];
list RECORDS=["Window","glass","Door","wood","Roof","slate"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORDS)%2)
        {
            llOwnerSay("Incomplete record.");
            return;
        }
        integer i;
        integer missing;
        for(i=0;i<llGetListLength(RECORDS);i+=2)
        {
            string target=llList2String(RECORDS,i+1);
            if(llListFindList(REGISTRY,[target])==-1)
            {
                ++missing;
                llOwnerSay(llList2String(RECORDS,i)+" references missing "+target);
            }
        }
        llOwnerSay("Missing references: "+(string)missing);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find missing template values

Collect brace-delimited placeholders and report which lack a supplied key.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEMPLATE and KEYS; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Literal single braces only; nested braces are rejected. This checks placeholder names and does not perform substitutions.

// Original Incoprea example. MIT.
string TEMPLATE="Welcome to {place}, {name}. Visit {place} at {time}.";
list KEYS=["place","name"];
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        string rest=TEMPLATE;
        list seen=[];
        integer rounds;
        while(rest!="" && rounds<50)
        {
            integer open=llSubStringIndex(rest,"{");
            if(open==-1)
            {
                rest="";
            }
            else
            {
                rest=llDeleteSubString(rest,0,open);
                integer close=llSubStringIndex(rest,"}");
                if(close==-1)
                {
                    llOwnerSay("Unclosed placeholder.");
                    return;
                }
                string token="";
                if(close>0) token=llGetSubString(rest,0,close-1);
                if(token=="" || llSubStringIndex(token,"{")!=-1)
                {
                    llOwnerSay("Empty or nested placeholder.");
                    return;
                }
                if(llListFindList(seen,[token])==-1)
                {
                    seen+=[token];
                    if(llListFindList(KEYS,[token])==-1) llOwnerSay("Missing value for: "+token);
                }
                rest=llDeleteSubString(rest,0,close);
            }
            ++rounds;
        }
        llOwnerSay("Distinct placeholders inspected: "+(string)llGetListLength(seen));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Find mixed leading tabs and spaces

Inspect each line’s indentation and flag a mixture of actual tabs and spaces.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Only checks leading indentation, not whitespace inside code or strings. Tabs are constructed with URL decoding in the sample.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string tab=llUnescapeURL("%09");
        string text="  first\n"+tab+"second\n "+tab+"mixed";
        list lines=llParseStringKeepNulls(text,["\n"],[]);
        integer i;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            integer spaces;
            integer tabs;
            integer j;
            integer scanning=TRUE;
            for(j=0;j<llStringLength(line) && scanning;++j)
            {
                string c=llGetSubString(line,j,j);
                if(c==" ")++spaces;
                else if(c==tab)++tabs;
                else scanning=FALSE;
            }
            if(spaces && tabs)llOwnerSay("Mixed indentation at line "+(string)(i+1));
        }
        llOwnerSay("Indentation scan complete.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Find shared collection tags

Find tags present in both lists and emit each shared tag only once.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit list A and list B, then touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Comparison is exact and case-sensitive. Keep examples small; repeated list searches are inefficient for very large data.

// Original Incoprea example. MIT.
list A = ["garden", "light", "water", "light"];
list B = ["water", "sound", "light"];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list shared = [];
        integer i;
        for (i = 0; i < llGetListLength(A); ++i)
        {
            string value = llList2String(A, i);
            if (llListFindList(B, [value]) != -1 && llListFindList(shared, [value]) == -1)
            shared += [value];
        }
        llOwnerSay("Shared tags: " + llDumpList2String(shared, ", "));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Find the first differing line

Compare two multiline text values and report the first changed or missing line.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Exact comparison includes whitespace. Does not compute a full diff or automatically choose which version is correct.

// Original Incoprea example. MIT.
string A="title=Lamp\ncolor=blue\nversion=1";
string B="title=Lamp\ncolor=green\nversion=1";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list left=llParseStringKeepNulls(A,["\n"],[]);
        list right=llParseStringKeepNulls(B,["\n"],[]);
        integer total=llGetListLength(left);
        if(llGetListLength(right)>total)total=llGetListLength(right);
        integer i;
        for(i=0;i<total;++i)
        {
            integer existsA=i<llGetListLength(left);
            integer existsB=i<llGetListLength(right);
            if(existsA!=existsB || llList2String(left,i)!=llList2String(right,i))
            {
                llOwnerSay("First difference at line "+(string)(i+1));
                if(existsA)llOwnerSay("A: "+llList2String(left,i));
                else llOwnerSay("A: [missing]");
                if(existsB)llOwnerSay("B: "+llList2String(right,i));
                else llOwnerSay("B: [missing]");
                return;
            }
        }
        llOwnerSay("Texts match line for line.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find the Monday starting a week

Return the Monday of the calendar week containing a date.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Uses Monday-first weeks. A result before year 2000 is rejected by the shared date formatter.

// Original Incoprea example. MIT.
string DATE="2026-09-26";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        integer serial=dateSerial(date);
        integer daysSinceMonday=(weekday(serial)+6)%7;
        llOwnerSay("Week begins: "+dateText(fromSerial(serial-daysSinceMonday)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find the next Monday-through-Friday date

Advance at least one day and skip Saturday and Sunday.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. No public holidays are considered. Friday advances to Monday; the current date is never returned.

// Original Incoprea example. MIT.
string DATE="2026-09-25";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        integer serial=dateSerial(date)+1;
        while(weekday(serial)==0 || weekday(serial)==6)++serial;
        llOwnerSay("Next weekday: "+dateText(fromSerial(serial)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find today at a fixed UTC offset

Shift the current UTC clock by a fixed minute offset and report the resulting calendar date.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. A fixed offset is not a named timezone and does not handle daylight-saving changes. Offset range is minus 12 through plus 14 hours.

// Original Incoprea example. MIT.
integer OFFSET_MINUTES=-300;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OFFSET_MINUTES < -720 || OFFSET_MINUTES>840)
        {
            llOwnerSay("Offset outside supported range.");
            return;
        }
        list today=parseDate(llGetDate());
        if(llGetListLength(today)!=3)
        {
            llOwnerSay("Current date unsupported.");
            return;
        }
        integer seconds=llGetUnixTime()%86400+OFFSET_MINUTES*60;
        integer change=0;
        if(seconds<0)change=-1;
        else if(seconds>=86400)change=1;
        llOwnerSay("Fixed-offset date: "+dateText(fromSerial(dateSerial(today)+change)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Find trailing spaces in text

Report line numbers that end with spaces without changing the content.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Checks ordinary spaces, not all Unicode whitespace. Blank lines containing spaces are also reported.

// Original Incoprea example. MIT.
string TEXT="Garden  \nLamp\n   ";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        integer i;
        integer findings;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            if(line!="" && llGetSubString(line,-1,-1)==" ")
            {
                ++findings;
                llOwnerSay("Trailing space at line "+(string)(i+1));
            }
        }
        llOwnerSay("Findings: "+(string)findings);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Format a byte count

Display a nonnegative byte count in bytes, KiB, or MiB.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit BYTES and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Binary units use 1024, not 1000. This formats a number and does not measure an asset, file download, or script allocation.

// Original Incoprea example. MIT.
integer BYTES=1536000;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(BYTES<0)
        {
            llOwnerSay("Bytes cannot be negative.");
            return;
        }
        if(BYTES<1024)llOwnerSay((string)BYTES+" bytes");
        else if(BYTES<1048576)llOwnerSay((string)((float)BYTES/1024.0)+" KiB");
        else llOwnerSay((string)((float)BYTES/1048576.0)+" MiB");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Format a simple title label

Uppercase the first ASCII letter after a space and lowercase subsequent letters.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

This is a mechanical label style, not correct title casing for every language, proper name, or acronym. Punctuation does not start a new word here.

// Original Incoprea example. MIT.
string TEXT="gARDEN lAMP COLLECTION";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string result="";
        integer start=TRUE;
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            if(c==" ")
            {
                result+=c;
                start=TRUE;
            }
            else
            {
                if(start)c=llToUpper(c);
                else c=llToLower(c);
                result+=c;
                start=FALSE;
            }
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Generate fixed-width sequence labels

Print bounded numbered labels with zero padding to a chosen width.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Never renames objects or inventory. Values wider than the width are preserved instead of truncated.

// Original Incoprea example. MIT.
string PREFIX="Panel-";
integer START=8;
integer COUNT=5;
integer WIDTH=3;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(START<0 || COUNT<1 || COUNT>20 || WIDTH<1 || WIDTH>8)
        {
            llOwnerSay("Invalid sequence settings.");
            return;
        }
        integer i;
        for(i=0;i<COUNT;++i)
        {
            string number=(string)(START+i);
            while(llStringLength(number)<WIDTH)number="0"+number;
            llOwnerSay(PREFIX+number);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Get a month’s date boundaries

Report first and last date and the number of days in the month containing a date.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. This describes a calendar month, not an interval measured in seconds. No timezone offset is applied.

// Original Incoprea example. MIT.
string DATE="2028-02-17";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        integer y=llList2Integer(date,0);
        integer m=llList2Integer(date,1);
        integer length=monthDays(y,m);
        llOwnerSay("First: "+dateText([y,m,1])+"; last: "+dateText([y,m,length])+"; days: "+(string)length);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Group catalog rows by category

Preserve first-seen category order while listing matching product rows.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS as category/name pairs and touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Rejects incomplete pairs. This is stable grouping rather than alphabetical sorting; it does not alter an external catalog.

// Original Incoprea example. MIT.
list ROWS=["Lighting","Lamp","Seating","Bench","Lighting","Lantern","Plants","Fern"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%2)
        {
            llOwnerSay("Incomplete record.");
            return;
        }
        list groups=[];
        integer i;
        integer j;
        for(i=0;i<llGetListLength(ROWS);i+=2)
        {
            string group=llList2String(ROWS,i);
            if(llListFindList(groups,[group])==-1)groups+=[group];
        }
        for(i=0;i<llGetListLength(groups);++i)
        {
            string group=llList2String(groups,i);
            llOwnerSay("Category: "+group);
            for(j=0;j<llGetListLength(ROWS);j+=2)if(llList2String(ROWS,j)==group)llOwnerSay("  "+llList2String(ROWS,j+1));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Index word positions in a note

Report all zero-based whitespace-token positions matching one normalized word.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Punctuation remains part of a token. This differs from character offsets and from a Unicode-aware word search.

// Original Incoprea example. MIT.
string TEXT="lamp beside a lamp near the garden";
string WORD="lamp";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list words=llParseString2List(llToLower(TEXT),[" ","\n",llUnescapeURL("%09")],[]);
        string needle=llToLower(WORD);
        if(needle=="")
        {
            llOwnerSay("Set a word.");
            return;
        }
        list positions=[];
        integer i;
        for(i=0;i<llGetListLength(words);++i)if(llList2String(words,i)==needle)positions += [i];
        llOwnerSay("Token positions: "+llList2CSV(positions));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Inspect a JSON document type

Distinguish objects, arrays, strings, numbers, booleans, null, and invalid JSON.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Reports only the top-level type; a valid JSON shape says nothing about the application schema.

// Original Incoprea example. MIT.
string DOCUMENT="{\"title\":\"Lamp\",\"size\":2}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string type=llJsonValueType(DOCUMENT,[]);
        string label="invalid";
        if(type==JSON_OBJECT)label="object";
        else if(type==JSON_ARRAY)label="array";
        else if(type==JSON_STRING)label="string";
        else if(type==JSON_NUMBER)label="number";
        else if(type==JSON_TRUE || type==JSON_FALSE)label="boolean";
        else if(type==JSON_NULL)label="null";
        llOwnerSay("Top-level JSON type: "+label);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Inspect text as hexadecimal bytes

Encode short printable ASCII text to hexadecimal and decode it back.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Rejects non-ASCII text instead of pretending each character is one UTF-8 byte. Useful for protocol inspection, not encryption.

// Original Incoprea example. MIT.
string TEXT="Lamp #12";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string hex="0123456789abcdef";
        string encoded="";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            integer value=llOrd(TEXT,i);
            if(value<32 || value>126)
            {
                llOwnerSay("Printable ASCII only.");
                return;
            }
            encoded+=llGetSubString(hex,value/16,value/16)+llGetSubString(hex,value%16,value%16);
        }
        string restored="";
        for(i=0;i<llStringLength(encoded);i+=2)
        {
            integer high=llSubStringIndex(hex,llGetSubString(encoded,i,i));
            integer low=llSubStringIndex(hex,llGetSubString(encoded,i+1,i+1));
            restored+=llChar(high*16+low);
        }
        llOwnerSay("HEX: "+encoded);
        llOwnerSay("Restored: "+restored);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Join explicitly continued config lines

Join lines ending in a single backslash into one logical line.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

A trailing backslash always means continuation in this simple format; escaping a literal terminal backslash is unsupported. Reports an unfinished final continuation.

// Original Incoprea example. MIT.
string TEXT="";
// Empty uses a demo with one actual backslash plus a newline.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TEXT=="")TEXT="label=A long "+llChar(92)+"\nlabel across lines\nmode=quiet";
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        string pending="";
        integer i;
        integer continued;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            continued=line!="" && llGetSubString(line,-1,-1)=="\\";
            if(continued)line=llDeleteSubString(line,-1,-1);
            pending+=line;
            if(!continued)
            {
                llOwnerSay(pending);
                pending="";
            }
        }
        if(continued)llOwnerSay("Unfinished continued line: "+pending);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Join product rows to a lookup table

Combine each product/material key with its matching material description.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit PRODUCTS and MATERIALS as alternating pairs; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

First matching lookup key wins. Missing matches are reported explicitly. This is a small local table join, not a database or inventory operation.

// Original Incoprea example. MIT.
list PRODUCTS=["Lamp","brass","Bench","wood","Vase","ceramic"];
list MATERIALS=["wood","warm grain","brass","polished metal"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(PRODUCTS)%2 || llGetListLength(MATERIALS)%2)
        {
            llOwnerSay("Tables need complete pairs.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<llGetListLength(PRODUCTS);i+=2)
        {
            string product=llList2String(PRODUCTS,i);
            string material=llList2String(PRODUCTS,i+1);
            string description="[unmatched]";
            integer found;
            for(j=0;j<llGetListLength(MATERIALS);j+=2)if(!found && llList2String(MATERIALS,j)==material)
            {
                description=llList2String(MATERIALS,j+1);
                found=TRUE;
            }
            llOwnerSay(product+" | "+material+" | "+description);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Data & lists · Intermediate

List five upcoming weekday occurrences

Find the next five dates matching a weekday, including today when it matches.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. No holidays or cancellations are considered. Creates no automation or simulator timer.

// Original Incoprea example. MIT.
string DATE="2026-09-26";
integer WEEKDAY=2;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(WEEKDAY<0 || WEEKDAY>6)
        {
            llOwnerSay("Weekday must be 0-6.");
            return;
        }
        integer serial=dateSerial(date);
        serial+=(WEEKDAY-weekday(serial)+7)%7;
        integer i;
        for(i=0;i<5;++i)llOwnerSay(dateText(fromSerial(serial+i*7)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

List JSON object field names and types

Report each top-level field and its JSON type without exposing the stored value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Useful for inspecting schema shape when values should stay out of a support note. Type names are rendered as plain labels.

// Original Incoprea example. MIT.
string DOCUMENT="{\"title\":\"Lamp\",\"tags\":[\"garden\"],\"enabled\":true,\"stock\":4}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_OBJECT)
        {
            llOwnerSay("Expected an object.");
            return;
        }
        list pairs=llJson2List(DOCUMENT);
        integer i;
        for(i=0;i<llGetListLength(pairs);i+=2)
        {
            string name=llList2String(pairs,i);
            string kind=llJsonValueType(DOCUMENT,[name]);
            string label="other";
            if(kind==JSON_STRING)label="string";
            else if(kind==JSON_NUMBER)label="number";
            else if(kind==JSON_ARRAY)label="array";
            else if(kind==JSON_OBJECT)label="object";
            else if(kind==JSON_NULL)label="null";
            else if(kind==JSON_TRUE || kind==JSON_FALSE)label="boolean";
            llOwnerSay(name+": "+label);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Locate every literal placeholder occurrence

Report line and character positions of a configured placeholder token.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Overlapping matches are permitted by advancing one character after each match. Limits output to fifty occurrences and does not replace text.

// Original Incoprea example. MIT.
string TEXT="Hello {name}.\nWelcome, {name}, to {place}.";
string TOKEN="{name}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TOKEN=="")
        {
            llOwnerSay("Set a token.");
            return;
        }
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        integer i;
        integer matches;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            integer offset;
            while(offset<llStringLength(line) && matches<50)
            {
                string tail=llGetSubString(line,offset,-1);
                integer at=llSubStringIndex(tail,TOKEN);
                if(at==-1)offset=llStringLength(line);
                else
                {
                    ++matches;
                    llOwnerSay("Line "+(string)(i+1)+", character "+(string)(offset+at)+": "+TOKEN);
                    offset+=at+1;
                }
            }
        }
        llOwnerSay("Occurrences shown: "+(string)matches);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Look up a value in a tiny table

Search only the key positions in an alternating key/value list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TABLE and QUERY, then touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Comparison is exact and case-sensitive. Searching only even positions avoids accidentally matching a value as though it were a key. First matching key wins.

// Original Incoprea example. MIT.
list TABLE = ["lantern", "warm", "fountain", "cool", "garden", "green"];
string QUERY = "garden";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetListLength(TABLE) % 2 != 0)
        {
            llOwnerSay("Table must contain complete key/value pairs.");
            return;
        }
        integer i;
        for (i = 0; i < llGetListLength(TABLE); i += 2)
        {
            if (llList2String(TABLE, i) == QUERY)
            {
                llOwnerSay(QUERY + " = " + llList2String(TABLE, i + 1));
                return;
            }
        }
        llOwnerSay("No matching key: " + QUERY);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Make a simple ASCII slug

Lowercase text, keep ASCII letters/digits, and collapse other runs into hyphens.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TITLE and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Does not transliterate accented characters; they become separators. A slug is not guaranteed unique and should not be used as an authorization token.

// Original Incoprea example. MIT.
string TITLE="  Garden & Glass: A Little Workshop!  ";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        string input=llToLower(TITLE);
        string result="";
        integer pendingDash;
        integer i;
        for(i=0;i<llStringLength(input);++i)
        {
            string c=llGetSubString(input,i,i);
            if(llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789",c)!=-1)
            {
                if(pendingDash && result!="") result+="-";
                result+=c;
                pendingDash=FALSE;
            }
            else pendingDash=TRUE;
        }
        llOwnerSay("Slug: "+result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Materialize a record in schema order

Produce ordered values from a unique-key record and a schema, retaining explicit presence flags.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Presence flags distinguish missing fields from fields deliberately set to empty text. Unknown record keys are rejected for a strict import preview.

// Original Incoprea example. MIT.
list SCHEMA=["name","color","license"];
list RECORD=["color","","name","Lamp"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Malformed record.");
            return;
        }
        list keys;
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string k=llList2String(RECORD,i);
            if(llListFindList(keys,[k])!=-1 || llListFindList(SCHEMA,[k])==-1)
            {
                llOwnerSay("Duplicate or unknown field: "+k);
                return;
            }
            keys += [k];
        }
        list values;
        list present;
        for(i=0;i<llGetListLength(SCHEMA);++i)
        {
            integer at=llListFindList(keys,[llList2String(SCHEMA,i)]);
            if(at==-1)
            {
                values += [""];
                present += [FALSE];
            }
            else
            {
                values += [llList2String(RECORD,at*2+1)];
                present += [TRUE];
            }
        }
        llOwnerSay("Values: "+llList2CSV(values));
        llOwnerSay("Present flags: "+llList2CSV(present));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Measure a waypoint route

Sum the straight-line lengths between consecutive vector waypoints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit POINTS using coordinates from one consistent coordinate system; touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

It does not move an object or find a walkable route. It ignores obstacles and does not automatically close a loop.

// Original Incoprea example. MIT.
list POINTS = [<0.0, 0.0, 0.0>, <3.0, 0.0, 0.0>, <3.0, 4.0, 0.0>];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetListLength(POINTS);
        if (total < 2)
        {
            llOwnerSay("Add at least two waypoints.");
            return;
        }
        float distance = 0.0;
        integer i;
        for (i = 1; i < total; ++i)
        distance += llVecDist(llList2Vector(POINTS, i - 1), llList2Vector(POINTS, i));
        llOwnerSay((string)(total - 1) + " segments, total length " + (string)distance + " meters.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Migrate a version-one color field

Preview a small schema migration from colour in version one to color in version two.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Only migrates the declared version and refuses an existing destination field. Retains unrelated fields; it does not persist or apply the configuration.

// Original Incoprea example. MIT.
string DOCUMENT="{\"version\":1,\"colour\":\"green\",\"title\":\"Lamp\"}";
string quoteJson(string value)
{
    string result="\"";
    string hex="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer n=llOrd(value,i);
        if(c=="\"" || c=="\\")result+="\\"+c;
        else if(n<32)result+="\\u00"+llGetSubString(hex,n/16,n/16)+llGetSubString(hex,n%16,n%16);
        else result+=c;
    }
    return result+"\"";
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,["version"])!=JSON_NUMBER || llJsonGetValue(DOCUMENT,["version"])!="1")
        {
            llOwnerSay("Expected version 1.");
            return;
        }
        if(llJsonValueType(DOCUMENT,["colour"])!=JSON_STRING || llJsonValueType(DOCUMENT,["color"])!=JSON_INVALID)
        {
            llOwnerSay("Invalid source or destination field collision.");
            return;
        }
        string result=llJsonSetValue(DOCUMENT,["color"],quoteJson(llJsonGetValue(DOCUMENT,["colour"])));
        result=llJsonSetValue(result,["colour"],JSON_DELETE);
        result=llJsonSetValue(result,["version"],"2");
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Normalize a compact UUID spelling

Validate 32 hexadecimal characters and insert the canonical hyphens.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

This reformats text only and does not verify that the identifier exists. It rejects already hyphenated input rather than stripping arbitrary punctuation.

// Original Incoprea example. MIT.
string INPUT="12345678123412341234123456789abc";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string value=llToLower(INPUT);
        if(llStringLength(value)!=32)
        {
            llOwnerSay("Expected 32 hex characters without hyphens.");
            return;
        }
        integer i;
        string result="";
        for(i=0;i<32;++i)
        {
            string c=llGetSubString(value,i,i);
            if(llSubStringIndex("0123456789abcdef",c)==-1)
            {
                llOwnerSay("Invalid hex character.");
                return;
            }
            if(i==8 || i==12 || i==16 || i==20)result+="-";
            result+=c;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Normalize pasted line endings

Convert CRLF and bare CR line endings to LF before further parsing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT, or leave it empty to generate a mixed-line-ending demonstration. Touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Does not trim content or collapse blank lines. Uses URL decoding to construct a literal carriage return portably.

// Original Incoprea example. MIT.
string TEXT="";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(TEXT=="") TEXT="One"+llUnescapeURL("%0D%0A")+"Two"+llUnescapeURL("%0D")+"Three\n\nFive";
        string result="";
        integer i;
        for(i=0;i<llStringLength(TEXT);++i)
        {
            string c=llGetSubString(TEXT,i,i);
            if(c==llUnescapeURL("%0D"))
            {
                result+="\n";
                if(i+1<llStringLength(TEXT) && llGetSubString(TEXT,i+1,i+1)=="\n") ++i;
            }
            else result+=c;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Beginner

Page through a local list

Show a list three entries at a time, wrapping back to the first page.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ITEMS; touch as owner for each page.

Stop / restore: Remove or disable the script. It does not change the build.

No listeners or dialogs are needed. Reset returns to the first page; an empty list is handled explicitly.

// Original Incoprea example. MIT.
list ITEMS = ["Lamp", "Book", "Cup", "Shell", "Plant", "Clock", "Key"];
integer PAGE_SIZE = 3;
integer cursor;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetListLength(ITEMS);
        if (total == 0)
        {
            llOwnerSay("The list is empty.");
            return;
        }
        if (cursor >= total) cursor = 0;
        integer last = cursor + PAGE_SIZE - 1;
        if (last >= total) last = total - 1;
        llOwnerSay("Entries " + (string)(cursor + 1) + "-" + (string)(last + 1) + " of " + (string)total);
        llOwnerSay(llDumpList2String(llList2List(ITEMS, cursor, last), " / "));
        cursor = last + 1;
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Parse a quoted CSV record

Parse one comma-separated record with quoted fields, escaped quotes, and empty cells.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROW to a single record and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

No multiline record support. Rejects quotes in unquoted fields and text after closing quotes. This is intentionally stricter than tolerant spreadsheet importers.

// Original Incoprea example. MIT.
string ROW="one,\"two, three\",,four";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list fields=[];
        string field="";
        integer quoted;
        integer closed;
        integer i;
        for(i=0;i<llStringLength(ROW);++i)
        {
            string c=llGetSubString(ROW,i,i);
            if(quoted)
            {
                if(c=="\"")
                {
                    if(i+1<llStringLength(ROW) && llGetSubString(ROW,i+1,i+1)=="\"")
                    {
                        field+="\"";
                        ++i;
                    }
                    else
                    {
                        quoted=FALSE;
                        closed=TRUE;
                    }
                }
                else field+=c;
            }
            else if(c==",")
            {
                fields+=[field];
                field="";
                closed=FALSE;
            }
            else if(c=="\"")
            {
                if(field!="" || closed)
                {
                    llOwnerSay("Unexpected quote.");
                    return;
                }
                quoted=TRUE;
            }
            else
            {
                if(closed)
                {
                    llOwnerSay("Unexpected text after closing quote.");
                    return;
                }
                field+=c;
            }
        }
        if(quoted)
        {
            llOwnerSay("Unclosed quoted field.");
            return;
        }
        fields+=[field];
        for(i=0;i<llGetListLength(fields);++i) llOwnerSay((string)i+": ["+llList2String(fields,i)+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Parse a record with escaped pipes

Split a short record on pipes while allowing backslash-pipe and escaped backslash inside fields.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Keeps empty fields and rejects unknown or trailing escapes. This is a declared custom format, not standard CSV.

// Original Incoprea example. MIT.
string INPUT="Garden|blue\\|green||glass";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list fields=[];
        string field="";
        integer escaped;
        integer i;
        for(i=0;i<llStringLength(INPUT);++i)
        {
            string c=llGetSubString(INPUT,i,i);
            if(escaped)
            {
                if(c!="|" && c!="\\")
                {
                    llOwnerSay("Unsupported escape.");
                    return;
                }
                field+=c;
                escaped=FALSE;
            }
            else if(c=="\\")escaped=TRUE;
            else if(c=="|")
            {
                fields += [field];
                field="";
            }
            else field+=c;
        }
        if(escaped)
        {
            llOwnerSay("Trailing escape.");
            return;
        }
        fields += [field];
        for(i=0;i<llGetListLength(fields);++i)llOwnerSay((string)i+": ["+llList2String(fields,i)+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Parse a three-number coordinate

Parse three comma-separated decimal components into a bounded vector.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT without angle brackets; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Each component must be a complete simple decimal and remain within one million in magnitude. Coordinates are reported, never applied to a build.

// Original Incoprea example. MIT.
string INPUT="12.5, -4, 30";
integer decimalOK(string value)
{
    integer length=llStringLength(value);
    if(length<1 || length>16)return FALSE;
    integer start=0;
    string first=llGetSubString(value,0,0);
    if(first=="-" || first=="+")start=1;
    integer digits;
    integer dots;
    integer i;
    for(i=start;i<length;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list parts=llParseStringKeepNulls(INPUT,[","],[]);
        if(llGetListLength(parts)!=3)
        {
            llOwnerSay("Provide exactly three components.");
            return;
        }
        list values=[];
        integer i;
        for(i=0;i<3;++i)
        {
            string p=llStringTrim(llList2String(parts,i),STRING_TRIM);
            if(!decimalOK(p) || llFabs((float)p)>1000000)
            {
                llOwnerSay("Invalid component "+(string)i);
                return;
            }
            values += [(float)p];
        }
        vector point=<llList2Float(values,0),llList2Float(values,1),llList2Float(values,2)>;
        llOwnerSay("Coordinate: "+(string)point);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Parse an hours:minutes:seconds duration

Convert a strictly formatted duration into total seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT such as 12:30:05 and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Hours are limited to 999; minutes and seconds to 0-59. This is elapsed time, not a timezone-aware clock or timestamp.

// Original Incoprea example. MIT.
string INPUT="12:30:05";
integer digitsOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list p=llParseStringKeepNulls(INPUT,[":"],[]);
        if(llGetListLength(p)!=3)
        {
            llOwnerSay("Use hours:minutes:seconds.");
            return;
        }
        integer i;
        for(i=0;i<3;++i)if(!digitsOK(llList2String(p,i)))
        {
            llOwnerSay("Digits only.");
            return;
        }
        integer hours=llList2Integer(p,0);
        integer minutes=llList2Integer(p,1);
        integer seconds=llList2Integer(p,2);
        if(hours>999 || minutes>59 || seconds>59)
        {
            llOwnerSay("Duration component out of range.");
            return;
        }
        llOwnerSay("Total seconds: "+(string)(hours*3600+minutes*60+seconds));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Data & lists · Intermediate

Parse explicit true and false words

Accept a small declared set of boolean spellings and reject ambiguous text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Recognizes true/yes/on/1 and false/no/off/0 after trimming and lowercasing. Empty text is rejected instead of treated as false.

// Original Incoprea example. MIT.
string INPUT=" Yes ";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string token=llToLower(llStringTrim(INPUT,STRING_TRIM));
        if(llListFindList(["true","yes","on","1"],[token])!=-1)llOwnerSay("Boolean TRUE");
        else if(llListFindList(["false","no","off","0"],[token])!=-1)llOwnerSay("Boolean FALSE");
        else llOwnerSay("Unrecognized boolean token.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Patch one catalog row by unique ID

Update one value only when its ID matches exactly one record.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS, TARGET, and VALUE; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Rejects missing or duplicate targets. Changes only a local copy, demonstrating safe update logic before adding persistence.

// Original Incoprea example. MIT.
list ROWS=["lamp-1","blue","bench-1","wood"];
string TARGET="lamp-1";
string VALUE="green";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%2)
        {
            llOwnerSay("Incomplete record.");
            return;
        }
        integer index=-1;
        integer matches;
        integer i;
        for(i=0;i<llGetListLength(ROWS);i+=2)if(llList2String(ROWS,i)==TARGET)
        {
            index=i;
            ++matches;
        }
        if(matches!=1)
        {
            llOwnerSay("Expected one target; found "+(string)matches);
            return;
        }
        list result=llListReplaceList(ROWS,[VALUE],index+1,index+1);
        llOwnerSay(llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Pivot sparse properties into a compact table

Convert entity/property/value triples into rows sharing a discovered property header.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Duplicate entity/property pairs are rejected rather than silently overwriting. Empty text marks absent properties; values containing pipe are rejected for readable output.

// Original Incoprea example. MIT.
list CELLS=["Lamp","color","green","Lamp","size","small","Bench","size","large"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(CELLS)%3 || llGetListLength(CELLS)>60)
        {
            llOwnerSay("Use at most 20 triples.");
            return;
        }
        list entities;
        list properties;
        list pairs;
        integer i;
        for(i=0;i<llGetListLength(CELLS);i+=3)
        {
            string a=llList2String(CELLS,i);
            string b=llList2String(CELLS,i+1);
            string c=llList2String(CELLS,i+2);
            if(a==""||b==""||llSubStringIndex(a+b+c,"|")!=-1)
            {
                llOwnerSay("Empty key or pipe in data.");
                return;
            }
            string pair=a+"|"+b;
            if(llListFindList(pairs,[pair])!=-1)
            {
                llOwnerSay("Duplicate cell: "+pair);
                return;
            }
            pairs += [pair];
            if(llListFindList(entities,[a])==-1)entities += [a];
            if(llListFindList(properties,[b])==-1)properties += [b];
        }
        llOwnerSay("entity|"+llDumpList2String(properties,"|"));
        for(i=0;i<llGetListLength(entities);++i)
        {
            string entity=llList2String(entities,i);
            list row=[entity];
            integer j;
            for(j=0;j<llGetListLength(properties);++j)
            {
                integer at=llListFindList(pairs,[entity+"|"+llList2String(properties,j)]);
                string value="";
                if(at!=-1)value=llList2String(CELLS,at*3+2);
                row += [value];
            }
            llOwnerSay(llDumpList2String(row,"|"));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Plan field-key migrations

Rename declared record keys in memory while rejecting collisions in the resulting schema.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD and RENAMES as pairs; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

The plan is applied only to a local copy. Migration mappings use exact case-sensitive names and first matching mapping wins.

// Original Incoprea example. MIT.
list RECORD=["colour","green","display_name","Lamp"];
list RENAMES=["colour","color","display_name","title"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2 || llGetListLength(RENAMES)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list result=[];
        list used=[];
        integer i;
        integer j;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string name=llList2String(RECORD,i);
            integer matched;
            for(j=0;j<llGetListLength(RENAMES);j+=2)if(!matched && name==llList2String(RENAMES,j))
            {
                name=llList2String(RENAMES,j+1);
                matched=TRUE;
            }
            if(name=="" || llListFindList(used,[name])!=-1)
            {
                llOwnerSay("Migration would create an empty or duplicate field: "+name);
                return;
            }
            used+=[name];
            result += [name,llList2String(RECORD,i+1)];
        }
        llOwnerSay(llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Plan pages without splitting records

Calculate record ranges for a table and a chosen page capacity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORDS and PER_PAGE; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Read-only pagination planning. Uses a maximum of 1000 records and 100 rows per page; no UI or network pagination occurs.

// Original Incoprea example. MIT.
integer RECORDS=23;
integer PER_PAGE=8;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RECORDS<0 || RECORDS>1000 || PER_PAGE<1 || PER_PAGE>100)
        {
            llOwnerSay("Invalid record count or page capacity.");
            return;
        }
        integer first;
        integer page;
        for(first=0;first<RECORDS;first+=PER_PAGE)
        {
            integer last=first+PER_PAGE-1;
            if(last>=RECORDS)last=RECORDS-1;
            ++page;
            llOwnerSay("Page "+(string)page+": records "+(string)(first+1)+"-"+(string)(last+1));
        }
        llOwnerSay("Pages: "+(string)page);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Prepare untrusted labels for spreadsheet text cells

Prefix an apostrophe when a label begins with a formula-triggering character after whitespace.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

A conservative text-export aid, not a complete spreadsheet security guarantee. The receiving application and import settings determine how the prefix is interpreted.

// Original Incoprea example. MIT.
string TEXT=" =SUM(A1:A3)";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string trimmed=llStringTrim(TEXT,STRING_TRIM_HEAD);
        if(trimmed!="" && llSubStringIndex("=+-@",llGetSubString(trimmed,0,0))!=-1)llOwnerSay("'"+TEXT);
        else llOwnerSay(TEXT);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Preserve empty table fields

Demonstrate why keeping empty fields matters when parsing a simple delimited row.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Edit ROW to your own pipe-separated data.

Stop / restore: Remove or disable the script. It does not change the build.

This is simple delimiter splitting, not a quoted CSV parser. An empty column stays in its original position.

// Original Incoprea example. MIT.
string ROW = "Chair||Blue|12";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list fields = llParseStringKeepNulls(ROW, ["|"], []);
        integer i;
        for (i = 0; i < llGetListLength(fields); ++i)
        llOwnerSay("Column " + (string)i + ": [" + llList2String(fields, i) + "]");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Preview a bounded JSON array slice

Copy an inclusive index range into a new JSON array while retaining element types.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Requires valid in-range indices and at most 40 elements. Uses typed value encoding so strings remain strings rather than being reinterpreted as JSON.

// Original Incoprea example. MIT.
string DOCUMENT="[\"Lamp\",\"true\",3,{\"color\":\"green\"}]";
integer FIRST=1;
integer LAST=3;
string quoteJson(string value)
{
    string result="\"";
    string hex="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer n=llOrd(value,i);
        if(c=="\"" || c=="\\")result+="\\"+c;
        else if(n<32)result+="\\u00"+llGetSubString(hex,n/16,n/16)+llGetSubString(hex,n%16,n%16);
        else result+=c;
    }
    return result+"\"";
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(FIRST<0 || LAST<FIRST || LAST>=total || LAST-FIRST>=40)
        {
            llOwnerSay("Invalid or excessive range.");
            return;
        }
        string result="[]";
        integer i;
        for(i=FIRST;i<=LAST;++i)
        {
            string kind=llJsonValueType(DOCUMENT,[i]);
            string value=llJsonGetValue(DOCUMENT,[i]);
            if(kind==JSON_STRING)value=quoteJson(value);
            result=llJsonSetValue(result,[JSON_APPEND],value);
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview a bounded JSON numeric update

Update an existing numeric setting only when its type and proposed range are valid.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Changes a preview string only. Requires the existing field already be numeric, so a schema mismatch is not silently repaired.

// Original Incoprea example. MIT.
string DOCUMENT="{\"intensity\":0.2,\"title\":\"Lamp\"}";
string FIELD="intensity";
float VALUE=0.6;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[FIELD])!=JSON_NUMBER)
        {
            llOwnerSay("Existing field is not numeric.");
            return;
        }
        if(VALUE<0 || VALUE>1)
        {
            llOwnerSay("New value must be 0-1.");
            return;
        }
        llOwnerSay(llJsonSetValue(DOCUMENT,[FIELD],(string)VALUE));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview an update with an expected revision

Refuse a draft record update if the current revision differs from the editor’s expected revision.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

A teaching pattern for optimistic concurrency. It is not an atomic server-side compare-and-swap or a persistence API.

// Original Incoprea example. MIT.
integer CURRENT_REVISION=4;
integer EXPECTED_REVISION=3;
string CURRENT_VALUE="green";
string PROPOSED_VALUE="blue";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(CURRENT_REVISION<0 || CURRENT_REVISION>=2000000000)
        {
            llOwnerSay("Revision out of supported range.");
            return;
        }
        if(CURRENT_REVISION!=EXPECTED_REVISION)
        {
            llOwnerSay("Conflict: expected "+(string)EXPECTED_REVISION+", current "+(string)CURRENT_REVISION+" value="+CURRENT_VALUE);
            return;
        }
        llOwnerSay("Proposed revision="+(string)(CURRENT_REVISION+1)+" value="+PROPOSED_VALUE);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview deleting a JSON object field

Remove one existing field from a JSON object using JSON_DELETE.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

The original source string is unchanged. Missing fields produce a report instead of silently treating deletion as success.

// Original Incoprea example. MIT.
string DOCUMENT="{\"title\":\"Lamp\",\"debug\":\"temporary\",\"color\":\"green\"}";
string FIELD="debug";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_OBJECT)
        {
            llOwnerSay("Expected an object.");
            return;
        }
        if(llJsonValueType(DOCUMENT,[FIELD])==JSON_INVALID)
        {
            llOwnerSay("Field does not exist.");
            return;
        }
        string result=llJsonSetValue(DOCUMENT,[FIELD],JSON_DELETE);
        if(result==JSON_INVALID)
        {
            llOwnerSay("Deletion preview failed.");
            return;
        }
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Preview evenly spaced points

Print five evenly spaced positions between two endpoints, including both ends.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit START and END. Touch as owner for a read-only preview.

Stop / restore: Remove or disable the script. It does not change the build.

This uses linear interpolation and creates no prims. The same calculation can later supply a carefully tested movement or layout tool.

// Original Incoprea example. MIT.
vector START = <0.0, 0.0, 0.0>;
vector END = <8.0, 4.0, 2.0>;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer i;
        for (i = 0; i <= 4; ++i)
        {
            float t = (float)i / 4.0;
            vector point = START + (END - START) * t;
            llOwnerSay((string)i + ": " + (string)point);
        }
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Preview migrating a key namespace

Replace only an exact leading namespace in a list of identifiers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Rejects collisions in the proposed complete key set before printing results. This never performs substring replacement inside unrelated keys.

// Original Incoprea example. MIT.
list KEYS=["old:lamp","old:bench","other:door"];
string OLD="old:";
string NEW="garden:";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OLD=="" || NEW=="")
        {
            llOwnerSay("Namespaces must be nonempty.");
            return;
        }
        list result;
        integer i;
        for(i=0;i<llGetListLength(KEYS);++i)
        {
            string value=llList2String(KEYS,i);
            if(llSubStringIndex(value,OLD)==0)
            {
                string tail="";
                if(llStringLength(value)>llStringLength(OLD))tail=llGetSubString(value,llStringLength(OLD),-1);
                value=NEW+tail;
            }
            if(llListFindList(result,[value])!=-1)
            {
                llOwnerSay("Migration collision: "+value);
                return;
            }
            result += [value];
        }
        llOwnerSay("Proposed keys: "+llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview removing one JSON array item

Remove a chosen existing array index and report the resulting compacted array.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Later indices shift down. Does not treat an out-of-range deletion as successful and does not modify the original source.

// Original Incoprea example. MIT.
string DOCUMENT="[\"Lamp\",\"Cup\",\"Bench\"]";
integer INDEX=1;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(INDEX<0 || INDEX>=total)
        {
            llOwnerSay("Index out of range.");
            return;
        }
        llOwnerSay(llJsonSetValue(DOCUMENT,[INDEX],JSON_DELETE));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview removing selected record fields

Remove exact declared keys from a local key/value record and report the result.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD and REMOVE_KEYS; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

No saved settings are altered. The original record remains available in source; only whole pairs are removed.

// Original Incoprea example. MIT.
list RECORD=["title","Lamp","debug","true","color","green","temporary","yes"];
list REMOVE_KEYS=["debug","temporary"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list result=[];
        integer i;
        integer removed;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            if(llListFindList(REMOVE_KEYS,[llList2String(RECORD,i)])==-1)result+=llList2List(RECORD,i,i+1);
            else ++removed;
        }
        llOwnerSay("Removed fields in preview: "+(string)removed);
        llOwnerSay(llList2CSV(result));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Preview renaming a referenced identifier

Rename one registry key and all exact references together in a preview.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Rejects a destination key that already exists. The source key must occur exactly once; output is a proposed migration, never applied automatically.

// Original Incoprea example. MIT.
list KEYS=["glass","wood"];
list REFERENCES=["window","glass","door","wood","bottle","glass"];
string OLD="glass";
string NEW="clear-glass";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OLD=="" || NEW=="" || llGetListLength(REFERENCES)%2 || llListFindList(KEYS,[NEW])!=-1)
        {
            llOwnerSay("Invalid names or references.");
            return;
        }
        integer count;
        integer at=-1;
        integer i;
        for(i=0;i<llGetListLength(KEYS);++i)if(llList2String(KEYS,i)==OLD)
        {
            ++count;
            at=i;
        }
        if(count!=1)
        {
            llOwnerSay("Source key must occur once.");
            return;
        }
        list keys=llListReplaceList(KEYS,[NEW],at,at);
        list refs=REFERENCES;
        for(i=1;i<llGetListLength(refs);i+=2)if(llList2String(refs,i)==OLD)refs=llListReplaceList(refs,[NEW],i,i);
        llOwnerSay("Proposed keys: "+llList2CSV(keys));
        llOwnerSay("Proposed references: "+llList2CSV(refs));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Print a small monthly calendar

Print a Sunday-first calendar grid for a selected month.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Character spacing may not align perfectly in proportional-font chat. This is a date overview and not an event calendar.

// Original Incoprea example. MIT.
integer YEAR=2026;
integer MONTH=10;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
integer weekday(integer serial)
{
    return (serial+6)%7;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(YEAR<2000 || YEAR>2099 || MONTH<1 || MONTH>12)
        {
            llOwnerSay("Invalid month.");
            return;
        }
        llOwnerSay("Su Mo Tu We Th Fr Sa");
        integer column=weekday(dateSerial([YEAR,MONTH,1]));
        string line="";
        integer i;
        for(i=0;i<column;++i)line+="   ";
        integer day;
        for(day=1;day<=monthDays(YEAR,MONTH);++day)
        {
            if(day<10)line+=" ";
            line+=(string)day+" ";
            ++column;
            if(column==7)
            {
                llOwnerSay(line);
                line="";
                column=0;
            }
        }
        if(line!="")llOwnerSay(line);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Print JSON fields in sorted-key order

Sort top-level keys and report values in stable order for comparing configurations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

This is a readable shallow report, not canonical JSON suitable for signatures or hashes. Nested object key order is not normalized.

// Original Incoprea example. MIT.
string DOCUMENT="{\"version\":2,\"title\":\"Lamp\",\"color\":\"green\"}";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_OBJECT)
        {
            llOwnerSay("Expected object.");
            return;
        }
        list pairs=llJson2List(DOCUMENT);
        list keys=[];
        integer i;
        for(i=0;i<llGetListLength(pairs);i+=2)keys += [llList2String(pairs,i)];
        keys=llListSort(keys,1,TRUE);
        for(i=0;i<llGetListLength(keys);++i)
        {
            string name=llList2String(keys,i);
            llOwnerSay(name+" => "+llJsonGetValue(DOCUMENT,[name]));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Print long records in bounded chunks

Split one long string into numbered owner-chat chunks of at most 180 characters.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Character chunks may divide words or combining marks but do not cut the LSL string encoding. Conservative 180-character chunks fit common owner-chat byte limits for typical text.

// Original Incoprea example. MIT.
string TEXT="Replace this with a longer build note that you want to inspect in manageable pieces.";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer size=llStringLength(TEXT);
        integer offset;
        integer chunk;
        integer total=(size+179)/180;
        if(size==0)
        {
            llOwnerSay("Text is empty.");
            return;
        }
        for(offset=0;offset<size;offset+=180)
        {
            ++chunk;
            llOwnerSay("["+(string)chunk+"/"+(string)total+"] "+llGetSubString(TEXT,offset,offset+179));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Project fields in a requested order

Output selected fields from a record in a specified presentation order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD and ORDER; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Missing fields receive an explicit marker. This does not change source order or add defaults to the original record.

// Original Incoprea example. MIT.
list RECORD=["color","green","title","Lamp","version","2"];
list ORDER=["title","version","author","color"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<llGetListLength(ORDER);++i)
        {
            string field=llList2String(ORDER,i);
            string value="[missing]";
            integer found;
            for(j=0;j<llGetListLength(RECORD);j+=2)if(!found && llList2String(RECORD,j)==field)
            {
                value=llList2String(RECORD,j+1);
                found=TRUE;
            }
            llOwnerSay(field+": "+value);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Read a filename extension

Find the last dot in a filename and report the lowercased extension.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit FILENAME and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Accepts a filename, not a complete URL or path. A leading dot alone is treated as a hidden filename, not an extension. An extension does not prove the file’s actual format.

// Original Incoprea example. MIT.
string FILENAME = "garden.preview.PNG";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer dot = -1;
        integer i;
        for (i = 1; i < llStringLength(FILENAME); ++i)
        if (llGetSubString(FILENAME, i, i) == ".") dot = i;
        if (dot == -1 || dot == llStringLength(FILENAME) - 1)
        llOwnerSay("No extension found.");
        else llOwnerSay("Extension: " + llToLower(llGetSubString(FILENAME, dot + 1, -1)));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Read a nested display setting

Read display.label only when it is a string, otherwise use a declared fallback.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Does not silently convert numbers or null to display text. Preserves an intentional empty string as a valid configured label.

// Original Incoprea example. MIT.
string DOCUMENT="{\"display\":{\"label\":\"Garden room\"}}";
string FALLBACK="Untitled";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string label=FALLBACK;
        if(llJsonValueType(DOCUMENT,["display","label"])==JSON_STRING)label=llJsonGetValue(DOCUMENT,["display","label"]);
        llOwnerSay("Resolved label: ["+label+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Read a validated numeric JSON vector

Convert exactly three bounded numeric JSON array elements into an LSL vector.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Rejects strings and excess components; magnitudes are limited to one million. Reports only and does not move a build.

// Original Incoprea example. MIT.
string DOCUMENT="[1.25,-2,3.5]";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY || llGetListLength(llJson2List(DOCUMENT))!=3)
        {
            llOwnerSay("Exactly three array elements required.");
            return;
        }
        list values=[];
        integer i;
        for(i=0;i<3;++i)
        {
            if(llJsonValueType(DOCUMENT,[i])!=JSON_NUMBER)
            {
                llOwnerSay("Numeric components only.");
                return;
            }
            float value=(float)llJsonGetValue(DOCUMENT,[i]);
            if(llFabs(value)>1000000)
            {
                llOwnerSay("Component exceeds bound.");
                return;
            }
            values += [value];
        }
        vector point=<llList2Float(values,0),llList2Float(values,1),llList2Float(values,2)>;
        llOwnerSay((string)point);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Read typed JSON settings

Read a string and a number from JSON only after checking their types.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit CONFIG and touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable the script. It does not change the build.

Malformed or missing values produce a helpful report. JSON support and behavior need checking on your OpenSim version.

// Original Incoprea example. MIT.
string CONFIG = "{\"label\":\"Garden\",\"interval\":30}";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llJsonValueType(CONFIG, ["label"]) != JSON_STRING ||
        llJsonValueType(CONFIG, ["interval"]) != JSON_NUMBER)
        {
            llOwnerSay("Expected a string label and a numeric interval.");
            return;
        }
        string label = llJsonGetValue(CONFIG, ["label"]);
        float interval = (float)llJsonGetValue(CONFIG, ["interval"]);
        if (interval < 1.0 || interval > 3600.0)
        {
            llOwnerSay("Interval must be 1 through 3600 seconds.");
            return;
        }
        llOwnerSay("Label: " + label + " / interval: " + (string)interval);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Beginner

Readable duration formatter

Turn a nonnegative number of seconds into days, hours, minutes, and seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit SECONDS and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

This formats a duration, not a calendar date. A day means exactly 86,400 seconds; no daylight-saving or timezone conversion is attempted.

// Original Incoprea example. MIT.
integer SECONDS = 93784;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (SECONDS < 0)
        {
            llOwnerSay("Duration cannot be negative.");
            return;
        }
        integer days = SECONDS / 86400;
        integer hours = (SECONDS % 86400) / 3600;
        integer minutes = (SECONDS % 3600) / 60;
        integer seconds = SECONDS % 60;
        llOwnerSay((string)days + "d " + (string)hours + "h " + (string)minutes + "m " + (string)seconds + "s");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Redact a declared phrase from a note

Replace all nonoverlapping exact occurrences with a fixed marker before sharing a note.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

This is a literal text tool, not automatic sensitive-data detection. Review the result yourself; case variants and other secrets are not found.

// Original Incoprea example. MIT.
string TEXT="Internal draft code ALPHA. Remove ALPHA before sharing.";
string PHRASE="ALPHA";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PHRASE=="")
        {
            llOwnerSay("Set a phrase.");
            return;
        }
        string rest=TEXT;
        string result="";
        integer occurrences;
        integer at=llSubStringIndex(rest,PHRASE);
        while(at!=-1 && occurrences<50)
        {
            if(at>0)result+=llGetSubString(rest,0,at-1);
            result+="[redacted]";
            rest=llDeleteSubString(rest,0,at+llStringLength(PHRASE)-1);
            ++occurrences;
            at=llSubStringIndex(rest,PHRASE);
        }
        if(at!=-1)
        {
            llOwnerSay("Too many matches; no preview emitted.");
            return;
        }
        llOwnerSay(result+rest);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Reject duplicate record fields

Validate that an alternating key/value list has nonempty, unique keys.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit RECORD and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Keys are exact and case-sensitive. Values may be empty. This catches malformed input before lookup or merge behavior can silently choose a duplicate.

// Original Incoprea example. MIT.
list RECORD=["title","Lamp","color","green","version","1"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(RECORD)%2)
        {
            llOwnerSay("Record has an incomplete pair.");
            return;
        }
        list seen=[];
        integer i;
        for(i=0;i<llGetListLength(RECORD);i+=2)
        {
            string name=llList2String(RECORD,i);
            if(name=="" || llListFindList(seen,[name])!=-1)
            {
                llOwnerSay("Empty or duplicate key at index "+(string)i);
                return;
            }
            seen += [name];
        }
        llOwnerSay("Record keys are nonempty and unique.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Remove a declared suffix exactly once

Remove an exact trailing suffix while leaving matching text elsewhere unchanged.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Case-sensitive and removes only one terminal occurrence. An empty suffix is rejected rather than interpreted as a match everywhere.

// Original Incoprea example. MIT.
string TEXT="Garden Lamp (copy)";
string SUFFIX=" (copy)";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SUFFIX=="")
        {
            llOwnerSay("Set a suffix.");
            return;
        }
        integer start=llStringLength(TEXT)-llStringLength(SUFFIX);
        if(start>=0 && llGetSubString(TEXT,start,-1)==SUFFIX)
        {
            if(start==0)llOwnerSay("");
            else llOwnerSay(llGetSubString(TEXT,0,start-1));
        }
        else llOwnerSay(TEXT);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Remove shared indentation

Remove the smallest leading-space indent found on nonblank lines.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Handles spaces only; tabs are left intact. Blank lines are retained. Useful for pasted multiline snippets; does not interpret code.

// Original Incoprea example. MIT.
string TEXT="    Garden\n      Lantern\n    Water";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list lines=llParseStringKeepNulls(TEXT,["\n"],[]);
        integer minimum=100000;
        integer i;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            if(llStringTrim(line,STRING_TRIM)!="")
            {
                integer indent=0;
                while(indent<llStringLength(line) && llGetSubString(line,indent,indent)==" ") ++indent;
                if(indent<minimum) minimum=indent;
            }
        }
        if(minimum==100000) minimum=0;
        for(i=0;i<llGetListLength(lines);++i)
        {
            string line=llList2String(lines,i);
            if(minimum>0 && llStringLength(line)>=minimum) line=llDeleteSubString(line,0,minimum-1);
            llOwnerSay(line);
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Rename one JSON field while preserving type

Move a field to a new name only if the source exists and destination does not.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Explicitly escapes string values and preserves raw object/array/number/boolean/null JSON values. This is a local preview, not a storage migration.

// Original Incoprea example. MIT.
string DOCUMENT="{\"label\":\"Lamp\",\"settings\":{\"enabled\":true}}";
string OLD="label";
string NEW="title";
string quoteJson(string value)
{
    string result="\"";
    string hex="0123456789abcdef";
    integer i;
    for(i=0;i<llStringLength(value);++i)
    {
        string c=llGetSubString(value,i,i);
        integer n=llOrd(value,i);
        if(c=="\"" || c=="\\")result+="\\"+c;
        else if(n<32)result+="\\u00"+llGetSubString(hex,n/16,n/16)+llGetSubString(hex,n%16,n%16);
        else result+=c;
    }
    return result+"\"";
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_OBJECT || NEW=="")
        {
            llOwnerSay("Object and nonempty new name required.");
            return;
        }
        string kind=llJsonValueType(DOCUMENT,[OLD]);
        if(kind==JSON_INVALID || llJsonValueType(DOCUMENT,[NEW])!=JSON_INVALID)
        {
            llOwnerSay("Missing source or destination already exists.");
            return;
        }
        string value=llJsonGetValue(DOCUMENT,[OLD]);
        if(kind==JSON_STRING)value=quoteJson(value);
        string result=llJsonSetValue(DOCUMENT,[NEW],value);
        result=llJsonSetValue(result,[OLD],JSON_DELETE);
        llOwnerSay(result);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Replace template tokens

Replace a fixed placeholder in short text without rescanning inserted replacement text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEMPLATE, TOKEN, and VALUE, then touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

An empty token leaves the input unchanged. This is literal, case-sensitive substitution with a 30-replacement limit; it is not a regular expression engine.

// Original Incoprea example. MIT.
string TEMPLATE = "Hello {place}. Welcome to {place}.";
string TOKEN = "{place}";
string VALUE = "the workshop";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (TOKEN == "")
        {
            llOwnerSay(TEMPLATE);
            return;
        }
        string rest = TEMPLATE;
        string result = "";
        integer replacements = 0;
        integer at = llSubStringIndex(rest, TOKEN);
        while (at != -1 && replacements < 30)
        {
            if (at > 0) result += llGetSubString(rest, 0, at - 1);
            result += VALUE;
            rest = llDeleteSubString(rest, 0, at + llStringLength(TOKEN) - 1);
            ++replacements;
            at = llSubStringIndex(rest, TOKEN);
        }
        llOwnerSay(result + rest);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Intermediate

Resolve a fallback text value

Choose the first nonblank value from a declared preference sequence while preserving its original spacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit OPTIONS; touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Whitespace-only values are skipped. The selected original string is returned unchanged; this is local configuration fallback, not an inventory lookup.

// Original Incoprea example. MIT.
list OPTIONS=["","   ","Custom label","Default label"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        for(i=0;i<llGetListLength(OPTIONS);++i)
        {
            string value=llList2String(OPTIONS,i);
            if(llStringTrim(value,STRING_TRIM)!="")
            {
                llOwnerSay("Selected option "+(string)i+": ["+value+"]");
                return;
            }
        }
        llOwnerSay("No nonblank value available.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Resolve a named table column

Find the unique index of a required header in an already parsed header list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Header matching is exact after trimming. Duplicate matching headers are rejected instead of choosing one silently.

// Original Incoprea example. MIT.
list HEADERS=["Name"," Color ","Quantity"];
string WANTED="Color";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer found=-1;
        integer matches;
        integer i;
        for(i=0;i<llGetListLength(HEADERS);++i)if(llStringTrim(llList2String(HEADERS,i),STRING_TRIM)==WANTED)
        {
            found=i;
            ++matches;
        }
        if(matches!=1)
        {
            llOwnerSay("Expected one header ["+WANTED+"], found "+(string)matches);
            return;
        }
        llOwnerSay("Column index: "+(string)found);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Resolve aliases with cycle protection

Follow alias-to-target pairs until reaching a terminal identifier.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Alias keys must be unique. The traversal is bounded and reports loops rather than hanging; it does not execute the resolved text.

// Original Incoprea example. MIT.
list ALIASES=["old-lamp","garden-lamp","garden-lamp","lamp-v3"];
string START="old-lamp";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ALIASES)%2 || llGetListLength(ALIASES)>40)
        {
            llOwnerSay("Use up to 20 alias pairs.");
            return;
        }
        list keys;
        integer i;
        for(i=0;i<llGetListLength(ALIASES);i+=2)
        {
            string k=llList2String(ALIASES,i);
            if(k=="" || llListFindList(keys,[k])!=-1)
            {
                llOwnerSay("Empty or duplicate alias key.");
                return;
            }
            keys += [k];
        }
        string value=START;
        list visited;
        integer steps;
        while(steps<=20)
        {
            if(llListFindList(visited,[value])!=-1)
            {
                llOwnerSay("Alias cycle at "+value);
                return;
            }
            visited += [value];
            integer at=llListFindList(keys,[value]);
            if(at==-1)
            {
                llOwnerSay("Resolved: "+value+" via "+llList2CSV(visited));
                return;
            }
            value=llList2String(ALIASES,at*2+1);
            ++steps;
        }
        llOwnerSay("Traversal bound reached.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Resolve an option to canonical spelling

Match a case-insensitive user option against a fixed list and return the canonical value.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit OPTIONS and INPUT; touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Rejects no matches and ambiguous case-colliding options. It does not accept partial prefixes, which prevents accidental option selection.

// Original Incoprea example. MIT.
list OPTIONS=["Wood","Glass","Metal"];
string INPUT=" glass ";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string needle=llToLower(llStringTrim(INPUT,STRING_TRIM));
        integer matches;
        string chosen;
        integer i;
        for(i=0;i<llGetListLength(OPTIONS);++i)
        {
            string option=llList2String(OPTIONS,i);
            if(llToLower(option)==needle)
            {
                ++matches;
                chosen=option;
            }
        }
        if(matches==1)llOwnerSay("Canonical option: "+chosen);
        else if(matches==0)llOwnerSay("Unknown option.");
        else llOwnerSay("Ambiguous options differ only by case.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Shift by calendar months

Add a signed month count and clamp the day to the destination month’s last day.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. For example, January 31 shifted one month becomes February’s last day. Clamping is an explicit policy; it is not a universal anniversary rule.

// Original Incoprea example. MIT.
string DATE="2028-01-31";
integer OFFSET=1;
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list date=parseDate(DATE);
        if(llGetListLength(date)!=3)
        {
            llOwnerSay("Invalid or unsupported date.");
            return;
        }
        if(OFFSET < -120 || OFFSET>120)
        {
            llOwnerSay("Use a month offset within ten years.");
            return;
        }
        integer total=(llList2Integer(date,0)-2000)*12+llList2Integer(date,1)-1+OFFSET;
        if(total<0 || total>=1200)
        {
            llOwnerSay("Result outside supported years.");
            return;
        }
        integer y=2000+total/12;
        integer m=total%12+1;
        integer d=llList2Integer(date,2);
        if(d>monthDays(y,m))d=monthDays(y,m);
        llOwnerSay(dateText([y,m,d]));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Show a keyword with nearby context

Find the first case-insensitive keyword and print a bounded excerpt around it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

The excerpt is character-based and can start mid-word. This searches only the configured text and never queries external sources.

// Original Incoprea example. MIT.
string TEXT="A quiet path leads past the brass lantern into the garden.";
string WORD="lantern";
integer CONTEXT=12;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WORD=="")
        {
            llOwnerSay("Set a keyword.");
            return;
        }
        integer at=llSubStringIndex(llToLower(TEXT),llToLower(WORD));
        if(at==-1)
        {
            llOwnerSay("Keyword absent.");
            return;
        }
        integer first=at-CONTEXT;
        if(first<0)first=0;
        integer last=at+llStringLength(WORD)-1+CONTEXT;
        llOwnerSay("Match at "+(string)at+": "+llGetSubString(TEXT,first,last));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Sort a strided price table

Sort numeric price/name pairs without separating a name from its price.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the alternating price/name list and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Every record must contain exactly two elements. This demonstrates local data sorting; it never takes or transfers money.

// Original Incoprea example. MIT.
list PRICES = [12.5, "Lantern", 5.0, "Cup", 8.0, "Planter"];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list sorted = llListSort(PRICES, 2, TRUE);
        integer i;
        for (i = 0; i < llGetListLength(sorted); i += 2)
        llOwnerSay(llList2String(sorted, i + 1) + ": " + (string)llList2Float(sorted, i));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Sort one numbered asset family naturally

Sort names sharing a prefix by their trailing nonnegative integer rather than lexicographically.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Every name must be PREFIX followed by 1-6 digits. Does not sort arbitrary mixed filenames or rename assets.

// Original Incoprea example. MIT.
string PREFIX="Panel-";
list NAMES=["Panel-10","Panel-2","Panel-1","Panel-12"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list keyed=[];
        integer i;
        for(i=0;i<llGetListLength(NAMES);++i)
        {
            string name=llList2String(NAMES,i);
            if(llSubStringIndex(name,PREFIX)!=0)
            {
                llOwnerSay("Unexpected prefix.");
                return;
            }
            string digits=llDeleteSubString(name,0,llStringLength(PREFIX)-1);
            if(digits=="" || llStringLength(digits)>6)
            {
                llOwnerSay("Invalid numeric suffix.");
                return;
            }
            integer j;
            for(j=0;j<llStringLength(digits);++j)if(llSubStringIndex("0123456789",llGetSubString(digits,j,j))==-1)
            {
                llOwnerSay("Suffix must be numeric.");
                return;
            }
            keyed += [(integer)digits,name];
        }
        keyed=llListSort(keyed,2,TRUE);
        for(i=0;i<llGetListLength(keyed);i+=2)llOwnerSay(llList2String(keyed,i+1));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Sort tasks by priority and then title

Use an insertion sort to order priority/title pairs while retaining exact ties.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

At most 20 rows. Priority must be an LSL integer list element, not arbitrary numeric text. Original source lists are unchanged.

// Original Incoprea example. MIT.
list ROWS=[2,"Paint",1,"Assemble",2,"Clean",1,"Inspect"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(ROWS);
        if(n%2 || n>40)
        {
            llOwnerSay("Use up to 20 pairs.");
            return;
        }
        integer i;
        for(i=0;i<n;i+=2)if(llGetListEntryType(ROWS,i)!=TYPE_INTEGER)
        {
            llOwnerSay("Priority must be integer typed.");
            return;
        }
        list sorted;
        for(i=0;i<n;i+=2)
        {
            integer priority=llList2Integer(ROWS,i);
            string title=llList2String(ROWS,i+1);
            integer at=0;
            integer found;
            while(at<llGetListLength(sorted) && !found)
            {
                integer p=llList2Integer(sorted,at);
                string t=llList2String(sorted,at+1);
                list lexical=llListSort([title,t],1,TRUE);
                if(priority<p || (priority==p && title!=t && llList2String(lexical,0)==title))found=TRUE;
                else at+=2;
            }
            sorted=llListInsertList(sorted,[priority,title],at);
        }
        for(i=0;i<n;i+=2)llOwnerSay(llList2CSV(llList2List(sorted,i,i+1)));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Sort validated ISO dates

Validate a short list of date strings, then sort them chronologically.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Exact zero-padded YYYY-MM-DD strings sort in calendar order. Duplicate dates are retained rather than silently removed.

// Original Incoprea example. MIT.
list DATES=["2026-10-01","2026-09-26","2028-02-29","2026-09-01"];
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        for(i=0;i<llGetListLength(DATES);++i)if(llGetListLength(parseDate(llList2String(DATES,i)))!=3)
        {
            llOwnerSay("Invalid date at index "+(string)i);
            return;
        }
        list sorted=llListSort(DATES,1,TRUE);
        for(i=0;i<llGetListLength(sorted);++i)llOwnerSay(llList2String(sorted,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Split a date span into monthly parts

Partition an inclusive short date interval into month-bounded date ranges.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the date and planning inputs, then touch as owner. Accepted calendar dates are YYYY-MM-DD in 2000-2099.

Stop / restore: Remove or disable. These are local calendar calculations, not scheduled actions.

Uses Gregorian dates without timezone or daylight-saving conversion unless explicitly stated. Caps the input span at 366 days. Unlike duration calculations, both start and end dates are included in the displayed partitions.

// Original Incoprea example. MIT.
string FROM="2026-09-26";
string TO="2026-12-03";
integer leap(integer y)
{
    return y%400==0 || (y%4==0 && y%100!=0);
}
integer monthDays(integer y,integer m)
{
    list days=[31,28,31,30,31,30,31,31,30,31,30,31];
    integer count=llList2Integer(days,m-1);
    if(m==2 && leap(y))++count;
    return count;
}
list parseDate(string text)
{
    if(llStringLength(text)!=10 || llGetSubString(text,4,4)!="-" || llGetSubString(text,7,7)!="-")return [];
    integer i;
    for(i=0;i<10;++i)if(i!=4 && i!=7 && llSubStringIndex("0123456789",llGetSubString(text,i,i))==-1)return [];
    integer y=(integer)llGetSubString(text,0,3);
    integer m=(integer)llGetSubString(text,5,6);
    integer d=(integer)llGetSubString(text,8,9);
    if(y<2000 || y>2099 || m<1 || m>12)return [];
    if(d<1 || d>monthDays(y,m))return [];
    return [y,m,d];
}
integer dateSerial(list date)
{
    integer y=llList2Integer(date,0);
    integer m=llList2Integer(date,1);
    integer result=llList2Integer(date,2)-1;
    integer i;
    for(i=2000;i<y;++i)result+=365+leap(i);
    for(i=1;i<m;++i)result+=monthDays(y,i);
    return result;
}
list fromSerial(integer value)
{
    if(value<0 || value>=36525)return [];
    integer y=2000;
    while(value>=365+leap(y))
    {
        value-=365+leap(y);
        ++y;
    }
    integer m=1;
    while(value>=monthDays(y,m))
    {
        value-=monthDays(y,m);
        ++m;
    }
    return [y,m,value+1];
}
string dateText(list date)
{
    if(llGetListLength(date)!=3)return "[outside 2000-2099]";
    integer m=llList2Integer(date,1);
    integer d=llList2Integer(date,2);
    string month=(string)m;
    string day=(string)d;
    if(m<10)month="0"+month;
    if(d<10)day="0"+day;
    return llList2String(date,0)+"-"+month+"-"+day;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list first=parseDate(FROM);
        list last=parseDate(TO);
        if(llGetListLength(first)!=3 || llGetListLength(last)!=3)
        {
            llOwnerSay("Invalid dates.");
            return;
        }
        integer cursor=dateSerial(first);
        integer end=dateSerial(last);
        if(end<cursor || end-cursor>366)
        {
            llOwnerSay("Use an ascending range of at most 367 included dates.");
            return;
        }
        while(cursor<=end)
        {
            list start=fromSerial(cursor);
            integer y=llList2Integer(start,0);
            integer m=llList2Integer(start,1);
            integer stop=dateSerial([y,m,monthDays(y,m)]);
            if(stop>end)stop=end;
            llOwnerSay(dateText(start)+" through "+dateText(fromSerial(stop)));
            cursor=stop+1;
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Split a key from a complex value

Split only on the first equals sign so values can themselves contain equals signs.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Trims outer whitespace on key and value; allows an empty value but rejects an empty key. Does not process escapes or comments.

// Original Incoprea example. MIT.
string INPUT=" url = https://example.org/?x=1&y=2 ";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer at=llSubStringIndex(INPUT,"=");
        if(at<=0)
        {
            llOwnerSay("Expected a nonempty key followed by equals.");
            return;
        }
        string name=llStringTrim(llGetSubString(INPUT,0,at-1),STRING_TRIM);
        string value=llStringTrim(llDeleteSubString(INPUT,0,at),STRING_TRIM);
        if(name=="")
        {
            llOwnerSay("Empty key.");
            return;
        }
        llOwnerSay("Key: ["+name+"]");
        llOwnerSay("Value: ["+value+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Split catalog rows by a rule

Partition name/quantity records into available and empty groups while preserving order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS with integer quantities, then touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

This is configured catalog data, not live sale stock. Negative quantities are reported as invalid instead of classed as empty.

// Original Incoprea example. MIT.
list ROWS=["Lamp",4,"Cup",0,"Bench",2,"Plant",0];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%2)
        {
            llOwnerSay("Incomplete pair.");
            return;
        }
        list available=[];
        list empty=[];
        integer i;
        for(i=0;i<llGetListLength(ROWS);i+=2)
        {
            integer quantity=llList2Integer(ROWS,i+1);
            if(quantity<0)
            {
                llOwnerSay("Invalid negative quantity.");
                return;
            }
            if(quantity>0)available+=llList2List(ROWS,i,i+1);
            else empty+=llList2List(ROWS,i,i+1);
        }
        llOwnerSay("Available rows: "+llList2CSV(available));
        llOwnerSay("Empty rows: "+llList2CSV(empty));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Strip line comments outside quoted text

Remove a // comment only when it begins outside a double-quoted string.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the example inputs in the script, then touch as owner.

Stop / restore: Remove or disable. This transforms text locally and sends no external requests.

Handles backslash escapes inside a single-line quoted string. It does not parse block comments, multiline strings, or complete LSL grammar.

// Original Incoprea example. MIT.
string LINE="string url = \"https://example.org/\"; // a note";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer quoted;
        integer escaped;
        integer i;
        integer cut=-1;
        for(i=0;i<llStringLength(LINE);++i)
        {
            string c=llGetSubString(LINE,i,i);
            if(quoted)
            {
                if(escaped)escaped=FALSE;
                else if(c=="\\")escaped=TRUE;
                else if(c=="\"")quoted=FALSE;
            }
            else if(c=="\"")quoted=TRUE;
            else if(c=="/" && i+1<llStringLength(LINE) && llGetSubString(LINE,i+1,i+1)=="/")
            {
                cut=i;
                i=llStringLength(LINE);
            }
        }
        if(quoted)
        {
            llOwnerSay("Unclosed string; no stripped output.");
            return;
        }
        if(cut==0)llOwnerSay("");
        else if(cut>0)llOwnerSay(llGetSubString(LINE,0,cut-1));
        else llOwnerSay(LINE);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Sum quantities by category

Aggregate category/quantity records into one total per category.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROWS in category/integer quantity pairs. Touch as owner.

Stop / restore: Remove or disable; it only reports locally to the owner.

Quantities are illustrative configured integers, not inventory counts. Negative quantities are rejected. Keep tables small to fit script memory.

// Original Incoprea example. MIT.
list ROWS=["Lights",3,"Seats",2,"Lights",4,"Plants",6];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ROWS)%2)
        {
            llOwnerSay("Incomplete record.");
            return;
        }
        list groups=[];
        list totals=[];
        integer i;
        for(i=0;i<llGetListLength(ROWS);i+=2)
        {
            string group=llList2String(ROWS,i);
            integer quantity=llList2Integer(ROWS,i+1);
            if(quantity<0)
            {
                llOwnerSay("Negative quantity.");
                return;
            }
            integer index=llListFindList(groups,[group]);
            if(index==-1)
            {
                groups+=[group];
                totals+=[quantity];
            }
            else totals=llListReplaceList(totals,[llList2Integer(totals,index)+quantity],index,index);
        }
        for(i=0;i<llGetListLength(groups);++i)llOwnerSay(llList2String(groups,i)+": "+llList2String(totals,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Beginner

Summarize numeric measurements

Compute the count, sum, mean, minimum, and maximum of a small numeric list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit VALUES with numbers only, then touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

This example handles an empty list but does not validate each element type. Non-numeric strings cast to zero and would distort the results.

// Original Incoprea example. MIT.
list VALUES = [1.5, 2.0, 4.25, 3.0];
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetListLength(VALUES);
        if (total == 0)
        {
            llOwnerSay("No measurements.");
            return;
        }
        float sum = 0.0;
        float low = llList2Float(VALUES, 0);
        float high = low;
        integer i;
        for (i = 0; i < total; ++i)
        {
            float value = llList2Float(VALUES, i);
            sum += value;
            if (value < low) low = value;
            if (value > high) high = value;
        }
        llOwnerSay("Count: " + (string)total + ", sum: " + (string)sum + ", mean: " + (string)(sum / total));
        llOwnerSay("Minimum: " + (string)low + ", maximum: " + (string)high);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Summarize repeated punctuation runs

Report runs of repeated punctuation characters useful for spotting accidental separators.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Only runs of hyphen, underscore, equals, and space are reported. This does not rewrite the source or judge intentional decoration.

// Original Incoprea example. MIT.
string TEXT="Garden---Lamp  ==== release__notes";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        while(i<llStringLength(TEXT))
        {
            string c=llGetSubString(TEXT,i,i);
            integer end=i+1;
            while(end<llStringLength(TEXT) && llGetSubString(TEXT,end,end)==c)++end;
            if(end-i>=2 && llSubStringIndex("-_= ",c)!=-1)llOwnerSay("Run ["+c+"] at "+(string)i+", length "+(string)(end-i));
            i=end;
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Summarize words excluding a stop list

Count normalized whitespace-separated tokens while ignoring declared common words.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

Punctuation remains attached, and counts are limited to at most 60 input tokens. No external language service is called.

// Original Incoprea example. MIT.
string TEXT="the lamp and the garden lamp beside the garden";
list STOP=["the","and","beside"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list words=llParseString2List(llToLower(TEXT),[" ","\n",llUnescapeURL("%09")],[]);
        if(llGetListLength(words)>60)
        {
            llOwnerSay("Maximum 60 words.");
            return;
        }
        list terms=[];
        list counts=[];
        integer i;
        for(i=0;i<llGetListLength(words);++i)
        {
            string word=llList2String(words,i);
            if(llListFindList(STOP,[word])==-1)
            {
                integer at=llListFindList(terms,[word]);
                if(at==-1)
                {
                    terms += [word];
                    counts += [1];
                }
                else counts=llListReplaceList(counts,[llList2Integer(counts,at)+1],at,at);
            }
        }
        for(i=0;i<llGetListLength(terms);++i)llOwnerSay(llList2String(terms,i)+": "+llList2String(counts,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Tokenize a short quoted command

Split a command at spaces while preserving spaces inside double quotes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Quotes can occur only at token boundaries. Escape sequences and multiline input are intentionally unsupported. Empty quoted arguments are retained.

// Original Incoprea example. MIT.
string INPUT="label \"Garden room\" green";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list tokens=[];
        string token="";
        integer quoted;
        integer active;
        integer closed;
        integer i;
        for(i=0;i<llStringLength(INPUT);++i)
        {
            string c=llGetSubString(INPUT,i,i);
            if(quoted)
            {
                if(c=="\"")
                {
                    quoted=FALSE;
                    closed=TRUE;
                }
                else token+=c;
            }
            else if(c==" ")
            {
                if(active)
                {
                    tokens += [token];
                    token="";
                    active=FALSE;
                    closed=FALSE;
                }
            }
            else if(c=="\"")
            {
                if(active)
                {
                    llOwnerSay("Quote must begin an argument.");
                    return;
                }
                active=TRUE;
                quoted=TRUE;
            }
            else
            {
                if(closed)
                {
                    llOwnerSay("Space required after closing quote.");
                    return;
                }
                active=TRUE;
                token+=c;
            }
        }
        if(quoted)
        {
            llOwnerSay("Unclosed quote.");
            return;
        }
        if(active)tokens += [token];
        for(i=0;i<llGetListLength(tokens);++i)llOwnerSay((string)i+": ["+llList2String(tokens,i)+"]");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Total a JSON numeric array

Validate every element is a bounded number before computing a sum.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Rejects arrays over 100 elements and values outside one million in magnitude. A nonnumeric element aborts the entire calculation.

// Original Incoprea example. MIT.
string DOCUMENT="[1.5,2.25,3]";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected an array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>100)
        {
            llOwnerSay("Too many values.");
            return;
        }
        float sum;
        integer i;
        for(i=0;i<total;++i)
        {
            if(llJsonValueType(DOCUMENT,[i])!=JSON_NUMBER)
            {
                llOwnerSay("Nonnumeric element at "+(string)i);
                return;
            }
            float value=(float)llJsonGetValue(DOCUMENT,[i]);
            if(llFabs(value)>1000000)
            {
                llOwnerSay("Value exceeds bound.");
                return;
            }
            sum+=value;
        }
        llOwnerSay("Numeric total: "+(string)sum);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Transpose a small rectangular table

Swap rows and columns of a flat row-major data list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit CELLS and COLUMNS; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Requires complete rows and caps the sample at 100 cells. It prints each transposed row; no spreadsheet or external file is changed.

// Original Incoprea example. MIT.
list CELLS=["Name","Color","Lamp","Green","Cup","Blue"];
integer COLUMNS=2;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        integer total=llGetListLength(CELLS);
        if(COLUMNS<1 || total%COLUMNS!=0 || total>100)
        {
            llOwnerSay("Invalid table dimensions.");
            return;
        }
        integer rows=total/COLUMNS;
        integer col;
        integer row;
        for(col=0;col<COLUMNS;++col)
        {
            list output=[];
            for(row=0;row<rows;++row) output += [llList2String(CELLS,row*COLUMNS+col)];
            llOwnerSay(llDumpList2String(output," | "));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Trim a declared set of edge characters

Remove selected characters only from the beginning and end of a label.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the sample inputs, then touch as owner.

Stop / restore: Remove or disable. All transformations are previews in owner chat.

The same characters inside the label are preserved. Empty results are handled explicitly to avoid negative-index substring surprises.

// Original Incoprea example. MIT.
string TEXT="--- Garden-Lamp ___";
string TRIM=" -_";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer first=0;
        integer last=llStringLength(TEXT)-1;
        while(first<=last && llSubStringIndex(TRIM,llGetSubString(TEXT,first,first))!=-1)++first;
        while(last>=first && llSubStringIndex(TRIM,llGetSubString(TEXT,last,last))!=-1)--last;
        if(first>last)llOwnerSay("[empty]");
        else llOwnerSay(llGetSubString(TEXT,first,last));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Turn a wide table into property records

Convert each row’s named columns to entity/property/value records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

The first column is the entity name. Empty cells are omitted; all rows must have the declared stride. Values are reported with CSV escaping.

// Original Incoprea example. MIT.
list HEADERS=["entity","color","size"];
list ROWS=["Lamp","green","small","Bench","","large"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer width=llGetListLength(HEADERS);
        if(width<2 || llGetListLength(ROWS)%width)
        {
            llOwnerSay("Invalid table shape.");
            return;
        }
        integer i;
        integer j;
        for(i=0;i<llGetListLength(ROWS);i+=width)for(j=1;j<width;++j)
        {
            string value=llList2String(ROWS,i+j);
            if(value!="")llOwnerSay(llList2CSV([llList2String(ROWS,i),llList2String(HEADERS,j),value]));
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Validate a calendar date

Check a YYYY-MM-DD date using Gregorian month lengths and leap-year rules.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DATE and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Accepts years 1900-2099. Validates a date only; does not convert to Unix time or enforce whether the date is in the future.

// Original Incoprea example. MIT.
string DATE="2028-02-29";
integer digitsOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list p=llParseStringKeepNulls(DATE,["-"],[]);
        if(llGetListLength(p)!=3 || llStringLength(DATE)!=10 || llStringLength(llList2String(p,0))!=4 || llStringLength(llList2String(p,1))!=2 || llStringLength(llList2String(p,2))!=2)
        {
            llOwnerSay("Use YYYY-MM-DD.");
            return;
        }
        integer i;
        for(i=0;i<3;++i)if(!digitsOK(llList2String(p,i)))
        {
            llOwnerSay("Digits required.");
            return;
        }
        integer y=llList2Integer(p,0);
        integer m=llList2Integer(p,1);
        integer d=llList2Integer(p,2);
        if(y<1900 || y>2099 || m<1 || m>12)
        {
            llOwnerSay("Year or month out of range.");
            return;
        }
        list lengths=[31,28,31,30,31,30,31,31,30,31,30,31];
        integer limit=llList2Integer(lengths,m-1);
        if(m==2 && (y%400==0 || (y%4==0 && y%100!=0)))limit=29;
        if(d<1 || d>limit)llOwnerSay("Day does not exist in that month.");
        else llOwnerSay("Valid Gregorian date.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Data & lists · Intermediate

Validate a declared workflow history

Check each adjacent status transition against an allowed transition table.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Reports invalid jumps; it does not enforce permissions or change real workflow state. The first history status has no predecessor.

// Original Incoprea example. MIT.
list HISTORY=["draft","review","ready","draft"];
list ALLOWED=["draft","review","review","draft","review","ready"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(ALLOWED)%2)
        {
            llOwnerSay("Use from/to pairs.");
            return;
        }
        integer i;
        for(i=1;i<llGetListLength(HISTORY);++i)
        {
            string from=llList2String(HISTORY,i-1);
            string to=llList2String(HISTORY,i);
            integer j;
            integer valid;
            for(j=0;j<llGetListLength(ALLOWED);j+=2)if(llList2String(ALLOWED,j)==from && llList2String(ALLOWED,j+1)==to)valid=TRUE;
            if(!valid)llOwnerSay("Invalid step "+(string)i+": "+from+" -> "+to);
        }
        llOwnerSay("History audit complete.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Validate a JSON string list

Reject a JSON array containing values other than strings and print the accepted values.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Checks at most 50 elements and rejects longer arrays. Empty arrays are valid. Requires simulator JSON support.

// Original Incoprea example. MIT.
string DOCUMENT="[\"garden\",\"lamp\",\"glass\"]";
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected an array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>50)
        {
            llOwnerSay("Array exceeds 50 entries.");
            return;
        }
        integer i;
        for(i=0;i<total;++i) if(llJsonValueType(DOCUMENT,[i])!=JSON_STRING)
        {
            llOwnerSay("Non-string at index "+(string)i);
            return;
        }
        for(i=0;i<total;++i) llOwnerSay((string)i+": "+llJsonGetValue(DOCUMENT,[i]));
        llOwnerSay("All entries are strings.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Data & lists · Beginner

Validate a positive integer

Reject partial numeric strings before converting a small positive integer.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit INPUT and touch as owner. Try 120, 12cats, a negative value, and whitespace.

Stop / restore: Remove or disable the script. It does not change the build.

Accepts only one to nine ASCII digits after trimming, then requires a value above zero. The length cap avoids signed-integer overflow; plus signs and decimals are intentionally rejected.

// Original Incoprea example. MIT.
string INPUT = " 120 ";
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string value = llStringTrim(INPUT, STRING_TRIM);
        integer length = llStringLength(value);
        if (length < 1 || length > 9)
        {
            llOwnerSay("Use 1-9 digits.");
            return;
        }
        integer i;
        for (i = 0; i < length; ++i)
        {
            if (llSubStringIndex("0123456789", llGetSubString(value, i, i)) == -1)
            {
                llOwnerSay("Only digits are accepted.");
                return;
            }
        }
        integer number = (integer)value;
        if (number <= 0)
        {
            llOwnerSay("Value must be positive.");
            return;
        }
        llOwnerSay("Accepted integer: " + (string)number);
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Validate a signed decimal

Require an entire string to be a simple decimal before casting it to float.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit VALUE and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

Accepts an optional sign and one decimal point, but no exponent, units, or commas. Applies an explicit magnitude limit after conversion.

// Original Incoprea example. MIT.
string VALUE=" -12.75 ";
integer decimalOK(string value)
{
    integer length=llStringLength(value);
    if(length<1 || length>16)return FALSE;
    integer start=0;
    string first=llGetSubString(value,0,0);
    if(first=="-" || first=="+")start=1;
    integer digits;
    integer dots;
    integer i;
    for(i=start;i<length;++i)
    {
        string c=llGetSubString(value,i,i);
        if(c==".")++dots;
        else if(llSubStringIndex("0123456789",c)!=-1)++digits;
        else return FALSE;
    }
    return digits>0 && dots<=1;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string input=llStringTrim(VALUE,STRING_TRIM);
        if(!decimalOK(input))
        {
            llOwnerSay("Expected a simple signed decimal.");
            return;
        }
        float value=(float)input;
        if(llFabs(value)>1000000)
        {
            llOwnerSay("Magnitude exceeds one million.");
            return;
        }
        llOwnerSay("Accepted: "+(string)value);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Validate a simple relative asset path

Reject absolute paths, parent traversal, empty segments, and control characters in a relative path.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit PATH and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

This is a conservative syntax check for exported configuration, not a filesystem security boundary. It neither reads nor writes a file and does not decode URL escapes.

// Original Incoprea example. MIT.
string PATH="images/garden-panel.png";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PATH=="" || llSubStringIndex(PATH,"\\")!=-1 || llSubStringIndex(PATH,":")!=-1 || llSubStringIndex(PATH,"%")!=-1)
        {
            llOwnerSay("Unsupported path syntax.");
            return;
        }
        list parts=llParseStringKeepNulls(PATH,["/"],[]);
        integer i;
        for(i=0;i<llGetListLength(parts);++i)
        {
            string part=llList2String(parts,i);
            if(part=="" || part=="." || part==".." || part!=llStringTrim(part,STRING_TRIM))
            {
                llOwnerSay("Unsafe or empty segment.");
                return;
            }
            integer j;
            for(j=0;j<llStringLength(part);++j)
            {
                integer c=llOrd(part,j);
                if(c<32 || c==127)
                {
                    llOwnerSay("Control character in path.");
                    return;
                }
            }
        }
        llOwnerSay("Relative-path syntax accepted.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Validate a three-column TSV row

Check a name, integer quantity, and allowed unit in a tab-separated record.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit ROW, or leave it empty for the generated sample. Format is name, quantity, unit separated by actual tabs.

Stop / restore: Remove or disable; results are reported only to the owner.

Quantity must be 0-9999; units are piece, meter, or set. Tabs inside fields and quoted fields are unsupported. Literal tab characters are constructed with URL decoding.

// Original Incoprea example. MIT.
string ROW="";
integer digitsOK(string value)
{
    integer i;
    if(value=="" || llStringLength(value)>6)return FALSE;
    for(i=0;i<llStringLength(value);++i)if(llSubStringIndex("0123456789",llGetSubString(value,i,i))==-1)return FALSE;
    return TRUE;
}
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string tab=llUnescapeURL("%09");
        if(ROW=="")ROW="Garden rail"+tab+"12"+tab+"meter";
        list fields=llParseStringKeepNulls(ROW,[tab],[]);
        if(llGetListLength(fields)!=3)
        {
            llOwnerSay("Expected three tab-separated fields.");
            return;
        }
        string name=llStringTrim(llList2String(fields,0),STRING_TRIM);
        string quantity=llList2String(fields,1);
        string unit=llList2String(fields,2);
        if(name=="" || !digitsOK(quantity) || (integer)quantity>9999 || llListFindList(["piece","meter","set"],[unit])==-1)
        {
            llOwnerSay("Invalid name, quantity, or unit.");
            return;
        }
        llOwnerSay("Accepted "+quantity+" "+unit+": "+name);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Validate an ASCII component name

Require a short component name beginning with a letter and containing only letters, digits, hyphen, or underscore.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit NAME and touch as owner.

Stop / restore: Remove or disable; results are reported only to the owner.

A configuration naming convention, not a platform requirement. Does not rename anything or guarantee uniqueness in a linkset.

// Original Incoprea example. MIT.
string NAME="Garden_Lamp-01";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string lower=llToLower(NAME);
        integer length=llStringLength(lower);
        if(length<1 || length>32)
        {
            llOwnerSay("Use 1-32 characters.");
            return;
        }
        if(llSubStringIndex("abcdefghijklmnopqrstuvwxyz",llGetSubString(lower,0,0))==-1)
        {
            llOwnerSay("Begin with a letter.");
            return;
        }
        integer i;
        for(i=0;i<length;++i)if(llSubStringIndex("abcdefghijklmnopqrstuvwxyz0123456789_-",llGetSubString(lower,i,i))==-1)
        {
            llOwnerSay("Unsupported character at "+(string)i);
            return;
        }
        llOwnerSay("Component name accepted: "+NAME);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Validate conditional release metadata

Require extra metadata only when a record is declared externally sourced or modified.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Uses explicit sample fields. A nonempty license string is not a legal compatibility or provenance verification.

// Original Incoprea example. MIT.
integer EXTERNAL=TRUE;
integer MODIFIED=TRUE;
string SOURCE_URL="https://example.com/asset";
string LICENSE="";
string CHANGE_NOTE="color adjusted";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer issues;
        if(EXTERNAL)
        {
            if(SOURCE_URL=="")
            {
                ++issues;
                llOwnerSay("External source requires a source URL.");
            }
            if(LICENSE=="")
            {
                ++issues;
                llOwnerSay("External source requires a license statement.");
            }
        }
        if(MODIFIED && CHANGE_NOTE=="")
        {
            ++issues;
            llOwnerSay("Modified material needs a change note.");
        }
        llOwnerSay("Metadata omissions: "+(string)issues);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Validate unique JSON product IDs

Require every array element to have a distinct nonempty string id.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit DOCUMENT and the example settings, then touch as owner. Requires simulator support for LSL JSON functions.

Stop / restore: Remove or disable. JSON changes occur only in a local preview string.

Checks identifier integrity without inspecting people or external records. This does not guarantee IDs are globally unique.

// Original Incoprea example. MIT.
string DOCUMENT="[{\"id\":\"lamp-1\",\"title\":\"Lamp\"},{\"id\":\"cup-1\",\"title\":\"Cup\"}]";
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llJsonValueType(DOCUMENT,[])!=JSON_ARRAY)
        {
            llOwnerSay("Expected array.");
            return;
        }
        integer total=llGetListLength(llJson2List(DOCUMENT));
        if(total>40)
        {
            llOwnerSay("Maximum 40 records.");
            return;
        }
        list ids=[];
        integer i;
        for(i=0;i<total;++i)
        {
            if(llJsonValueType(DOCUMENT,[i,"id"])!=JSON_STRING)
            {
                llOwnerSay("Missing string id at "+(string)i);
                return;
            }
            string id=llJsonGetValue(DOCUMENT,[i,"id"]);
            if(id=="" || llListFindList(ids,[id])!=-1)
            {
                llOwnerSay("Empty or duplicate id at "+(string)i);
                return;
            }
            ids += [id];
        }
        llOwnerSay("All product IDs are present and unique.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Visualize missing fields across a short table

Print one presence mask per record to show which required columns are blank.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit the small sample lists and touch as owner. These examples print previews only.

Stop / restore: Remove or disable; no simulator objects or persistent records are changed.

Empty strings count as missing; whitespace is trimmed. This does not infer whether zero, false, or a placeholder is a valid value.

// Original Incoprea example. MIT.
list HEADERS=["name","license","source"];
list ROWS=["Lamp","MIT","","Bench","","local design"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer width=llGetListLength(HEADERS);
        if(width==0 || llGetListLength(ROWS)%width)
        {
            llOwnerSay("Invalid shape.");
            return;
        }
        llOwnerSay("Columns: "+llList2CSV(HEADERS));
        integer i;
        for(i=0;i<llGetListLength(ROWS);i+=width)
        {
            string mask="";
            integer j;
            for(j=0;j<width;++j)
            {
                if(llStringTrim(llList2String(ROWS,i+j),STRING_TRIM)=="")mask+="-";
                else mask+="+";
            }
            llOwnerSay("Row "+(string)(i/width+1)+": "+mask);
        }
        llOwnerSay("+ present; - blank");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Data & lists · Intermediate

Wrap short prose by words

Wrap words into lines up to a chosen character width without splitting words.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT and WIDTH; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Collapses input whitespace. A single word longer than WIDTH stays intact on its own line. Uses character width, not proportional-font pixel width.

// Original Incoprea example. MIT.
string TEXT="A tiny garden can hold a surprising number of stories.";
integer WIDTH=24;
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(WIDTH<5 || WIDTH>100)
        {
            llOwnerSay("Width must be 5-100.");
            return;
        }
        list words=llParseString2List(TEXT,[" ","\n","\t"],[]);
        string line="";
        integer i;
        for(i=0;i<llGetListLength(words);++i)
        {
            string word=llList2String(words,i);
            if(line!="" && llStringLength(line)+1+llStringLength(word)>WIDTH)
            {
                llOwnerSay(line);
                line="";
            }
            if(line!="") line+=" ";
            line+=word;
        }
        if(line!="") llOwnerSay(line);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Write a properly quoted CSV row

Quote every field and double embedded quotation marks in a short CSV record.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit FIELDS and touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Produces one record. Field newlines are preserved inside quotes; the output is not saved to a file. Keep output short enough for owner chat.

// Original Incoprea example. MIT.
list FIELDS=["Garden","Blue, green","A \"small\" lamp",""];
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list output=[];
        integer i;
        for(i=0;i<llGetListLength(FIELDS);++i)
        {
            string source=llList2String(FIELDS,i);
            string value="";
            integer j;
            for(j=0;j<llStringLength(source);++j)
            {
                string c=llGetSubString(source,j,j);
                if(c=="\"") value+="\"";
                value+=c;
            }
            output += ["\""+value+"\""];
        }
        llOwnerSay(llDumpList2String(output,","));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Data & lists · Intermediate

Zip names with quantities

Combine equal-length name and quantity lists into labeled records.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit NAMES and COUNTS; touch as owner.

Stop / restore: Remove or disable. This example only calculates and reports to the owner.

Rejects mismatched list lengths instead of silently dropping entries. Quantities are illustrative local data; no sales or inventory operations occur.

// Original Incoprea example. MIT.
list NAMES=["Lantern","Bench","Planter"];
list COUNTS=[3,2,6];
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetListLength(NAMES)!=llGetListLength(COUNTS))
        {
            llOwnerSay("Names and quantities must have equal lengths.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(NAMES);++i) llOwnerSay(llList2String(NAMES,i)+": "+llList2String(COUNTS,i));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

DiagnosticsReadouts to help explain what your script is doing.79 scripts

Download this category (.zip)

Diagnostics · Intermediate

Attachment lifecycle counter

Count this script’s attach and detach events and report its current attachment point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own wearable object; touch as owner for the report.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Does not identify other avatars or request controls. Some detach-time reporting is unavailable, so counters are read later while the script runs. Resets clear counters.

// Original Incoprea example. MIT.
integer attachedEvents;
integer detachedEvents;
default
{
    attach(key avatar)
    {
        if(avatar==NULL_KEY)++detachedEvents;
        else if(avatar==llGetOwner())++attachedEvents;
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("Attach events: "+(string)attachedEvents+"; detach events: "+(string)detachedEvents+"; attachment point: "+(string)llGetAttached());
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Beginner

Build change reporter

Report selected build-change events privately to the owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a test prim, then edit its scale, shape, color, texture, links, or Contents.

Stop / restore: Remove or disable to stop reporting. No object settings change.

Events can combine several change bits and may differ across simulators. This logs no visitors and keeps no history. Avoid leaving it in rapidly animated builds.

// Original Incoprea example. MIT.
default
{
    state_entry()
    {
        llOwnerSay("Build-change reporter ready.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER)
        {
            llResetScript();
            return;
        }
        list names = [];
        if (flags & CHANGED_SCALE) names += ["scale"];
        if (flags & CHANGED_SHAPE) names += ["shape"];
        if (flags & CHANGED_COLOR) names += ["color"];
        if (flags & CHANGED_TEXTURE) names += ["texture"];
        if (flags & CHANGED_LINK) names += ["links"];
        if (flags & CHANGED_INVENTORY) names += ["inventory"];
        if (llGetListLength(names)) llOwnerSay("Changed: " + llDumpList2String(names, ", "));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Cache a notecard line until Contents changes

Read a line once, then serve later owner touches from the in-memory cache.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text Notes notecard. Touch once to fetch and again to read the cached result.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Contents changes reset the cache. Uses one outstanding request and a timeout; the cache is not persistent storage.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
integer ready;
string cached;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ready)
        {
            llOwnerSay("Cached: "+cached);
            return;
        }
        if(pending!=NULL_KEY)return;
        if(llGetInventoryType("Notes")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add Notes first.");
            return;
        }
        pending=llGetNotecardLine("Notes",0);
        llSetTimerEvent(20);
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        pending=NULL_KEY;
        llSetTimerEvent(0);
        if(data==EOF)
        {
            llOwnerSay("Card is empty; nothing cached.");
            return;
        }
        cached=data;
        ready=TRUE;
        llOwnerSay("Loaded: "+cached);
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0);
        llOwnerSay("Fetch timed out.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Check a child’s local up-axis alignment

Report a touched child’s tilt away from root-local vertical and its local forward heading.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Local heading becomes unstable when the forward axis is nearly vertical; that case is reported.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(link<2)
        {
            llOwnerSay("Touch a linked child.");
            return;
        }
        rotation r=llList2Rot(llGetLinkPrimitiveParams(link,[PRIM_ROT_LOCAL]),0);
        vector up=<0.0,0.0,1.0>*r;
        float dot=up.z;
        if(dot>1.0)dot=1.0;
        if(dot< -1.0)dot=-1.0;
        llOwnerSay("Up-axis tilt degrees="+(string)(llAcos(dot)*RAD_TO_DEG));
        vector forward=<1.0,0.0,0.0>*r;
        if(forward.x*forward.x+forward.y*forward.y<0.000001)llOwnerSay("Forward heading undefined near vertical.");
        else llOwnerSay("Local forward heading="+(string)(llAtan2(forward.y,forward.x)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Diagnostics · Intermediate

Check a planned memory budget

Compare this script’s free memory with a configured minimum headroom.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set REQUIRED_BYTES and touch as owner.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

This measures only this script at that instant; it cannot guarantee later allocations succeed. Engine accounting and garbage collection vary.

// Original Incoprea example. MIT.
integer REQUIRED_BYTES=8192;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(REQUIRED_BYTES<0 || REQUIRED_BYTES>65536)
        {
            llOwnerSay("Use a requirement from 0 to 65536 bytes.");
            return;
        }
        integer available=llGetFreeMemory();
        llOwnerSay("Observed free bytes: "+(string)available);
        if(available>=REQUIRED_BYTES)llOwnerSay("Current snapshot meets the configured headroom.");
        else llOwnerSay("Current snapshot is below the configured headroom.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Diagnostics · Intermediate

Check child offsets against a build grid

Report how far a touched child’s local position is from the nearest configured grid point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

This only suggests corrections. Root/unlinked positions are excluded because their coordinate frame differs.

// Original Incoprea. MIT. Owner-only live inspection.
float GRID=0.25;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(link<2)
        {
            llOwnerSay("Touch a linked child, not the root.");
            return;
        }
        if(GRID<=0.0)
        {
            llOwnerSay("Positive grid required.");
            return;
        }
        vector p=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL]),0);
        vector snapped=<llRound(p.x/GRID)*GRID,llRound(p.y/GRID)*GRID,llRound(p.z/GRID)*GRID>;
        llOwnerSay("Local position="+(string)p+" grid correction="+(string)(snapped-p));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Advanced

Check inventory count during a bounded enumeration

Compare inventory counts before and after reading up to100 names.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch; optional inventory edits during the test may reveal an unstable snapshot.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

One event usually completes quickly. Matching counts do not prove that no same-count replacement occurred.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer before=llGetInventoryNumber(INVENTORY_ALL);
        if(before>100)
        {
            llOwnerSay("Use at most100 inventory items.");
            return;
        }
        integer blanks;
        integer i;
        for(i=0;i<before;++i)if(llGetInventoryName(INVENTORY_ALL,i)=="")++blanks;
        integer after=llGetInventoryNumber(INVENTORY_ALL);
        llOwnerSay("Enumeration count stable="+(string)(before==after)+" before="+(string)before+" after="+(string)after+" empty names="+(string)blanks);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Check local link-message ordering

Queue ten numbered self-messages and verify their received sequence.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner to run one bounded probe.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Diagnostic only. It does not assume that unrelated scripts share a global event order. Reports completion or a five-second timeout.

// Original Incoprea example. MIT.
integer expected;
integer active;
key token=NULL_KEY;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner() || active)return;
        active=TRUE;
        expected=0;
        token=llGenerateKey();
        llSetTimerEvent(5);
        integer i;
        for(i=0;i<10;++i)llMessageLinked(LINK_THIS,71003,(string)i,token);
    }
    link_message(integer sender,integer code,string text,key id)
    {
        if(!active || code!=71003 || id!=token)return;
        integer value=(integer)text;
        if(value!=expected)
        {
            llOwnerSay("Order mismatch: expected "+(string)expected+", received "+text);
            active=FALSE;
            llSetTimerEvent(0);
            return;
        }
        ++expected;
        if(expected==10)
        {
            active=FALSE;
            llSetTimerEvent(0);
            llOwnerSay("All ten self-messages arrived in order.");
        }
    }
    timer()
    {
        active=FALSE;
        llSetTimerEvent(0);
        llOwnerSay("Probe timed out after "+(string)expected+" messages.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Check required scripts are running

Verify named script dependencies exist and have their Running flag set.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit REQUIRED and touch as owner.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

A running flag does not prove correct operation. This tool never starts, stops, or resets another script.

// Original Incoprea example. MIT.
list REQUIRED=["Controller","Display"];
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer i;
        integer issues;
        for(i=0;i<llGetListLength(REQUIRED);++i)
        {
            string name=llList2String(REQUIRED,i);
            if(llGetInventoryType(name)!=INVENTORY_SCRIPT)
            {
                ++issues;
                llOwnerSay("Missing script: "+name);
            }
            else if(!llGetScriptState(name))
            {
                ++issues;
                llOwnerSay("Stopped script: "+name);
            }
            else llOwnerSay("Running flag set: "+name);
        }
        llOwnerSay("Dependency findings: "+(string)issues);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Advanced

Check scale values through a JSON numeric record

Serialize actual prim dimensions as three JSON numbers and reconstruct the vector.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Resize the test prim, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

This checks field retrieval and numerical roundtrip for live dimensions; it does not preserve original textual formatting.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector size=llGetScale();
        string document=llList2Json(JSON_OBJECT,["x",size.x,"y",size.y,"z",size.z]);
        if(document==JSON_INVALID)
        {
            llOwnerSay("JSON construction failed.");
            return;
        }
        vector restored=<(float)llJsonGetValue(document,["x"]),(float)llJsonGetValue(document,["y"]),(float)llJsonGetValue(document,["z"])>;
        float error=llVecDist(size,restored);
        llOwnerSay("Scale JSON pass="+(string)(error<0.001)+" error="+(string)error+" record="+document);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Intermediate

Check texture rotation against quarter turns

Measure how far a touched texture’s rotation is from the nearest90-degree alignment.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Uses the stored texture rotation, not the prim’s world rotation. The result is a proposed correction only.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        float angle=llList2Float(llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]),3);
        float target=llRound(angle/PI_BY_TWO)*PI_BY_TWO;
        llOwnerSay("Texture degrees="+(string)(angle*RAD_TO_DEG)+" nearest quarter turn="+(string)(target*RAD_TO_DEG)+" correction="+(string)((target-angle)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Advanced

Check whether a Description changed since a checkpoint

Capture the current Description digest and compare against it on the next touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch to checkpoint, edit Description manually, then touch to compare.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Only a digest and change status are displayed; no Description text is exposed or overwritten.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
integer checkpoint;
string digest;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string current=llMD5String(llGetObjectDesc(),0);
        if(!checkpoint)
        {
            digest=current;
            checkpoint=TRUE;
            llOwnerSay("Description checkpoint captured.");
        }
        else
        {
            llOwnerSay("Description changed="+(string)(current!=digest));
            checkpoint=FALSE;
        }
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Check whether two components face each other

Compare two children’s local forward axes with the line joining their centers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Assumes local+X is each model’s front. It reports alignment cosines rather than rotating anything.

// Original Incoprea. MIT. Owner-only live inspection.
integer pending;
vector position;
rotation orientation;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(link<2)
        {
            llOwnerSay("Touch linked children.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_POS_LOCAL,PRIM_ROT_LOCAL]);
        vector p=llList2Vector(data,0);
        rotation r=llList2Rot(data,1);
        if(!pending)
        {
            position=p;
            orientation=r;
            pending=TRUE;
            llOwnerSay("First child captured; touch second child.");
            return;
        }
        pending=FALSE;
        vector d=p-position;
        if(llVecMag(d)<0.000001)
        {
            llOwnerSay("Centers coincide.");
            return;
        }
        d=llVecNorm(d);
        float first=(<1.0,0.0,0.0>*orientation)*d;
        float second=(<1.0,0.0,0.0>*r)*(-d);
        llOwnerSay("Facing-toward cosines: first="+(string)first+" second="+(string)second+" (1 directly toward)");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Diagnostics · Intermediate

Classify a component’s geometric proportions

Sort the actual prim’s three scale axes and report flatness and elongation ratios.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Scale describes the prim/mesh bounding dimensions, not internal mesh geometry or physical thickness.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        vector size=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_SIZE]),0);
        list axes=llListSort([size.x,"X",size.y,"Y",size.z,"Z"],2,TRUE);
        float small=llList2Float(axes,0);
        float middle=llList2Float(axes,2);
        float large=llList2Float(axes,4);
        if(small<=0.0||middle<=0.0)
        {
            llOwnerSay("Invalid scale.");
            return;
        }
        llOwnerSay("Shortest="+llList2String(axes,1)+" longest="+llList2String(axes,5)+" flatness(short/middle)="+(string)(small/middle)+" elongation(long/middle)="+(string)(large/middle));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Compare alpha render modes across faces

List legacy alpha mode and cutoff on every face of a clicked component.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

This reads configured modes rather than inferring texture alpha contents. Mode support can differ by grid/material pipeline.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use1..32 faces.");
            return;
        }
        integer i;
        for(i=0;i<count;++i)
        {
            list data=llGetLinkPrimitiveParams(link,[PRIM_ALPHA_MODE,i]);
            integer mode=llList2Integer(data,0);
            string label="unknown";
            if(mode==PRIM_ALPHA_MODE_NONE)label="none";
            else if(mode==PRIM_ALPHA_MODE_BLEND)label="blend";
            else if(mode==PRIM_ALPHA_MODE_MASK)label="mask";
            else if(mode==PRIM_ALPHA_MODE_EMISSIVE)label="emissive";
            llOwnerSay("Face "+(string)i+" mode="+label+" cutoff="+(string)llList2Integer(data,1));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Compare dimensions of two clicked components

Record a component’s size, then report per-axis ratios for a second component.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Both sizes are their own local-axis dimensions; rotations do not affect these ratios.

// Original Incoprea. MIT. Owner-only live inspection.
integer pending;
vector reference;
integer referenceLink;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        vector size=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_SIZE]),0);
        if(!pending)
        {
            reference=size;
            referenceLink=link;
            pending=TRUE;
            llOwnerSay("Reference size captured; touch another component.");
            return;
        }
        pending=FALSE;
        if(reference.x<=0.0||reference.y<=0.0||reference.z<=0.0)
        {
            llOwnerSay("Reference size invalid.");
            return;
        }
        llOwnerSay("Comparison/reference axis ratios="+(string)<size.x/reference.x,size.y/reference.y,size.z/reference.z>+" reference link="+(string)referenceLink);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Intermediate

Compare elapsed and Unix clocks

Compare a short runtime interval with the Unix-clock interval.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner, then touch again after a few seconds.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Unix time has integer-second resolution; a small difference is normal. This is a two-clock observation, not evidence of clock tampering.

// Original Incoprea example. MIT.
integer ready;
integer unixStart;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(!ready)
        {
            unixStart=llGetUnixTime();
            llResetTime();
            ready=TRUE;
            llOwnerSay("Clock sample started; touch again later.");
            return;
        }
        float elapsed=llGetTime();
        integer unixElapsed=llGetUnixTime()-unixStart;
        ready=FALSE;
        llOwnerSay("Runtime seconds: "+(string)elapsed+"; integer Unix seconds: "+(string)unixElapsed);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Compare normal-map and diffuseUV transforms

Report differences between the touched face’s legacy normal-map and diffuse repeats, offset and rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

A missing normal map is reported. Matching transforms are not always artistically required, and PBR materials are outside this legacy check.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        list diffuse=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]);
        list normal=llGetLinkPrimitiveParams(link,[PRIM_NORMAL,face]);
        if(llList2Key(normal,0)==NULL_KEY)
        {
            llOwnerSay("No legacy normal map.");
            return;
        }
        vector dr=llList2Vector(normal,1)-llList2Vector(diffuse,1);
        vector offset=llList2Vector(normal,2)-llList2Vector(diffuse,2);
        float angle=llList2Float(normal,3)-llList2Float(diffuse,3);
        llOwnerSay("Normal minus diffuse repeats="+(string)dr+" offset="+(string)offset+" rotation degrees="+(string)(angle*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Compare orientations of two clicked components

Record one linked component, then compare another component’s local orientation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

The first click is the reference; the next click reports minimum angular difference. Clicking again starts a new pair. Root is excluded.

// Original Incoprea. MIT. Owner-only live inspection.
integer pending;
rotation reference;
integer referenceLink;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(link<2)
        {
            llOwnerSay("Touch a linked child.");
            return;
        }
        rotation r=llList2Rot(llGetLinkPrimitiveParams(link,[PRIM_ROT_LOCAL]),0);
        if(!pending)
        {
            reference=r;
            referenceLink=link;
            pending=TRUE;
            llOwnerSay("Reference child recorded; touch comparison child.");
            return;
        }
        pending=FALSE;
        llOwnerSay("Children "+(string)referenceLink+" / "+(string)link+" minimum rotation difference="+(string)(llAngleBetween(reference,r)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Compare specular-map and diffuseUV transforms

Report mapping differences for the touched face’s legacy specular layer.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Does not evaluate roughness or modern glTF/PBR material transforms. Matching is a design choice, not a universal requirement.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        list diffuse=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]);
        list specular=llGetLinkPrimitiveParams(link,[PRIM_SPECULAR,face]);
        if(llList2Key(specular,0)==NULL_KEY)
        {
            llOwnerSay("No legacy specular map.");
            return;
        }
        llOwnerSay("Repeat delta="+(string)(llList2Vector(specular,1)-llList2Vector(diffuse,1))+" offset delta="+(string)(llList2Vector(specular,2)-llList2Vector(diffuse,2))+" rotation delta degrees="+(string)((llList2Float(specular,3)-llList2Float(diffuse,3))*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Compare texture assets on two touched faces

Record one touched face’s diffuse texture identifier and compare another.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Compares identifiers only; it does not compare pixel appearance, rights, repeats or rendered materials.

// Original Incoprea. MIT. Owner-only live inspection.
integer pending;
key reference;
string location;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        key texture=llList2Key(llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]),0);
        string current=(string)link+":"+(string)face;
        if(!pending)
        {
            reference=texture;
            location=current;
            pending=TRUE;
            llOwnerSay("Reference face recorded; touch another face.");
            return;
        }
        pending=FALSE;
        llOwnerSay("Faces "+location+" / "+current+" same diffuse asset="+(string)(reference==texture));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Correlate two notecard requests arriving asynchronously

Request line count and first line simultaneously and identify each response by its query key.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Add a notecard named testcard; touch once.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Responses may arrive in either order. This demonstrates correlation without assuming order; it stops after fifteen seconds.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
key countRequest;
key lineRequest;
integer waiting;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||waiting)return;
        if(llGetInventoryType("testcard")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add testcard notecard.");
            return;
        }
        waiting=2;
        countRequest=llGetNumberOfNotecardLines("testcard");
        lineRequest=llGetNotecardLine("testcard",0);
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(waiting==0)return;
        if(id==countRequest)
        {
            countRequest=NULL_KEY;
            --waiting;
            llOwnerSay("Count response="+data);
        }
        else if(id==lineRequest)
        {
            lineRequest=NULL_KEY;
            --waiting;
            llOwnerSay("First-line response received; EOF="+(string)(data==EOF)+" characters="+(string)llStringLength(data));
        }
        else return;
        if(waiting==0)
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Both requests correlated.");
        }
    }
    timer()
    {
        llSetTimerEvent(0.0);
        llOwnerSay("Responses still missing="+(string)waiting);
        waiting=0;
        countRequest=NULL_KEY;
        lineRequest=NULL_KEY;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Intermediate

Count build-edit events

Tally scale, color, texture, and inventory change events for this object’s testing session.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a test build, edit it, and touch as owner for totals.

Stop / restore: Remove or disable; it changes no object or parcel properties.

One event can carry several flags, and multiple changes can be coalesced. Counts represent events rather than individual user edits. No content or visitor history is stored.

// Original Incoprea example. MIT.
integer scales;
integer colors;
integer textures;
integer inventories;
default
{
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)
        {
            llResetScript();
            return;
        }
        if(flags & CHANGED_SCALE)++scales;
        if(flags & CHANGED_COLOR)++colors;
        if(flags & CHANGED_TEXTURE)++textures;
        if(flags & CHANGED_INVENTORY)++inventories;
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("Scale events: "+(string)scales+"; color: "+(string)colors+"; texture: "+(string)textures+"; inventory: "+(string)inventories);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Create a script support context report

Report script name, prim name, link position, simulator version, and memory in one support note.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in the object being tested.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Only current object metadata is included. Copy the report into a bug note; it does not transmit to a support service or prove a root cause.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("Script: "+llGetScriptName()+" / prim: "+llGetObjectName()+" / link: "+(string)llGetLinkNumber());
        llOwnerSay("Region: "+llGetRegionName()+" / server: "+llGetEnv("sim_version"));
        llOwnerSay("Free script memory: "+(string)llGetFreeMemory()+" bytes; prim inventory items: "+(string)llGetInventoryNumber(INVENTORY_ALL));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Current parcel metadata

Report the parcel’s name and description at this object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in a rezzed object.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Does not inspect or list residents, visitors, owners, or access lists. Parcel description text may be long and owner chat may truncate it.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list info=llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME,PARCEL_DETAILS_DESC]);
        if(llGetListLength(info)!=2)
        {
            llOwnerSay("Parcel metadata unavailable.");
            return;
        }
        llOwnerSay("Parcel: "+llList2String(info,0));
        llOwnerSay("Description: "+llList2String(info,1));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Diagnostics · Intermediate

Detect mirrored or collapsed texture axes

Classify the sign and zero status of touched-face texture repeats.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Negative repeats mirror an axis. A zero repeat collapses sampling along that coordinate; meshes and planar mapping add their own conventions.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        list params=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]);
        vector repeats=llList2Vector(params,1);
        llOwnerSay("Repeats="+(string)repeats+" U mirrored="+(string)(repeats.x<0.0)+" V mirrored="+(string)(repeats.y<0.0));
        if(llFabs(repeats.x)<0.000001||llFabs(repeats.y)<0.000001)llOwnerSay("At least one repeat axis is effectively zero.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Intermediate

Estimate summed component boxes versus envelope

Compare the sum of prim bounding-box volumes with the linkset’s overall bounding-box volume.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Bounding boxes can overlap and meshes can be hollow; this is a layout density indicator, not actual solid volume or land impact. At most64 prims.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetObjectPrimCount(llGetKey());
        if(count<1||count>64)
        {
            llOwnerSay("Use a rezzed build with1..64 prims.");
            return;
        }
        float sum;
        integer i;
        for(i=1;i<=count;++i)
        {
            vector size=llList2Vector(llGetLinkPrimitiveParams(i,[PRIM_SIZE]),0);
            sum+=size.x*size.y*size.z;
        }
        list bounds=llGetBoundingBox(llGetKey());
        vector size=llList2Vector(bounds,1)-llList2Vector(bounds,0);
        float envelope=size.x*size.y*size.z;
        llOwnerSay("Summed component boxes="+(string)sum+" envelope="+(string)envelope);
        if(envelope>0.0)llOwnerSay("Box ratio="+(string)(sum/envelope));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Diagnostics · Intermediate

Find alpha differences across one component

Compare configured face alpha values on the clicked component.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Reads tint alpha, not texture pixel transparency or material blend behavior. Scans at most32 faces.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use a component with1..32 faces.");
            return;
        }
        float reference=llList2Float(llGetLinkPrimitiveParams(link,[PRIM_COLOR,0]),1);
        integer mismatches;
        integer i;
        for(i=0;i<count;++i)
        {
            float alpha=llList2Float(llGetLinkPrimitiveParams(link,[PRIM_COLOR,i]),1);
            if(llFabs(alpha-reference)>0.001)
            {
                ++mismatches;
                llOwnerSay("Face "+(string)i+" alpha="+(string)alpha);
            }
        }
        llOwnerSay("Face0 alpha="+(string)reference+" differing faces="+(string)mismatches);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Find nearby objects you own

Scan objects within ten meters and report only those owned by the current owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object and touch as owner.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Never requests avatar sensing. Only owner-owned object results are displayed. Sensor results are capped by the simulator and are not a complete parcel inventory.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llSensor("",NULL_KEY,ACTIVE|PASSIVE,10,PI);
    }
    sensor(integer detections)
    {
        integer i;
        integer matches;
        for(i=0;i<detections;++i)if(llGetOwnerKey(llDetectedKey(i))==llGetOwner())
        {
            ++matches;
            llOwnerSay(llDetectedName(i)+": "+(string)llVecDist(llGetPos(),llDetectedPos(i))+" m");
        }
        llOwnerSay("Owner-owned objects in returned results: "+(string)matches);
    }
    no_sensor()
    {
        llOwnerSay("No objects returned by this scan.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Find the strongest configured glow face

Report minimum, maximum and average configured glow on a touched component.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

The average is a setting summary, not a physical brightness or performance measurement.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use1..32 faces.");
            return;
        }
        float minimum=1.0;
        float maximum;
        float total;
        integer strongest;
        integer i;
        for(i=0;i<count;++i)
        {
            float glow=llList2Float(llGetLinkPrimitiveParams(link,[PRIM_GLOW,i]),0);
            total+=glow;
            if(glow<minimum)minimum=glow;
            if(glow>maximum)
            {
                maximum=glow;
                strongest=i;
            }
        }
        llOwnerSay("Glow min="+(string)minimum+" max="+(string)maximum+" strongest face="+(string)strongest+" mean="+(string)(total/count));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Find tint differences across one component

Compare each face’s stored tint against face0 with a small vector tolerance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Texture pixels, PBR base color and lighting can change apparent color; this reports the stored legacy tint only.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use1..32 faces.");
            return;
        }
        vector reference=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_COLOR,0]),0);
        integer mismatches;
        integer i;
        for(i=0;i<count;++i)
        {
            vector tint=llList2Vector(llGetLinkPrimitiveParams(link,[PRIM_COLOR,i]),0);
            if(llVecDist(tint,reference)>0.001)
            {
                ++mismatches;
                llOwnerSay("Face "+(string)i+" tint="+(string)tint);
            }
        }
        llOwnerSay("Face0 tint="+(string)reference+" mismatches="+(string)mismatches);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Fingerprint the touched face’s mapping settings

Build a deterministic digest of legacy diffuse mapping settings for later comparisons.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

A digest is a change indicator, not proof of authorship, permissions or pixel equality. It prints the source settings too.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        if(face<0)
        {
            llOwnerSay("Touch a face.");
            return;
        }
        list params=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face,PRIM_TEXGEN,face]);
        string canonical=llDumpList2String(params,"|");
        llOwnerSay("Mapping="+canonical);
        llOwnerSay("MD5 change fingerprint="+llMD5String(canonical,0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5 · API reference 6

Diagnostics · Beginner

Five-sample timer check

Measure five actual gaps from a requested two-second timer, then stop.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner to start or restart one short measurement run.

Stop / restore: Stops automatically after five samples. Removing the script also stops it.

Timer intervals are requests, not exact deadlines. This script measures its own scheduling and does not identify the cause of delays.

// Original Incoprea example. MIT.
integer samples;
float total;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        samples = 0;
        total = 0.0;
        llResetTime();
        llSetTimerEvent(2.0);
        llOwnerSay("Measuring five timer intervals...");
    }
    timer()
    {
        float elapsed = llGetAndResetTime();
        total += elapsed;
        ++samples;
        llOwnerSay("Interval " + (string)samples + ": " + (string)elapsed + " seconds.");
        if (samples >= 5)
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Mean interval: " + (string)(total / (float)samples) + " seconds.");
        }
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Height above local terrain and water

Report the prim center’s vertical distance above terrain and water at its location.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object and touch as owner.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Measures the prim center, not its bottom or collision shape. It does not probe other objects or avatars. Water and terrain behavior can vary by simulator.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        if(llGetAttached())
        {
            llOwnerSay("Use a rezzed object.");
            return;
        }
        vector position=llGetPos();
        float terrain=llGround(ZERO_VECTOR);
        float water=llWater(ZERO_VECTOR);
        llOwnerSay("Center above terrain: "+(string)(position.z-terrain)+" m");
        llOwnerSay("Center above water: "+(string)(position.z-water)+" m");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Inspect a component’s floating-label footprint

Report floating-text length, line count and stored opacity without printing the label contents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Byte count uses Base64 length to measure UTF8 bytes. It does not assess visual line wrapping or viewer clipping.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        list data=llGetLinkPrimitiveParams(link,[PRIM_TEXT]);
        string label=llList2String(data,0);
        integer lines=0;
        if(label!="")lines=llGetListLength(llParseStringKeepNulls(label,["
"],[]));
        string encoded=llStringToBase64(label);
        integer length=llStringLength(encoded);
        integer padding;
        if(length>0&&llGetSubString(encoded,-1,-1)=="=")++padding;
        if(length>1&&llGetSubString(encoded,-2,-2)=="=")++padding;
        integer bytes=length*3/4-padding;
        llOwnerSay("Label characters="+(string)llStringLength(label)+" UTF8 bytes="+(string)bytes+" explicit lines="+(string)lines+" opacity="+(string)llList2Float(data,2));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Inspect a rez start parameter

Report the integer start parameter supplied when this object was rezzed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a test object. Touch as owner, or rez it through your own rezzer.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

The parameter is an integer supplied by a rez operation; it is not an authenticated identity. Ordinary manual rezzing commonly supplies zero.

// Original Incoprea example. MIT.
default
{
    on_rez(integer parameter)
    {
        llOwnerSay("on_rez parameter: "+(string)parameter);
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("llGetStartParameter: "+(string)llGetStartParameter());
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Beginner

Inspect physical motion vectors

Read this object’s velocity, acceleration, and angular velocity on owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object and touch as owner. A stationary object normally reports zero or near-zero motion.

Stop / restore: Remove or disable the script. It does not change the build.

These are simulator motion readings. Nonphysical target-omega is a viewer effect and may not appear as physical angular velocity here. The script never adds forces or stops motion.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Velocity (m/s): " + (string)llGetVel());
        llOwnerSay("Acceleration (m/s squared): " + (string)llGetAccel());
        llOwnerSay("Angular velocity (radians/s): " + (string)llGetOmega());
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Inspect planar versus default mapping modes

Report the texture-generation mode stored on each face of a touched component.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Planar mapping has different repeat semantics. This inspector does not infer whether a texture looks correctly scaled.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use1..32 faces.");
            return;
        }
        integer i;
        for(i=0;i<count;++i)
        {
            integer mode=llList2Integer(llGetLinkPrimitiveParams(link,[PRIM_TEXGEN,i]),0);
            string name="default";
            if(mode==PRIM_TEXGEN_PLANAR)name="planar";
            llOwnerSay("Face "+(string)i+" texgen="+name+" raw="+(string)mode);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Beginner

Inspect stored floating text

Read the text, color, and alpha stored on this prim, even if the original label script is gone.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the exact prim with the label and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

A zero alpha can hide a stored label visually, but it does not make the text private. To remove it, run Clear floating text after stopping scripts that recreate it.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list data = llGetPrimitiveParams([PRIM_TEXT]);
        if (llGetListLength(data) != 3)
        {
            llOwnerSay("Text data unavailable.");
            return;
        }
        llOwnerSay("Stored text: [" + llList2String(data, 0) + "]");
        llOwnerSay("Color: " + llList2String(data, 1) + "; alpha: " + llList2String(data, 2));
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Inspect this script’s inventory identity

Report this script’s exact inventory name and its own exposed asset key.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in the object containing the script.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Restricted permissions can hide an asset key. Script keys may be pseudo-identifiers; they are not proof of source-code equality or author rights.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string name=llGetScriptName();
        llOwnerSay("Script inventory name: ["+name+"]");
        key asset=llGetInventoryKey(name);
        if(asset==NULL_KEY)llOwnerSay("No exposed key; permissions or asset state may hide it.");
        else llOwnerSay("Exposed script identifier: "+(string)asset);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Inspect this script’s permission state

Report the currently held permission mask and whether its grantee is the owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Integrate the report into a permission-using script to inspect that script’s state.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

A separate diagnostic script cannot read another script’s permission state. This example requests no permissions and normally reports zero.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer permissions=llGetPermissions();
        key grantee=llGetPermissionsKey();
        llOwnerSay("This script permission mask: "+(string)permissions);
        llOwnerSay("Permission key is owner: "+(string)(grantee==llGetOwner()));
        if(permissions==0)llOwnerSay("No granted runtime permissions in this script.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Inspect touch routing through a linkset

Report the prim receiving the script event and the prim actually touched.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in one prim of a linkset and touch linked components as owner.

Stop / restore: Remove or disable. This inspector changes no build properties.

Touch propagation depends on other scripts and pass-touch settings. A silent component may consume its event elsewhere; the script does not modify routing.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        llOwnerSay("Script prim link: "+(string)llGetLinkNumber());
        llOwnerSay("Touched prim link: "+(string)llDetectedLinkNumber(0)+"; face: "+(string)llDetectedTouchFace(0));
        llOwnerSay("Detected owner touches in this event: "+(string)count);
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Map fullbright faces on a touched component

List which faces have legacy fullbright enabled.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare owned prim or linkset root. Touch the face or component to inspect. Child scripts may consume touches; face-based tools require a viewer that supplies touched-face data.

Stop / restore: Remove/disable. Inspectors read state and report only to the owner; they do not change the build.

Fullbright is a stored rendering flag; materials and viewers may affect appearance. No flags are changed.

// Original Incoprea. MIT. Owner-only live inspection.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        integer face=llDetectedTouchFace(0);
        integer count=llGetLinkNumberOfSides(link);
        if(count<1||count>32)
        {
            llOwnerSay("Use1..32 faces.");
            return;
        }
        list enabled;
        integer i;
        for(i=0;i<count;++i)if(llList2Integer(llGetLinkPrimitiveParams(link,[PRIM_FULLBRIGHT,i]),0))enabled+=[i];
        llOwnerSay("Fullbright faces="+llDumpList2String(enabled,",")+" / "+(string)count);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Intermediate

Measure a linked-message round trip

Send a correlated ping through the link-message event queue and report the elapsed time.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Works with one script; no companion needed.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Measures this script’s queue round trip, not network latency. Other scripts could use the same message numbers; a request token avoids confusing unrelated replies.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(pending!=NULL_KEY)return;
        pending=llGenerateKey();
        llResetTime();
        llSetTimerEvent(5);
        llMessageLinked(LINK_THIS,71001,"ping",pending);
    }
    link_message(integer sender,integer code,string text,key token)
    {
        if(token!=pending || pending==NULL_KEY)return;
        if(code==71001 && text=="ping")llMessageLinked(LINK_THIS,71002,"pong",token);
        else if(code==71002 && text=="pong")
        {
            float elapsed=llGetTime();
            pending=NULL_KEY;
            llSetTimerEvent(0);
            llOwnerSay("Linked-message round trip: "+(string)elapsed+" seconds.");
        }
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0);
        llOwnerSay("Probe timed out.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Measure a notecard line request

Time one asynchronous request for the first line of a saved notecard.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Add a saved plain-text Notes notecard and touch as owner.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Reports latency and returned character count, not the card contents. Includes simulator/cache effects and is not a network benchmark.

// Original Incoprea example. MIT.
key pending=NULL_KEY;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner() || pending!=NULL_KEY)return;
        if(llGetInventoryType("Notes")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add a saved Notes notecard.");
            return;
        }
        llResetTime();
        pending=llGetNotecardLine("Notes",0);
        llSetTimerEvent(20);
    }
    dataserver(key query,string data)
    {
        if(query!=pending || pending==NULL_KEY)return;
        float seconds=llGetTime();
        pending=NULL_KEY;
        llSetTimerEvent(0);
        if(data==EOF)llOwnerSay("EOF after "+(string)seconds+" seconds.");
        else llOwnerSay("First-line response: "+(string)seconds+" seconds; returned characters: "+(string)llStringLength(data));
    }
    timer()
    {
        pending=NULL_KEY;
        llSetTimerEvent(0);
        llOwnerSay("Request timed out.");
    }
    changed(integer flags)
    {
        if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Measure a small list’s memory footprint

Compare this script’s reported memory before and after creating a bounded list of strings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner; no configuration required.

Stop / restore: Remove or disable; it changes no object or parcel properties.

A teaching measurement, not a benchmark of all scripts. Garbage collection and simulator engine differences can alter readings. Uses only 100 small entries and clears them afterward.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        list sample=[];
        integer before=llGetUsedMemory();
        integer i;
        for(i=0;i<100;++i)sample += ["record-"+(string)i];
        integer after=llGetUsedMemory();
        llOwnerSay("100-entry list observed memory delta: "+(string)(after-before)+" bytes; entries="+(string)llGetListLength(sample));
        sample=[];
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Diagnostics · Intermediate

Measure an owner touch gesture

Measure elapsed time between the owner’s touch start and release events.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch and hold the prim as owner, then release.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Measures event timing, not precise human reaction time. Only the owner key is accepted; simultaneous touches from others are ignored.

// Original Incoprea example. MIT.
integer measuring;
default
{
    touch_start(integer touches)
    {
        integer i;
        for(i=0;i<touches;++i)if(llDetectedKey(i)==llGetOwner())
        {
            llResetTime();
            measuring=TRUE;
        }
    }
    touch_end(integer touches)
    {
        integer i;
        for(i=0;i<touches;++i)if(measuring && llDetectedKey(i)==llGetOwner())
        {
            float elapsed=llGetTime();
            measuring=FALSE;
            llOwnerSay("Held for approximately "+(string)elapsed+" seconds.");
        }
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Advanced

Measure coordinate loss through a string roundtrip

Serialize the actual position to its default LSL string form and parse it back.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Move the test object, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Default numeric formatting may lose precision; the harness reports the measured loss instead of requiring bitwise identity.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector original=llGetPos();
        string encoded=(string)original;
        vector restored=(vector)encoded;
        llOwnerSay("Position text="+encoded+" roundtrip error metres="+(string)llVecDist(original,restored));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Advanced

Observe how resetting script elapsed time behaves

Record elapsed time, reset it, then report immediate and delayed observations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch to start a one-second local timer test.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

This affects only this script’s elapsed clock; it does not reset the simulator clock or other scripts.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
integer active;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||active)return;
        float before=llGetTime();
        llResetTime();
        float immediate=llGetTime();
        active=TRUE;
        llOwnerSay("Before reset="+(string)before+" immediate after="+(string)immediate);
        llSetTimerEvent(1.0);
    }
    timer()
    {
        llSetTimerEvent(0.0);
        if(active)llOwnerSay("Elapsed at first timer="+(string)llGetTime());
        active=FALSE;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Observe timer cancellation after one event

Start a timer, cancel it on the first callback, and report callback count on the next touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch to start; after several seconds touch again for the count.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Queued events and simulator timing can vary. The handler ignores callbacks outside the active counting session.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
integer phase;
integer callbacks;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(phase==0)
        {
            callbacks=0;
            phase=1;
            llSetTimerEvent(0.5);
            llOwnerSay("Timer armed; touch later to report.");
        }
        else
        {
            llSetTimerEvent(0.0);
            llOwnerSay("Callbacks observed="+(string)callbacks);
            phase=0;
        }
    }
    timer()
    {
        if(phase==0)return;
        ++callbacks;
        llSetTimerEvent(0.0);
        phase=2;
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Observe two short string-join methods

Time repeated concatenation and list joining over the same small input.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Runs only fifty short words.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Tiny timing values can be dominated by scheduling and resolution. This is an observation tool, not a reliable cross-engine benchmark or optimization verdict.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list words=[];
        integer i;
        for(i=0;i<50;++i)words += ["word"];
        llResetTime();
        string joined="";
        for(i=0;i<50;++i)
        {
            if(i)joined+=" ";
            joined+=llList2String(words,i);
        }
        float concatTime=llGetTime();
        llResetTime();
        string dumped=llDumpList2String(words," ");
        float listTime=llGetTime();
        llOwnerSay("Concatenation seconds: "+(string)concatTime+"; list join seconds: "+(string)listTime+"; equal output="+(string)(joined==dumped));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Parcel general permission flags

Read public script, build, fly, and damage flags at the object’s position.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a rezzed object and touch as owner.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Flags are informational and do not fully resolve owner/group exceptions or region restrictions. A running diagnostic cannot prove every other script can run.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        integer flags=llGetParcelFlags(llGetPos());
        llOwnerSay("General scripts: "+(string)((flags & PARCEL_FLAG_ALLOW_SCRIPTS)!=0));
        llOwnerSay("General build: "+(string)((flags & PARCEL_FLAG_ALLOW_CREATE_OBJECTS)!=0));
        llOwnerSay("Fly: "+(string)((flags & PARCEL_FLAG_ALLOW_FLY)!=0)+"; damage: "+(string)((flags & PARCEL_FLAG_ALLOW_DAMAGE)!=0));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1

Diagnostics · Beginner

Physics and phantom status

Read whether an object is currently physical and phantom.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the object and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Reading flags does not prove collision behavior for every mesh physics shape, attachment, or region. This example changes no physics settings.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Physical: " + (string)llGetStatus(STATUS_PHYSICS));
        llOwnerSay("Phantom: " + (string)llGetStatus(STATUS_PHANTOM));
        llOwnerSay("Attached at point: " + (string)llGetAttached() + " (0 means not attached).");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Reassemble a chunked local message

Split a short string into fixed-size self-messages and reconstruct it in order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Edit TEXT under 400 characters; touch as owner.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

One transfer at a time. The token and expected index reject stale or out-of-order chunks. This does not send messages outside the object.

// Original Incoprea example. MIT.
string TEXT="A longer workshop note can be transported in several small linked-message chunks.";
key token=NULL_KEY;
integer expected;
integer total;
string assembled;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner() || token!=NULL_KEY)return;
        if(llStringLength(TEXT)>400)
        {
            llOwnerSay("Keep the sample under 401 characters.");
            return;
        }
        token=llGenerateKey();
        expected=0;
        assembled="";
        total=(llStringLength(TEXT)+19)/20;
        if(!total)
        {
            token=NULL_KEY;
            llOwnerSay("Empty source.");
            return;
        }
        llSetTimerEvent(5);
        integer i;
        for(i=0;i<total;++i)llMessageLinked(LINK_THIS,72000+i,llGetSubString(TEXT,i*20,i*20+19),token);
    }
    link_message(integer sender,integer code,string part,key id)
    {
        if(id!=token || token==NULL_KEY || code<72000 || code>=72000+total)return;
        if(code-72000!=expected)
        {
            token=NULL_KEY;
            llSetTimerEvent(0);
            llOwnerSay("Out-of-order transfer rejected.");
            return;
        }
        assembled+=part;
        ++expected;
        if(expected==total)
        {
            token=NULL_KEY;
            llSetTimerEvent(0);
            if(assembled==TEXT)llOwnerSay("Reassembled correctly: "+assembled);
            else llOwnerSay("Reassembled text differs.");
        }
    }
    timer()
    {
        token=NULL_KEY;
        assembled="";
        llSetTimerEvent(0);
        llOwnerSay("Transfer timed out.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Beginner

Region performance snapshot

Read simulator frame rate and time dilation on an owner touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a prim and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Simulator FPS is not your viewer’s graphics FPS. These values are a momentary signal, not a diagnosis of which object or person causes lag. Region targets may differ by grid.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Region: " + llGetRegionName());
        llOwnerSay("Simulator FPS: " + (string)llGetRegionFPS());
        llOwnerSay("Time dilation: " + (string)llGetRegionTimeDilation());
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Report collisions with your own objects

Report collision-start events only when the other object shares your owner.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a test object that can receive collision events.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Avatar detections are excluded and other owners’ objects are ignored. Does not change physics or store contact history; collision events depend on object physics and simulator behavior.

// Original Incoprea example. MIT.
default
{
    collision_start(integer contacts)
    {
        integer i;
        for(i=0;i<contacts;++i)
        {
            if(!(llDetectedType(i) & AGENT) && llGetOwnerKey(llDetectedKey(i))==llGetOwner())llOwnerSay("Own-object collision: "+llDetectedName(i)+"; detected speed="+(string)llVecMag(llDetectedVel(i))+" m/s");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Report object owner and group configuration

Compare the object’s owner and assigned group keys without examining nearby people.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in an avatar-owned object.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

An assigned group is not the same as group ownership. A group-owned object cannot use ordinary avatar-owner touch authorization and is outside this example.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list data=llGetObjectDetails(llGetKey(),[OBJECT_GROUP]);
        key group=llList2Key(data,0);
        llOwnerSay("Object owner: "+(string)llGetOwner());
        if(group==NULL_KEY)llOwnerSay("No group assigned.");
        else llOwnerSay("Assigned object group: "+(string)group);
        llOwnerSay("This report is configuration metadata, not a membership check.");
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Route namespaced linked commands

Demonstrate a small versioned command namespace with explicit allowed commands.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner to send three example self-commands.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

The same script receives its own messages, so no companion is required. Unknown versions and commands are rejected; text is never executed as code.

// Original Incoprea example. MIT.
key run=NULL_KEY;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        run=llGenerateKey();
        llMessageLinked(LINK_THIS,73001,"v1|name",run);
        llMessageLinked(LINK_THIS,73001,"v1|size",run);
        llMessageLinked(LINK_THIS,73001,"v9|delete",run);
    }
    link_message(integer sender,integer code,string text,key token)
    {
        if(code!=73001 || token!=run || run==NULL_KEY)return;
        list parts=llParseStringKeepNulls(text,["|"],[]);
        if(llGetListLength(parts)!=2 || llList2String(parts,0)!="v1")
        {
            llOwnerSay("Rejected unsupported message version/shape.");
            return;
        }
        string command=llList2String(parts,1);
        if(command=="name")llOwnerSay(llGetObjectName());
        else if(command=="size")llOwnerSay((string)llGetScale());
        else llOwnerSay("Rejected unknown command.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Run ten bounded dependency checks

Watch one named script’s existence and Running flag for ten seconds, reporting state changes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Set TARGET and touch as owner to start.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Stops after ten samples and does not restart dependencies. A Running flag cannot detect every runtime failure.

// Original Incoprea example. MIT.
string TARGET="Controller";
integer samples;
integer previous=-1;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        samples=0;
        previous=-1;
        llSetTimerEvent(1);
        llOwnerSay("Ten-sample watch started.");
    }
    timer()
    {
        integer status=0;
        if(llGetInventoryType(TARGET)==INVENTORY_SCRIPT)
        {
            status=1;
            if(llGetScriptState(TARGET))status=2;
        }
        if(status!=previous)
        {
            llOwnerSay("Dependency status: "+(string)status+" (0 missing, 1 stopped, 2 running flag)");
            previous=status;
        }
        ++samples;
        if(samples>=10)
        {
            llSetTimerEvent(0);
            llOwnerSay("Watch completed.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Sample a short region performance window

Collect twelve five-second dilation samples and report their minimum, maximum, and mean.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner and allow about one minute for completion.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

Measures region time dilation, not viewer FPS or an individual user’s impact. Stops after twelve samples; region idling can affect readings.

// Original Incoprea example. MIT.
integer samples;
float sum;
float low;
float high;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        samples=0;
        sum=0;
        low=1e30;
        high=-1;
        llSetTimerEvent(5);
        llOwnerSay("Twelve-sample window started.");
    }
    timer()
    {
        float value=llGetRegionTimeDilation();
        sum+=value;
        if(value<low)low=value;
        if(value>high)high=value;
        ++samples;
        if(samples>=12)
        {
            llSetTimerEvent(0);
            llOwnerSay("Dilation min="+(string)low+", max="+(string)high+", mean="+(string)(sum/samples));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Beginner

Script memory snapshot

Report memory figures for this diagnostic script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. To inspect your own code, integrate the three reporting calls into that script.

Stop / restore: Remove or disable the script. It does not change the build.

This cannot inspect another script’s allocations. Mono and LSO report differently; OpenSim engines may differ again. A single snapshot does not predict peak use.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("This script used bytes: " + (string)llGetUsedMemory());
        llOwnerSay("This script free bytes: " + (string)llGetFreeMemory());
        llOwnerSay("This script memory limit: " + (string)llGetMemoryLimit());
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Simulator version report

Record the region name, simulator channel, and version for reproducible bug reports.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner in the region being tested.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Unsupported environment keys may return empty strings on some grids. Version metadata does not prove support for every LSL function.

// Original Incoprea example. MIT.
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner()) return;
        llOwnerSay("Region: "+llGetRegionName());
        llOwnerSay("Simulator channel: "+llGetEnv("sim_channel"));
        llOwnerSay("Simulator version: "+llGetEnv("sim_version"));
    }
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Advanced

Test a touched world point through the object frame

Convert an actual touch point to object-local coordinates and back, reporting residual error.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch different parts of the test object.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

This checks transformation arithmetic using live inputs; it does not prove meshUV correctness.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Touch position unavailable.");
            return;
        }
        vector world=llDetectedTouchPos(0);
        vector origin=llGetPos();
        rotation r=llGetRot();
        vector local=(world-origin)/r;
        vector restored=origin+local*r;
        float error=llVecDist(world,restored);
        llOwnerSay("Touch roundtrip pass="+(string)(error<0.001)+" error="+(string)error+" local="+(string)local);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Test current orientation through axis-angle conversion

Reconstruct the object’s current rotation from its minimum axis-angle representation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Rotate the object, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Near identity, the axis itself is not unique; identity is handled directly.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation original=llGetRot();
        float angle=llRot2Angle(original);
        rotation restored=ZERO_ROTATION;
        if(angle>0.000001)restored=llAxisAngle2Rot(llRot2Axis(original),angle);
        float error=llAngleBetween(original,restored);
        llOwnerSay("Axis-angle roundtrip pass="+(string)(error<0.001)+" error degrees="+(string)(error*RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Test current orientation through Euler conversion

Convert the actual rotation to Euler angles and back, then compare orientations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Set arbitrary object rotations in Edit and touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Euler angles are nonunique and may jump near singularities; the angular comparison tests orientation rather than identical angle text.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation original=llGetRot();
        vector euler=llRot2Euler(original);
        rotation restored=llEuler2Rot(euler);
        float error=llAngleBetween(original,restored);
        llOwnerSay("Euler roundtrip pass="+(string)(error<0.001)+" angular error degrees="+(string)(error*RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Advanced

Test local-to-world orientation consistency

Reconstruct this child’s world rotation and compare with its current world rotation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Put inside a rezzed linked child, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Uses the minimum angular difference; tolerances account for float conversion.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()!=0||llGetLinkNumber()<2)
        {
            llOwnerSay("Use a rezzed child prim.");
            return;
        }
        rotation predicted=llGetLocalRot()*llGetRootRotation();
        float error=llAngleBetween(predicted,llGetRot());
        llOwnerSay("Orientation reconstruction pass="+(string)(error<0.001)+" error degrees="+(string)(error*RAD_TO_DEG));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Test object Description text through Base64

Round-trip the current Description through Base64 and report equality and sizes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Set Description to test text, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Base64 is encoding, not encryption. The output avoids printing the Description contents.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string original=llGetObjectDesc();
        string encoded=llStringToBase64(original);
        string decoded=llBase64ToString(encoded);
        llOwnerSay("Base64 exact="+(string)(original==decoded)+" source characters="+(string)llStringLength(original)+" encoded characters="+(string)llStringLength(encoded));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Test object-name escaping through JSON

Serialize the live object name as a JSON string property and read it back.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Set a name containing quotes or backslashes, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Tests the local JSON API only; the generated JSON is not published or transmitted.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string original=llGetObjectName();
        string document=llList2Json(JSON_OBJECT,["name",original]);
        if(document==JSON_INVALID)
        {
            llOwnerSay("JSON encoding failed.");
            return;
        }
        string restored=llJsonGetValue(document,["name"]);
        llOwnerSay("JSON roundtrip exact="+(string)(restored==original)+" document="+document);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Advanced

Test root/local/world position consistency

Reconstruct this child prim’s world position from its actual local position and root pose.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Place the script inside a linked child, then touch that child.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Root and attachment behavior differ; this harness requires a rezzed child prim.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetAttached()!=0||llGetLinkNumber()<2)
        {
            llOwnerSay("Use a rezzed child prim.");
            return;
        }
        vector predicted=llGetRootPosition()+llGetLocalPos()*llGetRootRotation();
        float error=llVecDist(predicted,llGetPos());
        llOwnerSay("World-position reconstruction pass="+(string)(error<0.005)+" error metres="+(string)error);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Diagnostics · Advanced

Test the current object name through URL encoding

Encode and decode the real object name and compare exact text.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Give the test object a name with spaces, punctuation or Unicode, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Only the name is used; no URL is opened and no text is sent to a network endpoint.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        string original=llGetObjectName();
        string encoded=llEscapeURL(original);
        string decoded=llUnescapeURL(encoded);
        llOwnerSay("URL roundtrip exact="+(string)(original==decoded)+" encoded="+encoded);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Test the current rotation’s basis invariants

Check the lengths, orthogonality and handedness of the actual object rotation axes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Rotate the test object in Edit, then touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Tolerance is numeric; a passing basis does not prove intended artistic orientation.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation r=llGetRot();
        vector x=<1.0,0.0,0.0>*r;
        vector y=<0.0,1.0,0.0>*r;
        vector z=<0.0,0.0,1.0>*r;
        float lengthError=llFabs(llVecMag(x)-1.0)+llFabs(llVecMag(y)-1.0)+llFabs(llVecMag(z)-1.0);
        float dotError=llFabs(x*y)+llFabs(x*z)+llFabs(y*z);
        float handed=(x%y)*z;
        llOwnerSay("Basis pass="+(string)(lengthError<0.001&&dotError<0.001&&handed>0.999)+" lengthError="+(string)lengthError+" dotError="+(string)dotError+" handedness="+(string)handed);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Advanced

Test the live touched surface frame

Check whether the supplied touch normal and binormal are nonzero and approximately perpendicular.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch several faces or mesh regions.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Mesh/viewer support varies; an unavailable frame is reported separately from a failed numeric check.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llDetectedTouchFace(0)<0)
        {
            llOwnerSay("Surface frame unavailable.");
            return;
        }
        vector normal=llDetectedTouchNormal(0);
        vector binormal=llDetectedTouchBinormal(0);
        if(llVecMag(normal)<0.000001||llVecMag(binormal)<0.000001)
        {
            llOwnerSay("Zero frame vector: unsupported or invalid touch.");
            return;
        }
        float dot=llVecNorm(normal)*llVecNorm(binormal);
        llOwnerSay("Frame perpendicular pass="+(string)(llFabs(dot)<0.01)+" dot="+(string)dot+" raw lengths="+(string)llVecMag(normal)+","+(string)llVecMag(binormal));
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Beginner

This object’s script load

Read the running-script count, total-script count, and average script CPU time for this object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed object and touch as owner.

Stop / restore: Remove or disable the script. It does not change the build.

Queries this object only, never visitors or avatars. CPU time is a simulator-reported average in seconds, converted here to milliseconds. Support and meaning can vary by grid.

// Original Incoprea example. MIT.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list data = llGetObjectDetails(llGetKey(),
        [OBJECT_RUNNING_SCRIPT_COUNT, OBJECT_TOTAL_SCRIPT_COUNT, OBJECT_SCRIPT_TIME]);
        if (llGetListLength(data) != 3)
        {
            llOwnerSay("Script-load details unavailable.");
            return;
        }
        if (llList2Integer(data, 0) < 0 || llList2Integer(data, 1) < 0)
        {
            llOwnerSay("These script-count details are unsupported.");
            return;
        }
        llOwnerSay("Running: " + llList2String(data, 0) + " / total: " + llList2String(data, 1));
        llOwnerSay("Reported average CPU time: " + (string)(llList2Float(data, 2) * 1000.0) + " ms.");
    }
    changed(integer flags)
    {
        if (flags & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Intermediate

Track this object’s region transitions

Count region-change events experienced by this object since reset.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in your own traveling object or attachment; touch as owner for the count.

Stop / restore: Remove or disable; it changes no object or parcel properties.

Records only a count and the current region, not a route history or avatar identities. Script resets clear the count.

// Original Incoprea example. MIT.
integer transitions;
default
{
    changed(integer flags)
    {
        if(flags & CHANGED_OWNER)
        {
            llResetScript();
            return;
        }
        if(flags & CHANGED_REGION)++transitions;
    }
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        llOwnerSay("Region-change events since reset: "+(string)transitions+"; current region: "+llGetRegionName());
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Diagnostics · Intermediate

Validate a typed linked payload

Send two JSON self-messages and accept only the one with a bounded numeric level.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Touch as owner. Requires simulator JSON support.

Stop / restore: Remove or reset the script to stop the diagnostic. No build properties are changed.

No prim properties are changed. The example illustrates type/range validation at an event boundary; a message key is a correlation token, not avatar authentication.

// Original Incoprea example. MIT.
key run=NULL_KEY;
default
{
    touch_start(integer touches)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        run=llGenerateKey();
        llMessageLinked(LINK_THIS,73002,"{\"level\":0.5}",run);
        llMessageLinked(LINK_THIS,73002,"{\"level\":\"loud\"}",run);
    }
    link_message(integer sender,integer code,string text,key token)
    {
        if(code!=73002 || token!=run || run==NULL_KEY)return;
        if(llJsonValueType(text,["level"])!=JSON_NUMBER)
        {
            llOwnerSay("Rejected nonnumeric level.");
            return;
        }
        float level=(float)llJsonGetValue(text,["level"]);
        if(level<0 || level>1)
        {
            llOwnerSay("Rejected out-of-range level.");
            return;
        }
        llOwnerSay("Accepted level: "+(string)level);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Diagnostics · Advanced

Verify a touched face’s texture query shape

Check the types and lengths returned by a combined diffuse texture parameter query.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Touch a valid face on the test object.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

This validates expected response structure, not texture permissions or visual rendering.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer face=llDetectedTouchFace(0);
        integer link=llDetectedLinkNumber(0);
        if(link==0)link=LINK_THIS;
        if(face<0)
        {
            llOwnerSay("Touch a valid face.");
            return;
        }
        list data=llGetLinkPrimitiveParams(link,[PRIM_TEXTURE,face]);
        integer length=llGetListLength(data);
        integer shape=(length==4);
        if(shape)shape=(llGetListEntryType(data,1)==TYPE_VECTOR&&llGetListEntryType(data,2)==TYPE_VECTOR&&llGetListEntryType(data,3)==TYPE_FLOAT);
        llOwnerSay("Texture tuple shape pass="+(string)shape+" fields="+(string)length);
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Advanced

Verify the reported notecard line-count boundary

Read at exactly the reported line count and check for EOF.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned test object. Add a short notecard named testcard and touch.

Stop / restore: Disable/remove. Tests report privately and do not change visual prim properties. Any temporary timer stops at completion or timeout.

Notecard changes during the test can invalidate the expectation. The count response and EOF query are separately correlated.

// Original Incoprea. MIT. Runtime verification, not pre-certified behavior.
key request;
integer phase;
key originalAsset;
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner()||phase)return;
        if(llGetInventoryType("testcard")!=INVENTORY_NOTECARD)
        {
            llOwnerSay("Add testcard notecard.");
            return;
        }
        originalAsset=llGetInventoryKey("testcard");
        phase=1;
        request=llGetNumberOfNotecardLines("testcard");
        llSetTimerEvent(15.0);
    }
    dataserver(key id,string data)
    {
        if(id!=request||phase==0)return;
        if(originalAsset!=llGetInventoryKey("testcard"))
        {
            phase=0;
            request=NULL_KEY;
            llSetTimerEvent(0.0);
            llOwnerSay("Notecard changed; test canceled.");
            return;
        }
        if(phase==1)
        {
            integer count=(integer)data;
            if(count<0)
            {
                phase=0;
                llSetTimerEvent(0.0);
                return;
            }
            phase=2;
            request=llGetNotecardLine("testcard",count);
        }
        else
        {
            phase=0;
            request=NULL_KEY;
            llSetTimerEvent(0.0);
            llOwnerSay("EOF at line-count boundary="+(string)(data==EOF));
        }
    }
    timer()
    {
        phase=0;
        request=NULL_KEY;
        llSetTimerEvent(0.0);
        llOwnerSay("Notecard test timed out.");
    }
    changed(integer flags)
    {
        if(flags&CHANGED_OWNER)llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Diagnostics · Beginner

Which scripts are running?

Report the running flag for up to ten scripts in this prim per touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim to inspect. Touch as owner repeatedly to browse all scripts.

Stop / restore: Remove or disable the script. It does not change the build.

This only reads running flags and never starts, stops, or resets another script. A running flag is not proof that a script is functioning correctly or allowed to act on the parcel.

// Original Incoprea example. MIT.
integer cursor;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetInventoryNumber(INVENTORY_SCRIPT);
        if (cursor >= total) cursor = 0;
        integer last = cursor + 9;
        if (last >= total) last = total - 1;
        integer i;
        for (i = cursor; i <= last; ++i)
        {
            string name = llGetInventoryName(INVENTORY_SCRIPT, i);
            if (llGetInventoryType(name) == INVENTORY_SCRIPT)
            {
                string status = "stopped";
                if (llGetScriptState(name)) status = "running flag set";
                llOwnerSay(name + ": " + status);
            }
        }
        cursor = last + 1;
    }
    changed(integer flags)
    {
        if (flags & (CHANGED_INVENTORY | CHANGED_OWNER)) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

TroubleshootingStop effects and clear persistent prim settings.14 scripts

Download this category (.zip)

Troubleshooting · Beginner

Clear floating text

Remove a floating label, including one left behind by a deleted script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in the exact prim showing the label. Disable any script that keeps setting that label.

Stop / restore: Runs once; remove the script after the label disappears.

Each linked prim can have its own text. Clearing the root does not clear every child.

// Original Incoprea example. MIT.
default
{
    state_entry()
    {
        llSetText("", <1.0, 1.0, 1.0>, 0.0);
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Intermediate

Clear keyframed motion

Clear a stored KFM path without changing physics or object position.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Disable scripts that restart the motion. Put in the affected nonphysical unattached root and save.

Stop / restore: Runs once; remove after verifying the movement stopped.

Does not stop target-omega, child timer animations, or physical momentum. It does not restore the object’s former position.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    state_entry()
    {
        if(llGetLinkNumber()>1||llGetAttached()||llGetStatus(STATUS_PHYSICS))
        {
            llOwnerSay("Use the nonphysical unattached root.");
            return;
        }
        llSetKeyframedMotion([],[]);
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Beginner

Clear sit target

Remove a stored sit target left on a prim by a seat script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Stand up first and disable scripts that set the seat target. Put in the exact seat prim.

Stop / restore: Runs once. Remove after the target is cleared.

Does not force an avatar to stand, remove animations, or prevent default viewer sitting on the object.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    state_entry()
    {
        llSitTarget(ZERO_VECTOR, ZERO_ROTATION);
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Beginner

Linked prim distance ruler

Touch two prims in one linkset to measure the distance between their centers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the root of a rezzed linked build. Child prims must pass touches to the root, usually by having no touch-handling script. Owner-touch one prim, then another.

Stop / restore: Remove or disable. No object settings are changed.

Measures prim center positions, not touched surface points or mesh bounds. Move or relink only between completed measurement pairs.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer pending;
integer firstLink;
vector first;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || llGetLinkNumber() > 1) return;
        integer link = llDetectedLinkNumber(0);
        vector position = llList2Vector(llGetLinkPrimitiveParams(link, [PRIM_POSITION]), 0);
        if (!pending)
        {
            pending = TRUE;
            first = position;
            firstLink = link;
            llOwnerSay("First prim selected. Touch the second prim.");
        }
        else
        {
            pending = FALSE;
            llOwnerSay("Center distance " + (string)firstLink + " to " + (string)link + ": " + (string)llVecDist(first, position) + " meters.");
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_LINK) pending = FALSE;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Troubleshooting · Beginner

Linked prim name map

List object prim numbers and names to help configure link-targeted scripts.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a rezzed object and owner-touch. Intended for small linksets; output is one line per object prim.

Stop / restore: Remove or disable. No link, name, or position is changed.

Uses the object prim count to exclude seated avatars. Link numbers may change after relinking. Large linksets can produce substantial owner chat.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer total = llGetObjectPrimCount(llGetKey());
        if (total <= 1)
        {
            llOwnerSay("Single object prim: " + llGetObjectName());
            return;
        }
        integer link;
        for (link = 1; link <= total; ++link)
        llOwnerSay((string)link + ": " + llGetLinkName(link));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Troubleshooting · Beginner

Prim effect inspector

Report stored rotation, light, face glow, and text settings without changing them.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim you want to inspect and owner-touch. Set FACE if you want a different face’s glow value.

Stop / restore: Remove or disable. This helper only reads settings and writes owner chat.

A stored property is not proof a script is currently running. Does not inspect particle settings, active timers, scripts in other prims, or physical momentum.

// Original Incoprea example. MIT. Not compiled or tested in-world.
integer FACE = 0;
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        llOwnerSay("Omega axis/rate/gain: " + llList2CSV(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_OMEGA])));
        llOwnerSay("Light enabled/color/intensity/radius/falloff: " + llList2CSV(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_POINT_LIGHT])));
        llOwnerSay("Face glow: " + llList2CSV(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_GLOW, FACE])));
        llOwnerSay("Hover text/color/alpha: " + llList2CSV(llGetLinkPrimitiveParams(LINK_THIS, [PRIM_TEXT])));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Troubleshooting · Beginner

Stop linked rotation

Clear target-omega rotation from the object and its linked prims.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: For nonphysical builds. Disable other scripts that restart rotation first. Place this in any prim of the affected object, save, and confirm Running is checked.

Stop / restore: This runs once. Remove it after confirming the rotation has stopped.

Does not stop a timer moving prim positions, keyframed motion, or physical momentum. Seated avatars are excluded. If server settings are cleared but the viewer still displays spin, refresh the view or relog.

// Original Incoprea example. MIT. Nonphysical rezzed object only.
default
{
    state_entry()
    {
        integer count = llGetObjectPrimCount(llGetKey());
        if (count <= 1)
        llSetLinkPrimitiveParamsFast(LINK_THIS,
        [PRIM_OMEGA, ZERO_VECTOR, 0.0, 0.0]);
        else
        {
            integer link;
            for (link = 1; link <= count; ++link)
            llSetLinkPrimitiveParamsFast(link,
            [PRIM_OMEGA, ZERO_VECTOR, 0.0, 0.0]);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Troubleshooting · Intermediate

Stop linked surface animation

Clear texture animations from each object prim in a rezzed linkset.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Disable scripts that restart animations first. Put in the affected rezzed object and save.

Stop / restore: Runs once. Remove after checking the surfaces.

Only texture animation is cleared; manual UV values and textures are not reset. Uses object prim count to exclude seated avatars.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    state_entry()
    {
        integer total=llGetObjectPrimCount(llGetKey());
        integer i;
        if(total<=1)llSetTextureAnim(FALSE,ALL_SIDES,0,0,0.0,0.0,1.0);
        else for(i=1;i<=total;++i)llSetLinkTextureAnim(i,FALSE,ALL_SIDES,0,0,0.0,0.0,1.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Troubleshooting · Beginner

Stop particle effect

Clear particles left behind by a deleted emitter script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim emitting particles and let it run once.

Stop / restore: Remove after confirming the particles stop.

If the emitter is in a child prim, this must be placed in that prim.

// Original Incoprea one-shot stopper.
default
{
    state_entry()
    {
        llParticleSystem([]);
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Beginner

Stop sound in this prim

Clear the attached sound playing in the prim that contains this script.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Disable scripts that restart audio first. Put this in the exact sounding prim and save.

Stop / restore: Runs once; remove after confirming silence.

Does not stop parcel media, parcel music, sounds in another prim, or already-triggered detached sounds.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    state_entry()
    {
        llStopSound();
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Beginner

Stop surface animation

Stop texture motion left running after the script was removed.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the exact prim whose texture is moving; save and let it run once.

Stop / restore: Remove this one-shot stopper after the motion ends.

Texture animation is stored as a prim setting. Other scripts can restart it.

// Original Incoprea one-shot stopper.
default
{
    state_entry()
    {
        llSetTextureAnim(FALSE, ALL_SIDES, 0, 0, 0.0, 0.0, 1.0);
    }
}

MIT · original Incoprea example

API reference 1

Troubleshooting · Beginner

Surface normal probe

Report the touched surface’s normal and angle from world-up for slope inspection.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in the prim being inspected. Owner-touch a surface; the viewer must supply touch-normal data.

Stop / restore: Remove or disable. It only reports to owner chat.

Uses the visual touched surface normal, not a guarantee of the physics shape’s slope. A flat upward-facing surface is 0 degrees; a vertical wall is 90.

// Original Incoprea example. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer count)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector normal = llDetectedTouchNormal(0);
        if (llVecMag(normal) < 0.1)
        {
            llOwnerSay("No usable touch normal returned.");
            return;
        }
        normal = llVecNorm(normal);
        float z = normal.z;
        if (z > 1.0) z = 1.0;
        if (z < -1.0) z = -1.0;
        llOwnerSay("Surface normal " + (string)normal + " | angle from up " + (string)(llAcos(z) * RAD_TO_DEG) + " degrees.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Troubleshooting · Intermediate

Terrain clearance and slope

Report center-to-terrain clearance and the terrain’s local slope.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Owner-touch a rezzed prim. Terrain is sampled under that prim.

Stop / restore: Remove/disable; no terraforming or movement occurs.

Terrain normal is normalized before computing slope. Mesh floors and collision shapes are excluded. Center clearance is not bottom-of-object clearance.

// Original Incoprea. MIT. Not compiled or tested in-world.
default
{
    touch_start(integer n)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector p=llGetPos();
        vector normal=llVecNorm(llGroundNormal(ZERO_VECTOR));
        float z=normal.z;
        if(z>1.0)z=1.0;
        if(z< -1.0)z=-1.0;
        llOwnerSay("Center clearance "+(string)(p.z-llGround(ZERO_VECTOR))+" m; terrain slope "+(string)(llAcos(z)*RAD_TO_DEG)+" degrees.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Scripting workbench 3 categories
Logic & stateReliable event patterns and reusable script behavior.60 scripts

Download this category (.zip)

Logic & state · Intermediate

A guarded three-stage workflow

Walk a simulated draft through review and approval with an explicit prerequisite.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Each touch advances the demonstration: create a draft, mark it checked, approve it, then start a fresh draft.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Only local variables and owner messages change. The state values and guard are reusable in a real workflow; this does not publish anything.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer stage;
integer checked;
integer revision;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (stage == 0)
        {
            ++revision;
            checked = FALSE;
            stage = 1;
            llOwnerSay("Draft " + (string)revision + " created; next touch reviews it.");
        }
        else if (stage == 1)
        {
            checked = TRUE;
            stage = 2;
            llOwnerSay("Review complete; next touch requests approval.");
        }
        else if (stage == 2)
        {
            if (!checked)
            {
                llOwnerSay("Approval blocked: review missing.");
                return;
            }
            stage = 3;
            llOwnerSay("Revision approved locally.");
        }
        else
        {
            stage = 0;
            checked = FALSE;
            llOwnerSay("Ready for a new draft.");
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

A threshold that does not chatter

Switch a simulated condition on at 0.7 and off at 0.3 while ignoring noise between those thresholds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch through the predefined sample levels and watch the state transitions.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

No sensor or scene effect is used. The separate on/off thresholds prevent rapid toggling around a single boundary.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list SAMPLES = [0.2,0.65,0.72,0.68,0.5,0.32,0.28,0.35];
integer cursor;
integer active;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float value = llList2Float(SAMPLES,cursor);
        cursor = (cursor+1)%llGetListLength(SAMPLES);
        integer previous = active;
        if (!active && value >= 0.7) active = TRUE;
        else if (active && value <= 0.3) active = FALSE;
        string change = "held";
        if (active != previous) change = "changed";
        llOwnerSay("Value="+(string)value+"; active="+(string)active+" ("+change+")");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Add an even parity bit to a byte

Count set bits and append a parity bit to detect any single-bit error in a byte-sized payload.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set PAYLOAD from0 to255. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Even parity misses many multi-bit errors and offers no authentication.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer PAYLOAD=173;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(PAYLOAD<0||PAYLOAD>255)
        {
            llOwnerSay("Byte required.");
            return;
        }
        integer ones;
        integer bit;
        for(bit=0;bit<8;++bit)ones+=(PAYLOAD>>bit)&1;
        integer parity=ones&1;
        integer word=PAYLOAD|(parity<<8);
        llOwnerSay("Payload bits set="+(string)ones+"; parity="+(string)parity+"; nine-bit word="+(string)word);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Age waiting jobs to prevent starvation

Increase queued jobs’ effective priority as they wait and select the highest score.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit paired base priorities and waiting ages. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

One scheduling decision is simulated. The age multiplier determines fairness versus original priority; ties keep the earliest job.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list LABELS=["urgent-new","old-low","routine"];
list PRIORITY=[9,2,5];
list AGE=[0,8,2];
integer AGE_WEIGHT=1;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(LABELS);
        if(n==0||n!=llGetListLength(PRIORITY)||n!=llGetListLength(AGE))
        {
            llOwnerSay("Mismatched tables.");
            return;
        }
        integer best=-1;
        integer bestScore=-2147483647;
        integer i;
        for(i=0;i<n;++i)
        {
            integer score=llList2Integer(PRIORITY,i)+AGE_WEIGHT*llList2Integer(AGE,i);
            llOwnerSay(llList2String(LABELS,i)+" score="+(string)score);
            if(best==-1||score>bestScore)
            {
                best=i;
                bestScore=score;
            }
        }
        llOwnerSay("Selected: "+llList2String(LABELS,best));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Assign jobs to the least-loaded worker

Greedily place each job on the currently least busy of three workers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive job DURATIONS, at most12. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Input order affects the heuristic. This simulates scheduling only and does not delegate work.

// Original Incoprea. MIT. Local planning demonstration.
list DURATIONS=[3.0,7.0,2.0,5.0,4.0,1.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(DURATIONS)>12)
        {
            llOwnerSay("At most12 jobs.");
            return;
        }
        list loads=[0.0,0.0,0.0];
        integer i;
        for(i=0;i<llGetListLength(DURATIONS);++i)
        {
            float duration=llList2Float(DURATIONS,i);
            if(duration<=0.0)
            {
                llOwnerSay("Positive durations required.");
                return;
            }
            integer best=0;
            integer worker;
            for(worker=1;worker<3;++worker)if(llList2Float(loads,worker)<llList2Float(loads,best))best=worker;
            float start=llList2Float(loads,best);
            loads=llListReplaceList(loads,[start+duration],best,best);
            llOwnerSay("Job "+(string)i+" worker="+(string)best+" start="+(string)start);
        }
        llOwnerSay("Worker loads="+llDumpList2String(loads,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Audit a single-worker cue schedule

Calculate completion time and lateness for jobs scheduled by earliest deadline.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set deadline/duration pairs with positive durations. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Assumes all jobs are available at time0 and run without preemption; this is a schedule preview.

// Original Incoprea. MIT. Local planning demonstration.
list JOBS=[6.0,3.0,4.0,2.0,12.0,5.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(JOBS)%2)
        {
            llOwnerSay("Use deadline/duration pairs.");
            return;
        }
        list sorted=llListSort(JOBS,2,TRUE);
        float elapsed;
        integer i;
        for(i=0;i<llGetListLength(sorted);i+=2)
        {
            float deadline=llList2Float(sorted,i);
            float duration=llList2Float(sorted,i+1);
            if(duration<=0.0)
            {
                llOwnerSay("Positive durations required.");
                return;
            }
            elapsed+=duration;
            llOwnerSay("Deadline="+(string)deadline+" finish="+(string)elapsed+" lateness="+(string)(elapsed-deadline));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Intermediate

Burst-friendly request budget

Allow a burst of three local actions, then refill the budget at one token every two seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to spend a token; wait to refill. Capacity and refill rate are editable constants.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Uses elapsed time instead of a repeating timer. This is a local usage budget, not an authorization or monetary system.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float CAPACITY = 3.0;
float REFILL_PER_SECOND = 0.5;
float tokens = 3.0;
float lastCheck;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        tokens += (now-lastCheck)*REFILL_PER_SECOND;
        lastCheck = now;
        if (tokens > CAPACITY) tokens = CAPACITY;
        if (tokens < 1.0)
        {
            llOwnerSay("Budget empty; let it refill.");
            return;
        }
        tokens -= 1.0;
        llOwnerSay("Accepted; tokens left: " + (string)tokens);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Cache a computed value for five seconds

Reuse a local computation briefly and recompute after its time-to-live expires.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch repeatedly, then wait more than five seconds and touch again.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The sample value is a deterministic computation counter, not external data. Uses lazy expiry and never requires a background timer.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer valid;
integer cached;
integer computations;
float expires;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        if (!valid || now >= expires)
        {
            ++computations;
            cached = computations*computations;
            expires = now+5.0;
            valid = TRUE;
            llOwnerSay("Recomputed cache.");
        }
        else llOwnerSay("Reused cache.");
        llOwnerSay("Value=" + (string)cached + "; expires in " + (string)(expires-now) + " seconds.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Calculate earliest completion through prerequisites

Compute finish times for a small task graph whose dependencies refer only to earlier rows.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set task durations and matching prerequisite bitmasks. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Earlier-row ordering is required and checked. This computes earliest finish with unlimited parallel workers, not a resource-constrained schedule.

// Original Incoprea. MIT. Local planning demonstration.
list LABELS=["assets","script","review","release-demo"];
list DURATIONS=[3.0,5.0,2.0,1.0];
list NEEDS=[0,0,3,4];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(DURATIONS);
        if(n<1||n>12||n!=llGetListLength(NEEDS)||n!=llGetListLength(LABELS))
        {
            llOwnerSay("Mismatched tasks.");
            return;
        }
        list finish;
        integer i;
        for(i=0;i<n;++i)
        {
            integer mask=llList2Integer(NEEDS,i);
            float duration=llList2Float(DURATIONS,i);
            if(mask<0||mask>=(1<<i)||duration<0.0)
            {
                llOwnerSay("Dependencies must refer to earlier rows; duration nonnegative.");
                return;
            }
            float start;
            integer j;
            for(j=0;j<i;++j)if(mask&(1<<j))if(llList2Float(finish,j)>start)start=llList2Float(finish,j);
            finish+=[start+duration];
            llOwnerSay(llList2String(LABELS,i)+" earliest="+(string)start+".."+(string)(start+duration));
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Intermediate

Cancel a pending delayed action

Start a three-second delayed report and cancel it with a second touch before its deadline.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch once to schedule; touch again to cancel. After completion, the next touch starts a new job.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

A pending flag and deadline are rechecked inside the timer so a queued stale event cannot report a canceled job.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer pending;
integer generation;
float due;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        ++generation;
        if (pending)
        {
            pending = FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Pending job canceled.");
            return;
        }
        pending = TRUE;
        due = llGetTime()+3.0;
        llSetTimerEvent(0.25);
        llOwnerSay("Scheduled generation " + (string)generation);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        if (!pending || llGetTime() < due) return;
        pending = FALSE;
        llSetTimerEvent(0.0);
        llOwnerSay("Completed generation " + (string)generation);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Choose a high-value subset within a small budget

Use a bounded0/1 dynamic program to maximize integer value under a small integer capacity.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set cost/value pairs, capacity0..50 and at most12 items. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Reports best attainable value; it does not spend anything or recover the chosen item set.

// Original Incoprea. MIT. Local planning demonstration.
list ITEMS=[3,5,4,7,2,3,5,8];
integer CAPACITY=9;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(ITEMS);
        if(n%2||n>24||CAPACITY<0||CAPACITY>50)
        {
            llOwnerSay("Invalid bounded problem.");
            return;
        }
        list values;
        integer c;
        for(c=0;c<=CAPACITY;++c)values+=[0];
        integer i;
        for(i=0;i<n;i+=2)
        {
            integer cost=llList2Integer(ITEMS,i);
            integer value=llList2Integer(ITEMS,i+1);
            if(cost<=0||value<0)
            {
                llOwnerSay("Positive cost/nonnegative value required.");
                return;
            }
            for(c=CAPACITY;c>=cost;--c)
            {
                integer candidate=llList2Integer(values,c-cost)+value;
                if(candidate>llList2Integer(values,c))values=llListReplaceList(values,[candidate],c,c);
            }
        }
        llOwnerSay("Best value within capacity="+(string)llList2Integer(values,CAPACITY));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Compare allocated slots with actual use

Calculate total capacity, used capacity and wasted capacity for fixed-size allocation slots.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive SLOT_SIZE and a list of positive item sizes. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

This is a generic packing estimate; it does not query actual script or inventory memory.

// Original Incoprea. MIT. Local planning demonstration.
integer SLOT_SIZE=64;
list SIZES=[10,64,65,120,1];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SLOT_SIZE<1||SLOT_SIZE>1000000)
        {
            llOwnerSay("Invalid slot size.");
            return;
        }
        integer used;
        integer allocated;
        integer i;
        for(i=0;i<llGetListLength(SIZES);++i)
        {
            integer size=llList2Integer(SIZES,i);
            if(size<1||size>1000000)
            {
                llOwnerSay("Use item sizes1..1000000.");
                return;
            }
            used+=size;
            allocated+=((size+SLOT_SIZE-1)/SLOT_SIZE)*SLOT_SIZE;
        }
        if(allocated==0)
        {
            llOwnerSay("No items.");
            return;
        }
        llOwnerSay("Used="+(string)used+" allocated="+(string)allocated+" waste="+(string)(allocated-used)+" utilization="+(string)((float)used/(float)allocated));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Compare sequence numbers across wrap

Determine whether a sixteen-bit sequence is newer using half-range modular comparison.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set CURRENT and CANDIDATE from0 to65535. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

A distance of exactly32768 is ambiguous. The method assumes updates never get more than half the sequence space apart.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer CURRENT=65532;
integer CANDIDATE=3;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(CURRENT<0||CURRENT>65535||CANDIDATE<0||CANDIDATE>65535)
        {
            llOwnerSay("Use16-bit sequence numbers.");
            return;
        }
        integer delta=(CANDIDATE-CURRENT)&65535;
        string result="older";
        if(delta==0)result="same";
        else if(delta==32768)result="ambiguous half-range";
        else if(delta<32768)result="newer";
        llOwnerSay("Candidate is "+result+"; modular distance="+(string)delta);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Connect planned stations with a short cable tree

Use Prim’s algorithm on pairwise Euclidean distances to connect every supplied point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINTS with2..10 station positions. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

This finds a minimum spanning tree of the complete distance graph; obstacles and cable-routing constraints are excluded.

// Original Incoprea. MIT. Local planning demonstration.
list POINTS=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<1.0,3.0,0.0>,<6.0,4.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<2||n>10)
        {
            llOwnerSay("Use2..10 points.");
            return;
        }
        integer connected=1;
        float total;
        integer step;
        for(step=1;step<n;++step)
        {
            integer from=-1;
            integer to=-1;
            float best=1000000.0;
            integer i;
            integer j;
            for(i=0;i<n;++i)if(connected&(1<<i))for(j=0;j<n;++j)if(!(connected&(1<<j)))
            {
                float d=llVecDist(llList2Vector(POINTS,i),llList2Vector(POINTS,j));
                if(d<best)
                {
                    best=d;
                    from=i;
                    to=j;
                }
            }
            if(to<0)
            {
                llOwnerSay("No edge under distance limit.");
                return;
            }
            connected=connected|(1<<to);
            total+=best;
            llOwnerSay("Connect "+(string)from+" -> "+(string)to+" length="+(string)best);
        }
        llOwnerSay("Total tree length="+(string)total);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Count disconnected zones in a room map

Label connected components of a small undirected graph.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set N1..12 and paired valid room indexes in EDGES. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Reports isolated rooms as their own zones. Duplicate edges do not change the result.

// Original Incoprea. MIT. Local planning demonstration.
integer N=6;
list EDGES=[0,1,1,2,3,4];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(N<1||N>12||llGetListLength(EDGES)%2)
        {
            llOwnerSay("Invalid graph.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(EDGES);++i)if(llList2Integer(EDGES,i)<0||llList2Integer(EDGES,i)>=N)
        {
            llOwnerSay("Invalid edge.");
            return;
        }
        integer seen;
        integer zones;
        integer seed;
        for(seed=0;seed<N;++seed)if(!(seen&(1<<seed)))
        {
            ++zones;
            list queue=[seed];
            seen=seen|(1<<seed);
            integer head;
            while(head<llGetListLength(queue))
            {
                integer current=llList2Integer(queue,head);
                ++head;
                for(i=0;i<llGetListLength(EDGES);i+=2)
                {
                    integer a=llList2Integer(EDGES,i);
                    integer b=llList2Integer(EDGES,i+1);
                    integer next=-1;
                    if(a==current)next=b;
                    else if(b==current)next=a;
                    if(next>=0&&!(seen&(1<<next)))
                    {
                        seen=seen|(1<<next);
                        queue+=[next];
                    }
                }
            }
            llOwnerSay("Zone "+(string)zones+": "+llDumpList2String(queue,","));
        }
        llOwnerSay("Connected zones="+(string)zones);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Count distinct votes toward a local quorum

Record each member’s yes vote once and announce when three of five members have voted.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch through a fixed member sequence including a repeated member. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

This does not authenticate real voters or implement consensus. It demonstrates unique-count bookkeeping only.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list MEMBERS=[0,2,2,4,1];
integer cursor;
integer votes;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(cursor>=llGetListLength(MEMBERS))
        {
            llOwnerSay("Voting sample complete.");
            return;
        }
        integer member=llList2Integer(MEMBERS,cursor);
        ++cursor;
        votes=votes|(1<<member);
        integer count;
        integer i;
        for(i=0;i<5;++i)if(votes&(1<<i))++count;
        llOwnerSay("Distinct votes="+(string)count+"; quorum reached="+(string)(count>=3));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Count reachable cells in a tiny floor plan

Flood-fill a four-by-four grid from one open start cell.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set sixteen CELLS, where0 is open and1 blocked, and START0..15. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Moves only north/south/east/west. No scene navigation or avatar pathfinding is performed.

// Original Incoprea. MIT. Local planning demonstration.
list CELLS=[0,0,1,0,1,0,1,0,0,0,0,0,0,1,1,0];
integer START=0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llGetListLength(CELLS)!=16||START<0||START>15||llList2Integer(CELLS,START)!=0)
        {
            llOwnerSay("Invalid grid/start.");
            return;
        }
        integer seen=1<<START;
        list queue=[START];
        integer head;
        while(head<llGetListLength(queue))
        {
            integer at=llList2Integer(queue,head);
            ++head;
            integer x=at%4;
            integer y=at/4;
            list nexts;
            if(x>0)nexts+=[at-1];
            if(x<3)nexts+=[at+1];
            if(y>0)nexts+=[at-4];
            if(y<3)nexts+=[at+4];
            integer i;
            for(i=0;i<llGetListLength(nexts);++i)
            {
                integer next=llList2Integer(nexts,i);
                if(!(seen&(1<<next))&&llList2Integer(CELLS,next)==0)
                {
                    seen=seen|(1<<next);
                    queue+=[next];
                }
            }
        }
        llOwnerSay("Reachable cells="+(string)llGetListLength(queue)+": "+llDumpList2String(queue,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Discard stale asynchronous results

Apply simulated results only when their generation matches the latest requested generation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch through requests and intentionally reordered responses. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

No external call is made; this isolates a reusable stale-response guard for real asynchronous handlers.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer step;
integer generation;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer phase=step%4;
        ++step;
        if(phase==0)
        {
            ++generation;
            llOwnerSay("Requested generation "+(string)generation);
        }
        else if(phase==1)
        {
            ++generation;
            llOwnerSay("Replaced request with generation "+(string)generation);
        }
        else
        {
            integer received=generation;
            if(phase==2)received=generation-1;
            if(received!=generation)llOwnerSay("Discarded stale result "+(string)received);
            else llOwnerSay("Applied current result "+(string)received);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Draft a short exhibit tour greedily

Visit the nearest unvisited planned point until every stop is used.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set POINTS with2..10 stops; stop0 is the start. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

This is a heuristic, not the shortest traveling-salesperson tour. It reports an open path and total length.

// Original Incoprea. MIT. Local planning demonstration.
list POINTS=[<0.0,0.0,0.0>,<5.0,0.0,0.0>,<2.0,3.0,0.0>,<7.0,5.0,0.0>,<1.0,6.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<2||n>10)
        {
            llOwnerSay("Use2..10 stops.");
            return;
        }
        integer visited=1;
        integer current;
        list path=[0];
        float total;
        integer step;
        for(step=1;step<n;++step)
        {
            integer best=-1;
            float distance=1000000.0;
            integer i;
            for(i=0;i<n;++i)if(!(visited&(1<<i)))
            {
                float d=llVecDist(llList2Vector(POINTS,current),llList2Vector(POINTS,i));
                if(d<distance)
                {
                    distance=d;
                    best=i;
                }
            }
            if(best<0)
            {
                llOwnerSay("No stop under distance limit.");
                return;
            }
            visited=visited|(1<<best);
            path+=[best];
            total+=distance;
            current=best;
        }
        llOwnerSay("Draft tour="+llDumpList2String(path," -> ")+" length="+(string)total);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Estimate variable-length integer bytes

Count base128 continuation bytes needed to encode a nonnegative integer.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set VALUE from zero through2147483647. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Prints each seven-bit payload in low-to-high order; continuation flag is set on every nonfinal byte.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer VALUE=16384;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(VALUE<0)
        {
            llOwnerSay("Nonnegative value required.");
            return;
        }
        integer remaining=VALUE;
        list bytes;
        do
        {
            integer part=remaining&127;
            remaining=remaining>>7;
            if(remaining>0)part=part|128;
            bytes+=[part];
        }
        while(remaining>0);
        llOwnerSay("Bytes decimal="+llDumpList2String(bytes,",")+"; count="+(string)llGetListLength(bytes));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Estimate waste for equal pieces from stock lengths

Calculate pieces per stock unit, stock units needed and total offcut waste including kerf.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive STOCK/PIECE, nonnegative KERF and required COUNT. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Assumes every piece except the final retained piece requires a kerf; this is a simple virtual-material planning convention.

// Original Incoprea. MIT. Local planning demonstration.
float STOCK=6.0;
float PIECE=1.2;
float KERF=0.01;
integer COUNT=17;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(STOCK<=0.0||PIECE<=0.0||KERF<0.0||COUNT<1)
        {
            llOwnerSay("Invalid dimensions/count.");
            return;
        }
        integer per=llFloor((STOCK+KERF)/(PIECE+KERF));
        if(per<1)
        {
            llOwnerSay("No piece fits.");
            return;
        }
        integer units=(COUNT+per-1)/per;
        float waste=units*STOCK-COUNT*PIECE;
        llOwnerSay("Pieces per stock="+(string)per+" stock units="+(string)units+" total non-piece material="+(string)waste);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Find a fewest-door route through rooms

Run breadth-first search through a small undirected room graph and reconstruct its route.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set room count1..12, paired EDGES, START and GOAL indexes. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Every edge has equal cost. Invalid edge indexes are rejected before traversal.

// Original Incoprea. MIT. Local planning demonstration.
integer ROOMS=6;
list EDGES=[0,1,0,2,1,3,2,4,4,5,3,5];
integer START=0;
integer GOAL=5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(ROOMS<1||ROOMS>12||START<0||START>=ROOMS||GOAL<0||GOAL>=ROOMS||llGetListLength(EDGES)%2)
        {
            llOwnerSay("Invalid graph.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(EDGES);++i)if(llList2Integer(EDGES,i)<0||llList2Integer(EDGES,i)>=ROOMS)
        {
            llOwnerSay("Bad edge index.");
            return;
        }
        list parent;
        for(i=0;i<ROOMS;++i)parent+=[-1];
        parent=llListReplaceList(parent,[START],START,START);
        list queue=[START];
        integer head;
        while(head<llGetListLength(queue))
        {
            integer current=llList2Integer(queue,head);
            ++head;
            for(i=0;i<llGetListLength(EDGES);i+=2)
            {
                integer a=llList2Integer(EDGES,i);
                integer b=llList2Integer(EDGES,i+1);
                integer next=-1;
                if(a==current)next=b;
                else if(b==current)next=a;
                if(next>=0&&llList2Integer(parent,next)==-1)
                {
                    parent=llListReplaceList(parent,[current],next,next);
                    queue+=[next];
                }
            }
        }
        if(llList2Integer(parent,GOAL)==-1)
        {
            llOwnerSay("No route.");
            return;
        }
        list path=[GOAL];
        integer at=GOAL;
        while(at!=START)
        {
            at=llList2Integer(parent,at);
            path=[at]+path;
        }
        llOwnerSay("Fewest-door route="+llDumpList2String(path," -> "));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Find a minimum-time route on a small map

Run Dijkstra search over positive weighted undirected edges.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set N2..10, START/GOAL and edge triples from,to,cost. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Uses a simple quadratic selection loop suited to a small graph. Negative or zero edge costs are rejected.

// Original Incoprea. MIT. Local planning demonstration.
integer N=5;
integer START=0;
integer GOAL=4;
list EDGES=[0,1,2.0,0,2,5.0,1,2,1.0,1,3,4.0,2,4,2.0,3,4,1.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(N<2||N>10||START<0||START>=N||GOAL<0||GOAL>=N||llGetListLength(EDGES)%3)
        {
            llOwnerSay("Invalid graph.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(EDGES);i+=3)if(llList2Integer(EDGES,i)<0||llList2Integer(EDGES,i)>=N||llList2Integer(EDGES,i+1)<0||llList2Integer(EDGES,i+1)>=N||llList2Float(EDGES,i+2)<=0.0)
        {
            llOwnerSay("Invalid edge.");
            return;
        }
        list distance;
        list parent;
        integer visited;
        for(i=0;i<N;++i)
        {
            distance+=[1000000.0];
            parent+=[-1];
        }
        distance=llListReplaceList(distance,[0.0],START,START);
        integer pass;
        for(pass=0;pass<N;++pass)
        {
            integer best=-1;
            float bestCost=1000000.0;
            for(i=0;i<N;++i)if(!(visited&(1<<i))&&llList2Float(distance,i)<bestCost)
            {
                best=i;
                bestCost=llList2Float(distance,i);
            }
            if(best>=0)
            {
                visited=visited|(1<<best);
                for(i=0;i<llGetListLength(EDGES);i+=3)
                {
                    integer a=llList2Integer(EDGES,i);
                    integer b=llList2Integer(EDGES,i+1);
                    integer next=-1;
                    if(a==best)next=b;
                    else if(b==best)next=a;
                    if(next>=0)
                    {
                        float candidate=bestCost+llList2Float(EDGES,i+2);
                        if(candidate<llList2Float(distance,next))
                        {
                            distance=llListReplaceList(distance,[candidate],next,next);
                            parent=llListReplaceList(parent,[best],next,next);
                        }
                    }
                }
            }
        }
        if(llList2Float(distance,GOAL)>=1000000.0)
        {
            llOwnerSay("No route under cost limit.");
            return;
        }
        list path=[GOAL];
        integer at=GOAL;
        integer guard;
        while(at!=START&&guard<N)
        {
            at=llList2Integer(parent,at);
            path=[at]+path;
            ++guard;
        }
        llOwnerSay("Route="+llDumpList2String(path," -> ")+" cost="+(string)llList2Float(distance,GOAL));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Find the first gap long enough for a cue

Locate the earliest available interval after a requested start among existing reservations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set reservation start/end pairs, EARLIEST and positive DURATION. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Reservations may overlap; sorting and advancing the candidate handles their union without modifying them.

// Original Incoprea. MIT. Local planning demonstration.
list BUSY=[2.0,4.0,5.0,6.0,8.0,10.0];
float EARLIEST=1.0;
float DURATION=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DURATION<=0.0||llGetListLength(BUSY)%2)
        {
            llOwnerSay("Invalid intervals/duration.");
            return;
        }
        integer i;
        for(i=0;i<llGetListLength(BUSY);i+=2)if(llList2Float(BUSY,i+1)<llList2Float(BUSY,i))
        {
            llOwnerSay("Invalid reservation.");
            return;
        }
        list sorted=llListSort(BUSY,2,TRUE);
        float candidate=EARLIEST;
        for(i=0;i<llGetListLength(sorted);i+=2)
        {
            float start=llList2Float(sorted,i);
            float end=llList2Float(sorted,i+1);
            if(candidate+DURATION<=start)
            {
                llOwnerSay("Free slot="+(string)candidate+".."+(string)(candidate+DURATION));
                return;
            }
            if(candidate<end)candidate=end;
        }
        llOwnerSay("Free slot="+(string)candidate+".."+(string)(candidate+DURATION));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Find when several discrete loops realign

Calculate the least common multiple of small positive loop periods.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set integer PERIODS1..100; combined result is capped at one million. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Only exact integer periods are supported; floating-point times need an explicit tick resolution first.

// Original Incoprea. MIT. Local planning demonstration.
list PERIODS=[6,8,9];
integer gcd(integer a,integer b)
{
    while(b)
    {
        integer remainder=a%b;
        a=b;
        b=remainder;
    }
    return a;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer result=1;
        integer i;
        for(i=0;i<llGetListLength(PERIODS);++i)
        {
            integer period=llList2Integer(PERIODS,i);
            if(period<1||period>100)
            {
                llOwnerSay("Periods1..100 required.");
                return;
            }
            integer reduced=result/gcd(result,period);
            if(reduced>1000000/period)
            {
                llOwnerSay("Combined period exceeds one million ticks.");
                return;
            }
            result=reduced*period;
        }
        llOwnerSay("Common repeat ticks="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Fit a loop by distributing dwell time

Calculate equal extra dwell per cue to reach a desired total loop duration.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive cue DURATIONS and TARGET_TOTAL at least their sum. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

All extra time is distributed equally; transition durations are assumed already included.

// Original Incoprea. MIT. Local planning demonstration.
list DURATIONS=[2.0,3.0,4.0];
float TARGET_TOTAL=15.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(DURATIONS);
        if(n==0)
        {
            llOwnerSay("No cues.");
            return;
        }
        float total;
        integer i;
        for(i=0;i<n;++i)
        {
            float d=llList2Float(DURATIONS,i);
            if(d<=0.0)
            {
                llOwnerSay("Positive durations required.");
                return;
            }
            total+=d;
        }
        if(TARGET_TOTAL<total)
        {
            llOwnerSay("Target shorter than active cues.");
            return;
        }
        float dwell=(TARGET_TOTAL-total)/(float)n;
        llOwnerSay("Extra dwell per cue="+(string)dwell+" active fraction="+(string)(total/TARGET_TOTAL));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Intermediate

Hold-to-confirm teaching pattern

Measure how long the owner holds a touch and confirm only after a two-second hold.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Press and hold the prim, then release. Owner chat reports accepted or too short.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Viewer interaction and lost touch events can vary. This measures event times, not a physical button; use a copy for testing.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer holding;
float began;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        holding = TRUE;
        began = llGetTime();
        llOwnerSay("Hold for at least two seconds, then release.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    touch_end(integer count)
    {
        if (llDetectedKey(0) != llGetOwner() || !holding) return;
        holding = FALSE;
        float elapsed = llGetTime()-began;
        if (elapsed >= 2.0) llOwnerSay("Hold confirmed: " + (string)elapsed + " seconds.");
        else llOwnerSay("Released too soon: " + (string)elapsed + " seconds.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

Ignore repeated request identifiers

Demonstrate a bounded recent-ID cache so duplicate requests do not apply the same increment twice.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch repeatedly to feed a sample sequence containing repeated request IDs.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Keeps the latest eight unique IDs in memory. Reset and eviction permit old requests again; it is not durable exactly-once processing.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list REQUESTS = ["A1","A2","A1","A3","A2","A4"];
list seen;
integer cursor;
integer applied;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string request = llList2String(REQUESTS,cursor);
        cursor = (cursor+1)%llGetListLength(REQUESTS);
        if (llListFindList(seen,[request]) != -1)
        {
            llOwnerSay("Ignored duplicate " + request);
            return;
        }
        seen += [request];
        if (llGetListLength(seen) > 8) seen = llList2List(seen,-8,-1);
        ++applied;
        llOwnerSay("Applied " + request + "; total unique actions=" + (string)applied);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

Immediate action with a cooldown

Accept the first touch immediately and reject subsequent actions until a five-second cooldown ends.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch repeatedly to see accepted and rejected requests. Edit COOLDOWN to suit a local tool.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The deadline is kept in script memory; reset clears it. No timer is needed because the deadline is tested when a request arrives.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float COOLDOWN = 5.0;
float nextAllowed;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        if (now < nextAllowed)
        {
            llOwnerSay("Wait " + (string)(nextAllowed-now) + " seconds.");
            return;
        }
        nextAllowed = now + COOLDOWN;
        llOwnerSay("Accepted: cooldown started.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Measure the peak simultaneous cue count

Use start/end events to find peak concurrency for half-open intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set valid nonzero start/end pairs. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

At equal times, ending events precede starting events, so back-to-back cues do not overlap.

// Original Incoprea. MIT. Local planning demonstration.
list WINDOWS=[0.0,3.0,1.0,4.0,3.0,5.0,2.0,3.5];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(WINDOWS);
        if(n%2)
        {
            llOwnerSay("Use pairs.");
            return;
        }
        list times;
        integer i;
        for(i=0;i<n;i+=2)
        {
            float a=llList2Float(WINDOWS,i);
            float b=llList2Float(WINDOWS,i+1);
            if(b<=a)
            {
                llOwnerSay("Positive durations required.");
                return;
            }
            times+=[a,b];
        }
        times=llListSort(times,1,TRUE);
        integer peak;
        float peakAt;
        for(i=0;i<llGetListLength(times);++i)
        {
            float t=llList2Float(times,i);
            integer active;
            integer j;
            for(j=0;j<n;j+=2)if(llList2Float(WINDOWS,j)<=t&&t<llList2Float(WINDOWS,j+1))++active;
            if(active>peak)
            {
                peak=active;
                peakAt=t;
            }
        }
        llOwnerSay("Peak simultaneous="+(string)peak+" first at="+(string)peakAt);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Merge overlapping exhibit time windows

Combine overlapping or touching intervals into a nonoverlapping union.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set start/end pairs in any order with end>=start. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

All times share one arbitrary unit. Touching intervals are merged; empty input yields an empty schedule.

// Original Incoprea. MIT. Local planning demonstration.
list WINDOWS=[1.0,3.0,2.0,5.0,8.0,9.0,9.0,11.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(WINDOWS);
        if(n%2)
        {
            llOwnerSay("Use start/end pairs.");
            return;
        }
        integer i;
        for(i=0;i<n;i+=2)if(llList2Float(WINDOWS,i+1)<llList2Float(WINDOWS,i))
        {
            llOwnerSay("Negative duration.");
            return;
        }
        list sorted=llListSort(WINDOWS,2,TRUE);
        list result;
        if(n==0)
        {
            llOwnerSay("No intervals.");
            return;
        }
        float start=llList2Float(sorted,0);
        float end=llList2Float(sorted,1);
        for(i=2;i<n;i+=2)
        {
            float a=llList2Float(sorted,i);
            float b=llList2Float(sorted,i+1);
            if(a<=end)
            {
                if(b>end)end=b;
            }
            else
            {
                result+=[start,end];
                start=a;
                end=b;
            }
        }
        result+=[start,end];
        llOwnerSay("Merged intervals="+llDumpList2String(result,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Migrate an old local settings record

Translate a version1 record into a version2 representation while rejecting unknown schemas.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set RECORD to the documented v1 sample. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Only sample fields are migrated; all fields are preserved as text until explicit validation. No persistence is written.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
string RECORD="v1|green|slow";
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list fields=llParseStringKeepNulls(RECORD,["|"],[]);
        string version=llList2String(fields,0);
        if(version=="v2"&&llGetListLength(fields)==4)
        {
            llOwnerSay("Already v2: "+RECORD);
            return;
        }
        if(version!="v1"||llGetListLength(fields)!=3)
        {
            llOwnerSay("Unsupported schema.");
            return;
        }
        string color=llList2String(fields,1);
        string speed=llList2String(fields,2);
        string upgraded="v2|"+color+"|"+speed+"|enabled";
        llOwnerSay("Migrated: "+upgraded);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Negotiate a shared feature set

Intersect two feature bitmaps and verify that all required features survived negotiation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set LOCAL_FLAGS, PEER_FLAGS and REQUIRED_FLAGS as bit fields. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

This demonstrates format negotiation, not trust or authorization. Unknown optional bits are naturally excluded if not shared.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer LOCAL_FLAGS=11;
integer PEER_FLAGS=13;
integer REQUIRED_FLAGS=9;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer agreed=LOCAL_FLAGS&PEER_FLAGS;
        integer missing=REQUIRED_FLAGS&~agreed;
        llOwnerSay("Agreed flags="+(string)agreed);
        if(missing)llOwnerSay("Cannot proceed; missing required flags="+(string)missing);
        else llOwnerSay("Required capabilities available.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Pack and unpack signed byte offsets

Store two signed offsets in a sixteen-bit word using two’s-complement byte encoding.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set X and Y from minus128 to127. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

The masking and sign restoration are explicit; this does not compress general floats.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer X=-23;
integer Y=110;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(X< -128||X>127||Y< -128||Y>127)
        {
            llOwnerSay("Offsets must fit signed bytes.");
            return;
        }
        integer packed=((X&255)<<8)|(Y&255);
        integer dx=(packed>>8)&255;
        integer dy=packed&255;
        if(dx>=128)dx-=256;
        if(dy>=128)dy-=256;
        llOwnerSay("Packed="+(string)packed+"; restored="+(string)dx+","+(string)dy);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Pack three bounded fields into an integer

Encode two byte-sized fields and a fifteen-bit field into one nonnegative integer, then decode.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit GROUP, MODE and VALUE within their documented ranges. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Thirty-one bits avoid the signed high bit. This defines a compact wire format, not encryption.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer GROUP=12;
integer MODE=7;
integer VALUE=2048;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(GROUP<0||GROUP>255||MODE<0||MODE>255||VALUE<0||VALUE>32767)
        {
            llOwnerSay("Field out of range.");
            return;
        }
        integer packed=(GROUP<<23)|(MODE<<15)|VALUE;
        llOwnerSay("Packed="+(string)packed+"; group="+(string)((packed>>23)&255)+"; mode="+(string)((packed>>15)&255)+"; value="+(string)(packed&32767));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Pause repeated failing work

Open a local circuit after three simulated failures, then permit a recovery probe after five seconds.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch repeatedly. The first three simulated attempts fail; the next attempt after the waiting period succeeds.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is a scheduling teaching pattern with no network or payment action. It demonstrates closed, open and probe behavior using local counters.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer failures;
integer attempts;
integer open;
float retryAfter;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        if (open && now < retryAfter)
        {
            llOwnerSay("Circuit open; wait before probing.");
            return;
        }
        if (open) llOwnerSay("Recovery probe permitted.");
        ++attempts;
        integer success = (attempts > 3);
        if (success)
        {
            failures = 0;
            open = FALSE;
            llOwnerSay("Success; circuit closed.");
        }
        else
        {
            ++failures;
            llOwnerSay("Simulated failure " + (string)failures);
            if (failures >= 3)
            {
                open = TRUE;
                retryAfter = now+5.0;
                llOwnerSay("Circuit opened for five seconds.");
            }
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Prepare before committing a setting

Separate validation, preparation, and commit in a local three-touch transaction demonstration.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch to prepare, commit, and then reset the simulated transaction. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

No distributed coordinator or external resource exists. A real two-phase protocol needs durable recovery and timeout policy.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer phase;
integer live=5;
integer staged;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(phase==0)
        {
            staged=12;
            if(staged<0||staged>100)
            {
                llOwnerSay("Prepare rejected.");
                return;
            }
            phase=1;
            llOwnerSay("Prepared12; live remains "+(string)live);
        }
        else if(phase==1)
        {
            live=staged;
            phase=2;
            llOwnerSay("Committed live="+(string)live);
        }
        else
        {
            phase=0;
            llOwnerSay("Ready for another transaction.");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Reach a target with the fewest standard modules

Find the minimum number of reusable integer-sized modules needed for an exact target.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive module lengths and TARGET0..100. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Unbounded reuse is allowed. This is exact integer arithmetic, not floating-point length matching.

// Original Incoprea. MIT. Local planning demonstration.
list LENGTHS=[3,5,8];
integer TARGET=19;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TARGET<0||TARGET>100)
        {
            llOwnerSay("Target0..100 required.");
            return;
        }
        list best=[0];
        integer i;
        for(i=1;i<=TARGET;++i)best+=[1000];
        integer amount;
        for(amount=1;amount<=TARGET;++amount)
        {
            integer j;
            integer minimum=1000;
            for(j=0;j<llGetListLength(LENGTHS);++j)
            {
                integer length=llList2Integer(LENGTHS,j);
                if(length<=0)
                {
                    llOwnerSay("Positive module lengths required.");
                    return;
                }
                if(length<=amount)
                {
                    integer candidate=llList2Integer(best,amount-length)+1;
                    if(candidate<minimum)minimum=candidate;
                }
            }
            best=llListReplaceList(best,[minimum],amount,amount);
        }
        integer result=llList2Integer(best,TARGET);
        if(result>=1000)llOwnerSay("No exact combination.");
        else llOwnerSay("Minimum module count="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Read length-prefixed text fields

Decode fixed two-digit character lengths followed by their payloads, preserving embedded separators.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit RECORD using two decimal digits then exactly that many characters for each field. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Lengths count LSL characters, not UTF-8 bytes. The full record is capped at200 characters and fields at99.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
string RECORD="05hello03a|b00";
integer digit(string ch)
{
    return llSubStringIndex("0123456789",ch);
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer length=llStringLength(RECORD);
        if(length>200)
        {
            llOwnerSay("Record too long.");
            return;
        }
        integer cursor;
        list fields;
        while(cursor<length)
        {
            if(cursor+2>length)
            {
                llOwnerSay("Truncated length.");
                return;
            }
            integer a=digit(llGetSubString(RECORD,cursor,cursor));
            integer b=digit(llGetSubString(RECORD,cursor+1,cursor+1));
            if(a<0||b<0)
            {
                llOwnerSay("Invalid length digits.");
                return;
            }
            integer size=10*a+b;
            cursor+=2;
            if(cursor+size>length)
            {
                llOwnerSay("Truncated payload.");
                return;
            }
            string field="";
            if(size>0)field=llGetSubString(RECORD,cursor,cursor+size-1);
            fields+=[field];
            cursor+=size;
        }
        llOwnerSay("Decoded fields="+(string)llGetListLength(fields)+": "+llDumpList2String(fields," / "));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Reassemble a tiny message out of order

Place three numbered fragments into slots and join them only when all arrive.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch repeatedly; the sample order is2,0,1. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Slots and message identity are fixed for this teaching example. A real receiver also needs size limits, sender validation, message IDs and expiry.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list ORDER=[2,0,1];
list TEXT=["hello ","virtual ","world"];
list slots=["","",""];
integer received;
integer cursor;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(cursor>=3)
        {
            llOwnerSay("Already complete; reset to replay.");
            return;
        }
        integer index=llList2Integer(ORDER,cursor);
        ++cursor;
        slots=llListReplaceList(slots,[llList2String(TEXT,index)],index,index);
        received=received|(1<<index);
        llOwnerSay("Received fragment "+(string)index);
        if(received==7)llOwnerSay("Assembled: "+llDumpList2String(slots,""));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Reject a stale edit revision

Apply simulated edits only when their expected revision matches the current record.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch through the sample requests: expected revisions 0, 0, 1 and 2. The second is intentionally stale.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This local demonstration explains a compare-before-write guard. It does not provide cross-script atomicity or persistent storage.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list EXPECTED = [0,0,1,2];
list VALUES = [12,99,18,24];
integer cursor;
integer revision;
integer stored;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (cursor >= 4)
        {
            llOwnerSay("Sequence complete; reset to replay.");
            return;
        }
        integer expected = llList2Integer(EXPECTED,cursor);
        integer value = llList2Integer(VALUES,cursor);
        ++cursor;
        if (expected != revision)
        {
            llOwnerSay("Rejected stale revision " + (string)expected);
            return;
        }
        stored = value;
        ++revision;
        llOwnerSay("Stored " + (string)stored + " at revision " + (string)revision);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Require several healthy samples

Open a readiness gate only after three consecutive good observations and close it immediately on failure.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch through the sample success/failure sequence. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

This is a local readiness model. It differs from averaging and hysteresis because one failure resets the success streak.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list SAMPLES=[TRUE,TRUE,FALSE,TRUE,TRUE,TRUE,FALSE];
integer cursor;
integer streak;
integer ready;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer good=llList2Integer(SAMPLES,cursor);
        cursor=(cursor+1)%llGetListLength(SAMPLES);
        if(good)++streak;
        else streak=0;
        ready=(streak>=3);
        llOwnerSay("Healthy="+(string)good+"; streak="+(string)streak+"; ready="+(string)ready);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Reserve preparation and cleanup around cues

Expand each cue interval with setup and cleanup buffers and report resulting conflicts.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set cue start/end pairs and nonnegative buffer durations. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Buffers may begin before time0; callers decide whether that is permitted.

// Original Incoprea. MIT. Local planning demonstration.
list CUES=[2.0,4.0,5.0,7.0,10.0,12.0];
float SETUP_TIME=0.75;
float CLEANUP_TIME=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(CUES);
        if(n%2||SETUP_TIME<0.0||CLEANUP_TIME<0.0)
        {
            llOwnerSay("Invalid input.");
            return;
        }
        list expanded;
        integer i;
        for(i=0;i<n;i+=2)
        {
            float a=llList2Float(CUES,i);
            float b=llList2Float(CUES,i+1);
            if(b<a)
            {
                llOwnerSay("Negative cue duration.");
                return;
            }
            expanded+=[a-SETUP_TIME,b+CLEANUP_TIME];
        }
        expanded=llListSort(expanded,2,TRUE);
        float end=-1000000.0;
        integer conflicts;
        for(i=0;i<n;i+=2)
        {
            float a=llList2Float(expanded,i);
            float b=llList2Float(expanded,i+1);
            if(a<end)++conflicts;
            if(b>end)end=b;
            llOwnerSay("Reserved="+(string)a+".."+(string)b);
        }
        llOwnerSay("Conflicting starts="+(string)conflicts);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Advanced

Retiming a sequence to a target duration

Scale all cue durations proportionally while retaining their relative pacing.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive DURATIONS and positive TARGET. Owner touch runs a bounded local calculation.

Stop / restore: Disable/remove. No travel, publication, payments or external operations occur.

Retiming may violate media lengths or platform minimum delays; this only calculates a proposed timeline.

// Original Incoprea. MIT. Local planning demonstration.
list DURATIONS=[2.0,5.0,3.0];
float TARGET=24.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TARGET<=0.0)
        {
            llOwnerSay("Positive target required.");
            return;
        }
        float total;
        integer i;
        for(i=0;i<llGetListLength(DURATIONS);++i)
        {
            float d=llList2Float(DURATIONS,i);
            if(d<=0.0)
            {
                llOwnerSay("Positive cue durations required.");
                return;
            }
            total+=d;
        }
        if(total<=0.0)
        {
            llOwnerSay("No cues.");
            return;
        }
        float scale=TARGET/total;
        float start;
        for(i=0;i<llGetListLength(DURATIONS);++i)
        {
            float duration=llList2Float(DURATIONS,i)*scale;
            llOwnerSay("Cue "+(string)i+" start="+(string)start+" duration="+(string)duration);
            start+=duration;
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Logic & state · Intermediate

Retry with increasing delay

Demonstrate nonblocking retry delays of one, two, then four seconds with a strict attempt limit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to start. The simulated operation fails twice, then succeeds on attempt three.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

No network requests are made. Replace only the simulated success check when adapting; cap attempts and handle permanent failures separately.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer running;
integer attempt;
float delay;
float due;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (running)
        {
            llOwnerSay("Retry sequence active.");
            return;
        }
        running = TRUE;
        attempt = 0;
        delay = 1.0;
        due = llGetTime()+delay;
        llSetTimerEvent(0.25);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        if (!running || llGetTime() < due) return;
        ++attempt;
        integer success = (attempt >= 3);
        if (success || attempt >= 4)
        {
            llOwnerSay("Finished on attempt " + (string)attempt + "; success=" + (string)success);
            running = FALSE;
            llSetTimerEvent(0.0);
            return;
        }
        delay *= 2.0;
        due = llGetTime()+delay;
        llOwnerSay("Simulated failure; retry in " + (string)delay + " seconds.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

Run a short timeline by deadlines

Run three labeled local jobs at elapsed offsets, catching up safely when a timer arrives late.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to start the three-job timeline. Touch again to restart it.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Uses elapsed deadlines instead of assuming perfect timer intervals. It processes at most the three configured jobs per event.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list OFFSETS = [1.0,3.0,6.0];
list LABELS = ["Prepare", "Preview", "Complete"];
integer nextJob;
float started;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        nextJob = 0;
        started = llGetTime();
        llSetTimerEvent(0.25);
        llOwnerSay("Timeline started.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        float elapsed = llGetTime()-started;
        while (nextJob < 3 && elapsed >= llList2Float(OFFSETS,nextJob))
        {
            llOwnerSay(llList2String(LABELS,nextJob));
            ++nextJob;
        }
        if (nextJob >= 3) llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Run jobs after their prerequisites

Execute a small directed acyclic job graph using dependency bitmasks.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit labels and matching prerequisite masks for at most8 jobs. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

The graph is local and small. Lack of progress reports a cycle or unavailable dependency; each job executes only once per run.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list LABELS=["load","validate","preview","publish-demo"];
list NEEDS=[0,1,2,6];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(LABELS);
        if(n==0||n>8||n!=llGetListLength(NEEDS))
        {
            llOwnerSay("Invalid job table.");
            return;
        }
        integer done;
        integer target=(1<<n)-1;
        integer pass;
        for(pass=0;pass<n;++pass)
        {
            integer before=done;
            integer i;
            for(i=0;i<n;++i)
            {
                integer bit=1<<i;
                integer needs=llList2Integer(NEEDS,i);
                if(!(done&bit)&&(done&needs)==needs)
                {
                    llOwnerSay("Run "+llList2String(LABELS,i));
                    done=done|bit;
                }
            }
            if(done==target)
            {
                llOwnerSay("All local jobs complete.");
                return;
            }
            if(done==before)
            {
                llOwnerSay("Blocked by cycle or missing dependency.");
                return;
            }
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Set membership in a compact bit field

Add, remove, toggle and test small numbered flags using bitwise operations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit the sample flag indexes in code, keeping them0 through30. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

A set has no ordering or duplicate count. The example intentionally avoids bit31 to keep values nonnegative.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer flags;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        flags=flags|(1<<2);
        flags=flags|(1<<7);
        flags=flags|(1<<12);
        flags=flags&~(1<<7);
        flags=flags^(1<<4);
        list present;
        integer i;
        for(i=0;i<31;++i)if(flags&(1<<i))present+=[i];
        llOwnerSay("Flags="+(string)flags+"; present indexes="+llDumpList2String(present,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Share work budgets across queues

Demonstrate deficit round-robin so jobs with different costs can share a scheduler.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit two job-cost queues and their quantum budget. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Runs four bounded scheduling rounds. Costs and quanta must be positive; no actual work besides owner messages is performed.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list QUEUE_A=[3,3,3];
list QUEUE_B=[5,2,5];
integer QUANTUM_A=3;
integer QUANTUM_B=3;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer a;
        integer b;
        integer budgetA;
        integer budgetB;
        integer round;
        for(round=0;round<4;++round)
        {
            budgetA+=QUANTUM_A;
            budgetB+=QUANTUM_B;
            while(a<llGetListLength(QUEUE_A)&&llList2Integer(QUEUE_A,a)<=budgetA)
            {
                integer cost=llList2Integer(QUEUE_A,a);
                if(cost<=0)
                {
                    llOwnerSay("Invalid cost.");
                    return;
                }
                budgetA-=cost;
                ++a;
                llOwnerSay("A job completed in round "+(string)round);
            }
            while(b<llGetListLength(QUEUE_B)&&llList2Integer(QUEUE_B,b)<=budgetB)
            {
                integer cost=llList2Integer(QUEUE_B,b);
                if(cost<=0)
                {
                    llOwnerSay("Invalid cost.");
                    return;
                }
                budgetB-=cost;
                ++b;
                llOwnerSay("B job completed in round "+(string)round);
            }
        }
        llOwnerSay("Completed A="+(string)a+" B="+(string)b);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Small bounded work queue

Queue up to five owner requests and process them one at a time without blocking event handling.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to enqueue numbered demonstration jobs; one job completes per second.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Rejects new work when full instead of growing without bound. Jobs are only owner-chat messages; reset discards pending work.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list queue;
integer sequence;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llGetListLength(queue) >= 5)
        {
            llOwnerSay("Queue full; try later.");
            return;
        }
        ++sequence;
        queue += [sequence];
        llSetTimerEvent(1.0);
        llOwnerSay("Queued job " + (string)sequence);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        if (llGetListLength(queue) == 0)
        {
            llSetTimerEvent(0.0);
            return;
        }
        integer job = llList2Integer(queue,0);
        queue = llDeleteSubList(queue,0,0);
        llOwnerSay("Completed job " + (string)job);
        if (llGetListLength(queue) == 0) llSetTimerEvent(0.0);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

Split a calculation across events

Sum squares from one to one hundred in ten small batches to demonstrate cooperative work scheduling.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch once to start. Further touches report busy until completion.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The arithmetic is intentionally small; the pattern shows bounded work per event rather than a long loop or sleep.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer cursor;
integer total;
integer running;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (running)
        {
            llOwnerSay("Calculation already running.");
            return;
        }
        running = TRUE;
        cursor = 1;
        total = 0;
        llSetTimerEvent(0.25);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        integer batch;
        for (batch = 0; batch < 10 && cursor <= 100; ++batch)
        {
            total += cursor*cursor;
            ++cursor;
        }
        if (cursor > 100)
        {
            running = FALSE;
            llSetTimerEvent(0.0);
            llOwnerSay("Sum of squares 1..100: " + (string)total + " (expected 338350).");
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Temporary job lease with expiry

Reserve a local job slot for four seconds and reject competing owner requests until it expires.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to acquire a numbered lease. Touch again during its lifetime to see the remaining wait.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is a single-script coordination model, not a distributed lock. Reset clears it, and no avatar permissions or external resources are locked.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer leaseNumber;
float leaseEnds;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        if (now < leaseEnds)
        {
            llOwnerSay("Lease " + (string)leaseNumber + " busy for " + (string)(leaseEnds-now) + " seconds.");
            return;
        }
        ++leaseNumber;
        leaseEnds = now+4.0;
        llOwnerSay("Acquired lease " + (string)leaseNumber + "; expires in four seconds.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Advanced

Track recent sequence numbers with a bitmap

Accept recent out-of-order sequence numbers once using an eight-position sliding bitmap.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch through the fixed sequence containing duplicates and stale values. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

No wrap handling in this small demo; combine with a carefully specified sequence scheme in a real protocol. State disappears on reset.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list INPUT=[10,12,11,12,4,15,9];
integer cursor;
integer highest=-1;
integer bitmap;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(cursor>=llGetListLength(INPUT))
        {
            llOwnerSay("Sequence finished; reset to replay.");
            return;
        }
        integer sequence=llList2Integer(INPUT,cursor);
        ++cursor;
        integer accept=TRUE;
        if(highest<0)
        {
            highest=sequence;
            bitmap=1;
        }
        else if(sequence>highest)
        {
            integer shift=sequence-highest;
            if(shift>=8)bitmap=1;
            else bitmap=((bitmap<<shift)|1)&255;
            highest=sequence;
        }
        else
        {
            integer behind=highest-sequence;
            if(behind>=8)accept=FALSE;
            else if(bitmap&(1<<behind))accept=FALSE;
            else bitmap=bitmap|(1<<behind);
        }
        llOwnerSay("Sequence="+(string)sequence+" accepted="+(string)accept+" highest="+(string)highest+" bitmap="+(string)bitmap);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Two-tap confirmation window

Require a second owner touch within three seconds before reporting a confirmed action.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch once to arm, then again within three seconds to confirm. Nothing destructive is performed.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The confirmation state expires lazily on the next touch. Add a separate per-user identity check before adapting for multiple users.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer armed;
float deadline;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float now = llGetTime();
        if (armed && now <= deadline)
        {
            armed = FALSE;
            llOwnerSay("Confirmed demonstration action.");
            return;
        }
        armed = TRUE;
        deadline = now + 3.0;
        llOwnerSay("Armed: touch again within three seconds to confirm.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Undo and redo a local setting

Demonstrate editing a numeric setting, undoing, redoing, and clearing the redo branch after a fresh edit.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch through a five-step repeating sequence. The setting exists only in script memory.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

History is capped at eight values. A new edit after undo truncates the old forward branch.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list history = [0];
integer at;
integer step;
setValue(integer value)
{
    history = llList2List(history,0,at) + [value];
    ++at;
    if (llGetListLength(history) > 8)
    {
        history = llDeleteSubList(history,0,0);
        --at;
    }
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer action = step % 5;
        ++step;
        if (action == 0) setValue(step*10);
        else if (action == 1) setValue(step*10);
        else if (action == 2 && at > 0) --at;
        else if (action == 3 && at < llGetListLength(history)-1) ++at;
        else setValue(step*10);
        llOwnerSay("Current=" + (string)llList2Integer(history,at) + "; history=" + llDumpList2String(history,",") + "; cursor=" + (string)at);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Undo completed steps after a failure

Demonstrate a compensation stack that reverses earlier simulated steps when a later step fails.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Touch once to run three steps, with the third deliberately failing. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Compensation is not true atomic rollback. Each simulated step only prints owner chat and appends a reversible label.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
list undo;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        undo=[];
        llOwnerSay("Step1: reserve sample slot.");
        undo+=["release sample slot"];
        llOwnerSay("Step2: stage sample label.");
        undo+=["discard staged label"];
        llOwnerSay("Step3: simulated failure; compensating.");
        integer i;
        for(i=llGetListLength(undo)-1;i>=0;--i)llOwnerSay("Undo: "+llList2String(undo,i));
        undo=[];
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Validate a whole batch before commit

Stage a batch of stock adjustments, rejecting the entire batch if any intermediate balance would go negative.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to test an invalid batch followed by a valid batch against the same local stock balance.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

No money or real inventory is involved. The example stages all calculations before assigning the final balance.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer stock = 10;
integer demonstration;
integer applyBatch(list adjustments)
{
    integer staged = stock;
    integer i;
    for (i = 0; i < llGetListLength(adjustments); ++i)
    {
        staged += llList2Integer(adjustments,i);
        if (staged < 0) return FALSE;
    }
    stock = staged;
    return TRUE;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list changes = [-4,-9,8];
        if (demonstration % 2) changes = [-3,5,-2];
        ++demonstration;
        integer accepted = applyBatch(changes);
        llOwnerSay("Batch accepted=" + (string)accepted + "; stock=" + (string)stock);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Logic & state · Intermediate

Version and verify a checkpoint

Encode a small local record into a versioned string and verify its checksum before restoring it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to build and validate a checkpoint. Copy the printed string elsewhere if you want to retain it.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The checksum detects accidental modification, not malicious tampering. This script does not write persistent storage; resetting loses its variables.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
string makeCheckpoint(integer count, integer mode)
{
    string payload = "v1|"+(string)count+"|"+(string)mode;
    return payload+"|"+llMD5String(payload,0);
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        string saved = makeCheckpoint(27,2);
        list fields = llParseStringKeepNulls(saved,["|"],[]);
        if (llGetListLength(fields) != 4 || llList2String(fields,0) != "v1")
        {
            llOwnerSay("Unsupported checkpoint.");
            return;
        }
        string payload = llDumpList2String(llList2List(fields,0,2),"|");
        if (llMD5String(payload,0) != llList2String(fields,3))
        {
            llOwnerSay("Checksum mismatch.");
            return;
        }
        integer restoredCount = (integer)llList2String(fields,1);
        integer restoredMode = (integer)llList2String(fields,2);
        llOwnerSay(saved);
        llOwnerSay("Restored count="+(string)restoredCount+"; mode="+(string)restoredMode);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Intermediate

Wait until a burst of edits settles

Coalesce a series of owner touches into one report two seconds after the final touch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch several times quickly, then stop touching. Each touch is a simulated edit.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Timer delivery can be late. The elapsed-time check prevents an old timer event from committing a newer edit too early.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer edits;
float lastEdit;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        ++edits;
        lastEdit = llGetTime();
        llSetTimerEvent(0.25);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
    timer()
    {
        if (llGetTime() - lastEdit < 2.0) return;
        llSetTimerEvent(0.0);
        llOwnerSay("Committed one report for " + (string)edits + " simulated edits.");
        edits = 0;
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Logic & state · Advanced

Zigzag small signed integers

Map small signed values to nonnegative values ordered around zero, then reverse the mapping.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set VALUE within minus1000000 through1000000. Owner touch runs the local demonstration.

Stop / restore: Disable/remove. No external requests or scene changes occur; reset clears memory.

Useful before variable-length encoding. The chosen cap avoids overflow; zigzag alone does not reduce LSL integer storage.

// Original Incoprea. MIT. Local owner-only protocol laboratory.
integer VALUE=-37;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(VALUE< -1000000||VALUE>1000000)
        {
            llOwnerSay("Input outside demonstration range.");
            return;
        }
        integer encoded=2*VALUE;
        if(VALUE<0)encoded=-2*VALUE-1;
        integer decoded=encoded/2;
        if(encoded&1)decoded=-(encoded+1)/2;
        llOwnerSay("Encoded="+(string)encoded+"; decoded="+(string)decoded);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometryBuilder calculations, spatial reasoning, and motion curves.100 scripts

Download this category (.zip)

Math & geometry · Advanced

Aim a ray through a physical display panel

Construct a direction from an eye point through normalized coordinates on a rectangular panel.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set EYE, PANEL_ORIGIN at lower-left, RIGHT/UP full-edge vectors and UV. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

RIGHT andUP define a plane and need not align with world axes. This is a virtual geometry model, not viewer camera control.

// Original Incoprea. MIT. Transform planning only.
vector EYE=<0.0,0.0,2.0>;
vector PANEL_ORIGIN=<5.0,2.0,0.0>;
vector RIGHT=<0.0,-4.0,0.0>;
vector UP=<0.0,0.0,3.0>;
vector UV=<0.7,0.6,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(RIGHT%UP)<0.000001)
        {
            llOwnerSay("Panel edges are degenerate.");
            return;
        }
        vector target=PANEL_ORIGIN+RIGHT*UV.x+UP*UV.y;
        vector ray=target-EYE;
        if(llVecMag(ray)<0.000001)
        {
            llOwnerSay("Eye lies on target point.");
            return;
        }
        llOwnerSay("Panel point="+(string)target+" ray="+(string)llVecNorm(ray));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Area shared by two circular footprints

Calculate the lens area of partially overlapping circles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set radii R1/R2 and center distance D. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Handles separation and full containment before evaluating the lens formula. Input values are ideal geometry.

// Original Incoprea. MIT. Ideal geometry only.
float R1=3.0;
float R2=2.0;
float D=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(R1<=0.0||R2<=0.0||D<0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        if(D>=R1+R2)
        {
            llOwnerSay("Overlap area0.");
            return;
        }
        if(D<=llFabs(R1-R2))
        {
            float small=R1;
            if(R2<small)small=R2;
            llOwnerSay("Contained area="+(string)(PI*small*small));
            return;
        }
        float a=(D*D+R1*R1-R2*R2)/(2.0*D*R1);
        float b=(D*D+R2*R2-R1*R1)/(2.0*D*R2);
        if(a>1.0)a=1.0;
        if(a< -1.0)a=-1.0;
        if(b>1.0)b=1.0;
        if(b< -1.0)b=-1.0;
        float product=(-D+R1+R2)*(D+R1-R2)*(D-R1+R2)*(D+R1+R2);
        if(product<0.0)product=0.0;
        llOwnerSay("Lens area="+(string)(R1*R1*llAcos(a)+R2*R2*llAcos(b)-0.5*llSqrt(product)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Area-weighted polygon centre

Calculate an irregular flat polygon’s area-weighted centroid rather than the average of its corners.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Enter an ordered simple XY boundary in POINTS, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Output Z is zero. Concave polygons can have their centroid outside the boundary; zero-area shapes are rejected.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list POINTS = [<0.0,0.0,0.0>, <6.0,0.0,0.0>, <6.0,2.0,0.0>, <2.0,4.0,0.0>, <0.0,4.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n = llGetListLength(POINTS);
        if (n < 3)
        {
            llOwnerSay("Need three vertices.");
            return;
        }
        float area2 = 0.0;
        float sx = 0.0;
        float sy = 0.0;
        integer i;
        for (i = 0; i < n; ++i)
        {
            vector a = llList2Vector(POINTS, i);
            vector b = llList2Vector(POINTS, (i + 1) % n);
            float cross = a.x * b.y - b.x * a.y;
            area2 += cross;
            sx += (a.x + b.x) * cross;
            sy += (a.y + b.y) * cross;
        }
        if (llFabs(area2) < 0.000001)
        {
            llOwnerSay("Polygon area is zero.");
            return;
        }
        llOwnerSay("Centroid: " + (string)<sx / (3.0 * area2), sy / (3.0 * area2), 0.0>);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Balance a display by weighted points

Compute a weighted centroid for planned components with relative masses or visual weights.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Enter alternating vector/positive-weight pairs. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Weights are user-supplied estimates; no physical masses are queried. All points must share one coordinate frame.

// Original Incoprea. MIT. Owner-only calculation.
list DATA=[<0.0,0.0,0.0>,2.0,<5.0,0.0,0.0>,1.0,<1.0,4.0,0.0>,3.0];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        integer n=llGetListLength(DATA);
        if(n==0||n%2)
        {
            llOwnerSay("Use vector/weight pairs.");
            return;
        }
        vector sum=ZERO_VECTOR;
        float total;
        integer i;
        for(i=0;i<n;i+=2)
        {
            float w=llList2Float(DATA,i+1);
            if(w<=0.0)
            {
                llOwnerSay("Weights must be positive.");
                return;
            }
            sum+=llList2Vector(DATA,i)*w;
            total+=w;
        }
        llOwnerSay("Weighted centre="+(string)(sum/total));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Blend nearby rotations with normalized interpolation

Interpolate quaternion components after choosing matching quaternion signs, then normalize.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set two Euler poses and T0..1. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Normalized linear interpolation is not constant angular speed. It is useful for inexpensive blends of nearby orientations.

// Original Incoprea. MIT. Transform planning only.
vector START=<0.0,0.0,10.0>;
vector END=<20.0,30.0,50.0>;
float T=0.4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(T<0.0||T>1.0)
        {
            llOwnerSay("T must be0..1.");
            return;
        }
        rotation a=llEuler2Rot(START*DEG_TO_RAD);
        rotation b=llEuler2Rot(END*DEG_TO_RAD);
        float dot=a.x*b.x+a.y*b.y+a.z*b.z+a.s*b.s;
        if(dot<0.0)b=<-b.x,-b.y,-b.z,-b.s>;
        rotation q=<a.x+(b.x-a.x)*T,a.y+(b.y-a.y)*T,a.z+(b.z-a.z)*T,a.s+(b.s-a.s)*T>;
        float length=llSqrt(q.x*q.x+q.y*q.y+q.z*q.z+q.s*q.s);
        if(length<0.000001)
        {
            llOwnerSay("Degenerate quaternion blend.");
            return;
        }
        q=<q.x/length,q.y/length,q.z/length,q.s/length>;
        llOwnerSay("Normalized blend="+(string)q);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Bounds of a planned point cloud

Compute minimum and maximum coordinates and a center from a list of planned points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Edit POINTS with vector values. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

This examines the supplied list, not scene objects. The center is the bounds midpoint, not the average or mass center.

// Original Incoprea. MIT. Owner-only calculation.
list POINTS=[<-2.0,1.0,0.0>,<4.0,-3.0,2.0>,<1.0,5.0,7.0>];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        integer n=llGetListLength(POINTS);
        if(n==0)
        {
            llOwnerSay("No points.");
            return;
        }
        vector low=llList2Vector(POINTS,0);
        vector high=low;
        integer i;
        for(i=1;i<n;++i)
        {
            vector p=llList2Vector(POINTS,i);
            if(p.x<low.x)low.x=p.x;
            if(p.y<low.y)low.y=p.y;
            if(p.z<low.z)low.z=p.z;
            if(p.x>high.x)high.x=p.x;
            if(p.y>high.y)high.y=p.y;
            if(p.z>high.z)high.z=p.z;
        }
        llOwnerSay("Min="+(string)low+"; max="+(string)high+"; size="+(string)(high-low)+"; centre="+(string)((high+low)*0.5));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Build a stable local frame

Construct perpendicular forward/left/up axes from a heading and an approximate up vector.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Edit FORWARD and UP_HINT. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Parallel up hints require a fallback axis; the resulting frame may not retain the original roll.

// Original Incoprea. MIT.
vector FORWARD=<1.0,2.0,0.4>;
vector UP_HINT=<0.0,0.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(FORWARD)<0.000001)
        {
            llOwnerSay("Zero forward vector.");
            return;
        }
        vector f=llVecNorm(FORWARD);
        vector left=UP_HINT%f;
        if(llVecMag(left)<0.000001)
        {
            vector fallback=<0.0,1.0,0.0>;
            if(llFabs(f.y)>0.9)fallback=<1.0,0.0,0.0>;
            left=fallback%f;
        }
        left=llVecNorm(left);
        vector up=f%left;
        rotation r=llAxes2Rot(f,left,up);
        llOwnerSay("Forward="+(string)f+" left="+(string)left+" up="+(string)up+" rotation="+(string)r);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Calculate a new local pose after reparenting

Convert a fixed world pose into local coordinates under a different parent.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set world position/Euler and new parent position/Euler. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

No actual linking occurs. This provides the transform needed to preserve the pose during a planned hierarchy change.

// Original Incoprea. MIT. Transform planning only.
vector WORLD_POS=<12.0,8.0,3.0>;
vector WORLD_EULER=<10.0,20.0,40.0>;
vector PARENT_POS=<10.0,5.0,2.0>;
vector PARENT_EULER=<0.0,0.0,60.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation world=llEuler2Rot(WORLD_EULER*DEG_TO_RAD);
        rotation parent=llEuler2Rot(PARENT_EULER*DEG_TO_RAD);
        llOwnerSay("New local position="+(string)((WORLD_POS-PARENT_POS)/parent)+" local rotation="+(string)(world/parent));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Check a point against a convex boundary

Classify an XY point using consistent signs of edge cross products.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set ordered convex polygon VERTICES and test POINT. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Requires a convex polygon with consistent winding; zero cross products count as boundary and therefore inside.

// Original Incoprea. MIT. Ideal geometry only.
list VERTICES=[<0.0,0.0,0.0>,<4.0,0.0,0.0>,<5.0,3.0,0.0>,<1.0,5.0,0.0>];
vector POINT=<2.0,2.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(VERTICES);
        if(n<3)
        {
            llOwnerSay("Need three vertices.");
            return;
        }
        integer positive;
        integer negative;
        integer i;
        for(i=0;i<n;++i)
        {
            vector a=llList2Vector(VERTICES,i);
            vector b=llList2Vector(VERTICES,(i+1)%n);
            float cross=(b.x-a.x)*(POINT.y-a.y)-(b.y-a.y)*(POINT.x-a.x);
            if(cross>0.000001)positive=TRUE;
            if(cross< -0.000001)negative=TRUE;
        }
        llOwnerSay("Inside/boundary="+(string)(!(positive&&negative)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Check a round bound against a box

Find whether a sphere touches or overlaps an axis-aligned box using closest-point distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set sphere CENTER/RADIUS and box LOW/HIGH. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

The test uses ideal solid bounds and accepts tangency as overlap.

// Original Incoprea. MIT. Ideal geometry only.
vector CENTER=<3.0,1.0,0.0>;
float RADIUS=1.5;
vector LOW=<-2.0,-2.0,-2.0>;
vector HIGH=<2.0,2.0,2.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<0.0||LOW.x>HIGH.x||LOW.y>HIGH.y||LOW.z>HIGH.z)
        {
            llOwnerSay("Invalid bounds.");
            return;
        }
        vector q=CENTER;
        if(q.x<LOW.x)q.x=LOW.x;
        if(q.x>HIGH.x)q.x=HIGH.x;
        if(q.y<LOW.y)q.y=LOW.y;
        if(q.y>HIGH.y)q.y=HIGH.y;
        if(q.z<LOW.z)q.z=LOW.z;
        if(q.z>HIGH.z)q.z=HIGH.z;
        llOwnerSay("Touches/overlaps="+(string)(llVecDist(q,CENTER)<=RADIUS)+" clearance="+(string)(llVecDist(q,CENTER)-RADIUS));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Check a spherical bound against a virtual view

Classify an ideal sphere as potentially visible against near/far and four side planes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set local camera-space CENTER,+X forward, radius and view parameters. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

A conservative sphere-frustum test; it does not check occlusion or actual rendering.

// Original Incoprea. MIT. Transform planning only.
vector CENTER=<10.0,-4.0,2.0>;
float RADIUS=1.0;
float FOV=60.0;
float ASPECT=1.7777778;
float NEAR=0.1;
float FAR=30.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<0.0||FOV<=1.0||FOV>=170.0||ASPECT<=0.0||NEAR<=0.0||FAR<=NEAR)
        {
            llOwnerSay("Invalid view.");
            return;
        }
        float v=llTan(FOV*DEG_TO_RAD*0.5);
        float h=v*ASPECT;
        integer visible=TRUE;
        if(CENTER.x+RADIUS<NEAR||CENTER.x-RADIUS>FAR)visible=FALSE;
        if(CENTER.x*h-llFabs(CENTER.y)< -RADIUS*llSqrt(1.0+h*h))visible=FALSE;
        if(CENTER.x*v-llFabs(CENTER.z)< -RADIUS*llSqrt(1.0+v*v))visible=FALSE;
        llOwnerSay("Potentially visible="+(string)visible);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Check turn severity from three path points

Calculate the circumradius through three path samples as a local bend estimate.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set A/B/C in one plane. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Large radius means a gentle bend; nearly collinear points report a straight path. This is not a guaranteed trajectory curvature bound.

// Original Incoprea. MIT. Ideal geometry only.
vector A=<0.0,0.0,0.0>;
vector B=<3.0,1.0,0.0>;
vector C=<5.0,4.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float a=llVecDist(B,C);
        float b=llVecDist(A,C);
        float c=llVecDist(A,B);
        float twiceArea=llVecMag((B-A)%(C-A));
        if(a<0.000001||b<0.000001||c<0.000001)
        {
            llOwnerSay("Repeated point.");
            return;
        }
        if(twiceArea<0.000001)
        {
            llOwnerSay("Approximately straight; radius unbounded.");
            return;
        }
        llOwnerSay("Three-point bend radius="+(string)(a*b*c/(2.0*twiceArea)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Choose a viewing distance that frames a sphere

Calculate the minimum centered camera distance needed to contain a spherical bound.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive radius, vertical FOV and aspect ratio. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Uses the more restrictive half-angle; add margin in your own layout for labels or off-center framing.

// Original Incoprea. MIT. Transform planning only.
float RADIUS=3.0;
float VERTICAL_FOV=60.0;
float ASPECT=1.7777778;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||VERTICAL_FOV<=1.0||VERTICAL_FOV>=170.0||ASPECT<=0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        float vertical=VERTICAL_FOV*DEG_TO_RAD*0.5;
        float horizontal=llAtan2(llTan(vertical)*ASPECT,1.0);
        float limit=vertical;
        if(horizontal<limit)limit=horizontal;
        llOwnerSay("Minimum centered distance="+(string)(RADIUS/llSin(limit)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Choose ring detail from error tolerance

Estimate the minimum segment count for a circle polygon within a maximum radial deviation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set RADIUS and ERROR smaller than radius. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Caps the answer at4096 and reports when tolerance is too small; does not generate geometry.

// Original Incoprea. MIT.
float RADIUS=8.0;
float ERROR=0.02;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||ERROR<=0.0||ERROR>=RADIUS)
        {
            llOwnerSay("Require0<error<radius.");
            return;
        }
        float angle=llAcos(1.0-ERROR/RADIUS);
        if(angle<0.000001)
        {
            llOwnerSay("Tolerance too small for precision.");
            return;
        }
        integer segments=llCeil(PI/angle);
        if(segments<3)segments=3;
        if(segments>4096)
        {
            llOwnerSay("More than4096 segments; loosen tolerance.");
            return;
        }
        llOwnerSay("Minimum estimated segments="+(string)segments+"; actual sagitta="+(string)(RADIUS*(1.0-llCos(PI/(float)segments))));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Intermediate

Circle fitting inside a triangle

Calculate the incenter and inscribed-circle radius of a nondegenerate triangle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set three 3D vertices A/B/C. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

The weighted point lies in the triangle plane. Near-collinear input is rejected; dimensions are in the input coordinate units.

// Original Incoprea. MIT. Owner-only calculation.
vector A=<0.0,0.0,0.0>;
vector B=<6.0,0.0,0.0>;
vector C=<1.0,4.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        float a=llVecDist(B,C);
        float b=llVecDist(A,C);
        float c=llVecDist(A,B);
        float perimeter=a+b+c;
        float area=0.5*llVecMag((B-A)%(C-A));
        if(area<0.000001||perimeter<0.000001)
        {
            llOwnerSay("Degenerate triangle.");
            return;
        }
        llOwnerSay("Incenter="+(string)((a*A+b*B+c*C)/perimeter)+"; inradius="+(string)(2.0*area/perimeter));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Circle through three floor points

Find the centre and radius of a circle passing through three XY points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set A, B and C to three noncollinear points; touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Z is ignored. Nearly collinear inputs are unstable and rejected below the selected denominator tolerance.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0,0.0,0.0>;
vector B = <4.0,0.0,0.0>;
vector C = <1.0,3.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float denominator = 2.0*(A.x*(B.y-C.y)+B.x*(C.y-A.y)+C.x*(A.y-B.y));
        if (llFabs(denominator) < 0.000001)
        {
            llOwnerSay("Points are collinear or too close.");
            return;
        }
        float a2=A.x*A.x+A.y*A.y;
        float b2=B.x*B.x+B.y*B.y;
        float c2=C.x*C.x+C.y*C.y;
        float x=(a2*(B.y-C.y)+b2*(C.y-A.y)+c2*(A.y-B.y))/denominator;
        float y=(a2*(C.x-B.x)+b2*(A.x-C.x)+c2*(B.x-A.x))/denominator;
        vector centre = <x,y,0.0>;
        llOwnerSay("Centre: " + (string)centre + "; radius: " + (string)llVecDist(centre,<A.x,A.y,0.0>));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Circular arch from span and rise

Recover a circular arch radius and center elevation from chord span and crown rise.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set SPAN and RISE positive. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Models the circular segment through the two spring points and crown. A rise greater than half-span describes a major segment.

// Original Incoprea. MIT. Owner-only calculation.
float SPAN=6.0;
float RISE=1.4;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(SPAN<=0.0||RISE<=0.0)
        {
            llOwnerSay("Positive span and rise required.");
            return;
        }
        float radius=(SPAN*SPAN)/(8.0*RISE)+RISE*0.5;
        llOwnerSay("Radius="+(string)radius+"; centre elevation above spring line="+(string)(RISE-radius));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Classify a sphere against a plane

Determine whether a sphere is entirely on one side of a plane or intersects it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set sphere center/radius and plane point/normal. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Classification concerns an ideal sphere; a zero normal is rejected.

// Original Incoprea. MIT. Ideal geometry only.
vector CENTER=<1.0,2.0,3.0>;
float RADIUS=1.5;
vector ON_PLANE=<0.0,0.0,2.0>;
vector NORMAL=<0.0,0.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<0.0||llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Invalid radius/normal.");
            return;
        }
        float d=(CENTER-ON_PLANE)*llVecNorm(NORMAL);
        string result="intersects plane";
        if(d>RADIUS)result="entirely positive";
        else if(d< -RADIUS)result="entirely negative";
        llOwnerSay(result+"; signed center distance="+(string)d);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Classify an aligned box against a plane

Use projected half-extents to classify an axis-aligned box against a plane.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set center, positive half-extents and a nonzero plane normal. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

The projected support radius avoids testing all eight corners.

// Original Incoprea. MIT. Ideal geometry only.
vector CENTER=<2.0,2.0,3.0>;
vector HALF=<1.0,2.0,1.0>;
vector NORMAL=<1.0,0.0,1.0>;
vector ON_PLANE=<0.0,0.0,2.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(HALF.x<=0.0||HALF.y<=0.0||HALF.z<=0.0||llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Invalid box/normal.");
            return;
        }
        vector n=llVecNorm(NORMAL);
        float radius=HALF.x*llFabs(n.x)+HALF.y*llFabs(n.y)+HALF.z*llFabs(n.z);
        float d=(CENTER-ON_PLANE)*n;
        string result="intersects plane";
        if(d>radius)result="positive side";
        else if(d< -radius)result="negative side";
        llOwnerSay(result+" support radius="+(string)radius);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Classify points around a plane

Classify each planned point as above, below, or within a tolerance band of a plane.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set NORMAL, ON_PLANE, POINTS and TOLERANCE. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Normal direction determines positive side; the tolerance is measured in coordinate distance units.

// Original Incoprea. MIT.
vector NORMAL=<0.0,0.0,1.0>;
vector ON_PLANE=<0.0,0.0,2.0>;
float TOLERANCE=0.01;
list POINTS=[<1.0,2.0,3.0>,<1.0,1.0,2.005>,<0.0,0.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL)<0.000001||TOLERANCE<0.0)
        {
            llOwnerSay("Invalid normal/tolerance.");
            return;
        }
        vector n=llVecNorm(NORMAL);
        integer i;
        for(i=0;i<llGetListLength(POINTS);++i)
        {
            float d=(llList2Vector(POINTS,i)-ON_PLANE)*n;
            string side="on plane";
            if(d>TOLERANCE)side="positive side";
            else if(d< -TOLERANCE)side="negative side";
            llOwnerSay((string)i+": "+side+" distance="+(string)d);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Clip a finite segment at a plane

Find a crossing point only if it lies between segment endpoints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set A/B and plane point/normal. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

A segment lying in the plane is reported separately from a unique crossing.

// Original Incoprea. MIT. Ideal geometry only.
vector A=<1.0,2.0,-1.0>;
vector B=<3.0,2.0,4.0>;
vector NORMAL=<0.0,0.0,1.0>;
vector ON_PLANE=ZERO_VECTOR;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Zero normal.");
            return;
        }
        float da=(A-ON_PLANE)*NORMAL;
        float db=(B-ON_PLANE)*NORMAL;
        float denominator=da-db;
        if(llFabs(denominator)<0.000001)
        {
            if(llFabs(da)<0.000001)llOwnerSay("Segment lies in plane.");
            else llOwnerSay("Parallel without crossing.");
            return;
        }
        float t=da/denominator;
        if(t<0.0||t>1.0)
        {
            llOwnerSay("Crossing outside segment.");
            return;
        }
        llOwnerSay("Crossing="+(string)(A+(B-A)*t)+" fraction="+(string)t);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Clip a line segment to a circular boundary

Find circle intersections whose parameters fall within a finite segment.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set XY endpoints A/B, CENTER and positive RADIUS. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Prints entry and exit independently; tangency can print the same point twice. Z is discarded.

// Original Incoprea. MIT. Ideal geometry only.
vector A=<-5.0,1.0,0.0>;
vector B=<5.0,1.0,0.0>;
vector CENTER=ZERO_VECTOR;
float RADIUS=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector d=B-A;
        d.z=0.0;
        vector f=A-CENTER;
        f.z=0.0;
        float a=d*d;
        if(a<0.000001||RADIUS<=0.0)
        {
            llOwnerSay("Invalid segment/radius.");
            return;
        }
        float b=2.0*(f*d);
        float c=f*f-RADIUS*RADIUS;
        float disc=b*b-4.0*a*c;
        if(disc<0.0)
        {
            llOwnerSay("No crossings.");
            return;
        }
        float root=llSqrt(disc);
        list parameters=[(-b-root)/(2.0*a),(-b+root)/(2.0*a)];
        integer found;
        integer i;
        for(i=0;i<2;++i)
        {
            float t=llList2Float(parameters,i);
            if(t>=0.0&&t<=1.0)
            {
                ++found;
                llOwnerSay("Crossing="+(string)(A+t*d));
            }
        }
        if(!found)llOwnerSay("Intersections lie outside the segment.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Closest point on a rail segment

Find the nearest location on a finite rail and the distance from a test point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit endpoints A and B and test point P, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Unlike an infinite-line projection, the result is clamped to the endpoints. A zero-length segment returns A.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0, 0.0, 0.0>;
vector B = <8.0, 0.0, 2.0>;
vector P = <3.0, 4.0, 1.0>;
vector closest(vector p, vector a, vector b)
{
    vector d = b - a;
    float denominator = d * d;
    if (denominator < 0.000001) return a;
    float t = ((p - a) * d) / denominator;
    if (t < 0.0) t = 0.0;
    if (t > 1.0) t = 1.0;
    return a + t * d;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector result = closest(P, A, B);
        llOwnerSay("Closest: " + (string)result + "; distance: " + (string)llVecDist(P, result));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Closest point on or inside an aligned box

Clamp a point independently to the bounds of a box.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINT, CENTER and positive SIZE. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

A point already inside returns itself; this is nearest point in the solid box, not necessarily on its surface.

// Original Incoprea. MIT. Ideal geometry only.
vector POINT=<5.0,1.0,-3.0>;
vector CENTER=ZERO_VECTOR;
vector SIZE=<4.0,4.0,4.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SIZE.x<=0.0||SIZE.y<=0.0||SIZE.z<=0.0)
        {
            llOwnerSay("Positive sizes required.");
            return;
        }
        vector low=CENTER-SIZE*0.5;
        vector high=CENTER+SIZE*0.5;
        vector q=POINT;
        if(q.x<low.x)q.x=low.x;
        if(q.x>high.x)q.x=high.x;
        if(q.y<low.y)q.y=low.y;
        if(q.y>high.y)q.y=high.y;
        if(q.z<low.z)q.z=low.z;
        if(q.z>high.z)q.z=high.z;
        llOwnerSay("Closest="+(string)q+" distance="+(string)llVecDist(POINT,q));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Compare a local turn with a world turn

Show how multiplication order changes a rotation around a tilted object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set initial Euler pose and a delta Euler rotation. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

LSL composes rotations left-to-right; local delta precedes the starting world pose.

// Original Incoprea. MIT. Transform planning only.
vector POSE=<30.0,20.0,45.0>;
vector DELTA=<25.0,0.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation pose=llEuler2Rot(POSE*DEG_TO_RAD);
        rotation delta=llEuler2Rot(DELTA*DEG_TO_RAD);
        llOwnerSay("Local turn Euler="+(string)(llRot2Euler(delta*pose)*RAD_TO_DEG));
        llOwnerSay("World turn Euler="+(string)(llRot2Euler(pose*delta)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Compose a child pose with a parent pose

Calculate a child’s world position and world rotation from its local transform.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set parent position/Euler and child offset/Euler. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Assumes no scale transform; LSL linksets use local child transforms relative to the root.

// Original Incoprea. MIT. Transform planning only.
vector PARENT_POS=<10.0,20.0,3.0>;
vector PARENT_EULER=<0.0,0.0,40.0>;
vector CHILD_POS=<2.0,1.0,0.0>;
vector CHILD_EULER=<15.0,0.0,20.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation parent=llEuler2Rot(PARENT_EULER*DEG_TO_RAD);
        rotation local=llEuler2Rot(CHILD_EULER*DEG_TO_RAD);
        llOwnerSay("World position="+(string)(PARENT_POS+CHILD_POS*parent)+" world rotation="+(string)(local*parent));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Convert vertical and horizontal field of view

Calculate horizontal FOV from vertical FOV and aspect ratio.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set vertical degrees and positive ASPECT. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Uses a symmetric perspective projection. Diagonal FOV is also reported for planning.

// Original Incoprea. MIT. Transform planning only.
float VERTICAL_FOV=60.0;
float ASPECT=1.7777778;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(VERTICAL_FOV<=1.0||VERTICAL_FOV>=170.0||ASPECT<=0.0)
        {
            llOwnerSay("Invalid view parameters.");
            return;
        }
        float t=llTan(VERTICAL_FOV*DEG_TO_RAD*0.5);
        llOwnerSay("Horizontal FOV="+(string)(2.0*llAtan2(t*ASPECT,1.0)*RAD_TO_DEG)+" diagonal FOV="+(string)(2.0*llAtan2(t*llSqrt(1.0+ASPECT*ASPECT),1.0)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Convert world size into screen pixels

Estimate the pixel height of a frontal object at a given camera depth.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive object height, depth, viewport pixel height and vertical FOV. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Assumes a flat front-facing object centered at one depth; complex meshes require projection of their bounds.

// Original Incoprea. MIT. Transform planning only.
float OBJECT_HEIGHT=2.0;
float DEPTH=10.0;
float VIEWPORT_HEIGHT=1080.0;
float FOV=60.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OBJECT_HEIGHT<=0.0||DEPTH<=0.0||VIEWPORT_HEIGHT<=0.0||FOV<=1.0||FOV>=170.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        float pixels=OBJECT_HEIGHT*VIEWPORT_HEIGHT/(2.0*DEPTH*llTan(FOV*DEG_TO_RAD*0.5));
        llOwnerSay("Projected height pixels="+(string)pixels);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Cubic path position and tangent

Evaluate a four-control-point curve and its forward tangent at one parameter.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set A/B/C/D and T between zero and one, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

A zero derivative gives no unique direction. This only prints a vector; mesh forward axes must be handled when adapting it to motion.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0,0.0,0.0>;
vector B = <2.0,4.0,0.0>;
vector C = <6.0,-2.0,0.0>;
vector D = <8.0,0.0,0.0>;
float T = 0.5;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (T < 0.0 || T > 1.0)
        {
            llOwnerSay("T must be between zero and one.");
            return;
        }
        float u = 1.0 - T;
        vector p = u*u*u*A + 3.0*u*u*T*B + 3.0*u*T*T*C + T*T*T*D;
        vector d = 3.0*u*u*(B-A) + 6.0*u*T*(C-B) + 3.0*T*T*(D-C);
        llOwnerSay("Point: " + (string)p);
        if (llVecMag(d) < 0.000001) llOwnerSay("Stationary point: tangent is undefined.");
        else llOwnerSay("Unit tangent: " + (string)llVecNorm(d));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Distance across a spherical world

Calculate the shortest surface arc between two latitude/longitude pairs on an ideal sphere.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set RADIUS and both latitude/longitude pairs in degrees. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Uses the haversine formula with clamping. This is a model-sphere tool; it does not query real-world geolocation.

// Original Incoprea. MIT. Owner-only calculation.
float RADIUS=10.0;
float LAT1=10.0;
float LON1=20.0;
float LAT2=35.0;
float LON2=75.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(RADIUS<=0.0||llFabs(LAT1)>90.0||llFabs(LAT2)>90.0)
        {
            llOwnerSay("Invalid radius/latitude.");
            return;
        }
        float p1=LAT1*DEG_TO_RAD;
        float p2=LAT2*DEG_TO_RAD;
        float dp=(LAT2-LAT1)*DEG_TO_RAD;
        float dl=(LON2-LON1)*DEG_TO_RAD;
        float h=llPow(llSin(dp*0.5),2.0)+llCos(p1)*llCos(p2)*llPow(llSin(dl*0.5),2.0);
        if(h<0.0)h=0.0;
        if(h>1.0)h=1.0;
        llOwnerSay("Surface arc="+(string)(2.0*RADIUS*llAtan2(llSqrt(h),llSqrt(1.0-h))));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Distance along a circular path

Convert travel distance along a circle into an angle and destination offset.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set RADIUS, DISTANCE, and START_DEGREES. Touch to calculate an XY offset around the origin.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Negative distance travels clockwise. Radius must be positive. Multiple revolutions are allowed; no object moves.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float RADIUS = 4.0;
float DISTANCE = 6.0;
float START_DEGREES = 30.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (RADIUS <= 0.0)
        {
            llOwnerSay("Radius must be positive.");
            return;
        }
        float delta = DISTANCE / RADIUS;
        float angle = START_DEGREES * DEG_TO_RAD + delta;
        llOwnerSay("Travel angle: " + (string)(delta * RAD_TO_DEG) + " degrees");
        llOwnerSay("Offset: " + (string)<RADIUS*llCos(angle), RADIUS*llSin(angle), 0.0>);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Advanced

Distance from a point to a capsule

Find signed clearance from a point to a swept-sphere segment.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set segment A/B, nonnegative RADIUS and point P. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Negative clearance means inside the ideal capsule. A zero-length segment becomes a sphere.

// Original Incoprea. MIT. Ideal geometry only.
vector A=ZERO_VECTOR;
vector B=<6.0,0.0,0.0>;
vector P=<3.0,2.0,1.0>;
float RADIUS=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<0.0)
        {
            llOwnerSay("Nonnegative radius required.");
            return;
        }
        vector d=B-A;
        float den=d*d;
        float t=0.0;
        if(den>0.000001)t=((P-A)*d)/den;
        if(t<0.0)t=0.0;
        if(t>1.0)t=1.0;
        vector q=A+t*d;
        llOwnerSay("Axis point="+(string)q+" capsule clearance="+(string)(llVecDist(P,q)-RADIUS));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Do two floor-plan segments cross?

Find the intersection of two finite XY segments and distinguish crossings from extended-line intersections.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set segment endpoints A/B and C/D, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Z is ignored. Parallel and collinear segments are reported together; overlapping collinear intervals need a separate test.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0,0.0,0.0>;
vector B = <5.0,5.0,0.0>;
vector C = <0.0,4.0,0.0>;
vector D = <6.0,1.0,0.0>;
float cross2(vector a, vector b)
{
    return a.x*b.y - a.y*b.x;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector r = B-A;
        vector s = D-C;
        float denominator = cross2(r,s);
        if (llFabs(denominator) < 0.000001)
        {
            llOwnerSay("Parallel or collinear; no unique crossing.");
            return;
        }
        float t = cross2(C-A,s)/denominator;
        float u = cross2(C-A,r)/denominator;
        if (t < 0.0 || t > 1.0 || u < 0.0 || u > 1.0)
        {
            llOwnerSay("Extended lines cross, finite segments do not.");
            return;
        }
        vector p = A+t*r;
        p.z = 0.0;
        llOwnerSay("Crossing: " + (string)p);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Ellipse border length estimate

Estimate an ellipse perimeter using Ramanujan’s second approximation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set positive semi-axes A and B. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

The result is approximate, especially for extremely flat ellipses. Semi-axes are half the overall width and height.

// Original Incoprea. MIT. Owner-only calculation.
float A=5.0;
float B=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(A<=0.0||B<=0.0)
        {
            llOwnerSay("Positive semi-axes required.");
            return;
        }
        float h=((A-B)*(A-B))/((A+B)*(A+B));
        float perimeter=PI*(A+B)*(1.0+3.0*h/(10.0+llSqrt(4.0-3.0*h)));
        llOwnerSay("Approximate ellipse perimeter="+(string)perimeter);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Ellipse position and tangent heading

Evaluate an ellipse point and the direction of increasing parameter around it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set semi-axes and parameter degrees. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Parameter angle is not the same as the point’s polar bearing except on a circle.

// Original Incoprea. MIT. Owner-only calculation.
float A=5.0;
float B=2.0;
float ANGLE=40.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(A<=0.0||B<=0.0)
        {
            llOwnerSay("Positive semi-axes required.");
            return;
        }
        float t=ANGLE*DEG_TO_RAD;
        vector point=<A*llCos(t),B*llSin(t),0.0>;
        vector direction=<-A*llSin(t),B*llCos(t),0.0>;
        llOwnerSay("Point="+(string)point+"; tangent heading="+(string)(llAtan2(direction.y,direction.x)*RAD_TO_DEG));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Advanced

Estimate a cubic curve’s length

Sum short straight samples to approximate the length of a cubic Bézier curve.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set four control points and SAMPLES between2 and100. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

This underestimates a curved path; refine the sample count and compare results before using it as a distance budget.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<2.0,5.0,0.0>;
vector C=<6.0,-3.0,0.0>;
vector D=<10.0,0.0,0.0>;
integer SAMPLES=30;
vector curve(float t)
{
    float u=1.0-t;
    return u*u*u*A+3.0*u*u*t*B+3.0*u*t*t*C+t*t*t*D;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SAMPLES<2||SAMPLES>100)
        {
            llOwnerSay("Use2..100 samples.");
            return;
        }
        vector previous=A;
        float length;
        integer i;
        for(i=1;i<=SAMPLES;++i)
        {
            vector p=curve((float)i/(float)SAMPLES);
            length+=llVecDist(previous,p);
            previous=p;
        }
        llOwnerSay("Sampled curve length="+(string)length);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Estimate angular speed between two recorded poses

Calculate minimum rotation magnitude per elapsed second.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set two Euler poses and positive DT. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

The shortest difference loses revolutions greater than180 degrees between samples; sample fast enough for the intended motion.

// Original Incoprea. MIT. Transform planning only.
vector BEFORE=<0.0,0.0,10.0>;
vector AFTER=<0.0,0.0,35.0>;
float DT=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(DT<=0.0)
        {
            llOwnerSay("Positive elapsed time required.");
            return;
        }
        rotation a=llEuler2Rot(BEFORE*DEG_TO_RAD);
        rotation b=llEuler2Rot(AFTER*DEG_TO_RAD);
        rotation relative=b/a;
        float angle=llRot2Angle(relative);
        llOwnerSay("Minimum angular speed rad/s="+(string)(angle/DT)+" deg/s="+(string)(angle*RAD_TO_DEG/DT));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Evaluate a three-level transform chain

Compose base, arm and tool offsets through a small hierarchy.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set the supplied local poses for each level. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Parent scale is excluded. Prints both the final world point and orientation.

// Original Incoprea. MIT. Transform planning only.
vector BASE_POS=<5.0,5.0,1.0>;
vector ARM_OFFSET=<2.0,0.0,0.0>;
vector TOOL_OFFSET=<1.5,0.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation base=llEuler2Rot(<0.0,0.0,30.0>*DEG_TO_RAD);
        rotation armLocal=llEuler2Rot(<0.0,20.0,40.0>*DEG_TO_RAD);
        rotation toolLocal=llEuler2Rot(<10.0,0.0,0.0>*DEG_TO_RAD);
        vector armPos=BASE_POS+ARM_OFFSET*base;
        rotation armWorld=armLocal*base;
        vector toolPos=armPos+TOOL_OFFSET*armWorld;
        llOwnerSay("Tool position="+(string)toolPos+" rotation="+(string)(toolLocal*armWorld));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Even stair riser planner

Choose an integer riser count that stays below a target rise, then distribute the total height evenly.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set TOTAL_RISE, MAX_RISER and AVAILABLE_RUN in metres, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is virtual-world geometry, not construction-code advice. Assumes the top landing is the final level and therefore one fewer tread than risers.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float TOTAL_RISE = 3.0;
float MAX_RISER = 0.22;
float AVAILABLE_RUN = 4.5;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (TOTAL_RISE <= 0.0 || MAX_RISER <= 0.0 || AVAILABLE_RUN <= 0.0)
        {
            llOwnerSay("All dimensions must be positive.");
            return;
        }
        integer risers = llCeil(TOTAL_RISE / MAX_RISER);
        if (risers < 2) risers = 2;
        integer treads = risers - 1;
        llOwnerSay((string)risers + " risers at " + (string)(TOTAL_RISE/(float)risers) + " m");
        llOwnerSay((string)treads + " treads at " + (string)(AVAILABLE_RUN/(float)treads) + " m run");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Expand bounds by a clearance margin

Compute padded box bounds and the added bounding volume.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive full SIZE, CENTER and nonnegative MARGIN. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Padding is axis-aligned and conservative near corners; it is not the exact rounded Minkowski sum with a sphere.

// Original Incoprea. MIT. Ideal geometry only.
vector SIZE=<4.0,3.0,2.0>;
vector CENTER=<5.0,5.0,2.0>;
float MARGIN=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SIZE.x<=0.0||SIZE.y<=0.0||SIZE.z<=0.0||MARGIN<0.0)
        {
            llOwnerSay("Invalid size/margin.");
            return;
        }
        vector padded=SIZE+<2.0*MARGIN,2.0*MARGIN,2.0*MARGIN>;
        llOwnerSay("Low="+(string)(CENTER-padded*0.5)+" high="+(string)(CENTER+padded*0.5)+" extra volume="+(string)(padded.x*padded.y*padded.z-SIZE.x*SIZE.y*SIZE.z));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Face a target while preserving an upright frame

Calculate a yaw-only pose from an origin to a target after discarding height difference.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set ORIGIN and TARGET with differentXY positions. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Assumes local+X is the model front; no actual rotation is applied.

// Original Incoprea. MIT. Transform planning only.
vector ORIGIN=<4.0,5.0,1.0>;
vector TARGET=<8.0,2.0,7.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector delta=TARGET-ORIGIN;
        delta.z=0.0;
        if(llVecMag(delta)<0.000001)
        {
            llOwnerSay("Target has no horizontal bearing.");
            return;
        }
        float yaw=llAtan2(delta.y,delta.x);
        llOwnerSay("Yaw degrees="+(string)(yaw*RAD_TO_DEG)+" rotation="+(string)llEuler2Rot(<0.0,0.0,yaw>));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Find a corner from three planes

Find the unique point where three independent planes meet.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set normals N1/N2/N3 and offsets for n dot x = d. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Rejects a near-zero determinant. Ill-conditioned plane combinations amplify numeric error.

// Original Incoprea. MIT.
vector N1=<1.0,0.0,0.0>;
vector N2=<0.0,1.0,0.0>;
vector N3=<1.0,1.0,1.0>;
float D1=2.0;
float D2=3.0;
float D3=9.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float determinant=N1*(N2%N3);
        if(llFabs(determinant)<0.000001)
        {
            llOwnerSay("Planes have no stable unique corner.");
            return;
        }
        vector point=(D1*(N2%N3)+D2*(N3%N1)+D3*(N1%N2))/determinant;
        llOwnerSay("Corner="+(string)point);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Fit a circular footprint in a rectangle

Report the minimum wall clearance for a circular footprint inside a rectangle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set circle X/Y/RADIUS and rectangular width/height from origin. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Negative clearance identifies a boundary violation; the rectangle is axis-aligned inXY.

// Original Incoprea. MIT. Ideal geometry only.
float X=2.0;
float Y=1.5;
float RADIUS=0.8;
float WIDTH=6.0;
float HEIGHT=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<0.0||WIDTH<=0.0||HEIGHT<=0.0)
        {
            llOwnerSay("Invalid dimensions.");
            return;
        }
        float gap=X-RADIUS;
        float other=WIDTH-X-RADIUS;
        if(other<gap)gap=other;
        other=Y-RADIUS;
        if(other<gap)gap=other;
        other=HEIGHT-Y-RADIUS;
        if(other<gap)gap=other;
        llOwnerSay("Minimum edge clearance="+(string)gap+" fully inside="+(string)(gap>=0.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Fit panels with equal gaps

Calculate the gap around and between a chosen number of equal-width panels.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set span, panel width, and panel count. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Includes one equal gap at each end. Negative leftover span is reported instead of creating overlap.

// Original Incoprea. MIT. Owner-only calculation.
float SPAN=12.0;
float WIDTH=1.4;
integer COUNT=6;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(SPAN<=0.0||WIDTH<=0.0||COUNT<1)
        {
            llOwnerSay("Invalid dimensions/count.");
            return;
        }
        float spare=SPAN-(float)COUNT*WIDTH;
        if(spare<0.0)
        {
            llOwnerSay("Panels do not fit.");
            return;
        }
        float gap=spare/(float)(COUNT+1);
        llOwnerSay("Gap="+(string)gap+"; first centre="+(string)(gap+WIDTH*0.5)+"; pitch="+(string)(WIDTH+gap));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Frame a flat artwork with a perspective view

Calculate viewing distance for a centered front-facing rectangular artwork.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set width/height, vertical FOV and aspect ratio. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

The artwork must face the camera directly. Unlike spherical fitting, it uses tangent rather than sine.

// Original Incoprea. MIT. Transform planning only.
float WIDTH=6.0;
float HEIGHT=4.0;
float VERTICAL_FOV=50.0;
float ASPECT=1.7777778;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||HEIGHT<=0.0||VERTICAL_FOV<=1.0||VERTICAL_FOV>=170.0||ASPECT<=0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        float t=llTan(VERTICAL_FOV*DEG_TO_RAD*0.5);
        float d=HEIGHT*0.5/t;
        float horizontal=WIDTH*0.5/(t*ASPECT);
        if(horizontal>d)d=horizontal;
        llOwnerSay("Minimum frontal distance="+(string)d);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Gable roof cross-section

Calculate a symmetric gable ridge height and sloped rafter length from span and pitch.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set span and pitch degrees between zero and eighty. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

An idealized cross-section; ignores thickness, overhangs and structural loads.

// Original Incoprea. MIT. Owner-only calculation.
float SPAN=10.0;
float PITCH=35.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(SPAN<=0.0||PITCH<=0.0||PITCH>=80.0)
        {
            llOwnerSay("Use positive span and pitch between0 and80.");
            return;
        }
        float angle=PITCH*DEG_TO_RAD;
        float half=SPAN*0.5;
        float rise=half*llTan(angle);
        llOwnerSay("Ridge rise="+(string)rise+"; slope length="+(string)(half/llCos(angle)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Helical display layout

Print eight evenly spaced samples on a helix for planning a spiral display.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set RADIUS, HEIGHT and TURNS. Touch to print offsets; add your chosen centre later.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Samples include both endpoints. Points are evenly spaced in parameter, and for a constant-radius helix this also gives equal arc intervals.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float RADIUS = 2.0;
float HEIGHT = 4.0;
float TURNS = 1.5;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (RADIUS <= 0.0)
        {
            llOwnerSay("Use a positive radius.");
            return;
        }
        integer i;
        for (i = 0; i < 8; ++i)
        {
            float t = (float)i / 7.0;
            float angle = TWO_PI * TURNS * t;
            llOwnerSay((string)i + ": " + (string)<RADIUS*llCos(angle), RADIUS*llSin(angle), HEIGHT*t>);
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Advanced

Intersection line of two planes

Solve for one point and a direction on the intersection of two nonparallel planes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set normal N1/N2 and scalar offsets D1/D2 for equations n dot x = d. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Normals need not be unit length. Nearly parallel planes are rejected; output is an infinite line.

// Original Incoprea. MIT.
vector N1=<0.0,0.0,1.0>;
float D1=2.0;
vector N2=<1.0,1.0,0.0>;
float D2=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector direction=N1%N2;
        float denominator=direction*direction;
        if(denominator<0.000001)
        {
            llOwnerSay("Parallel planes or zero normals.");
            return;
        }
        vector point=((D1*N2-D2*N1)%direction)/denominator;
        llOwnerSay("Point="+(string)point+"; direction="+(string)llVecNorm(direction));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Irregular floor area by vertices

Measure the XY area of an ordered polygon using its boundary vertices.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Replace POINTS with your boundary in clockwise or counterclockwise order, without repeating the first point. Touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Assumes a simple, non-self-intersecting polygon. Z is ignored. Signed area also reveals winding; no prim measurements are changed.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list POINTS = [<0.0,0.0,0.0>, <6.0,0.0,0.0>, <6.0,2.0,0.0>, <3.0,4.0,0.0>, <0.0,4.0,0.0>];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n = llGetListLength(POINTS);
        if (n < 3)
        {
            llOwnerSay("Need at least three vertices.");
            return;
        }
        float twiceArea = 0.0;
        integer i;
        for (i = 0; i < n; ++i)
        {
            vector a = llList2Vector(POINTS, i);
            vector b = llList2Vector(POINTS, (i + 1) % n);
            twiceArea += a.x * b.y - b.x * a.y;
        }
        llOwnerSay("Area: " + (string)(llFabs(twiceArea) * 0.5) + " square metres; signed: " + (string)(twiceArea * 0.5));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Limit a displacement without changing direction

Clamp a displacement by magnitude instead of clipping each coordinate independently.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set DISPLACEMENT and positive MAXIMUM. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Useful as a reusable movement-budget calculation; no actual movement occurs.

// Original Incoprea. MIT.
vector DISPLACEMENT=<8.0,6.0,1.0>;
float MAXIMUM=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MAXIMUM<0.0)
        {
            llOwnerSay("Maximum cannot be negative.");
            return;
        }
        vector result=DISPLACEMENT;
        float length=llVecMag(result);
        if(length>MAXIMUM&&length>0.0)result*=MAXIMUM/length;
        llOwnerSay("Limited displacement="+(string)result+"; retained fraction="+(string)(llVecMag(result)/(length+0.000001)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Limit a full3D pose change by angular speed

Choose the interpolation fraction allowed by a maximum degrees-per-second rate.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set Euler current/target, positive MAX_SPEED and nonnegative DT. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Uses the minimum rotation path and clamps to the target when the budget is sufficient.

// Original Incoprea. MIT. Transform planning only.
vector CURRENT=<10.0,15.0,20.0>;
vector TARGET=<70.0,-20.0,100.0>;
float MAX_SPEED=45.0;
float DT=0.2;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MAX_SPEED<=0.0||DT<0.0)
        {
            llOwnerSay("Invalid rate/time.");
            return;
        }
        rotation a=llEuler2Rot(CURRENT*DEG_TO_RAD);
        rotation b=llEuler2Rot(TARGET*DEG_TO_RAD);
        rotation delta=b/a;
        float angle=llRot2Angle(delta);
        if(angle<0.000001)
        {
            llOwnerSay("Already at target.");
            return;
        }
        float step=MAX_SPEED*DEG_TO_RAD*DT;
        if(step>angle)step=angle;
        rotation result=llAxisAngle2Rot(llRot2Axis(delta),step)*a;
        llOwnerSay("Next rotation="+(string)result+" fraction="+(string)(step/angle));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Locate a point by approximate curve distance

Build a sampled arc-length lookup and find the position halfway along a cubic curve.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set control points and FRACTION in zero through one. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Twenty segments approximate distance; interpolating between samples introduces error. Useful for even travel, not exact arc-length inversion.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<1.0,8.0,0.0>;
vector C=<3.0,-2.0,0.0>;
vector D=<10.0,0.0,0.0>;
float FRACTION=0.5;
vector curve(float t)
{
    float u=1.0-t;
    return u*u*u*A+3.0*u*u*t*B+3.0*u*t*t*C+t*t*t*D;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(FRACTION<0.0||FRACTION>1.0)
        {
            llOwnerSay("Fraction must be0..1.");
            return;
        }
        list points=[A];
        list lengths=[0.0];
        float total;
        vector last=A;
        integer i;
        for(i=1;i<=20;++i)
        {
            vector p=curve((float)i/20.0);
            total+=llVecDist(last,p);
            points+=[p];
            lengths+=[total];
            last=p;
        }
        float wanted=total*FRACTION;
        integer at=1;
        while(at<20&&llList2Float(lengths,at)<wanted)++at;
        float low=llList2Float(lengths,at-1);
        float span=llList2Float(lengths,at)-low;
        float mix=0.0;
        if(span>0.000001)mix=(wanted-low)/span;
        vector first=llList2Vector(points,at-1);
        llOwnerSay("Approximate point="+(string)(first+(llList2Vector(points,at)-first)*mix));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Map a decal point between triangles

Transfer a point from a source triangle onto a destination triangle using barycentric coordinates.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set source A/B/C, target U/V/W and source point P. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Target need not share the source plane. Points outside the source triangle extrapolate outside the target.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<1.0,0.0,0.0>;
vector C=<0.0,1.0,0.0>;
vector P=<0.25,0.5,0.0>;
vector U=<3.0,4.0,2.0>;
vector V=<7.0,4.0,2.0>;
vector W=<3.0,8.0,5.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector a=B-A;
        vector b=C-A;
        vector p=P-A;
        float aa=a*a;
        float ab=a*b;
        float bb=b*b;
        float pa=p*a;
        float pb=p*b;
        float d=aa*bb-ab*ab;
        if(llFabs(d)<0.000001)
        {
            llOwnerSay("Degenerate source triangle.");
            return;
        }
        float v=(bb*pa-ab*pb)/d;
        float w=(aa*pb-ab*pa)/d;
        llOwnerSay("Mapped point="+(string)((1.0-v-w)*U+v*V+w*W));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Maximum panels with minimum spacing

Find how many panels fit in a span with specified end margins and minimum internal gaps.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set span, margins, panel width, and gap. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

End margins are reserved first. Reports the extra slack that remains after placing the maximum count.

// Original Incoprea. MIT. Owner-only calculation.
float SPAN=14.0;
float MARGIN=0.75;
float WIDTH=1.8;
float GAP=0.35;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(WIDTH<=0.0||GAP<0.0||MARGIN<0.0)
        {
            llOwnerSay("Invalid inputs.");
            return;
        }
        float available=SPAN-2.0*MARGIN;
        integer count=llFloor((available+GAP)/(WIDTH+GAP));
        if(count<1)
        {
            llOwnerSay("No panel fits.");
            return;
        }
        float used=count*WIDTH+(count-1)*GAP;
        llOwnerSay("Panels="+(string)count+"; extra slack="+(string)(available-used));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Mirror a planned point across a plane

Reflect a position across an offset plane while retaining its perpendicular distance.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINT, ON_PLANE and nonzero NORMAL. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Unlike reflecting a direction, position reflection includes the plane origin.

// Original Incoprea. MIT.
vector POINT=<2.0,3.0,8.0>;
vector ON_PLANE=<0.0,0.0,2.0>;
vector NORMAL=<0.0,0.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Zero normal.");
            return;
        }
        vector n=llVecNorm(NORMAL);
        float distance=(POINT-ON_PLANE)*n;
        llOwnerSay("Mirrored point="+(string)(POINT-2.0*distance*n));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Move a pose partway along its shortest rotation

Interpolate two orientations through their relative axis and minimum rotation angle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set Euler START/END and T0..1. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

This uses the shortest relative rotation; it cannot preserve a deliberately requested extra revolution.

// Original Incoprea. MIT. Transform planning only.
vector START=<10.0,20.0,350.0>;
vector END=<40.0,-10.0,15.0>;
float T=0.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(T<0.0||T>1.0)
        {
            llOwnerSay("T must be0..1.");
            return;
        }
        rotation a=llEuler2Rot(START*DEG_TO_RAD);
        rotation b=llEuler2Rot(END*DEG_TO_RAD);
        rotation relative=b/a;
        float angle=llRot2Angle(relative);
        rotation partial=ZERO_ROTATION;
        if(angle>0.000001)partial=llAxisAngle2Rot(llRot2Axis(relative),angle*T);
        llOwnerSay("Interpolated rotation="+(string)(partial*a));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Overlap volume of two aligned boxes

Find the intersection box and its volume for two axis-aligned boxes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set centers A/B and positive full sizes SA/SB. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Ideal boxes only; face touching has zero overlap volume.

// Original Incoprea. MIT. Ideal geometry only.
vector A=ZERO_VECTOR;
vector SA=<4.0,4.0,4.0>;
vector B=<2.0,1.0,0.0>;
vector SB=<3.0,3.0,2.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(SA.x<=0.0||SA.y<=0.0||SA.z<=0.0||SB.x<=0.0||SB.y<=0.0||SB.z<=0.0)
        {
            llOwnerSay("Positive sizes required.");
            return;
        }
        vector low=A-SA*0.5;
        vector high=A+SA*0.5;
        vector bl=B-SB*0.5;
        vector bh=B+SB*0.5;
        if(bl.x>low.x)low.x=bl.x;
        if(bl.y>low.y)low.y=bl.y;
        if(bl.z>low.z)low.z=bl.z;
        if(bh.x<high.x)high.x=bh.x;
        if(bh.y<high.y)high.y=bh.y;
        if(bh.z<high.z)high.z=bh.z;
        vector size=high-low;
        if(size.x<=0.0||size.y<=0.0||size.z<=0.0)
        {
            llOwnerSay("No positive-volume overlap.");
            return;
        }
        llOwnerSay("Overlap center="+(string)((low+high)*0.5)+" size="+(string)size+" volume="+(string)(size.x*size.y*size.z));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Point at distance along a polyline

Walk a polyline to find a location at a chosen distance from its beginning.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINTS and nonnegative DISTANCE. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Duplicate points are skipped naturally. Distances longer than the route clamp to the final point.

// Original Incoprea. MIT.
list POINTS=[<0.0,0.0,0.0>,<3.0,0.0,0.0>,<3.0,4.0,0.0>,<6.0,4.0,2.0>];
float DISTANCE=5.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(POINTS);
        if(n<1||DISTANCE<0.0)
        {
            llOwnerSay("Need points and nonnegative distance.");
            return;
        }
        float remaining=DISTANCE;
        integer i;
        for(i=1;i<n;++i)
        {
            vector a=llList2Vector(POINTS,i-1);
            vector b=llList2Vector(POINTS,i);
            float length=llVecDist(a,b);
            if(length>0.000001&&remaining<=length)
            {
                llOwnerSay("Point="+(string)(a+(b-a)*(remaining/length)));
                return;
            }
            remaining-=length;
        }
        llOwnerSay("Clamped endpoint="+(string)llList2Vector(POINTS,-1));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Point inside a rotated box?

Transform a test point into a box’s local frame and check all three half-extents.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set CENTRE, SIZE, EULER_DEGREES, and POINT. Touch for a result.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

SIZE represents full dimensions and must be positive. This is an ideal box test, not a mesh collision check.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector CENTRE = <5.0,5.0,1.0>;
vector SIZE = <4.0,2.0,2.0>;
vector EULER_DEGREES = <0.0,0.0,45.0>;
vector POINT = <6.0,5.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (SIZE.x <= 0.0 || SIZE.y <= 0.0 || SIZE.z <= 0.0)
        {
            llOwnerSay("Box size must be positive.");
            return;
        }
        rotation r = llEuler2Rot(EULER_DEGREES * DEG_TO_RAD);
        vector p = (POINT - CENTRE) / r;
        vector halfSize = SIZE * 0.5;
        integer inside = (llFabs(p.x) <= halfSize.x) && (llFabs(p.y) <= halfSize.y) && (llFabs(p.z) <= halfSize.z);
        llOwnerSay("Inside or on boundary (1=yes): " + (string)inside + "; local point: " + (string)p);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Intermediate

Point inside an irregular boundary

Use even-odd ray crossings to check a point against a simple XY polygon.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set ordered boundary POINTS and test P. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Boundary points are not assigned a special inside/outside guarantee; use a distance-to-edge tolerance when boundaries matter. Z is ignored.

// Original Incoprea. MIT. Owner-only calculation.
list POINTS=[<0.0,0.0,0.0>,<5.0,0.0,0.0>,<5.0,2.0,0.0>,<2.0,2.0,0.0>,<2.0,5.0,0.0>,<0.0,5.0,0.0>];
vector P=<1.0,3.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        integer n=llGetListLength(POINTS);
        if(n<3)
        {
            llOwnerSay("Need three or more vertices.");
            return;
        }
        integer inside=FALSE;
        integer i;
        integer j=n-1;
        for(i=0;i<n;++i)
        {
            vector a=llList2Vector(POINTS,i);
            vector b=llList2Vector(POINTS,j);
            if((a.y>P.y)!=(b.y>P.y))
            {
                float crossing=(b.x-a.x)*(P.y-a.y)/(b.y-a.y)+a.x;
                if(P.x<crossing)inside=!inside;
            }
            j=i;
        }
        llOwnerSay("Inside (excluding boundary ambiguity): "+(string)inside);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Point to nearest hex-grid cell

Convert an XY position into a pointy-top axial hex coordinate and reconstruct its center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINT and positive hex RADIUS. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Uses cube-coordinate rounding to keep the three hex axes consistent; radius is center-to-corner distance.

// Original Incoprea. MIT.
vector POINT=<5.2,3.1,0.0>;
float RADIUS=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0)
        {
            llOwnerSay("Positive radius required.");
            return;
        }
        float q=(llSqrt(3.0)/3.0*POINT.x-POINT.y/3.0)/RADIUS;
        float r=(2.0/3.0*POINT.y)/RADIUS;
        float y=-q-r;
        integer rx=llRound(q);
        integer ry=llRound(y);
        integer rz=llRound(r);
        float dx=llFabs(rx-q);
        float dy=llFabs(ry-y);
        float dz=llFabs(rz-r);
        if(dx>dy&&dx>dz)rx=-ry-rz;
        else if(dy>dz)ry=-rx-rz;
        else rz=-rx-ry;
        vector centre=<RADIUS*llSqrt(3.0)*((float)rx+(float)rz*0.5),RADIUS*1.5*(float)rz,0.0>;
        llOwnerSay("Axial q/r="+(string)rx+"/"+(string)rz+"; centre="+(string)centre);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Polygon across-flats sizing

Translate a regular polygon circumradius into its across-flats diameter and side length.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set side count at least three and circumradius positive. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Across-flats diameter is twice the apothem; for odd-sided polygons it is not the total width between opposite edges.

// Original Incoprea. MIT. Owner-only calculation.
integer SIDES=8;
float RADIUS=4.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(SIDES<3||RADIUS<=0.0)
        {
            llOwnerSay("Invalid polygon.");
            return;
        }
        float a=PI/(float)SIDES;
        llOwnerSay("Apothem="+(string)(RADIUS*llCos(a))+"; twice apothem="+(string)(2.0*RADIUS*llCos(a))+"; side="+(string)(2.0*RADIUS*llSin(a)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Predict first contact of two moving circular bounds

Solve first future contact time from relative position, velocity and combined radius.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set relative POSITION/VELOCITY and nonnegative radii. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

The supplied vectors should be planar for circles; the same equation also models spheres. No live entities are tracked.

// Original Incoprea. MIT. Ideal geometry only.
vector POSITION=<8.0,2.0,0.0>;
vector VELOCITY=<-2.0,0.0,0.0>;
float R1=1.0;
float R2=1.5;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(R1<0.0||R2<0.0)
        {
            llOwnerSay("Invalid radius.");
            return;
        }
        float radius=R1+R2;
        float c=POSITION*POSITION-radius*radius;
        if(c<=0.0)
        {
            llOwnerSay("Already touching or overlapping.");
            return;
        }
        float a=VELOCITY*VELOCITY;
        if(a<0.000001)
        {
            llOwnerSay("No relative motion.");
            return;
        }
        float b=2.0*(POSITION*VELOCITY);
        float disc=b*b-4.0*a*c;
        if(disc<0.0)
        {
            llOwnerSay("No contact on trajectories.");
            return;
        }
        float t=(-b-llSqrt(disc))/(2.0*a);
        if(t<0.0)
        {
            llOwnerSay("Contact lies in the past.");
            return;
        }
        llOwnerSay("First contact in "+(string)t+" seconds.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Preserve apparent size when moving deeper

Calculate a uniform scale factor that preserves frontal perspective size at a new depth.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive OLD_DEPTH/NEW_DEPTH and original SIZE. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Works for a centered frontal approximation; it does not preserve parallax or perspective within a deep object.

// Original Incoprea. MIT. Transform planning only.
float OLD_DEPTH=6.0;
float NEW_DEPTH=10.0;
vector SIZE=<2.0,3.0,0.2>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(OLD_DEPTH<=0.0||NEW_DEPTH<=0.0||SIZE.x<=0.0||SIZE.y<=0.0||SIZE.z<=0.0)
        {
            llOwnerSay("Positive depths/size required.");
            return;
        }
        float factor=NEW_DEPTH/OLD_DEPTH;
        llOwnerSay("Uniform scale="+(string)factor+" new size="+(string)(SIZE*factor));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Project a planned point into a view rectangle

Calculate normalized screen coordinates using a virtual camera pose and vertical field of view.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set camera pose, point, aspect ratio and FOV between1 and170 degrees. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Camera local+X is forward,+Y left,+Z up. Output screen coordinates are rightwardU and downwardV.

// Original Incoprea. MIT. Transform planning only.
vector CAMERA=<0.0,0.0,2.0>;
vector CAMERA_EULER=ZERO_VECTOR;
vector POINT=<8.0,-2.0,4.0>;
float FOV=60.0;
float ASPECT=1.7777778;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(FOV<=1.0||FOV>=170.0||ASPECT<=0.0)
        {
            llOwnerSay("Invalid FOV/aspect.");
            return;
        }
        rotation r=llEuler2Rot(CAMERA_EULER*DEG_TO_RAD);
        vector p=(POINT-CAMERA)/r;
        if(p.x<=0.000001)
        {
            llOwnerSay("Point behind camera plane.");
            return;
        }
        float scale=llTan(FOV*DEG_TO_RAD*0.5);
        float x=-p.y/(p.x*scale*ASPECT);
        float y=p.z/(p.x*scale);
        llOwnerSay("ScreenUV="+(string)<(x+1.0)*0.5,(1.0-y)*0.5,0.0>+" depth="+(string)p.x);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Project a point into an orthographic plan

Map virtual-camera localY/Z into normalized coordinates without perspective scaling.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set camera pose, view width/height and point. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Depth is reported separately and does not affect projected size.

// Original Incoprea. MIT. Transform planning only.
vector CAMERA=ZERO_VECTOR;
vector CAMERA_EULER=<0.0,0.0,0.0>;
vector POINT=<10.0,-2.0,1.0>;
float WIDTH=8.0;
float HEIGHT=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(WIDTH<=0.0||HEIGHT<=0.0)
        {
            llOwnerSay("Positive view size required.");
            return;
        }
        vector p=(POINT-CAMERA)/llEuler2Rot(CAMERA_EULER*DEG_TO_RAD);
        llOwnerSay("ScreenUV="+(string)<0.5-p.y/WIDTH,0.5-p.z/HEIGHT,0.0>+" depth="+(string)p.x);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Intermediate

Project a point onto a building plane

Remove the component of a point above a plane to obtain its perpendicular footprint.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set POINT, a point ON_PLANE, and the plane NORMAL; touch to calculate.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

NORMAL need not be normalized but must not be zero. The signed distance follows its direction.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector POINT = <3.0, 4.0, 5.0>;
vector ON_PLANE = <0.0, 0.0, 1.0>;
vector NORMAL = <0.0, 0.0, 1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llVecMag(NORMAL) < 0.000001)
        {
            llOwnerSay("Use a nonzero normal.");
            return;
        }
        vector n = llVecNorm(NORMAL);
        float height = (POINT - ON_PLANE) * n;
        llOwnerSay("Footprint: " + (string)(POINT - height * n) + "; signed height: " + (string)height);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Intermediate

Ramp slope and length

Translate rise and horizontal run into a sloped length, angle, and grade percentage.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit RISE and RUN in metres. Touch for virtual-building measurements.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

RUN must be positive. Negative RISE reports a descending slope. These measurements do not establish accessibility or safety compliance.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float RISE = 2.0;
float RUN = 9.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (RUN <= 0.0)
        {
            llOwnerSay("Horizontal run must be positive.");
            return;
        }
        llOwnerSay("Length: " + (string)llSqrt(RISE*RISE + RUN*RUN) + " m");
        llOwnerSay("Angle: " + (string)(llAtan2(RISE,RUN)*RAD_TO_DEG) + " degrees; grade: " + (string)(100.0*RISE/RUN) + "%");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Ray against a planned triangle

Use the Möller–Trumbore method to test a forward ray against a triangle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set triangle A/B/C and START/DIRECTION. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Both triangle sides are accepted. Near-parallel rays are rejected. Pure calculation, not collision sensing.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<5.0,0.0,0.0>;
vector C=<0.0,5.0,0.0>;
vector START=<1.0,1.0,4.0>;
vector DIRECTION=<0.0,0.0,-1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector e1=B-A;
        vector e2=C-A;
        vector h=DIRECTION%e2;
        float determinant=e1*h;
        if(llFabs(determinant)<0.000001)
        {
            llOwnerSay("Parallel or degenerate.");
            return;
        }
        float inverse=1.0/determinant;
        vector s=START-A;
        float u=inverse*(s*h);
        if(u<0.0||u>1.0)
        {
            llOwnerSay("Miss.");
            return;
        }
        vector q=s%e1;
        float v=inverse*(DIRECTION*q);
        if(v<0.0||u+v>1.0)
        {
            llOwnerSay("Miss.");
            return;
        }
        float t=inverse*(e2*q);
        if(t<0.0)
        {
            llOwnerSay("Hit behind ray.");
            return;
        }
        llOwnerSay("Hit="+(string)(START+t*DIRECTION)+"; barycentric="+(string)<1.0-u-v,u,v>);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Ray entry and exit through a box

Intersect an infinite ray with three axis-aligned slab intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set START/DIRECTION and LOW/HIGH box bounds. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Returns parameter interval for the unnormalized direction. Parallel axes outside the box reject the ray.

// Original Incoprea. MIT. Ideal geometry only.
vector START=<-5.0,0.0,0.0>;
vector DIRECTION=<1.0,0.2,0.0>;
vector LOW=<-1.0,-1.0,-1.0>;
vector HIGH=<1.0,1.0,1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LOW.x>HIGH.x||LOW.y>HIGH.y||LOW.z>HIGH.z||llVecMag(DIRECTION)<0.000001)
        {
            llOwnerSay("Invalid bounds/direction.");
            return;
        }
        list origins=[START.x,START.y,START.z];
        list directions=[DIRECTION.x,DIRECTION.y,DIRECTION.z];
        list lows=[LOW.x,LOW.y,LOW.z];
        list highs=[HIGH.x,HIGH.y,HIGH.z];
        float enter=0.0;
        float leave=1000000000.0;
        integer i;
        for(i=0;i<3;++i)
        {
            float origin=llList2Float(origins,i);
            float direction=llList2Float(directions,i);
            float lo=llList2Float(lows,i);
            float hi=llList2Float(highs,i);
            if(llFabs(direction)<0.000001)
            {
                if(origin<lo||origin>hi)
                {
                    llOwnerSay("Miss: parallel slab.");
                    return;
                }
            }
            else
            {
                float a=(lo-origin)/direction;
                float b=(hi-origin)/direction;
                if(a>b)
                {
                    float temp=a;
                    a=b;
                    b=temp;
                }
                if(a>enter)enter=a;
                if(b<leave)leave=b;
                if(enter>leave)
                {
                    llOwnerSay("Miss.");
                    return;
                }
            }
        }
        llOwnerSay("Entry="+(string)enter+" exit="+(string)leave+" entry point="+(string)(START+enter*DIRECTION));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Ray entry and exit through a sphere

Solve the quadratic intersection of a ray with a theoretical sphere.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set START, nonzero DIRECTION, CENTER and RADIUS. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Parameters multiply the unnormalized direction. Negative parameters are behind the ray; this does not query physical scene geometry.

// Original Incoprea. MIT.
vector START=<-8.0,1.0,0.0>;
vector DIRECTION=<1.0,0.0,0.0>;
vector CENTER=ZERO_VECTOR;
float RADIUS=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector offset=START-CENTER;
        float a=DIRECTION*DIRECTION;
        if(a<0.000001||RADIUS<=0.0)
        {
            llOwnerSay("Invalid direction/radius.");
            return;
        }
        float b=2.0*(offset*DIRECTION);
        float c=offset*offset-RADIUS*RADIUS;
        float discriminant=b*b-4.0*a*c;
        if(discriminant<0.0)
        {
            llOwnerSay("Ray line misses sphere.");
            return;
        }
        float root=llSqrt(discriminant);
        float t1=(-b-root)/(2.0*a);
        float t2=(-b+root)/(2.0*a);
        if(t2<0.0)
        {
            llOwnerSay("Sphere lies behind ray.");
            return;
        }
        llOwnerSay("Parameters entry="+(string)t1+" exit="+(string)t2+"; exit point="+(string)(START+t2*DIRECTION));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Ray meets a plane

Calculate where a forward ray crosses an infinite plane, with parallel and behind-ray checks.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit RAY_START, DIRECTION, PLANE_POINT and NORMAL. Touch for a result.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is pure geometry, not llCastRay; it does not query real objects or terrain. Direction length controls the reported parameter.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector RAY_START = <1.0, 2.0, 8.0>;
vector DIRECTION = <0.5, 0.0, -1.0>;
vector PLANE_POINT = <0.0, 0.0, 0.0>;
vector NORMAL = <0.0, 0.0, 1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float denominator = DIRECTION * NORMAL;
        if (llFabs(denominator) < 0.000001)
        {
            llOwnerSay("Parallel ray or invalid normal.");
            return;
        }
        float t = ((PLANE_POINT - RAY_START) * NORMAL) / denominator;
        if (t < 0.0)
        {
            llOwnerSay("The plane is behind the ray.");
            return;
        }
        llOwnerSay("Intersection: " + (string)(RAY_START + DIRECTION * t));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Reflect a direction from a plane

Compute the direction of a theoretical reflected ray without moving a physical object.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set incoming DIRECTION and surface NORMAL, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The normal is normalized internally. The reflection preserves the original vector magnitude; this is not a physics collision response.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector DIRECTION = <1.0, -2.0, -3.0>;
vector NORMAL = <0.0, 0.0, 1.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llVecMag(NORMAL) < 0.000001)
        {
            llOwnerSay("Normal is zero.");
            return;
        }
        vector n = llVecNorm(NORMAL);
        vector reflected = DIRECTION - 2.0 * (DIRECTION * n) * n;
        llOwnerSay("Reflected direction: " + (string)reflected);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Ring panel chord planner

Calculate chord width, angular spacing, and radial sagitta for equal panels around a ring.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set RADIUS and PANELS, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

PANELS must be at least three. Chord width describes straight edges; the sagitta is the gap from chord midpoint to the circle.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float RADIUS = 5.0;
integer PANELS = 12;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (RADIUS <= 0.0 || PANELS < 3)
        {
            llOwnerSay("Use a positive radius and at least three panels.");
            return;
        }
        float halfAngle = PI / (float)PANELS;
        llOwnerSay("Chord width: " + (string)(2.0*RADIUS*llSin(halfAngle)) + " m");
        llOwnerSay("Angle step: " + (string)(360.0/(float)PANELS) + " degrees; sagitta: " + (string)(RADIUS*(1.0-llCos(halfAngle))) + " m");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Math & geometry · Advanced

Rotate a point around an arbitrary pivot

Calculate a new point after a rotation around a pivot instead of around the origin.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINT, PIVOT and Euler ANGLES. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

The rotation is applied to the offset, then the pivot is restored. This is a position calculation only.

// Original Incoprea. MIT.
vector POINT=<8.0,5.0,1.0>;
vector PIVOT=<5.0,5.0,1.0>;
vector ANGLES=<0.0,0.0,90.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation r=llEuler2Rot(ANGLES*DEG_TO_RAD);
        llOwnerSay("Rotated point="+(string)(PIVOT+(POINT-PIVOT)*r));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Separate two overlapping aligned footprints

Calculate a minimum-axis displacement that separates two axis-aligned rectangles.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set centers A/B and positive XY half-extents HA/HB. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Chooses one of equally minimal directions deterministically; it is not a swept collision solver.

// Original Incoprea. MIT. Ideal geometry only.
vector A=ZERO_VECTOR;
vector B=<1.5,0.5,0.0>;
vector HA=<2.0,1.0,0.0>;
vector HB=<1.0,1.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(HA.x<=0.0||HA.y<=0.0||HB.x<=0.0||HB.y<=0.0)
        {
            llOwnerSay("Positive half-extents required.");
            return;
        }
        vector d=B-A;
        float x=HA.x+HB.x-llFabs(d.x);
        float y=HA.y+HB.y-llFabs(d.y);
        if(x<=0.0||y<=0.0)
        {
            llOwnerSay("No overlap.");
            return;
        }
        vector shift=ZERO_VECTOR;
        if(x<y)
        {
            shift.x=-x;
            if(d.x<0.0)shift.x=x;
        }
        else
        {
            shift.y=-y;
            if(d.y<0.0)shift.y=y;
        }
        llOwnerSay("Move A by "+(string)shift+" to reach tangency.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Set an offset length safely

Rescale an arbitrary direction to a requested distance and reject a zero direction.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set DIRECTION and desired LENGTH. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

This preserves direction, unlike component-wise clamping. Negative lengths are rejected.

// Original Incoprea. MIT.
vector DIRECTION=<3.0,4.0,2.0>;
float LENGTH=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(LENGTH<0.0||llVecMag(DIRECTION)<0.000001)
        {
            llOwnerSay("Nonzero direction and nonnegative length required.");
            return;
        }
        vector result=llVecNorm(DIRECTION)*LENGTH;
        llOwnerSay("Offset="+(string)result+"; measured length="+(string)llVecMag(result));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Signed distance to a finite cylinder

Calculate signed distance to an ideal capped cylinder.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set POINT, positive RADIUS and HALF_HEIGHT. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Aligned alongZ and centered at the origin. Exact distance combines radial and cap distances.

// Original Incoprea. MIT. Ideal geometry only.
vector POINT=<3.0,1.0,4.0>;
float RADIUS=2.0;
float HALF_HEIGHT=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(RADIUS<=0.0||HALF_HEIGHT<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        float radial=llSqrt(POINT.x*POINT.x+POINT.y*POINT.y)-RADIUS;
        float vertical=llFabs(POINT.z)-HALF_HEIGHT;
        float ox=radial;
        float oy=vertical;
        if(ox<0.0)ox=0.0;
        if(oy<0.0)oy=0.0;
        float inside=radial;
        if(vertical>inside)inside=vertical;
        if(inside>0.0)inside=0.0;
        llOwnerSay("Signed distance="+(string)(llSqrt(ox*ox+oy*oy)+inside));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Signed distance to a ring-shaped bound

Calculate a torus signed-distance value for a point relative to its center.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set major radius larger than minor radius and test POINT. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

The torus is aligned around theZ axis. Negative values indicate inside the ideal tube.

// Original Incoprea. MIT. Ideal geometry only.
vector POINT=<4.0,1.0,0.5>;
float MAJOR=4.0;
float MINOR=0.8;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(MAJOR<=MINOR||MINOR<=0.0)
        {
            llOwnerSay("Need major>minor>0.");
            return;
        }
        float radial=llSqrt(POINT.x*POINT.x+POINT.y*POINT.y)-MAJOR;
        llOwnerSay("Signed distance="+(string)(llSqrt(radial*radial+POINT.z*POINT.z)-MINOR));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2

Math & geometry · Advanced

Signed distance to a solid box

Calculate exact signed distance to an axis-aligned box from a test point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive HALF extents and POINT relative to box center. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Inside points return a negative nearest-face distance; outside points combine excess distances.

// Original Incoprea. MIT. Ideal geometry only.
vector POINT=<3.0,1.0,4.0>;
vector HALF=<2.0,2.0,3.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(HALF.x<=0.0||HALF.y<=0.0||HALF.z<=0.0)
        {
            llOwnerSay("Positive extents required.");
            return;
        }
        vector q=<llFabs(POINT.x),llFabs(POINT.y),llFabs(POINT.z)>-HALF;
        vector outside=q;
        if(outside.x<0.0)outside.x=0.0;
        if(outside.y<0.0)outside.y=0.0;
        if(outside.z<0.0)outside.z=0.0;
        float inside=q.x;
        if(q.y>inside)inside=q.y;
        if(q.z>inside)inside=q.z;
        if(inside>0.0)inside=0.0;
        llOwnerSay("Signed distance="+(string)(llVecMag(outside)+inside));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Signed horizontal turn angle

Measure the shortest signed turn between two horizontal headings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit FROM and TO direction vectors. Touch to see degrees.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Ignores Z. Positive means counterclockwise viewed from above; a zero horizontal heading is rejected.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector FROM = <1.0, 0.0, 0.0>;
vector TO = <-1.0, 1.0, 0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if ((FROM.x * FROM.x + FROM.y * FROM.y < 0.000001) ||
        (TO.x * TO.x + TO.y * TO.y < 0.000001))
        {
            llOwnerSay("Headings must be nonzero.");
            return;
        }
        float crossZ = FROM.x * TO.y - FROM.y * TO.x;
        float dot = FROM.x * TO.x + FROM.y * TO.y;
        llOwnerSay("Signed turn: " + (string)(llAtan2(crossZ, dot) * RAD_TO_DEG) + " degrees");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Smooth segment through waypoints

Interpolate a segment passing through its middle pair of four control points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit P0 through P3; touch to print samples between P1 and P2.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is uniform Catmull–Rom, which can overshoot near unevenly spaced points. It is a planning calculation, not a collision-safe route.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector P0 = <0.0,0.0,0.0>;
vector P1 = <2.0,2.0,0.0>;
vector P2 = <6.0,3.0,0.0>;
vector P3 = <8.0,0.0,0.0>;
vector interpolate(float t)
{
    return 0.5 * (2.0*P1 + (-P0+P2)*t + (2.0*P0-5.0*P1+4.0*P2-P3)*t*t + (-P0+3.0*P1-3.0*P2+P3)*t*t*t);
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer i;
        for (i = 0; i <= 4; ++i) llOwnerSay((string)interpolate((float)i / 4.0));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Snap a point to a builder grid

Calculate the nearest grid intersection relative to a chosen origin without moving anything.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit POINT, ORIGIN, and STEP in metres, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

A positive step is required. Coordinates and origin must use the same coordinate frame.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector POINT = <2.13, -1.28, 0.66>;
vector ORIGIN = <0.0, 0.0, 0.0>;
float STEP = 0.25;
vector snap(vector p, vector origin, float step)
{
    vector q = (p - origin) / step;
    return origin + <llRound(q.x), llRound(q.y), llRound(q.z)> * step;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (STEP <= 0.0)
        {
            llOwnerSay("STEP must be positive.");
            return;
        }
        llOwnerSay("Snapped point: " + (string)snap(POINT, ORIGIN, STEP));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Sphere latitude display ring

Find the ring radius, elevation, and circumference at a latitude on a sphere.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set sphere radius and latitude from minus90 to90 degrees. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Latitude zero is the equator. This outputs local offsets from the sphere center.

// Original Incoprea. MIT. Owner-only calculation.
float RADIUS=5.0;
float LATITUDE=40.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(RADIUS<=0.0||LATITUDE < -90.0||LATITUDE>90.0)
        {
            llOwnerSay("Invalid radius or latitude.");
            return;
        }
        float a=LATITUDE*DEG_TO_RAD;
        float ring=RADIUS*llCos(a);
        llOwnerSay("Ring radius="+(string)ring+"; elevation="+(string)(RADIUS*llSin(a))+"; circumference="+(string)(TWO_PI*ring));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Split an offset along a rail

Decompose a vector into components parallel and perpendicular to a chosen axis.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set OFFSET and AXIS. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

The two reported vectors add back to the input; a zero axis has no meaningful decomposition.

// Original Incoprea. MIT.
vector OFFSET=<4.0,5.0,2.0>;
vector AXIS=<1.0,1.0,0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float denominator=AXIS*AXIS;
        if(denominator<0.000001)
        {
            llOwnerSay("Axis is zero.");
            return;
        }
        vector parallel=AXIS*((OFFSET*AXIS)/denominator);
        llOwnerSay("Along="+(string)parallel+"; across="+(string)(OFFSET-parallel));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Staggered brick row coordinates

Print a compact two-row staggered masonry layout with clipped edge bricks.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set wall width, nominal brick length and gap. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Coordinates are horizontal intervals. Odd rows start with half a nominal brick; this is a preview rather than a mesh generator.

// Original Incoprea. MIT. Owner-only calculation.
float WALL=4.0;
float BRICK=0.8;
float GAP=0.02;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(WALL<=0.0||BRICK<=0.0||GAP<0.0||WALL/BRICK>16.0)
        {
            llOwnerSay("Use positive dimensions and at most16 bricks per row.");
            return;
        }
        integer row;
        for(row=0;row<2;++row)
        {
            float x=0.0;
            float length=BRICK;
            if(row==1)length=BRICK*0.5;
            string report="Row "+(string)row+":";
            while(x<WALL)
            {
                float end=x+length;
                if(end>WALL)end=WALL;
                report+=" ["+(string)x+","+(string)end+"]";
                x=end+GAP;
                length=BRICK;
            }
            llOwnerSay(report);
        }
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Tangent points from an outside anchor

Locate the two tangency points on a circle visible from an external point.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set circle CENTER, RADIUS, and exterior POINT in the same XY plane. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

The point must lie strictly outside the circle. Useful for straight paths meeting a circular border smoothly.

// Original Incoprea. MIT. Owner-only calculation.
vector CENTER=<0.0,0.0,0.0>;
vector POINT=<8.0,3.0,0.0>;
float RADIUS=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        vector delta=POINT-CENTER;
        delta.z=0.0;
        float d2=delta*delta;
        if(RADIUS<=0.0||d2<=RADIUS*RADIUS)
        {
            llOwnerSay("Point must be outside a positive-radius circle.");
            return;
        }
        float a=RADIUS*RADIUS/d2;
        float b=RADIUS*llSqrt(d2-RADIUS*RADIUS)/d2;
        vector perpendicular=<-delta.y,delta.x,0.0>;
        llOwnerSay("Tangent points: "+(string)(CENTER+a*delta+b*perpendicular)+" and "+(string)(CENTER+a*delta-b*perpendicular));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Test overlap of two rotated floor rectangles

Use four separating axes to check oriented rectangles inXY.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set centers, positive half-extents and yaw degrees. Touch for owner-only calculation output.

Stop / restore: Remove/disable. Does not sense, collide with, or modify actual objects.

Tangency counts as overlap. This is a static test and does not calculate a collision response.

// Original Incoprea. MIT. Ideal geometry only.
vector A=ZERO_VECTOR;
vector B=<3.0,1.0,0.0>;
vector HA=<2.0,1.0,0.0>;
vector HB=<1.5,1.0,0.0>;
float ANGLE_A=20.0;
float ANGLE_B=-15.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(HA.x<=0.0||HA.y<=0.0||HB.x<=0.0||HB.y<=0.0)
        {
            llOwnerSay("Positive extents required.");
            return;
        }
        float a=ANGLE_A*DEG_TO_RAD;
        float b=ANGLE_B*DEG_TO_RAD;
        vector ax=<llCos(a),llSin(a),0.0>;
        vector ay=<-ax.y,ax.x,0.0>;
        vector bx=<llCos(b),llSin(b),0.0>;
        vector by=<-bx.y,bx.x,0.0>;
        list axes=[ax,ay,bx,by];
        vector delta=B-A;
        integer i;
        for(i=0;i<4;++i)
        {
            vector axis=llList2Vector(axes,i);
            float ra=HA.x*llFabs(ax*axis)+HA.y*llFabs(ay*axis);
            float rb=HB.x*llFabs(bx*axis)+HB.y*llFabs(by*axis);
            if(llFabs(delta*axis)>ra+rb)
            {
                llOwnerSay("Separated on axis "+(string)i);
                return;
            }
        }
        llOwnerSay("Rectangles touch or overlap.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Three-point curve sampler

Print six positions along a quadratic Bézier curve for planning a curved build.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit start A, control B, and end C. Touch to print normalized parameters and positions.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The curve usually does not pass through B. Equal parameter steps are not equal spatial distances.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0,0.0,0.0>;
vector B = <4.0,0.0,6.0>;
vector C = <8.0,0.0,0.0>;
vector curve(float t)
{
    float u = 1.0 - t;
    return u*u*A + 2.0*u*t*B + t*t*C;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer i;
        for (i = 0; i <= 5; ++i)
        {
            float t = (float)i / 5.0;
            llOwnerSay((string)t + ": " + (string)curve(t));
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Tile coverage with edge cuts

Calculate full-grid tile count and final row/column cut dimensions.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set floor dimensions and tile width/depth. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Assumes a rectangular aligned layout with no grout gap. Count includes tiles trimmed at the edges.

// Original Incoprea. MIT. Owner-only calculation.
float W=7.3;
float D=4.2;
float TW=0.6;
float TD=0.6;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(W<=0.0||D<=0.0||TW<=0.0||TD<=0.0)
        {
            llOwnerSay("Positive dimensions required.");
            return;
        }
        integer columns=llCeil(W/TW);
        integer rows=llCeil(D/TD);
        llOwnerSay("Grid "+(string)columns+" x "+(string)rows+"; total "+(string)(columns*rows));
        llOwnerSay("Final column width "+(string)(W-(columns-1)*TW)+"; final row depth "+(string)(D-(rows-1)*TD));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Transform a normal under nonuniform scale

Apply inverse scale to a surface normal before rotating and normalizing it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set positive AXIS_SCALE, nonzero NORMAL and Euler ROTATION_DEGREES. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

Normals transform differently from positions under nonuniform scaling. Zero scale components are rejected.

// Original Incoprea. MIT. Transform planning only.
vector AXIS_SCALE=<2.0,1.0,0.5>;
vector NORMAL=<1.0,0.0,1.0>;
vector ROTATION_DEGREES=<0.0,30.0,20.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(AXIS_SCALE.x<=0.0||AXIS_SCALE.y<=0.0||AXIS_SCALE.z<=0.0||llVecMag(NORMAL)<0.000001)
        {
            llOwnerSay("Positive scale and nonzero normal required.");
            return;
        }
        vector n=<NORMAL.x/AXIS_SCALE.x,NORMAL.y/AXIS_SCALE.y,NORMAL.z/AXIS_SCALE.z>;
        rotation r=llEuler2Rot(ROTATION_DEGREES*DEG_TO_RAD);
        llOwnerSay("World normal="+(string)llVecNorm(n*r));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Triangle coordinate inspector

Calculate the three barycentric weights of a point relative to a triangle.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit triangle A/B/C and point P; touch. Use a point in the triangle plane.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Weights sum to one. Negative weights indicate an outside projection. A noncoplanar input is implicitly projected; degenerate triangles are rejected.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
vector A = <0.0, 0.0, 0.0>;
vector B = <4.0, 0.0, 0.0>;
vector C = <0.0, 3.0, 0.0>;
vector P = <1.0, 1.0, 0.0>;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        vector v0 = B - A;
        vector v1 = C - A;
        vector v2 = P - A;
        float d00 = v0 * v0;
        float d01 = v0 * v1;
        float d11 = v1 * v1;
        float d20 = v2 * v0;
        float d21 = v2 * v1;
        float denominator = d00 * d11 - d01 * d01;
        if (llFabs(denominator) < 0.000001)
        {
            llOwnerSay("Degenerate triangle.");
            return;
        }
        float v = (d11 * d20 - d01 * d21) / denominator;
        float w = (d00 * d21 - d01 * d20) / denominator;
        llOwnerSay("Weights A/B/C: " + (string)<1.0 - v - w, v, w>);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Triangle winding and area vector

Calculate the oriented face normal and area implied by a triangle’s vertex order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set three noncollinear vectors A/B/C. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Swapping two vertices reverses the normal; this does not inspect or change an actual mesh face.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<4.0,0.0,1.0>;
vector C=<1.0,3.0,2.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        vector cross=(B-A)%(C-A);
        float magnitude=llVecMag(cross);
        if(magnitude<0.000001)
        {
            llOwnerSay("Degenerate triangle.");
            return;
        }
        llOwnerSay("Unit normal="+(string)(cross/magnitude)+"; area="+(string)(magnitude*0.5));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Unproject a screen coordinate into a world ray

Convert normalized screenUV into a direction through a virtual perspective camera.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set SCREEN_UV, camera Euler pose, vertical FOV and aspect. Touch for private calculations.

Stop / restore: Disable/remove. No camera or object settings are changed.

The output is a unit direction. It does not perform a scene raycast or access the user’s camera.

// Original Incoprea. MIT. Transform planning only.
vector SCREEN_UV=<0.75,0.3,0.0>;
vector CAMERA_EULER=<0.0,0.0,30.0>;
float FOV=60.0;
float ASPECT=1.7777778;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(FOV<=1.0||FOV>=170.0||ASPECT<=0.0)
        {
            llOwnerSay("Invalid FOV/aspect.");
            return;
        }
        float tanHalf=llTan(FOV*DEG_TO_RAD*0.5);
        float x=2.0*SCREEN_UV.x-1.0;
        float y=1.0-2.0*SCREEN_UV.y;
        vector local=<1.0,-x*tanHalf*ASPECT,y*tanHalf>;
        llOwnerSay("World ray direction="+(string)(llVecNorm(local)*llEuler2Rot(CAMERA_EULER*DEG_TO_RAD)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Intermediate

Unroll a cone into a sector

Calculate the radius and angle of the flat sector corresponding to an ideal cone surface.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set base radius and vertical height. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Excludes the base disk and material thickness. Useful for texture/layout reasoning, not manufacturing certification.

// Original Incoprea. MIT. Owner-only calculation.
float RADIUS=2.0;
float HEIGHT=5.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(RADIUS<=0.0||HEIGHT<=0.0)
        {
            llOwnerSay("Positive radius and height required.");
            return;
        }
        float slant=llSqrt(RADIUS*RADIUS+HEIGHT*HEIGHT);
        llOwnerSay("Sector radius="+(string)slant+"; sector degrees="+(string)(360.0*RADIUS/slant)+"; lateral area="+(string)(PI*RADIUS*slant));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Unroll a tapered tower wall

Calculate an annular sector for a cone frustum with different top and bottom radii.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set BOTTOM greater than TOP, TOP nonnegative, and HEIGHT positive. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Idealized geometry excludes seam allowance and thickness. Equal radii form a cylinder and are deliberately rejected.

// Original Incoprea. MIT. Owner-only calculation.
float BOTTOM=4.0;
float TOP=2.0;
float HEIGHT=6.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if(BOTTOM<=TOP||TOP<0.0||HEIGHT<=0.0)
        {
            llOwnerSay("Need bottom>top>=0 and height>0.");
            return;
        }
        float difference=BOTTOM-TOP;
        float slant=llSqrt(HEIGHT*HEIGHT+difference*difference);
        float outer=slant*BOTTOM/difference;
        float inner=slant*TOP/difference;
        llOwnerSay("Outer sector radius="+(string)outer+"; inner="+(string)inner+"; angle="+(string)(360.0*BOTTOM/outer));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Advanced

Verify a point transform round trip

Transform a local point into world coordinates and back to expose coordinate-frame mistakes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set ORIGIN, local POINT and Euler DEGREES. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

LSL rotates vectors by multiplying on the right; division applies the inverse rotation.

// Original Incoprea. MIT.
vector ORIGIN=<20.0,30.0,5.0>;
vector POINT=<2.0,-1.0,0.5>;
vector DEGREES=<20.0,15.0,60.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        rotation r=llEuler2Rot(DEGREES*DEG_TO_RAD);
        vector world=ORIGIN+POINT*r;
        vector restored=(world-ORIGIN)/r;
        llOwnerSay("World="+(string)world+"; restored="+(string)restored+"; error="+(string)llVecDist(POINT,restored));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Math & geometry · Advanced

Volume of four planned vertices

Compute a tetrahedron’s signed and absolute volume from four points.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Use a spare owned prim. Set A/B/C/D in the same frame. Touch for owner-only results.

Stop / restore: Disable/remove. No scene properties change.

Signed volume follows vertex order. A near-zero result indicates coplanar or degenerate input.

// Original Incoprea. MIT.
vector A=<0.0,0.0,0.0>;
vector B=<4.0,0.0,0.0>;
vector C=<0.0,3.0,0.0>;
vector D=<0.0,0.0,6.0>;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float signedVolume=((B-A)*((C-A)%(D-A)))/6.0;
        llOwnerSay("Signed volume="+(string)signedVolume+"; absolute volume="+(string)llFabs(signedVolume));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Wall area after openings

Estimate paintable wall area after subtracting rectangular openings.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set wall size and paired opening widths/heights. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Openings must not overlap and must lie within the wall; this arithmetic does not check their positions.

// Original Incoprea. MIT. Owner-only calculation.
float WIDTH=12.0;
float HEIGHT=3.0;
list OPENINGS=[1.0,2.1,2.0,1.2];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        if (WIDTH<=0.0 || HEIGHT<=0.0 || llGetListLength(OPENINGS)%2)
        {
            llOwnerSay("Invalid wall or opening pairs.");
            return;
        }
        float area=WIDTH*HEIGHT;
        integer i;
        for(i=0;i<llGetListLength(OPENINGS);i+=2)
        {
            float w=llList2Float(OPENINGS,i);
            float h=llList2Float(OPENINGS,i+1);
            if(w<0.0||h<0.0)
            {
                llOwnerSay("Negative opening.");
                return;
            }
            area-=w*h;
        }
        if(area<0.0)
        {
            llOwnerSay("Openings exceed wall area.");
            return;
        }
        llOwnerSay("Net area: "+(string)area+" m2");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Math & geometry · Intermediate

Where two circular guides cross

Find the two intersections of circles in an XY build plan.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare prim. Set centers A/B and positive radii RA/RB. Owner touch prints results without altering the scene.

Stop / restore: Disable or remove. No prim properties are changed.

Coincident centers, separated circles and containment are handled. Tangency produces two equal points within numerical precision.

// Original Incoprea. MIT. Owner-only calculation.
vector A=<0.0,0.0,0.0>;
vector B=<5.0,0.0,0.0>;
float RA=4.0;
float RB=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0)!=llGetOwner()) return;
        float distance=llVecDist(A,B);
        if(RA<=0.0||RB<=0.0||llFabs(A.z-B.z)>0.0001)
        {
            llOwnerSay("Use positive radii and equal Z planes.");
            return;
        }
        if(distance<0.000001)
        {
            llOwnerSay("Coincident centres: no unique pair.");
            return;
        }
        if(distance>RA+RB||distance<llFabs(RA-RB))
        {
            llOwnerSay("No crossing.");
            return;
        }
        float x=(RA*RA-RB*RB+distance*distance)/(2.0*distance);
        float h2=RA*RA-x*x;
        if(h2<0.0)h2=0.0;
        vector direction=(B-A)/distance;
        vector base=A+x*direction;
        vector side=<-direction.y,direction.x,0.0>*llSqrt(h2);
        llOwnerSay("Crossings "+(string)(base+side)+" and "+(string)(base-side));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning labSmall working demonstrations to study and adapt.40 scripts

Download this category (.zip)

Learning lab · Intermediate

Build a weighted lookup table

Convert positive relative weights into cumulative probability boundaries and locate a chosen normalized sample.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit LABELS, WEIGHTS and SAMPLE in zero through just under one; touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Uses a fixed sample so results are reproducible. Substitute a random sample only for nonfinancial play or procedural variation, not security.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list LABELS=["common","unusual","rare"];
list WEIGHTS=[6.0,3.0,1.0];
float SAMPLE=0.75;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n=llGetListLength(WEIGHTS);
        if (n==0 || n!=llGetListLength(LABELS) || SAMPLE<0.0 || SAMPLE>=1.0)
        {
            llOwnerSay("Check matching lists and sample range [0,1).");
            return;
        }
        float total=0.0;
        integer i;
        for (i=0; i<n; ++i)
        {
            float weight=llList2Float(WEIGHTS,i);
            if (weight<=0.0)
            {
                llOwnerSay("Weights must be positive.");
                return;
            }
            total+=weight;
        }
        float cumulative=0.0;
        string selected=llList2String(LABELS,-1);
        integer found=FALSE;
        for (i=0; i<n; ++i)
        {
            cumulative+=llList2Float(WEIGHTS,i)/total;
            llOwnerSay(llList2String(LABELS,i)+" upper boundary: "+(string)cumulative);
            if (!found && SAMPLE<cumulative)
            {
                selected=llList2String(LABELS,i);
                found=TRUE;
            }
        }
        llOwnerSay("Sample selects: "+selected);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Chance of exactly k successes

Compute a small binomial probability with bounded trial count.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set TRIALS0..30, SUCCESSES0..TRIALS, and probability0..1. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Assumes independent trials with constant success probability. This is an educational calculation, not a gambling system.

// Original Incoprea. MIT.
integer TRIALS=10;
integer SUCCESSES=3;
float PROBABILITY=0.25;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(TRIALS<0||TRIALS>30||SUCCESSES<0||SUCCESSES>TRIALS||PROBABILITY<0.0||PROBABILITY>1.0)
        {
            llOwnerSay("Invalid binomial inputs.");
            return;
        }
        if(PROBABILITY==0.0)
        {
            llOwnerSay("Probability="+(string)(SUCCESSES==0));
            return;
        }
        if(PROBABILITY==1.0)
        {
            llOwnerSay("Probability="+(string)(SUCCESSES==TRIALS));
            return;
        }
        float choose=1.0;
        integer k=SUCCESSES;
        if(k>TRIALS-k)k=TRIALS-k;
        integer i;
        for(i=1;i<=k;++i)choose*=((float)(TRIALS-k+i)/(float)i);
        float result=choose*llPow(PROBABILITY,(float)SUCCESSES)*llPow(1.0-PROBABILITY,(float)(TRIALS-SUCCESSES));
        llOwnerSay("Probability="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Checksum a short ASCII message

Compute a Fletcher-16 checksum for a short ASCII string using two rolling sums.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit MESSAGE, keeping it ASCII and at most two hundred characters, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Rejects non-ASCII text to avoid confusing Unicode characters with bytes. This detects some accidental changes; it is not a secure signature or password hash.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
string MESSAGE="panel=west;revision=7";
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer length=llStringLength(MESSAGE);
        if (length>200)
        {
            llOwnerSay("Keep the demonstration under 201 characters.");
            return;
        }
        integer first=0;
        integer second=0;
        integer i;
        for (i=0; i<length; ++i)
        {
            integer code=llOrd(MESSAGE,i);
            if (code>127 || code<0)
            {
                llOwnerSay("ASCII only for this byte-checksum example.");
                return;
            }
            first=(first+code)%255;
            second=(second+first)%255;
        }
        llOwnerSay("Fletcher-16 decimal checksum: "+(string)((second<<8)|first));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Common spacing for repeating patterns

Find the greatest shared divisor and first common repeat interval of two small positive step counts.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set A and B between one and ten thousand, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The input cap keeps the least-common-multiple result within signed 32-bit integer range. Use this for discrete repeat counts, not arbitrary floats.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer A=12;
integer B=18;
integer gcd(integer a, integer b)
{
    while (b!=0)
    {
        integer remainder=a%b;
        a=b;
        b=remainder;
    }
    return a;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (A<1 || B<1 || A>10000 || B>10000)
        {
            llOwnerSay("Use integers 1..10000.");
            return;
        }
        integer divisor=gcd(A,B);
        llOwnerSay("Greatest common divisor="+(string)divisor+"; least common multiple="+(string)((A/divisor)*B));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Compare two short labels by edits

Count the minimum insertions, deletions, and substitutions needed to transform one short label into another.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set A and B up to twenty-four characters, then touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Comparison is case sensitive and counts LSL string characters, not visual grapheme clusters. Two rolling rows keep memory bounded.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
string A="lantern";
string B="lantren";
integer minimum(integer a, integer b, integer c)
{
    if (b<a) a=b;
    if (c<a) a=c;
    return a;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n=llStringLength(A);
        integer m=llStringLength(B);
        if (n>24 || m>24)
        {
            llOwnerSay("Use labels of at most 24 characters.");
            return;
        }
        list previous;
        integer i;
        integer j;
        for (j=0; j<=m; ++j) previous += [j];
        for (i=1; i<=n; ++i)
        {
            list current=[i];
            for (j=1; j<=m; ++j)
            {
                integer cost=1;
                if (llGetSubString(A,i-1,i-1)==llGetSubString(B,j-1,j-1)) cost=0;
                current += [minimum(llList2Integer(previous,j)+1,llList2Integer(current,j-1)+1,llList2Integer(previous,j-1)+cost)];
            }
            previous=current;
        }
        llOwnerSay("Edit distance: "+(string)llList2Integer(previous,m));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Compress repeated tokens as runs

Convert a token sequence into token/count pairs and reconstruct it to verify the round trip.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit TOKENS and touch. The example prints both compact runs and decoded tokens.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This is list-based encoding, so tokens may contain punctuation without delimiter ambiguity. Compression helps only when neighboring tokens repeat.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list TOKENS=["red","red","red","blue","blue","green","red"];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list runs;
        integer i=0;
        integer n=llGetListLength(TOKENS);
        while (i<n)
        {
            string value=llList2String(TOKENS,i);
            integer count=1;
            ++i;
            while (i<n && llList2String(TOKENS,i)==value)
            {
                ++count;
                ++i;
            }
            runs += [value,count];
        }
        list decoded;
        for (i=0; i<llGetListLength(runs); i+=2)
        {
            integer repeat=llList2Integer(runs,i+1);
            integer j;
            for (j=0; j<repeat; ++j) decoded += [llList2String(runs,i)];
        }
        llOwnerSay("Runs: "+llDumpList2String(runs," | "));
        llOwnerSay("Decoded: "+llDumpList2String(decoded,","));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Count samples into histogram bins

Group a bounded numeric sample set into five equal-width bins and report the counts.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit SAMPLES, LOW and HIGH. Touch to count; values outside the range are reported separately.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Bins include the lower edge and exclude the upper, except the last bin includes HIGH. HIGH must exceed LOW.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list SAMPLES=[0.0,1.0,2.0,2.5,4.0,7.0,9.0,10.0,12.0];
float LOW=0.0;
float HIGH=10.0;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (HIGH<=LOW)
        {
            llOwnerSay("HIGH must exceed LOW.");
            return;
        }
        list bins=[0,0,0,0,0];
        integer outside;
        integer i;
        for (i=0; i<llGetListLength(SAMPLES); ++i)
        {
            float value=llList2Float(SAMPLES,i);
            if (value<LOW || value>HIGH) ++outside;
            else
            {
                integer at=llFloor(5.0*(value-LOW)/(HIGH-LOW));
                if (at>4) at=4;
                bins=llListReplaceList(bins,[llList2Integer(bins,at)+1],at,at);
            }
        }
        llOwnerSay("Five bins: "+llDumpList2String(bins,",")+"; outside="+(string)outside);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Count small unordered selections

Compute how many ways k items can be selected from n without enumerating them.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set N0..30 and K0..N. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Uses float arithmetic for a bounded demonstration; larger values quickly lose integer precision. Does not generate combinations.

// Original Incoprea. MIT.
integer N=12;
integer K=4;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(N<0||N>30||K<0||K>N)
        {
            llOwnerSay("Use0<=k<=n<=30.");
            return;
        }
        integer k=K;
        if(k>N-k)k=N-k;
        float result=1.0;
        integer i;
        for(i=1;i<=k;++i)result*=((float)(N-k+i)/(float)i);
        llOwnerSay("Combination count approximately="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Distribute a fixed count by weights

Allocate integer slots proportionally with the largest-remainder method.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set positive WEIGHTS and TOTAL0..1000. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Ties go to earlier entries. This preserves the exact total while approximating relative weights.

// Original Incoprea. MIT.
list WEIGHTS=[5.0,3.0,2.0];
integer TOTAL=17;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(WEIGHTS);
        if(n==0||n>20||TOTAL<0||TOTAL>1000)
        {
            llOwnerSay("Invalid size/total.");
            return;
        }
        float sum;
        integer i;
        for(i=0;i<n;++i)
        {
            float w=llList2Float(WEIGHTS,i);
            if(w<=0.0)
            {
                llOwnerSay("Positive weights required.");
                return;
            }
            sum+=w;
        }
        list counts;
        list remainders;
        integer assigned;
        for(i=0;i<n;++i)
        {
            float exact=TOTAL*llList2Float(WEIGHTS,i)/sum;
            integer base=llFloor(exact);
            counts+=[base];
            remainders+=[exact-base];
            assigned+=base;
        }
        while(assigned<TOTAL)
        {
            integer best=0;
            for(i=1;i<n;++i)if(llList2Float(remainders,i)>llList2Float(remainders,best))best=i;
            counts=llListReplaceList(counts,[llList2Integer(counts,best)+1],best,best);
            remainders=llListReplaceList(remainders,[-1.0],best,best);
            ++assigned;
        }
        llOwnerSay("Allocated="+llDumpList2String(counts,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Estimate area under a profile

Approximate the integral of a height profile using equal-width trapezoids.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to integrate height(x) = x squared on zero through three using twelve slices.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The exact result here is nine. More slices reduce this smooth example’s error but increase work; it is a numerical estimate.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float height(float x)
{
    return x*x;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float left=0.0;
        float right=3.0;
        integer slices=12;
        float width=(right-left)/(float)slices;
        float sum=0.5*(height(left)+height(right));
        integer i;
        for (i=1; i<slices; ++i) sum+=height(left+width*(float)i);
        llOwnerSay("Estimated area="+(string)(sum*width)+"; exact example area=9.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Estimate slope by symmetric samples

Approximate a derivative with a central finite difference and compare with the exact example.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set X and positive H for the supplied cubic function. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

An extremely small step amplifies rounding error; a large step adds approximation error.

// Original Incoprea. MIT.
float X=2.0;
float H=0.01;
float f(float x)
{
    return x*x*x-2.0*x;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(H<=0.0)
        {
            llOwnerSay("Positive step required.");
            return;
        }
        float slope=(f(X+H)-f(X-H))/(2.0*H);
        llOwnerSay("Approximate slope="+(string)slope+" exact="+(string)(3.0*X*X-2.0));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Evaluate a custom piecewise response curve

Interpolate within an ordered table of input/output knots, clamping beyond its endpoints.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set paired KNOTS in strictly increasing input order and VALUE. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Each interval is linear. The table is validated before lookup; this differs from a smooth spline.

// Original Incoprea. MIT.
list KNOTS=[0.0,0.0,0.2,0.05,0.6,0.8,1.0,1.0];
float VALUE=0.45;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(KNOTS);
        if(n<4||n%2)
        {
            llOwnerSay("Need at least two input/output pairs.");
            return;
        }
        integer i;
        for(i=2;i<n;i+=2)if(llList2Float(KNOTS,i)<=llList2Float(KNOTS,i-2))
        {
            llOwnerSay("Inputs must strictly increase.");
            return;
        }
        if(VALUE<=llList2Float(KNOTS,0))
        {
            llOwnerSay((string)llList2Float(KNOTS,1));
            return;
        }
        for(i=2;i<n;i+=2)
        {
            float right=llList2Float(KNOTS,i);
            if(VALUE<=right)
            {
                float left=llList2Float(KNOTS,i-2);
                float t=(VALUE-left)/(right-left);
                float y=llList2Float(KNOTS,i-1);
                llOwnerSay("Output="+(string)(y+t*(llList2Float(KNOTS,i+1)-y)));
                return;
            }
        }
        llOwnerSay("Clamped="+(string)llList2Float(KNOTS,-1));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Evaluate a polynomial and its derivative together

Extend Horner evaluation to return both the value and first derivative in one pass.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set descending-order COEFFICIENTS and X. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Works for constants too, returning derivative zero. Coefficient type is consistently float.

// Original Incoprea. MIT.
list COEFFICIENTS=[1.0,0.0,-2.0,4.0];
float X=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(COEFFICIENTS);
        if(n==0)
        {
            llOwnerSay("No coefficients.");
            return;
        }
        float value=llList2Float(COEFFICIENTS,0);
        float derivative;
        integer i;
        for(i=1;i<n;++i)
        {
            derivative=derivative*X+value;
            value=value*X+llList2Float(COEFFICIENTS,i);
        }
        llOwnerSay("Value="+(string)value+" derivative="+(string)derivative);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Evaluate a polynomial with Horner’s method

Evaluate a coefficient list with fewer multiplications than separate powers.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Enter coefficients in descending degree order and set X. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

An empty coefficient list is rejected. High-degree or large-value polynomials can still overflow or lose precision.

// Original Incoprea. MIT.
list COEFFICIENTS=[2.0,-3.0,0.0,5.0];
float X=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(COEFFICIENTS);
        if(n==0)
        {
            llOwnerSay("No coefficients.");
            return;
        }
        float value=llList2Float(COEFFICIENTS,0);
        integer i;
        for(i=1;i<n;++i)value=value*X+llList2Float(COEFFICIENTS,i);
        llOwnerSay("Polynomial value="+(string)value);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Factor a small repeat count

Factor a positive integer into its prime building blocks using bounded trial division.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Set NUMBER from two to one million and touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The cap prevents excessive event work. This is a numeric learning aid, not cryptographic factorization.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
integer NUMBER=756;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (NUMBER<2 || NUMBER>1000000)
        {
            llOwnerSay("Use a number from 2 to 1000000.");
            return;
        }
        integer remaining=NUMBER;
        integer divisor=2;
        list factors;
        while (divisor<=remaining/divisor)
        {
            if (remaining%divisor==0)
            {
                factors += [divisor];
                remaining/=divisor;
            }
            else ++divisor;
        }
        if (remaining>1) factors += [remaining];
        llOwnerSay((string)NUMBER+" = "+llDumpList2String(factors," x "));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Find a minimum in a bounded interval

Use golden-section search on a unimodal example function without calculating derivatives.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit function f and its bracket together. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Requires a unimodal function on the bracket; a fixed32-step cap limits work. Does not guarantee a global minimum on arbitrary functions.

// Original Incoprea. MIT.
float f(float x)
{
    return (x-2.3)*(x-2.3)+1.0;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float a=-2.0;
        float b=6.0;
        float ratio=0.618033989;
        float c=b-ratio*(b-a);
        float d=a+ratio*(b-a);
        float fc=f(c);
        float fd=f(d);
        integer i;
        for(i=0;i<32;++i)
        {
            if(fc<fd)
            {
                b=d;
                d=c;
                fd=fc;
                c=b-ratio*(b-a);
                fc=f(c);
            }
            else
            {
                a=c;
                c=d;
                fc=fd;
                d=a+ratio*(b-a);
                fd=f(d);
            }
        }
        float x=(a+b)*0.5;
        llOwnerSay("Minimum near x="+(string)x+" value="+(string)f(x));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Find an insertion point in a sorted list

Locate the first sorted integer greater than or equal to a requested value using binary search.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Keep VALUES sorted ascending, set TARGET, and touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Returns the list length if every element is smaller. For duplicate values it returns the first match. This example uses integers consistently.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list VALUES=[2,4,4,7,12,19,25];
integer TARGET=4;
integer lowerBound(list values, integer target)
{
    integer low=0;
    integer high=llGetListLength(values);
    while (low<high)
    {
        integer middle=low+(high-low)/2;
        if (llList2Integer(values,middle)<target) low=middle+1;
        else high=middle;
    }
    return low;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer index=lowerBound(VALUES,TARGET);
        llOwnerSay("Insertion or first matching index: "+(string)index);
        if (index<llGetListLength(VALUES)) llOwnerSay("Value there: "+(string)llList2Integer(VALUES,index));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Find an interpolated percentile

Sort float samples and interpolate between neighbors at a requested quantile.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set SAMPLES and QUANTILE between0 and1. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Uses the index(q*(n-1)) convention; other percentile definitions differ. Non-float sample types are not supported by this example.

// Original Incoprea. MIT.
list SAMPLES=[1.0,2.0,4.0,8.0,16.0];
float QUANTILE=0.75;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(SAMPLES);
        if(n==0||QUANTILE<0.0||QUANTILE>1.0)
        {
            llOwnerSay("Need data and quantile0..1.");
            return;
        }
        list sorted=llListSort(SAMPLES,1,TRUE);
        float index=QUANTILE*(n-1);
        integer low=llFloor(index);
        integer high=llCeil(index);
        float a=llList2Float(sorted,low);
        float b=llList2Float(sorted,high);
        llOwnerSay("Quantile="+(string)(a+(b-a)*(index-low)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4 · API reference 5

Learning lab · Intermediate

Fit a trend line through paired values

Fit y = slope × x + intercept to a short list of coordinate pairs.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit alternating x/y numbers in DATA and touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

A least-squares fit is descriptive, not predictive assurance. At least two pairs with varying x are needed; small samples can be unstable.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list DATA=[0.0,1.2,1.0,2.9,2.0,5.1,3.0,6.8];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer length=llGetListLength(DATA);
        if (length<4 || length%2)
        {
            llOwnerSay("Need at least two x/y pairs.");
            return;
        }
        float n=(float)(length/2);
        float sx;
        float sy;
        float sxx;
        float sxy;
        integer i;
        for (i=0; i<length; i+=2)
        {
            float x=llList2Float(DATA,i);
            float y=llList2Float(DATA,i+1);
            sx+=x;
            sy+=y;
            sxx+=x*x;
            sxy+=x*y;
        }
        float denominator=n*sxx-sx*sx;
        if (llFabs(denominator)<0.000001)
        {
            llOwnerSay("X values do not vary enough.");
            return;
        }
        float slope=(n*sxy-sx*sy)/denominator;
        llOwnerSay("Slope="+(string)slope+"; intercept="+(string)((sy-slope*sx)/n));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Frame-independent approach to a target

Show how elapsed-time exponential damping approaches a target at the same rate with different step sizes.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to simulate one second using ten small steps and four larger steps.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The response constant is positive inverse-seconds. The constant target is important: changing targets between samples can produce different paths.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float approach(float value, float target, float response, float elapsed)
{
    if (elapsed <= 0.0) return value;
    if (response <= 0.0) return value;
    float weight = 1.0-llPow(2.718281828,-response*elapsed);
    return value+(target-value)*weight;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float a = 0.0;
        float b = 0.0;
        integer i;
        for (i=0; i<10; ++i) a=approach(a,10.0,3.0,0.1);
        for (i=0; i<4; ++i) b=approach(b,10.0,3.0,0.25);
        llOwnerSay("10 x 0.1 seconds: "+(string)a+"; 4 x 0.25 seconds: "+(string)b);
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Integrate a smooth profile with Simpson weights

Estimate area using alternating1/4/2 Simpson weights across an even number of intervals.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set even INTERVALS between2 and100. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

The supplied cubic integrates exactly apart from float error. General profiles are approximate and should be checked by refinement.

// Original Incoprea. MIT.
integer INTERVALS=10;
float f(float x)
{
    return x*x*x+2.0*x;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(INTERVALS<2||INTERVALS>100||INTERVALS%2)
        {
            llOwnerSay("Use an even interval count2..100.");
            return;
        }
        float left=0.0;
        float right=2.0;
        float h=(right-left)/(float)INTERVALS;
        float total=f(left)+f(right);
        integer i;
        for(i=1;i<INTERVALS;++i)
        {
            float weight=2.0;
            if(i%2)weight=4.0;
            total+=weight*f(left+i*h);
        }
        llOwnerSay("Integral="+(string)(total*h/3.0)+" exact example=8.");
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Interpolate a three-point calibration

Fit the unique quadratic through three calibration pairs and evaluate at a selected input.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set X0/Y0, X1/Y1, X2/Y2 and INPUT. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Distinct input coordinates are required. Extrapolation outside the calibration range may be unreliable.

// Original Incoprea. MIT.
float X0=0.0;
float Y0=1.0;
float X1=2.0;
float Y1=4.0;
float X2=5.0;
float Y2=16.0;
float INPUT=3.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llFabs(X0-X1)<0.000001||llFabs(X0-X2)<0.000001||llFabs(X1-X2)<0.000001)
        {
            llOwnerSay("Calibration inputs must differ.");
            return;
        }
        float result=Y0*(INPUT-X1)*(INPUT-X2)/((X0-X1)*(X0-X2))+Y1*(INPUT-X0)*(INPUT-X2)/((X1-X0)*(X1-X2))+Y2*(INPUT-X0)*(INPUT-X1)/((X2-X0)*(X2-X1));
        llOwnerSay("Interpolated output="+(string)result);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Interpolate across the heading seam

Interpolate from 350 to 10 degrees along the short path across zero.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit FROM_DEGREES and TO_DEGREES, then touch to see five samples.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

The exact 180-degree tie chooses the negative turn. This handles scalar headings; full 3D orientation needs quaternion methods.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float FROM_DEGREES = 350.0;
float TO_DEGREES = 10.0;
float wrap(float angle)
{
    return angle-360.0*llFloor(angle/360.0);
}
float shortDelta(float a, float b)
{
    return wrap(b-a+180.0)-180.0;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float delta=shortDelta(FROM_DEGREES,TO_DEGREES);
        integer i;
        for (i=0; i<=4; ++i) llOwnerSay((string)wrap(FROM_DEGREES+delta*(float)i/4.0));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Mean and variance without storing samples

Process a numeric stream using running count, mean, and squared deviations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch once per predefined sample. After the sequence ends, reset to repeat.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Reports sample variance, requiring at least two samples. This avoids the numerically fragile difference of large sums of squares.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list INPUT=[1000.1,1000.4,999.9,1000.2,1000.6];
integer count;
float mean;
float m2;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (count>=llGetListLength(INPUT))
        {
            llOwnerSay("All samples consumed; reset to replay.");
            return;
        }
        float value=llList2Float(INPUT,count);
        ++count;
        float delta=value-mean;
        mean+=delta/(float)count;
        m2+=delta*(value-mean);
        llOwnerSay("Count="+(string)count+"; mean="+(string)mean);
        if (count>1) llOwnerSay("Sample variance="+(string)(m2/(float)(count-1)));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Measure balance across a weighted collection

Compute normalized Shannon entropy from positive category weights.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set WEIGHTS with at least two positive entries. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Returns zero for highly concentrated weights in the limit and one for equal weights. Uses natural logarithms; it is a balance descriptor, not a quality score.

// Original Incoprea. MIT.
list WEIGHTS=[6.0,3.0,1.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(WEIGHTS);
        if(n<2)
        {
            llOwnerSay("Need at least two weights.");
            return;
        }
        float total;
        integer i;
        for(i=0;i<n;++i)
        {
            float w=llList2Float(WEIGHTS,i);
            if(w<=0.0)
            {
                llOwnerSay("Weights must be positive.");
                return;
            }
            total+=w;
        }
        float entropy;
        for(i=0;i<n;++i)
        {
            float p=llList2Float(WEIGHTS,i)/total;
            entropy-=p*llLog(p);
        }
        llOwnerSay("Normalized entropy="+(string)(entropy/llLog((float)n)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Measure paired linear association

Calculate Pearson correlation for a small paired x/y list using centered deviations.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set DATA as x/y pairs with at least two observations. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Correlation describes linear association and does not establish causation. Constant input series are rejected.

// Original Incoprea. MIT.
list DATA=[1.0,2.0,2.0,3.0,3.0,5.0,4.0,4.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer length=llGetListLength(DATA);
        if(length<4||length%2)
        {
            llOwnerSay("Need two or more pairs.");
            return;
        }
        float count=(float)(length/2);
        float mx;
        float my;
        integer i;
        for(i=0;i<length;i+=2)
        {
            mx+=llList2Float(DATA,i);
            my+=llList2Float(DATA,i+1);
        }
        mx/=count;
        my/=count;
        float xx;
        float yy;
        float xy;
        for(i=0;i<length;i+=2)
        {
            float x=llList2Float(DATA,i)-mx;
            float y=llList2Float(DATA,i+1)-my;
            xx+=x*x;
            yy+=y*y;
            xy+=x*y;
        }
        if(xx<0.000001||yy<0.000001)
        {
            llOwnerSay("Constant or nearly constant series.");
            return;
        }
        llOwnerSay("Correlation="+(string)(xy/llSqrt(xx*yy)));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Measure spread robustly around the median

Calculate median absolute deviation for a small float sample list.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit SAMPLES; touch to compare the median with typical absolute distance from it. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

MAD is robust to isolated outliers but is not the same as standard deviation; no normal-distribution scaling is applied.

// Original Incoprea. MIT.
list SAMPLES=[9.0,10.0,10.0,11.0,12.0,100.0];
float median(list values)
{
    values=llListSort(values,1,TRUE);
    integer n=llGetListLength(values);
    float result=llList2Float(values,n/2);
    if(!(n%2))result=(result+llList2Float(values,n/2-1))*0.5;
    return result;
}
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(SAMPLES);
        if(n==0)
        {
            llOwnerSay("No samples.");
            return;
        }
        float centre=median(SAMPLES);
        list differences;
        integer i;
        for(i=0;i<n;++i)differences+=[llFabs(llList2Float(SAMPLES,i)-centre)];
        llOwnerSay("Median="+(string)centre+" MAD="+(string)median(differences));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Newton iteration with a convergence check

Approximate a positive square root using a bounded Newton iteration.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set VALUE positive. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Stops on a relative change threshold or after thirty steps; llSqrt is printed as a reference, not used in the iteration.

// Original Incoprea. MIT.
float VALUE=37.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(VALUE<=0.0)
        {
            llOwnerSay("Positive value required.");
            return;
        }
        float guess=VALUE;
        if(guess<1.0)guess=1.0;
        integer i;
        integer done;
        for(i=0;i<30&&!done;++i)
        {
            float next=0.5*(guess+VALUE/guess);
            done=(llFabs(next-guess)<0.000001*(1.0+llFabs(next)));
            guess=next;
        }
        llOwnerSay("Root="+(string)guess+" reference="+(string)llSqrt(VALUE)+" iterations="+(string)i);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Normalize nonnegative blend weights

Clamp negative channels to zero and normalize their sum for a convex blend.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set raw float WEIGHTS with at least one positive value. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

This is clamp-and-renormalize, not Euclidean projection onto a simplex. The title describes normalization; negative contributions are intentionally discarded.

// Original Incoprea. MIT.
list WEIGHTS=[0.6,-0.2,1.4,0.3];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        list cleaned;
        float total;
        integer i;
        for(i=0;i<llGetListLength(WEIGHTS);++i)
        {
            float w=llList2Float(WEIGHTS,i);
            if(w<0.0)w=0.0;
            cleaned+=[w];
            total+=w;
        }
        if(total<=0.0)
        {
            llOwnerSay("At least one positive weight required.");
            return;
        }
        list normalized;
        for(i=0;i<llGetListLength(cleaned);++i)normalized+=[llList2Float(cleaned,i)/total];
        llOwnerSay("Convex weights="+llDumpList2String(normalized,","));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Reduce rounding error in a numeric sum

Compare plain accumulation with Kahan compensated summation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Edit SAMPLES with float values of different magnitudes. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Compensation reduces but cannot eliminate floating-point error; behavior depends on values and simulator float implementation.

// Original Incoprea. MIT.
list SAMPLES=[100000.0,0.01,0.01,0.01,0.01,-100000.0];
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float ordinary;
        float compensated;
        float correction;
        integer i;
        for(i=0;i<llGetListLength(SAMPLES);++i)
        {
            float value=llList2Float(SAMPLES,i);
            ordinary+=value;
            float adjusted=value-correction;
            float next=compensated+adjusted;
            correction=(next-compensated)-adjusted;
            compensated=next;
        }
        llOwnerSay("Ordinary="+(string)ordinary+" compensated="+(string)compensated);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Reject spikes with a rolling median

Maintain a five-sample window and report its median as a spike-resistant estimate.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch through a sample sequence containing one large outlier.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

All sample values are floats so LSL sorting treats them as one type. The filter delays fast genuine changes as well as rejecting isolated spikes.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list INPUT=[10.0,11.0,10.0,80.0,12.0,11.0,10.0];
list window;
integer cursor;
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float value=llList2Float(INPUT,cursor);
        cursor=(cursor+1)%llGetListLength(INPUT);
        window += [value];
        if (llGetListLength(window)>5) window=llList2List(window,-5,-1);
        list sorted=llListSort(window,1,TRUE);
        integer n=llGetListLength(sorted);
        float median=llList2Float(sorted,n/2);
        if (!(n%2)) median=(median+llList2Float(sorted,n/2-1))*0.5;
        llOwnerSay("Input="+(string)value+"; median="+(string)median+"; window="+llDumpList2String(window,","));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Remap a control dead zone

Ignore small signed input noise and rescale the remaining range smoothly to full output.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to process the sample inputs. Reuse remap for a signed value between minus one and one.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

This demonstration does not request avatar controls. Dead zone must be between zero and one, excluding one.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float remap(float value, float zone)
{
    if (zone < 0.0 || zone >= 1.0) return 0.0;
    float magnitude=llFabs(value);
    if (magnitude <= zone) return 0.0;
    if (magnitude > 1.0) magnitude=1.0;
    float output=(magnitude-zone)/(1.0-zone);
    if (value < 0.0) output=-output;
    return output;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        list values=[-1.0,-0.5,-0.1,0.0,0.1,0.5,1.0];
        integer i;
        for (i=0; i<llGetListLength(values); ++i)
        {
            float v=llList2Float(values,i);
            llOwnerSay((string)v+" -> "+(string)remap(v,0.2));
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Smooth starts and stops

Compare linear, smoothstep, and smootherstep progress at six points along a transition.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to print a compact progress table. Reuse the functions to shape a normalized animation parameter.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Inputs are clamped to zero through one. These functions reshape time; they do not themselves animate objects.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float clamp01(float t)
{
    if (t < 0.0) return 0.0;
    if (t > 1.0) return 1.0;
    return t;
}
float smooth(float t)
{
    t = clamp01(t);
    return t*t*(3.0-2.0*t);
}
float smoother(float t)
{
    t = clamp01(t);
    return t*t*t*(t*(t*6.0-15.0)+10.0);
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer i;
        for (i = 0; i <= 5; ++i)
        {
            float t = (float)i/5.0;
            llOwnerSay((string)t + " | " + (string)smooth(t) + " | " + (string)smoother(t));
        }
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Solve a nonlinear equation by bisection

Find a root of x cubed plus x minus ten using a bracketed numerical search.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Touch to solve on the interval zero to three. Adapt equation() and the bracket together.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Bisection requires a continuous function and opposite signs at the bracket endpoints. Iteration count is capped at thirty.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
float equation(float x)
{
    return x*x*x+x-10.0;
}
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        float low=0.0;
        float high=3.0;
        float fLow=equation(low);
        float fHigh=equation(high);
        if (fLow*fHigh>0.0)
        {
            llOwnerSay("Bracket does not straddle a root.");
            return;
        }
        integer i;
        for (i=0; i<30; ++i)
        {
            float middle=(low+high)*0.5;
            float fMiddle=equation(middle);
            if (fLow*fMiddle<=0.0) high=middle;
            else
            {
                low=middle;
                fLow=fMiddle;
            }
        }
        float result=(low+high)*0.5;
        llOwnerSay("Root approximately "+(string)result+"; residual="+(string)equation(result));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Solve a quadratic with reduced cancellation

Compute real quadratic roots using a stable q formulation.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set A/B/C for A*x*x+B*x+C=0. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Handles linear equations, repeated roots and negative discriminants. Very large coefficients can still overflow float arithmetic.

// Original Incoprea. MIT.
float A=1.0;
float B=-100.0;
float C=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        if(llFabs(A)<0.000001)
        {
            if(llFabs(B)<0.000001)
            {
                llOwnerSay("No unique linear root.");
                return;
            }
            llOwnerSay("Linear root="+(string)(-C/B));
            return;
        }
        float discriminant=B*B-4.0*A*C;
        if(discriminant<0.0)
        {
            llOwnerSay("No real roots.");
            return;
        }
        float root=llSqrt(discriminant);
        float signedRoot=root;
        if(B<0.0)signedRoot=-root;
        float q=-0.5*(B+signedRoot);
        if(llFabs(q)<0.000001)
        {
            llOwnerSay("Repeated root="+(string)(-B/(2.0*A)));
            return;
        }
        llOwnerSay("Roots="+(string)(q/A)+" and "+(string)(C/q));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Advanced

Solve two coupled linear equations

Solve a two-by-two system and reject a near-zero determinant.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set coefficients for A*x+B*y=C and D*x+E*y=F. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Small determinants indicate an unstable solution. Inputs are examples, not measurements of scene objects.

// Original Incoprea. MIT.
float A=2.0;
float B=1.0;
float C=7.0;
float D=1.0;
float E=-1.0;
float F=2.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        float determinant=A*E-B*D;
        if(llFabs(determinant)<0.000001)
        {
            llOwnerSay("No stable unique solution.");
            return;
        }
        float x=(C*E-B*F)/determinant;
        float y=(A*F-C*D)/determinant;
        llOwnerSay("x="+(string)x+" y="+(string)y);
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Intermediate

Store integer positions as deltas

Express a sequence as its first absolute integer followed by successive differences, then reconstruct it.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit POSITIONS with small integer coordinates and touch.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Deltas do not automatically shrink LSL list memory; they are useful before an external compact encoding. Values must stay within integer range.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list POSITIONS=[100,102,105,104,110,111];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n=llGetListLength(POSITIONS);
        if (n==0)
        {
            llOwnerSay("No positions.");
            return;
        }
        list deltas=[llList2Integer(POSITIONS,0)];
        integer i;
        for (i=1; i<n; ++i) deltas += [llList2Integer(POSITIONS,i)-llList2Integer(POSITIONS,i-1)];
        list restored;
        integer current=0;
        for (i=0; i<n; ++i)
        {
            current+=llList2Integer(deltas,i);
            restored += [current];
        }
        llOwnerSay("Deltas: "+llDumpList2String(deltas,","));
        llOwnerSay("Restored: "+llDumpList2String(restored,","));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

Learning lab · Advanced

Turn scores into normalized softmax weights

Convert arbitrary scores into positive normalized weights using a numerically safer maximum shift.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Place in a spare owned prim. Set float SCORES and positive TEMPERATURE. Touch to run; output is private to the owner.

Stop / restore: Disable/remove. No scene changes or external calls.

Temperature controls concentration; these are mathematical weights, not calibrated confidence values.

// Original Incoprea. MIT.
list SCORES=[1.0,3.0,2.0];
float TEMPERATURE=1.0;
default
{
    touch_start(integer detectedCount)
    {
        if(llDetectedKey(0)!=llGetOwner())return;
        integer n=llGetListLength(SCORES);
        if(n==0||TEMPERATURE<=0.0)
        {
            llOwnerSay("Need scores and positive temperature.");
            return;
        }
        float maximum=llList2Float(SCORES,0);
        integer i;
        for(i=1;i<n;++i)if(llList2Float(SCORES,i)>maximum)maximum=llList2Float(SCORES,i);
        list weights;
        float total;
        for(i=0;i<n;++i)
        {
            float w=llPow(2.718281828,(llList2Float(SCORES,i)-maximum)/TEMPERATURE);
            weights+=[w];
            total+=w;
        }
        for(i=0;i<n;++i)llOwnerSay((string)i+" weight="+(string)(llList2Float(weights,i)/total));
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Validate nested delimiter pairs

Use a stack to check that round, square, and curly delimiters close in the correct nesting order.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit TEXT and touch. The example validates delimiters only.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

It is not a complete LSL parser: delimiters inside quoted text or comments are still counted. Input is capped at two hundred characters.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
string TEXT="{panel:[(north),(south)]}";
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        if (llStringLength(TEXT)>200)
        {
            llOwnerSay("Use at most 200 characters.");
            return;
        }
        string opens="([{";
        string closes=")]}";
        list stack;
        integer i;
        for (i=0; i<llStringLength(TEXT); ++i)
        {
            string ch=llGetSubString(TEXT,i,i);
            integer opening=llSubStringIndex(opens,ch);
            integer closing=llSubStringIndex(closes,ch);
            if (opening!=-1) stack += [opening];
            else if (closing!=-1)
            {
                integer size=llGetListLength(stack);
                if (size==0 || llList2Integer(stack,-1)!=closing)
                {
                    llOwnerSay("Mismatched closing delimiter at character "+(string)i);
                    return;
                }
                stack=llDeleteSubList(stack,-1,-1);
            }
        }
        if (llGetListLength(stack)) llOwnerSay("An opening delimiter was not closed.");
        else llOwnerSay("All delimiters are correctly nested.");
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3 · API reference 4

Learning lab · Intermediate

Weighted blend of numeric samples

Combine values with different nonnegative weights and reject malformed or weightless input.

LSL · Second Life / OpenSim candidate
Not compiled or tested in-world

Code & how to use

Setup: Put in a spare prim you own. Edit alternating value/weight pairs in DATA. Touch to calculate the weighted mean.

Stop / restore: Disable or remove the script. It only reports to its owner and does not change prim properties. Reset clears its temporary state.

Weights describe relative influence, not percentages; their sum need not be one. Negative weights are deliberately rejected.

// Original Incoprea example. MIT. Owner-only calculation; no scene changes.
list DATA=[10.0,1.0,20.0,3.0,40.0,2.0];
default
{
    touch_start(integer detectedCount)
    {
        if (llDetectedKey(0) != llGetOwner()) return;
        integer n=llGetListLength(DATA);
        if (n==0 || n%2)
        {
            llOwnerSay("Use value/weight pairs.");
            return;
        }
        float sum=0.0;
        float weightSum=0.0;
        integer i;
        for (i=0; i<n; i+=2)
        {
            float weight=llList2Float(DATA,i+1);
            if (weight<0.0)
            {
                llOwnerSay("Weights cannot be negative.");
                return;
            }
            sum+=llList2Float(DATA,i)*weight;
            weightSum+=weight;
        }
        if (weightSum<=0.0)
        {
            llOwnerSay("At least one positive weight is required.");
            return;
        }
        llOwnerSay("Weighted mean: "+(string)(sum/weightSum));
    }
    changed(integer change)
    {
        if (change & CHANGED_OWNER) llResetScript();
    }
}

MIT · original Incoprea example

API reference 1 · API reference 2 · API reference 3

The maker’s field guide

A little guidance.
A lot more confidence.

You don’t need to learn everything at once. Pick what you’re making, open a short guide, and try one small change.

68 short guides · 6 topics

7 short guidesStart hereMake your first script, understand the labels, and try it on a spare object.
Your first script

Build a spare prim you can modify. Open Edit → Content → New Script, replace the default code, and Save. Check the compiler result and Running checkbox. Land permissions can prevent scripts from running. Work on a copy until the result is right.

What this library’s labels mean

“LSL candidate” means the example uses documented LSL names and includes setup notes; it does not mean it was compiled. “Not compiled or tested in-world” is shown honestly until a specific simulator and result can be recorded. OpenSim configuration and viewer differences matter.

Second Life, OSgrid, and OpenSim

OpenSimulator implements LSL and adds OSSL extensions. OSgrid runs on OpenSimulator; behavior can depend on region version and configuration. An OSSL-only example must be labeled separately, and some functions require administrator permission. A shared function name is not proof of identical behavior.

LSL and OSSL are not interchangeable

Second Life documents LSL. OpenSimulator implements a subset of LSL and adds OSSL; region settings can block OSSL calls. A script marked LSL candidate is not a promise that every grid, engine, or parcel will behave identically. Check OpenSim function support and ask the region owner about OSSL permissions.

Test on a spare object

Compile before placing. Try a copy in a permitted parcel, watch the object and viewer, and note whether the effect is stored as a prim property. Read each entry’s stop and restore step before running it. Keep a backup of important builds.

Read-only tools first

A measurement script is a useful first step before moving, resizing, or recoloring a build. Put it in the exact prim named in setup. Owner chat reports are private to the current owner; floating text is visible to everyone. These examples do not back up your object automatically.

A quick compile-error routine

Read the first compiler error and its line. Check braces, quotation marks, commas, and whether your object has the inventory item or linked prim named in setup. Make one edit at a time. The compiler confirms syntax, not that the script does the right thing in-world.

15 short guidesMove & buildChoose a pivot, understand linked parts, and preview changes before moving a build.
Choose the rotation center

For a simple two-part nonphysical build, select the moving shape first and the center prim last, then link. Put the automatic rotation script in the root. Position and orient the moving shape before running. A decorative orbit does not change the collision path.

World space and root-local space

A rezzed object position uses region coordinates. A child prim position is relative to its root, and root rotation changes how that offset points in the region. Bounding boxes are measured along local axes; they are not always the same as the visible outline of a mesh. Measure a stationary copy without seated avatars when you want build dimensions.

Root, child, and hinge coordinates

A root rotation changes the whole linkset. A child local rotation turns that child about its own pivot, not an imaginary hinge at an edge. A useful door or pendulum often needs a hinge-centered mesh or an appropriate cut prim. Child positions are expressed in the root coordinate system; a child-local travel vector must be rotated by the child’s local rotation. Configure and reset reversible examples only in their resting pose.

Coordinate frames for moving exhibits

Child local positions use the root coordinate frame. A world-space direction such as north, wind or sun must be converted by the inverse root rotation before aiming a child. A modeled front may be +X, +Y or another axis: these examples explicitly choose +X. Hinge-centered meshes can rotate directly; centered boxes need their center translated around the chosen edge.

Choose a coordinate frame before calculating

A point, a direction, and a rotation are different kinds of input. Use one coordinate frame for all operands in a calculation. Subtract an origin to form an offset; divide that offset by a rotation to express it in the rotated local frame. Calculation examples print results without moving your build, so inspect their output before adapting it to prim changes.

Measure by touching the actual build

A measurement script only receives touches on its object or forwarded touches in its linkset. It cannot collect arbitrary points from unrelated objects. Click the intended corners carefully and read the required order. The next full sequence replaces the previous one; reset clears incomplete measurements. Curved surfaces need more than a few straight-line samples.

Inspect linked components without touching avatars

For rezzed builds, llGetObjectPrimCount excludes seated avatars. A bounded inspector can then read individual real prims safely. Attachments need separate handling; these linkset tools explicitly require a rezzed build.

Menus for real build adjustments

A menu can change actual geometry, even when it looks like a harmless panel. Use spare nonphysical builds, small step sizes, and a Home or Restore action. Capture only the parameters you need, keep each target list bounded, and do not relink while the script depends on saved link numbers. Test a restore cycle before doing a long editing session.

Builder helpers need explicit geometry assumptions

A bounding-box calculation is not a collision test, and a diffuse UV rule is not a PBR material transform. Keep each helper’s assumed forward axis, face, mapping mode and dimensions visible in setup. A useful preview should restore its captured state, reject unsupported object types, and avoid changing physics or link topology behind the user’s back.

Preview geometry before changing the build

These planning tools report coordinates, dimensions, and fits privately to the owner. Enter consistent units and one coordinate frame. Inspect the result before converting the calculation to movement or geometry changes; an ideal mathematical shape does not establish actual mesh bounds, collision geometry, or building safety.

A placement plan is not a resize operation

Root-local offsets, prim scales, mesh visual bounds, and physics bounds are different quantities. These planners report proposed numbers while leaving the build unchanged. Test a copy before applying them, especially when scripts depend on link names or when a pivot changes.

Curves do not guarantee safe motion

Bézier and Catmull–Rom examples calculate positions, not navigable paths. Control points are not necessarily points on the curve; equal parameter steps are not generally equal distances. Check for overshoot, collisions, parcel boundaries, and the mesh forward axis before driving a real object. Keep visual-only target-omega separate from server-side motion.

Use a controller preview before live motion

Motion planners and controllers here compute numbers without moving the build. Check their units, elapsed-time assumptions and stop conditions first. A stable mathematical simulation can behave differently under simulator delays, collision physics and script scheduling; introduce actual movement only in a controlled copy with a reliable stop.

Turn geometry functions into reusable helpers

Keep pure calculation functions separate from event handlers and scene-changing calls. Give every helper an explicit coordinate frame, valid input range, and failure result. Test known cases, degenerate inputs, and round trips before attaching the helper to motion or collision handling.

Use a prim face as an interactive math pad

The procedural-pattern samplers read the actual touched surface position and report a mask, field value, or cell. They do not render or upload a texture. Test on a simple cube first: meshUV layouts and some viewer conventions can differ. Reuse the pure pattern function separately when building a material tool.

10 short guidesAdd life & atmosphereExplore textures, particles, sound, and readable exhibits—with clear ways to stop each effect.
Texture animation needs the right image

A scrolling texture should repeat. A flipbook expects a sprite sheet divided into equally sized frames in row order. Record the original texture settings; animation settings can remain on the prim even after the script that set them is removed.

Classic faces and PBR materials

The classic PRIM_TEXTURE, PRIM_COLOR, glow, and fullbright controls are not interchangeable with a PBR material’s texture slots, alpha mode, and emissive settings. First test on a simple prim with a classic diffuse texture you can read and restore. Confirm the face number; some meshes have several material faces. Texture permissions can prevent a readback UUID from being usable for restoration.

Choose a particle budget

Particles are drawn by viewers and do not collide like physical objects. Start with one or two particles per burst and a generous interval, then check the scene from normal viewing distance. A finite emitter may still need an explicit empty particle system to remove its stored configuration. Clear old emitters, test with particles enabled, and never assume every viewer shows identical results.

Particles have their own coordinate rules

A particle effect can follow its source, remain in world space, react to wind, target a linked prim, or use a special horizontal bounce plane. Those are different mechanics, not physical objects. Test one flag at a time at low emission rates. The simulator stores the emitter settings, so use an explicit empty particle system to stop them before deleting the controlling script.

Sound and script permissions

A sound example needs a sound asset the object can use. Add your own properly licensed sound to the exact prim mentioned in the code. Check creator, transfer, copy, and modify terms before redistribution; script code rights do not grant rights to included sounds or textures.

Audio controls and honest timing

LSL exposes playback and volume operations, not a general audio workstation. Do not label restart as resume, or volume as pitch. Put receiver sounds in the correct prim, close dialog listeners, keep repeated cues quiet, and explicitly stop loops before script removal. A timer passing static analysis is not evidence of sample-accurate playback.

A sound controller should have a clear ending

An introduction, loop, muted state, released ducking state, outro and stopped state are different. Keep transitions explicit. Inventory loading and simulator event timing can delay cues; no short LSL example should promise sample-accurate music playback or pretend it can infer a clip duration.

Timers, sounds, and small games

A timer requests callbacks, not a guaranteed frame rate. Simulator load, script delays, network latency, and sound asset loading affect what a visitor sees or hears. Measure elapsed time for countdowns instead of assuming every timer tick arrived exactly on time. Keep audio quiet, close dialog listeners after use, and label reaction games and metronomes as approximate toys rather than precision instruments.

Accessible exhibit content is authored content

Pair sounds with accurate text, keep hover captions short, and provide an on-demand chat reading path when labels overlap. Notecard-driven displays should correlate every asynchronous response with its request, use timeouts, and reject missing inventory assets. A script can offer a handout, but it cannot prove the viewer accepted it; preserve no-copy originals.

A visual preview must own its rollback

Store per-face state rather than assuming every face had alpha one or the same tint. Do not apply a saved link-number snapshot after relinking: those numbers may now identify different prims. Restore while the original topology still exists, then remove or reset the tool.

9 short guidesMake it interactiveBuild useful buttons, dialogs, and puzzles while respecting ownership and privacy.
Small linked control panels

A root script receives child touches only when touch propagation allows it. Put passive labels and descriptions on buttons, keep commands short, and validate sender names or numbers in receivers. Link messages stay inside one object but are visible to its scripts, so they are not a secret channel. Restore visible state before relinking because link numbers can change.

Owner dialogs and short-lived listeners

Filter a listener to the current owner key, use a nonzero private channel, and check the speaker again in the listen event. Remove the listener after a response or timeout. Channel numbers alone do not authenticate a command. Reset on ownership change so the new owner starts with fresh runtime state.

Treat owner dialogs as temporary sessions

Filter listeners by the current owner, use a fresh nonzero channel, expire old listeners, and cancel state on ownership change. A dialog reply is a message, so validate the expected choice and step before using it. Confirmation interfaces are useful only when the real action also has appropriate permissions, bounds, and a recovery plan.

Puzzle interfaces without persistent listeners

A compact toy can open an owner-restricted text listener only while a round is active. Validate each reply, offer a clear retry instruction, and close the listener when the round ends or times out. Keep rules and feedback in the prompt so the player does not need to study the source code. These examples deliberately avoid wagering, visitor tracking, and irreversible world actions.

Text puzzles are real interactions, not permissions systems

These owner-operated tabletop examples keep all game state in script memory and change no scene geometry. Their text boxes are private-input controls, not private output storage. Reset or script removal discards the round; no persistence or anti-cheat guarantees are implied.

Sensing without visitor surveillance

Often an exhibit needs only its own state, an owned-prop count, or a contact event. Explicitly exclude agents and filter objects to the owner. Retain only the small state the behavior needs. Sensors return capped subsets, not a complete land inventory. Arm repeated checks deliberately and disarm them when finished.

Public signs versus private reports

Hover text is public object data even when its alpha is zero. Put only display-safe content on signs. Owner-chat diagnostics limit the audience but do not replace simulator access controls or good asset permissions.

A permission flag is not the whole answer

Parcel and object flags are useful evidence, but owner/group exceptions, nested inventory, simulator configuration, and licensing can affect the final result. Read-only inspectors report the specific flags they can see without promising an action will succeed.

A protocol example is not a security boundary

These local examples demonstrate framing, versions, sequence tracking, work scheduling and state transitions. A real receiver must also authenticate the sender, bound every input, correlate requests, expire incomplete state and define recovery after reset. Checksums, sequence numbers and feature flags are not credentials.

17 short guidesWork with dataRead notecards, organize lists and JSON, and check input before using it.
Small tables, lists, and JSON

LSL lists can mix types. A strided list groups fixed-size records; sorting must use the correct stride so fields stay together. Simple delimiter splitting cannot parse quoted CSV. JSON is useful for structured data, but validate each value type and check simulator support before relying on it.

Notecard reads are asynchronous

Request a line, keep the returned query key, and accept only the matching dataserver reply. Start at line zero and stop at EOF. Read one line at a time, set a sensible maximum, and add a timeout. Editing inventory during a read should restart it so old and new versions are not combined.

Keep notecard readers bounded and honest

Notecard requests return asynchronously. Match each dataserver reply to its request key, use a timeout, and discard incomplete caches. These readers reject oversized input rather than presenting partial data as complete. Cached content is reset when inventory changes. A parsed manifest or license label is not verification that its claims are true.

Notecard audits are bounded

Use saved plain-text notecards with short lines. The audit tools cap input at 100 lines and stop stalled requests. A report from a capped or timed-out scan is not evidence that the entire document passed.

Inventory audit limits

Contents belong to the exact prim containing a script. A UUID lookup can return no key even when the item exists, and metadata alone does not establish licensing. These audit examples report privately and do not transfer, delete, or rename assets.

Parsers need a declared format

State whether your input supports quoting, embedded separators, blank fields, Unicode, and multiple records. These utilities intentionally reject unsupported forms instead of pretending that every string cast or delimiter split is a complete parser.

Validate before casting

LSL casts can accept an initial numeric portion or turn invalid text into zero. If the complete input must be trustworthy, first validate every character and field count, then apply bounds after conversion. A valid-looking identifier or URL is still not proof of existence or authorization.

Treat configuration as input, not authority

A config card can contain names, paths, labels, and action tokens, but it should not be allowed to execute arbitrary instructions. These auditors validate a narrow declared format and report findings without applying changes. Verify the full file if the line cap or timeout is reached.

JSON values have types

The JSON strings "true" and "null" are not a boolean and a null value. Explicitly quote string values before passing them to APIs that interpret JSON. Validate array sizes, required paths, and value ranges before using a configuration to change the world.

Escaping depends on destination

LSL source strings, JSON, HTML text, URL parameters, Markdown labels, and CSV fields have different escaping rules. Use the formatter for the specific context. None of these helpers turns untrusted input into safe executable code or validates a remote destination.

Text inspectors do not understand all syntax

A quote checker, wildcard matcher, continuation reader, or comment stripper implements a deliberately small grammar. Keep its declared limits visible. Do not use a lightweight helper as a substitute for a real language parser or a security boundary.

Records need stable identities

When updating a table, match an explicit unique key and require exactly one target. Preserve full record widths when filtering, paging, or sorting. A preview that changes only an in-memory copy is a useful first test before adding storage or external actions.

Keep queues and histories bounded

Every pending job, cached request ID, undo record, and sample window uses script memory. Choose a maximum size and an explicit overflow rule: reject new work, discard the oldest, or coalesce equivalent edits. A bounded cache only suppresses duplicates while the identifier remains in it; it is not a permanent exactly-once guarantee.

Validate before committing state

Stage candidate values in local variables, check the whole operation, and only then assign the live state. Revision guards can reject stale edits. For checkpoints, include a format version and validate all fields before restoring. A checksum is useful for accidental corruption but does not authenticate a sender, and an in-memory snapshot does not survive reset.

Preview migrations before changing real data

A field rename can break references even when the new name looks correct. These examples validate full input shapes, duplicate keys, collisions, and old-value preconditions before producing proposed output. They do not provide database transactions or durable storage; retain a backup and recheck current data when integrating them.

Calendar dates are not timezones

A date-only calculation should state its supported year range, inclusive/exclusive endpoint convention, weekend policy, and leap-day policy. Fixed UTC offsets do not automatically follow daylight-saving transitions. These tools plan dates but do not create reminders or scheduled tasks.

Session tools need an export habit

These owner tools deliberately keep data only in script memory. Reset, ownership changes, or script replacement can erase it. Use their list/report commands and copy important notes to a durable document before ending the session.

10 short guidesTest, stop & restoreTroubleshoot one change at a time, understand limits, and protect your original build.
Stop an effect properly

Some scripts set persistent prim properties. Rotation, text, color, and glow can remain after deleting the script. Each library entry includes a stopping or restoration step. A timer, keyframed motion, and a physical object require different stopping methods.

Restoration is part of an effect

A script can save a prim’s current color, alpha, text, or rotation in memory and restore it when toggled off. That saved copy is lost on reset or recompile. Stop and restore before deleting, resetting, relinking, or installing a second controller on the same property. Use a duplicate object for tests, especially when an API cannot read back the old settings.

Reversible preview scripts

A reversible preview stores a startup snapshot. Restore before recompile, reset, relink, or removal. If you change the same property manually or through another script, restoration replaces that newer value with the snapshot. Test on a copy, and verify texture permissions allow the saved texture references to be reused.

A preview snapshot is not a backup

Reversible workbench scripts retain their originals only in running script memory. Restore before resetting, deleting or transferring the script; keep an untouched copy, disable competing scripts, and do not relink during a preview. Scene transforms and names can affect collisions or role-based scripts. Linked-key checks avoid restoring to a different prim but cannot recover a discarded snapshot.

Diagnostics should be bounded and specific

A timer sample, permission mask, running flag, and round-trip probe each answer a narrow question. A good diagnostic states that question, stops when it has enough data, and avoids blaming a person or component from a single measurement.

Sampled monitors report observations, not continuous truth

One-second sessions can miss rapid motion, brief flashes or asset changes between callbacks. Timers are delayed by simulator load. The measurements are bounded diagnostic observations of your own object, not guarantees that no unobserved change occurred.

Use deadlines instead of counting timer ticks

Simulator timers may arrive late, and busy event queues add delay. Store an elapsed-time deadline and check it when the timer fires. Bound the work done in each event, stop timers when idle, and define what happens after reset. A deadline-aware scheduler can catch up; a repeating tick counter simply drifts.

Give numeric algorithms a small safe domain

Check zero denominators, empty lists, invalid sizes, and integer overflow before calculating. Keep numeric lists consistently typed when sorting. Choose a small tolerance appropriate to the scale of the build, cap iteration counts, and print a known-answer example. Mathematical plausibility and static checking still do not substitute for compilation and testing on the intended simulator.

Know what a numerical answer means

Algorithms may produce an approximation, a convention-dependent statistic, or an exact mathematical answer limited by floating-point precision. Read each entry’s domain and expected result. Compare small known cases, vary sample resolution, and reject degenerate inputs instead of silently dividing by nearly zero.

Label simulation boundaries explicitly

Small virtual-world learning models are useful when their assumptions are visible: finite grids, dead or wrapped edges, invented units, bounded queues, and manually advanced steps. They should not be presented as calibrated science or as controllers for real equipment.

A few strange little inventions

Explore breathing lanterns, a pocket oracle, a firefly jar, and more small experiments in the Novelties collection.

A jar of geometric fireflies, glowing ceramic lantern, miniature moon orrery, and mysterious oracle pebble.
AI-generated concept art for the novelty collection.

Explore more libraries

Use these independent references for wider coverage. Their content has its own authors and licenses.