Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

I am interested in scripting but the lang looks indeciphrable.

Nomaken Horus
Second Life Resident
Join date: 16 Oct 2004
Posts: 1
02-18-2005 05:01
Can someone direct me to a guide to scripting for total clueless idiots? Because i am totally clueless and have never touched a programing languaged before. I want to make moving objects. The object crafting thing looks pretty intuitive but the programing language went right over my head.

I have the idea in my head that it might be possible to make an extremely complex object/script in order to make a bot which mimics a player. And i know just jumping into scripts is like trying to fly before you can crawl but it seems like i'm just not understanding something key which would make the programing lanaguage understandable.
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
02-18-2005 05:18
Here are some tips:

LSL (Linden Scripting Language), like many other high-level languages, is made up of just a few main concepts. I will try to describe them in installments (as time permits).
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
1) Comments
02-18-2005 05:20
Comments are lines prefixed with double-slash ( // ). Here is an example:

CODE

// this is a comment


The double-slash may appear almost anywhere, and anything after it on the same line will be ignored by the compiler, and some humans. :)
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
2) Values
02-18-2005 05:28
Values (variables, "constants", literals, etc):

variable -- has a name, has a value, value can change
constant -- has a name, has a value which is fixed -- in LSL, you fake a const by using a variable, and not changing its value
literal -- an actual value that can be assigned to a variable, or used as an argument (you'll get to this in a sec)

Values have a type as well: integer, string, float, are three types; you can find more in the help file.

Examples of usage:

Declaring a variable:
CODE
integer score = 0;
string loginName;

The initial (or default) value of 0 has been assigned to a variable called score of the type integer. The default value of the variable is optional. Some languages offer implicit default values (usually 0 for integers, empty (as a concept) for strings, etc). It's generally intuitive, if supported. The variable loginName of type string is declared, and is probably empty by implicit default.

Declaring a constant:
CODE
integer MAX_MOVES = 10;

It's a good idea to identify constants in a different style than variables, so give a visual reminder that they are not to be modified. I use all-caps, usually. Note, a default value is specified, and it is hoped that this value will not change at runtime.

Using a literal:
CODE
loginName = "testuser";

Here, loginName from our earlier example is being re-assigned to contain the literal string "testuser". So, "testuser" is a literal.

For more details on the types, and their limitations, see the documentation.
Eggy Lippmann
Wiktator
Join date: 1 May 2003
Posts: 7,939
02-18-2005 05:35
The language is pretty standard C/Java syntax.
If you've never programmed anything in your life, the learning curve is steep.
If you have, you shouldn't have much of a problem adjusting.
A fake avatar will be very hard to pull off. Any sort of animated object will.
The reason for this is that we dont have hierarchical linking, and so cannot move/rotate a subset of an object's primitives. We can only do one at a time.
Plus LSL is slow =)
There isn't much of a point in going the hard way about it, since the new physics engine will have support for ragdolls, and I'm sure LL would love to expose it :)
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
3) Code blocks
02-18-2005 05:36
A code block is a well-formed sub-piece of a program/script. In LSL, it is enclosed in curly braces.

Example:
CODE
if (0 == 1)
{
// this could never occur! if it does, shoot me!
llWhisper(0, "houston, we have a problem.");
}

Notice that the block contains a comment and a function call. We are passing two arguments to the function llWhisper, enclosed in parentheses, namely the 0 (an integer literal), and "houston, we have a problem." (a string literal), respectively.

You may declare variables inside a code block, and they will be useable within that block or sub-blocks inside it. Outside the context of that block (called "scope";), things are not meaningful. So this is nonsense:
CODE
if (0 == 1)
{
// this could never occur! if it does, shoot me!
integer x = 0;
llWhisper(x, "houston, we have a problem.");
}
integer oldChannel = x;

When we try to assign the variable oldChannel the value of x, we notice that x is no longer in scope, so we'll get an error. If we had declared x outside that block, in the parent block (which is implied), it would be okay.
Rhombur Volos
King of Scripture & Kebab
Join date: 6 Oct 2004
Posts: 102
02-18-2005 06:01
A generous wave of applause to gene Poole for showing such enthusiasm in helping the newcomer tho :)
Treacly Brodsky
Pixel SLinger
Join date: 23 Jul 2004
Posts: 186
Kudos
02-18-2005 07:17
Please keep it up Gene :D I need as much help as I can get as well!!!


