Jump to content

Best Scripter Tips and Shortcuts


Lexie Linden
 Share

Recommended Posts

6 minutes ago, Ruthven Willenov said:

you need to disable the timer or collision event so it doesn't die while you're working on it

So you write
 

on_rez (integer startup)
{
    if (startup)
    {
        llSetTimerEvent(5.0);  
       // or llSetLinkPrimitiveParams (LINK_THIS,[PRIM_TEMP_ON_REZ,TRUE]); 
       // or change state to a new state with a collision_start event in it.
       // or whatever other trick strikes your fancy.
    }
}

And then be sure that you pass the object a non-zero startup parameter from the llRezAtRoot statement in your rezzer script.  That way, your object disappears in a flash if it's rezzed from the script but it lasts forever if you rez it from inventory.

Link to comment
Share on other sites

1 minute ago, Rolig Loon said:

So you write
 


on_rez (integer startup)
{
    if (startup)
    {
        llSetTimerEvent(5.0);  
       // or llSetLinkPrimitiveParams (LINK_THIS,[PRIM_TEMP_ON_REZ,TRUE]); 
       // or change state to a new state with a collision_start event in it.
       // or whatever other trick strikes your fancy.
    }
}

And then be sure that you pass the object a non-zero startup parameter from the llRezAtRoot statement in your rezzer script.  That way, your object disappears in a flash if it's rezzed from the script but it lasts forever if you rez it from inventory.

true, but sometimes I forgot to not use a 0 in that lol. or if i'm using a rez script that i can't mod and they do use a 0, like a wand I have, that i can put my own spells into, so i use

on_rez(integer start_params)
{
    list details = llGetObjectDetails(llGetKey(),[OBJECT_REZZER_KEY]);
    if(llList2Key(details,0) != llGetOwner())//makes sure it was rezzed by an object, and not the owner
	{
        //do stuff if rezzed by object
    }
	else
	{
		//do stuff if rezzed by owner
	}
}

 

  • Like 1
  • Haha 1
Link to comment
Share on other sites

// Comment
// Comment more
// Comment a LOT
// Comment beyond sanity

When "in the moment" code can just flow like water off your fingertips. But 3 years from now when you need to tweak it just that wee tiny bit ... ???

-----------------------------------

Version Management

This is more a management technique than coding, but I think it can be helpful. As I am modifying / developing a script, I will often grab a copy into my Inventory. It helps me recover from those dead-end wild ideas. If I suddenly discover I've gone and done something totally stupid, I can just pull back a saved copy and save myself trying to unwind that "Great Idea!"

I also begin each coding session by adding a new Notecard at the top of the Inventory Folder holding my developing code. I then rename the Notecard something like:

        --- 2017-08-18 -----------------------

I will also sometimes throw version numbers and times into the name. That way I get a good idea what happened when. It provides a handy chronological history of a script's development process.

  • Like 8
Link to comment
Share on other sites

  • 5 months later...

Google is a much under-rated resource, I find.   

When I'm looking for either an example or a discussion of how to do something,  I often find that simply searching for whatever it is, preceded by LSL (so "LSL visitor counter", for example, without the quote marks) provides links to both scripts in LL script libraries and elsewhere and to discussions  here, and in previous versions of this forum and in third-party forums, too.

Related (not script-specific) tip.   Using Google advanced search to restrict your search to the domain https://marketplace.secondlife.com and then applying various filters (to return only entries that include the word "mesh" but not the word "demo", for example) is often far more effective and less frustrating than is using  Marketplace search.

 

  • Thanks 1
Link to comment
Share on other sites

  • 3 months later...