(GMF99)
_____________________
Meatwad Extraordinaire
Nomnomnom
Join date: 6 Aug 2004
Posts: 545
02-18-2005 07:52
Here ya go. This website taught me almost everything i know (except for Jia's classes and my friends... Thanks Guys :D):

http://www.tyrellcorporation.org/disabled/HomePage

They have eerything there and a tutorial with the most basic things in it!
_____________________
Rhombur Volos
King of Scripture & Kebab
Join date: 6 Oct 2004
Posts: 102
02-18-2005 07:59
Better to use http://www.secondlife.com/badgeo , as it is hosted at secondlife.com and probabvly slightly less vulnerable to malicious attacks than the last host, and therefore a bit more stable.
Hank Ramos
Lifetime Scripter
Join date: 15 Nov 2003
Posts: 2,328
02-18-2005 08:11
Plus http://secondlife.com/badgeo is continuously updated. The one at the other site is a very old copy of the LSL Wiki.
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
4) Functions
02-18-2005 14:08
A function, in general, does some work, and returns a result. In LSL, as in C, a function can return a meaningless result -- in C, this is called void, in LSL, it's left blank. Pedants will say that a function that doesn't return a result is actually a procedure, but we won't get too worried about that. ;)

Anyway, here's an example function in LSL:
CODE
integer sum(integer a, integer b)
{
integer result = a + b;
return result;
}
Here we see the basic layout of a function: it's calling convention (that is, the name of the function, how many arguments (AKA parameters) it takes, in what order they appear, what their types are, and how they're identified), sometimes also called a prototype, followed by a code block (which of course, can contain sub-code-blocks).

Now, there are a few abstract ideas to get down:

1) A function can, inside of its code, call another function. Program flow in the caller stops temporarily, and control is passed to the function being called; when it returns, flow continues after the call.

Example:
CODE

integer negate(integer x)
{
return x * (-1); // efficiency is not our chief concern here ;-)
}

integer difference(integer a, integer b)
{
integer negB = negate(b);
integer result = a + negB;
return result;
}
So, here, when you call difference with two numbers, first, the second argument (b) has its value passed to negate, which takes control, and negates the value passed to it, then returns the negated value of b. Control returns to the difference function, and the result is stored in negB. Then, we add the two operands again. Adding a negative is equivalent to subtracting, so the difference function really does compute the difference between the two original arguments (a and b). Fantastic!

2) A function can take almost any number of arguments, including none:
Example:
CODE

doNothing()
{
// takes no arguments, and does nothing, and returns nothing -- what a waste!
}


3) Arguments passed into a function are copies of values, and can be modified with no effect on the caller (note: this is specific to LSL, not programming in general).

Example:
CODE

// assume we have the negate function from before already defined

integer foo()
{
integer q = 1;
integer negQ = negate(q);
// what is the value of q now? that's right, still 1 -- can you explain why?
}
The variable q is still 1 because a copy of its value was passed to the negate function, so when the negate function modified its argument, it didn't modify q, but rather a copy of the value that q had when the function was called. This is a very important concept. If you do not understand it fully -- I mean crystal clarity -- ask someone in-world (IM me or another scripter) to explain it better. Most problems students have in learning are not caused by their lack of capability, but by poor teaching. ;)

Okay, now you might be thinking "great, now I have to implement all kinds of basic functions before I can even get to real scripting," and if so, cheer up. There are many, many useful built-in functions, and almost all of them begin with double-lowercase-ell (ll). You can call these functions to determine where your avatar is, to change the colour of a prim, and much more. You will find a great resource for these functions (as mentioned earlier) here:

http://secondlife.com/badgeo/
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
5) Events
02-18-2005 14:21
LSL is a modern language, and as such, it supports event-driven programming. This simply means that instead of having to write a program that anticipates all possibilities, it can react to things as they occur.

There is a special class of function called an event handler (may have other common names too). Normally, a program is a main (entry) function which in turn calls other functions, and runs in a fairly linear fashion. When you have event-driven programs, however, things can happen out of the blue, and interrupt your program flow. This is actually a good thing. Think about it like this:

Suppose you are reading a good book, but you want a cup of tea to sip while reading. You have at least two ways to manage this:
1) Put the book down, put the kettle on, and watch it until it boils (it never will until you look away, you know ;)), make your tea, pick up your book, and enjoy.

2) Put the book down just for a moment, use a whistling kettle, put it on, and resume reading. Once it boils, you interrupt your reading just for a moment to make the tea, and then you can read and sip.

You can probably agree that option 2 is better because it allows you to keep reading while the water is coming to a boil, instead of staring balefully at the kettle until steam is shooting out of it.

If you were to translate this situation to a programming frame of mind, the kettle boiling would be an event, and you would have an event handler that would be called when the boiling event occurred. Simple, no?

Usually, you have to set up an interest in the event to be notified of it. In the case of the kettle, you tune your ears to the whistling sound, and when it happens, you notice.

In LSL, there are a bunch of events you can watch for, and react to. See the Wiki (again, it's at http://secondlife.com/badgeo/ ) for a list of the events and more details.

One very simple event in LSL is the timer. You can set up a timer event, and every x seconds, the timer event handler will be called. Thus, you could make a script that does something on the hour, or whatever. If you want to learn about events practically, however, I recommend you start with touch_start. Lucky for you, it's part of the default code that is added when you create a new script for an object. ;)
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
6) Statements, conditionals (meat and potatoes 1)
02-18-2005 14:32
Now we get to the part of programming that actually accomplishes something -- the logic. Everything else is more of a framework to allow us to describe the organization of the code, more or less.

Fundamentally, a computer program takes input, make a decision based on some conditions, and produces output. Often that output is fed right back in for further decision-making.

Let's take a look at a simple, yet non-trivial, conditional block:
CODE

// assume x is an integer
if (x < 0)
{
x = 0;
}
else if (x > 9)
{
x = 9;
}
Can you guess what this chunk of code is trying to do? That's right, it's bounding x to be between 0 and 9. It's very much like English, isn't it? Once the symbols become more familiar to you, it will be easy to read the code, and write your own. Notice something new -- the else keyword. If the first condition fails (that is, if x is not less than zero), then control is passed to the other conditional. Makes sense?

Right, so, basically, many scripts will figure out where things are, what colour they are, how big they are, etc, and change some of those things. For instance, if you build a security door, it will "watch" or "listen" for a command from an avatar, and then it will react by modifying its position or rotation to allow you passage. Naturally, it's going to need some conditionals -- it might check if the command came from the owner, or just some random passerby. Or it might check if it's already open. You get the idea.
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
7) Loops, typecasting (meat and potatoes 2)
02-18-2005 14:49
Okay, so far, you've learned a fair bit, and with a bit of practice and effort, you can make a bunch of simple scripts already. But most of those scripts will just be reactions to things, without much sophistication. If you want to make more powerful scripts, you'll need to consider loops.

Looping is quite simple, really. It just means a block of code is repeated several times, and during each iteration, small changes take place in what happens. You already know how to run loops in real life. Try counting from 1 to 10 out loud. In effect, you're looping from 1 to 10, and on each iteration, you're saying the current number out loud, then incrementing that number. When you reach 10, your memory tells you (hopefully) that you are to stop at 10, and so you do. You're doing the same action again and again (saying something out loud), but each time, what you're is changing.

One of the simplest loops is the for. It basically says "for each value of this variable in the given bounds, do something".

Example:
CODE
integer i;
for (i=0; i < 10; i++)
{
llWhisper(0, "i has value " + (string)i);
}


What do you suppose happens here? That's right, the object will whisper 10 times, first saying "i has value 0", then "i has value 1", until it says "i has value 9". There are other types of loops, and you can read more about them on the Wiki under "FlowControl".

Now, you probably noticed the weird (string)i. This is called typecasting. Remember that functions take arguments by type, and sometimes you have a number (eg. integer), and you want to pass it to a function that takes a string. To convert it, simply put the desired new type in parentheses in front of the variable. A temporary copy of its value will be converted to the type you want. So, I know that llWhisper takes a string as its second argument. I typecast the integer i to a string, and then concatenated it with (tacked it onto) the literal string "i has value ".

Is it always possible to typecast one thing to another? Probably not. For instance, there is a type called vector, which is an aggregate (group) of 3 floats. Does it make sense to typecast a vector to a single float? Nope. How could one number represent three distinct ones? That's nonsense (simply speaking). However, a vector variable could be rendered as a string, right? So, that's fine. In fact, almost everything can be typecast to a string.
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
8) States
02-18-2005 15:06
Have you ever heard of a finite state machine? Well, it's just a fancy way to say that programs can behave differently depending on what state they're in, and that there's a limited number of states that a program can be in. Never mind the fancy terminology, it's really quite simple. :)

Let's take a real-world example again. A human can be said to have two main states -- awake, and asleep (or unconscious). When awake, a human will react to various stimuli in a particular way. When asleep, the very same stimuli might produce a different reaction. Yes, you guessed it -- the stimuli can be thought of as events, and the reactions as event handlers.

In LSL, there is a default state, and then you can define your own additional states. A script when saved always resets to the default state. When a state is entered or exited, the state_entry and state_exit event handlers, respectively, are called. States are named, then followed by a code block.