You should also join some inworld groups (probably where you'll get the most help) and visit places that teach scripting. There are many advanced scripters  inworld willing to mentor and advise you on your scripting projects as well as self-paced tutorial courses.

 

Places to visit: 

 

The College of Music, Scripting & Science : http://maps.secondlife.com/secondlife/Horsa/177/244/2165 

Caledon Oxbridge University: http://maps.secondlife.com/secondlife/Caledon Oxbridge/92/198/28

Builders Brewery: http://maps.secondlife.com/secondlife/Builders Resource/128/113/23

 

Groups to join (type these URIs into chat to bring up the group link):

 

The College of Music, Scripting & Science : secondlife:///app/group/fd616ea5-fa9e-1315-def7-4edf25132f09/about

Builders Brewery: secondlife:///app/group/04f595b0-cdc8-97f0-e710-9564824c03b2/about

Advanced Scripters of Second Life: secondlife:///app/group/ff1ad504-e388-b65d-195b-1e474e3e59cc/about

Scripters Support Group: secondlife:///app/group/c4ecb11e-7d7b-26ad-a7cc-6c9da41fbb0b/about 

 

Edited by Gayngel
  • Like 1
Link to comment
Share on other sites

  • 4 weeks later...

Scripts don't run for free, the N°1 reason regions slow down to a croawl (after simply too many avatars) is too many scripts.

  • A single script can do a lot of small tasks quite competently and efficiently, try to avoid using multiple scripts for a task that can be performed by a single one.
  • Avoid using multiple scripts because "it makes things convenient for you", script count adds up very quickly, especially if you are making parcel decorations, try to work with efficiency in mind.
  • If you are a seasoned programmer coming from more advanced languages or object oriented programming, resist falling into your habits, the LSL/Mono compilers are crude and simple, You have to do the micro optimizations yourself, possibly at the expense of readability.
  • Learn to use llSetLinkPrimitiveParamsFast() for all your visual changes and only call it when the changes you make are significant (no 0.0001 changes in transparency/color for instance.)
  • Keep a tight leash on how many listeners you use and close them (llListenRemove/llListenControl) as soon as you have no use for them anymore.
  • Cache data that you rely on frequently rather than requesting it constantly.

 

  • Like 1
Link to comment
Share on other sites

22 minutes ago, Kyrah Abattoir said:

the N°1 reason regions slow down to a croawl (after simply too many avatars) is too many scripts.

No. The other bits of advice in this post are good, but this particular bit of information is false.  Scripts are far from the #2 reason why regions may slow to a crawl. Server resources are allocated in such a way that all other demands are addressed before scripts.  Scripts have the lowest priority on server time.  As a result, avatars, physics, communication, and all other region operations can lag scripts, not the other way around.  Scripts can indeed lag each other when server resources have been drawn down by other demands and there is no spare time left even for scripts.   Also, scripted objects can cause lag, for example by rezzing objects or by managing vehicles or physical objects, but in those cases it is the act of rezzing and the physical objects themselves that are using server resources.  There is no excuse for sloppy or inefficient scripting, which is why most of the other advice is valuable, but region lag is not the primary reason for writing tight, efficient scripts. 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

1 hour ago, Rolig Loon said:

No. The other bits of advice in this post are good, but this particular bit of information is false.  Scripts are far from the #2 reason why regions may slow to a crawl. Server resources are allocated in such a way that all other demands are addressed before scripts.  Scripts have the lowest priority on server time.  As a result, avatars, physics, communication, and all other region operations can lag scripts, not the other way around.  Scripts can indeed lag each other when server resources have been drawn down by other demands and there is no spare time left even for scripts.   Also, scripted objects can cause lag, for example by rezzing objects or by managing vehicles or physical objects, but in those cases it is the act of rezzing and the physical objects themselves that are using server resources.  There is no excuse for sloppy or inefficient scripting, which is why most of the other advice is valuable, but region lag is not the primary reason for writing tight, efficient scripts. 

Allright i might have made a slight hyperbole, I did mention avatars as number one, and laggy objects rarely happen without scripts.

I've seen regions that had performance problems due to an over abundance of individual trees that each had their own script/menu, while they don't do anything most of the time they still eat a sizeable amount of memory and event processing by just sitting there.

Edited by Kyrah Abattoir
Link to comment
Share on other sites

On 14 May 2018 at 4:05 AM, Kyrah Abattoir said:

the N°1 reason regions slow down

On 14 May 2018 at 6:04 AM, Kyrah Abattoir said:

and laggy objects rarely happen without scripts.

Actually the biggest hit on sim performance in many laggy objects isn't that they are scripted, but that they are either set physical, or even worse, set to use pathfinding in the script they have, on sims where the thousands of prims in hundreds of linksets have not been optimised into the pathfinding navmesh bake.

A single pathfinding scripted prim critter, can add 7-9 ms of physics time to a sim as it bumps it's way around obstacles, that drops script time by 7-9 ms and leads to a low low % figure for scripts run, and thus laggy menus, vendor systems, etc.

People experiencing the lag look at the % of scripts run and assume "too many scripts" when in fact it's ONE script doing something stupid.

A couple pf pathfinding prim ponies constantly crashing into the wall of a prim barn can lag a sim to death and drop Sim FPS/Physics FPS to dreadful levels, like swimming in molasses in wintertime.

As for masses of scripted trees, while I can agree that most trees don't need any damn scripts, if the scripts are compiled in mono, they are far less serious than old school non-mono lsl.

It's what IBM Mainframe operations staff refer to as "single requester terminal" programs vs "multiple requester terminal".

Old lsl is SRT... Every user of that script is running their own copy. so 50 trees, 50 single requester scripts, while mono is MRT, ONE script with 50 copies of the data, it eases the load.

A bigger issue with such trees as far as perceived client side lag is the damn alpha blend on their leaves and on the damn particle blossom fall etc.

In addition... memory reporting isn't as useful as it was way back, SRT style lsl, reports actual memoryt allocated and theoretically used, but MRT style mono lsl reports a standard 64kb figure even if it's NOT using that, script cpu time is far more relevant.
 

  • Like 2
Link to comment
Share on other sites

Scripted trees are a good example of use of MRT (since they are typically shift copied around) but that's the one big example I can think of where it works well in SecondLife, and you lose the MRT benefit as soon as you recompile that script I believe.

Link to comment
Share on other sites

  • 4 weeks later...

I've probably said it before, and I'll probably say it again, but I think the best advice for anyone, new or old to scripting, is to make a habit of reading the wiki.

I've met several people this week who had scripting questions for me, and when I mentioned finding the answer on the wiki, they had no idea it even existed.

It's strange to me, because in my world, if it exists, there's a wiki for it, and to know how to do it, you read the wiki. In most of the online communities I've participated in, "Read the wiki" has been almost a cliche. If there isn't a wiki, at least there's a forum, but can you believe it, there are people in SL who not only do not know of the existence of the wiki, but also do not even know this forum exists.

I advise anyone who reads this forum to put the wiki on speed dial, seriously. I also agree with Innula on Googling. Knowing how to use Google properly is what separates the tech-savvy from the... um, non-tech-savvy (I once made $20 an hour at an IT job, and my entire job was Googling for people who didn't know how, basically).

  • Like 2
Link to comment
Share on other sites

What Berksey said - and start using llOwnerSay a lot if you do not understand what it does in specific moment: make it talk to you about what was before and what is after whatever was happening. Output to screen is the first debug tool you should ever learn - in fact you usually are tought using it so early you do not even consider it a degug tool at all in a regular programming course - nevertheless it is the most often used one and works across all languages.  (well it has other uses too oustide of debugging of course, so no, it is not a purebreed debugging tool)

Edited by Fionalein
  • Like 2
Link to comment
Share on other sites

Good scripters use diagnostic messages a lot.  It's a cheap way to keep your sanity while building a long script.  Test individual calculations and operations as you go, just to be sure that they yield predictable results.  Rather than using llOwnerSay, however, I tend to use a homemade message generator:

string debugSay( string m)
{
    if (iDebug)
    {
        llRegionSayTo( ME, TEST_CHANNEL, m);
    }
}

Then I define three global variables:

iDebug = TRUE;

ME = my_own_UUID_goes_here;

TEST_CHANNEL = 0;   // Or maybe a high negative number so I can redirect messages to some relay object if I want.

Then I can pepper my script with statements like 

debugSay("The value of iCount here is " + (string)iCount);

This method has a couple of advantages over llOwnerSay. The biggest one is that I can turn diagnostic messages on/off any time I want, and can leave any debugSay statements in my final script. I can send diagnostic messages to a nearby talking box or to a wearable prim so that my alt or other people can hear them, if I want.

I have to give my friend, Innula, most of the credit for showing me how flexible this approach can be. 

  • Like 5
Link to comment
Share on other sites

17 minutes ago, Rolig Loon said:

Good scripters use diagnostic messages a lot.

You bet!

Back when I worked for a living, I was infamous for my use of debug messages and logs. The prototypes of some of my designs contained extra memory and faster processors to allow for debugging overhead.

It's a shame that LSL doesn't have conditional interpretation, allowing unwanted debug code to be ignored. "if(iDebug)" doesn't take much time to execute, but it does take time and the debug code takes script memory. In the world where I worked, there were "preprocessor" variables that controlled how the compiler handled various statements. If I'd made "iDebug" a preprocessor variable rather than a program variable and set it to FALSE, the compiler would ignore the block and no code would be generated for it at all. If "iDebug" were TRUE then the code would be generated and no test for its value was necessary. It's no longer a matter of deciding whether to execute debug statements as the program runs, they're either in the program or they aren't.

Having easy control over the presence/absence of debugging code encouraged me to use it liberally. I also used logs (often nothing more than arrays) to track program flow when there was no time to issue messages. A post-mortem analysis revealed the errors. Many of us are familiar with digging through pages of logs to find the place where everything starts to go wrong. Sometimes I wrote little programs to scan the logs for me, sometimes while the main code was running. It was a great came of cat and mouse, where both animals were of my creation.

I also had a nifty text editor that wouldn't even show debug code if the controlling preprocessor variable was FALSE. It was not uncommon for my debugging code to be longer than the stuff it was debugging, and for nearly every other line of code to be for debugging. With the change of a preprocessor variable it all went invisible, revealing nothing but the beauty of the code I'd stumbled into by dint of perseverance and debug messages. I imagine there are such text editors, suitable for LSL scripting, that could strip away debugging statements with the click of a variable.

 

  • Like 2
Link to comment
Share on other sites

Make the parameter of your debug function a list and output that list as CSVs. This saves a lot of effort casting all the different types of variables and literals when you call the function.

Debug (list values)
{
    llOwnerSay ("Debug: " + llList2CSV (values));

}

You can now chuck in whatever strings, floats, vectors, etc., etc. you like, in whatever order you like.

Debug (["Some state, some event", "my vector", my_vector, "my integer", my_integer, "my list"] + my_list + ["the end"]);

  • Like 4
Link to comment
Share on other sites

On 6/10/2018 at 8:27 PM, KT Kingsley said:

Make the parameter of your debug function a list and output that list as CSVs. This saves a lot of effort casting all the different types of variables and literals when you call the function.

Debug (list values)
{
    llOwnerSay ("Debug: " + llList2CSV (values));

}

You can now chuck in whatever strings, floats, vectors, etc., etc. you like, in whatever order you like.

Debug (["Some state, some event", "my vector", my_vector, "my integer", my_integer, "my list"] + my_list + ["the end"]);

This is exactly what I do, sans the custom function. 

I have an automatic snippet in my text editor which lets me type "os" and press Tab, which gives me "llOwnerSay(llList2CSV([]));" with the caret placed between the list brackets. 

  • Like 2
Link to comment
Share on other sites

  • 3 months later...

A lot of what I would say is very much akin to any other good programming practices.

Keep your code clean, use the same syntax and styling throughout, name your variables and functions so they are understandable, comment where necessary but not excessively.

One great way to keep consistency is to re-use the same script base, you can set your default create cube to have an embedded inventory item on creation (at least in firestorm).

img.png.9f88ebc687e670f2d205312310c719c4.png

So I generally add my own script with my standardization I use across every script so every event has the same variable names and it and some of my most used functions there ready to go.

Debugging is important, my debugging is usually included in its own custom function so I can toggle it on and off and during clean up it's easier to find/replace/delete for when I'm done with it.

When communicating between objects I highly recommend using llRegionSay(); and llRegionSayTo(); the majority of the time as it's the fastest out of all the communication methods. Also generally use negative channels.

The LSL wiki is your friend.

Don't forget to save, you never know when SL is going to blow up, again. (or net/power outages)

  • Like 2
Link to comment
Share on other sites

  • 3 weeks later...

I suppose it's ok to reply to a several months old post in this particular thread.

On 5/14/2018 at 5:50 AM, Rolig Loon said:

Scripts have the lowest priority on server time.  As a result, avatars, physics, communication, and all other region operations can lag scripts, not the other way around.

I'm beginning to think it's time to do a reality check to see if that is still true.

A friend of mine who runs a club/mall sim told me of an incident when a visitor turned up wearing several hundred scripts and the sim eprformance immediately dropped to a crawl. Once the script wearer was evicted, it returned to normal. I also remember an incident a while ago when another friend of mine who is a very good scripter (no name given and she's left SL anyway) managed to lag down her home sim with a single script. She did it on purpose to get rid of a bothersome neighbour...

Recently I've seen on several occasions sims running (or creeping) with frame times well into the forties and fifites and even hundreds and still with two digit script time figures.

Link to comment
Share on other sites

As with anything we can say about performance in SL, there are edge cases that we can point at as counter-examples.  It is certainly true that people entering a region while wearing or carrying a lot of scripted items will demand server resources to get them running, even if only in the background.  That effect is well-documented and can be non-trivial.  It's like the effect of bringing any new asset into the region, whether it's a new-rezzed object, a vehicle crossing a region boundary, or an avatar.  It's also transient. Unless the region has a steady influx of new assets, these are not making a measurable difference to long-term performance.  That's not to argue that RP regions and heavy shopping regions, for example, shouldn't worry about people entering with a ton of scripted stuff.  For them, even transient spikes are annoying.

It's also true that a script can do things that create lag, even if the script itself isn't.  The most obvious is a rezzer which, by its nature, causes a brief demand on server resources.  Even an amateur griefer can bring a region to its knees by writing a self-replicating script that fills the region with garbage prims.  Scripts that facilitate physical movement make work for the physics engine too.  It all piles up.  It may be nitpicky to argue about whether the script itself is causing a drop in region performance or whether it's the things that are created and moved by the scripts that do it, but from a scripter's perspective that's an important distinction.  The fact remains that when system resources get tight and free time disappears, the servers grab time from script first, so script time is capped even as physics time and other demands increase.

  • Like 3
Link to comment
Share on other sites

  • 2 weeks later...

Scripts also compete for time with eachothers and unfortunately I don't think Scripts owned by landowners get any priorities over scripts owned by visitors.

When I travel around I see a lot of regions that only reports executing 1% to 20% of the total script events during this frame. And yeah it doesn't affect avatars, but it can disrupt "legitimate" (lets use that word) scripts that perform time sensitive operations.

Edited by Kyrah Abattoir
  • Like 1
Link to comment
Share on other sites

On 10/10/2018 at 4:45 PM, ChinRey said:

I suppose it's ok to reply to a several months old post in this particular thread.

Yes, that’s what this thread must be for, not just “tips” but discussion. I could swear some posts were added from other threads to this one..

Edited by Love Zhaoying
  • Like 1
Link to comment
Share on other sites

  • 1 month later...

I write my scripts using an offline editor.  Before i even start writting the code i write a proceedure of events in plain English first. Keep it simple and tidy, one can use a better method later on parts. It is easy to improve sections when new methods are learnt later when the section does what it is supposed to do. I wrote fifty lines of functions moving a box a bit at a time in the early days until i learnt counting loops. It may have looked totally dumb but it ran as intended. And at the end of the day that is all a counting loop does anyway.

A person mentioned comments in the code and years later. Well the code should be polished enough and easy to understand not to need hardly any when running correctly. 

The one thing that does still catches me out is inbuilt function delays. I had a headache with that issue recently. Something so simple can really do ones head in.

Link to comment
Share on other sites

  • 3 months later...
On 12/15/2018 at 10:47 PM, steph Arnott said:

A person mentioned comments in the code and years later. Well the code should be polished enough and easy to understand not to need hardly any when running correctly. 

You ended up pointing out an excellent reason for why it's a smart idea to comment on what pieces of your code do....

Quote

It is easy to improve sections when new methods are learnt later when the section does what it is supposed to do.

New functions are added all the time that replace the old way of doing things.  Documentation gives the creator a clue to what all those lines actually do years later, after they've gotten into the habit of using new functions like llSetAnimationOverride, llSetRegionPos, llGetObjectDetails(agentKey, OBJECT_BODY_SHAPE_TYPE), and llSetPrimitiveParamsFast to replace blocks of obsolete code, timers, and outdated user created functions they may have included in their code years ago.

Our writing style changes too, depending on mood, circumstances, and time...whether it's writing a term paper, or recreating a board game in LSL.  Hammering out 6 of 12 pages of a history paper the night before it's due is going to have an effect on recall when we reread it a month or a couple of years later.  The same is going to happen during a crazed self-imposed deadline in getting a complex script to do what we need it to do.  That "oh, yeah...that was pretty cool, I forgot I did that" or "what was I thinking" reaction.  Documentation does a pretty good job of walking us through the fog.

Link to comment
Share on other sites

  • 9 months later...

Here's a way of distinguishing between an attach event triggered by attaching from inventory and one triggered on login:

    attach (key id)
    {
        if (id) //is this an attach? (as indicated by a valid non-null key)
        {
            if (llGetColor (1) == ZERO_VECTOR) //is face 1 coloured black?
            {
                llSetColor (<1.0, 1.0, 1.0>, 1); //restore face 1 to its normal colour
                //attached from inventory
            }
            else
            {
                //attached on login
            }
        }
        else //or a detach?
        {
            llSetColor (ZERO_VECTOR, 1); //colour face 1 black
            //normal detach, not triggered by logging out (but see below)
        }
    }

Note that the wiki entry for the attach event very sensibly points out that currently logging out does not trigger the attach event will a null id, but that scripters should anticipate the possibility that this might not alway be the case. I have very sensibly ignored that advice here.

In this example I'm using a face colour to flag a detach, but there's any number of other prim parameters that could be used instead. When an object is being detached you can usually squeeze in a couple of lines of simple code that'll execute fairly reliably before the script stops running. My experience (and a brief test) suggest that any such code not executed at the time of the detach will pick up again when the object is reattached, and do so before the attach event is triggered with its owner's key, so this should still work even if the flagging code doesn't actually execute at the time of the detach.

It used to be the case that calling llGetAgentSize would return ZERO_VECTOR for a few moments immediately after login, but having just tried to use that method I found it not to work, hence this alternative.

  • Thanks 1
Link to comment
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...