Here is how a simple human might be programmed in LSL, supposing we could make up our own additional events/event handlers:
CODE
default // the "birth" state :-)
{
state_entry()
{
llWhisper(0, "I'm alive!");
state awake;
}
}

state awake
{
state_entry()
{
open_eyes();
}

on_hunger_pangs(integer starving)
{ // called when stomach growls (not a real LSL event)
eat();
}

on_getting_sleepy(float energyLeftPercentage)
{ // called periodically (not a real LSL event)
llWhisper(0, "*yawn*");
if (energyLeftPercentage <= 0.10)
{
state sleep;
}
}
}

state sleep
{
state_entry()
{
close_eyes();
llSetTimer(60*60*7); // set timer for 7 hours
}

on_hunger_pangs(integer starving)
{
if (starving == TRUE)
{
state awake;
}
}

timer()
{
state awake;
}
}


Notice that our fake event "on_hunger_pangs(integer starving)" behaves differently depending on our state. If awake, we eat whenever we are hungry. If asleep, we wait until we are starving before waking up.
I've left out the "llSetTimer(0);" to keep it simple -- hardcore scripters can argue about this one endlessly if they like ;)
Also, you'll notice that we don't have to implement a handler in each state; we can ignore the events if we like.

Many scripts won't need anything other than the default state, and you can make your own state-indicating variable as an alternative -- but the support is there, so if you need it, use it. ;)
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
9) Other assorted stuff
02-18-2005 17:54
Some general tips/hints:
  1. When you save a script (which is inside an object), it automatically resets and enters the default state.
  2. It is possible to have more than one script in an object, and all can run simultaneously.
  3. One object cannot directly modify another, even if linked. You will need to implement a control protocol using the communications functions (link messages, or llSay/llListen on a special channel) to control the objects.
  4. When using llListen, try to think about how it can be used most effectively, and most efficiently. There are discussions on the forum about it. Check 'em out.
  5. There are many ways to do cool things by using functions in ways they were not originally intended. This is an art, of sorts. Think creatively.
  6. Comments are not bad, but good code needs few (if any) comments. ;)
  7. First write your code for functionality and readability/expandability. Then worry about optimization.
  8. Don't forget to check for appropriate permissions when applicable.
  9. Remember that objects can change ownership while scripts are running. Make sure your scripts can handle this. There are other subtleties to consider as well. Try to be as thorough as possible when designing.


Other scripters are encouraged to add to the tips/share their secrets.
Eloise Pasteur
Curious Individual
Join date: 14 Jul 2004
Posts: 1,952
02-19-2005 02:50
Thank you Gene!

I don't think you've taught me anything new (I've been beating my head against LSL for 6 months now and something went in!), but I wish this had been there to start with. Can we petition to add it to the LSL Wiki please!

Some tricks - don't overlook the value of llSay() as a piece of error checking. If something isn't working quite how you expected it, some well thought out 'says' can tell you what is actually happening.

Like anything else planning helps. So does smart naming your variables. If you can, test in chunks. This gets harder and harder with bigger pieces of code and more complex operations, but you can often write little bits of code and then build them up into bigger and bigger sections.

Like any other coding environment when you find a good piece of code keep it! The first time I started handling lists it was clunky and horrible. Gradually I evolved a piece of code that is far from perfect (and how I wish I'd read llListGetList() now it needs rewriting!) but that works really quite efficiently. Suddenly it is being used in several other pieces of code that handle lists that I've written.

The hard one is to know when to adapt and when to write from scratch. I still get it wrong! But generally adapting code, or at least looking at code for something you have that is similar helps quite a bit.

Ask here, flick through the script library as well - there is a lot of scripting out there that people share freely, that might do what you want. If you see someone that has something doing something you want ask them for help anyway, most people in SL are friendly and will help, or if you are not going to sell it may give you their script directly.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
02-19-2005 05:41
Eloise Pasteur you are welcome to add it to the wiki. Thats what wiki's are for. Just create a username on the wiki and you can add and edit pages.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Eggy Lippmann
Wiktator
Join date: 1 May 2003
Posts: 7,939
02-19-2005 06:35
Dude, you sure have a lot of time on your hands :O
Congratulations on having the patience and energy to write this up.
From now on I will refer noobs to this thread :)
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
02-19-2005 12:03
From: Eloise Pasteur
Ask here, flick through the script library as well - there is a lot of scripting out there that people share freely, that might do what you want.

In addition, check out the script library on the wiki, it has a few things not in the forums script library.
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
02-23-2005 06:37
All of my rambling can be found here...

http://secondlife.com/badgeo/wakka.php?wakka=CrashCourse

...nd it will contain updates/improvements. This thread can now be considered a relic. :D