A long time ago, I posted a script system to make butterflies appear when the sun came up in SL, and disappear when it went down. The system consisted of a script to place in some copy/mod butterflies available on the marketplace, and a script to rez them and delete them at the appropriate times.
In the nine (!) years since I posted those, things have changed. As a naïve scripter back then, I didn’t think about co-ordination between the script in the rezzer and the script in the butterflies. The scripts needed to communicate because back then, the only piece of information you could pass to a rezzed object was an integer. Because the butterflies need a position to move to after being rezzed, they established a communication channel using the integer so that the rezzer could pass the butterflies a position vector, and also pass them a “delete yourself” command.
Usually, this just worked. But as the computers that run the simulator code have become faster, the potential co-ordination issue became more apparent, and Linden Labs even came out with official advice to scripters as to how to perform proper communication co-ordination. The link to the official advice seems to have disappeared from the Lab’s blog, but the example scripts have been incorporated in the object_rez documentation if you want to read about how to do co-ordination properly.
As you might have guessed, I wrote the scripts for myself, and posted them on the blog because, well, LSL is one of my passions in SL. I don’t sell the system, and I neglected to update the scripts in my in-world system (and on this blog) to follow the Lab’s advice.
So, this article updates the scripts, and having just talked about communications co-ordination, eliminates the old way of passing data to a rezzed object by using new functionality introduced by the Lab in the last twelve months.
These changes are new LSL functions, llRezObjectWithParams (), llGetStartString (), and llDerezObject (). These were mostly introduced to help people making combat systems, but they can completely remove the need for the scripts to do communication via the listen event on rez, thus removing the potential co-ordination issue.
Let’s dive right in to the scripts. You can ignore the debug.lsl and profile.lsl and associated stuff in the following, or click the links to get the included code.
First, here’s the new script to place in the butterfly object that will be rezzed.
#undef DEBUG
#include "debug.lsl"
#undef PROFILE
#define MEMLIMIT 6000
#include "profile.lsl"
default {
on_rez (integer s) {
init_profile ();
if (s != 0) {
vector pos = (vector)llGetStartString ();
llSetRegionPos (pos);
llRemoveInventory (llGetScriptName ());
}
show_profile ("");
}
}
This got significantly simpler. Now, if the object is rezzed by the rezzer (s is not equal zero), then the script gets the start string (which you’ll see in the next script), interprets it as a vector, moves to the position specified, and deletes itself (as once the object is moved, the script has nothing else to do).
Here’s the rezzer script:
#undef DEBUG
#include "debug.lsl"
#define MEMLIMIT 16000
#undef PROFILE
#include "profile.lsl"
// To rez and derez immediately the sun comes up or goes down,
// #undef IGNORE_TWILIGHT
#define IGNORE_TWILIGHT
integer g_nc_line;
string g_nc_name = "config";
key g_nc_id;
integer g_pos_count;
list g_positions;
list g_inv_objs;
integer g_obj_count;
list g_rezzed_objs;
integer g_prev_sun = -1;
integer sun_up () {
// Return true if the sun is up, false otherwise.
vector sun = llGetSunDirection ();
integer result;
#ifdef IGNORE_TWILIGHT
if (llFabs (sun.z) < 0.1) { return FALSE; } else { result = (sun.z > 0);
}
#else
result = (sun.z > 0);
#endif
return (result);
}
default {
on_rez (integer n) {
llResetScript ();
}
state_entry () {
init_profile ();
llSetObjectDesc (VERSION);
g_inv_objs = [];
g_positions = [];
g_pos_count = 0;
g_obj_count = llGetInventoryNumber (INVENTORY_OBJECT);
if (g_obj_count == 0) {
llOwnerSay ("There are no butterflys objects in the inventory!");
return;
} else {
integer i;
string name;
for (i = 0; i < g_obj_count; i++) {
name = llGetInventoryName (INVENTORY_OBJECT, i);
if (llGetSubString (name, 0, -2) == "butterflys") {
g_inv_objs += name;
}
}
}
g_obj_count = llGetListLength (g_inv_objs);
g_nc_line = 0;
if (llGetInventoryType (g_nc_name) == INVENTORY_NOTECARD) {
g_nc_id = llGetNotecardLine (g_nc_name, g_nc_line);
} else {
llOwnerSay ("Notecard " + g_nc_name + " not found - stopping");
return;
}
}
dataserver (key id, string data) {
if (id == g_nc_id) {
if (data != EOF) {
if (llGetSubString (data, 0, 0) != "#") {
g_positions += (vector)data;
}
g_nc_id = llGetNotecardLine (g_nc_name, ++g_nc_line);
} else {
g_pos_count = llGetListLength (g_positions);
llSetTimerEvent (0.1);
}
}
}
timer () {
llSetTimerEvent (0.0);
integer sun = sun_up ();
if (sun != g_prev_sun) {
if (sun) {
// Sun is now up, rez
integer i;
integer r = (integer)llFrand (g_obj_count);
string which;
for (i = 0; i < g_pos_count; i++) {
which = llList2String (g_inv_objs, r);
llRezObjectWithParams (which,
[REZ_POS, <0.0, 0.0, 0.5>, TRUE, FALSE,
REZ_PARAM, -1,
REZ_PARAM_STRING, llList2String (g_positions, i)]);
}
} else {
// Sun is now down, derez
integer i;
integer n = llGetListLength (g_rezzed_objs);
key id;
for (i = 0; i < n; i++) {
id = llList2Key (g_rezzed_objs, i);
debug ("derez " + (string)id);
llDerezObject (id, DEREZ_DIE);
}
g_rezzed_objs = [];
}
g_prev_sun = sun;
}
llSetTimerEvent (60.0);
show_profile ("");
}
object_rez (key id) {
g_rezzed_objs += id;
}
}
The most important change here is the call to llRezObjectWithParams (). Note the we are passing -1 to REZ_PARAM, which is how the new function passes the integer, and we are passing a vector with the REZ_STRING_PARAM.
I also made a few other changes, including only performing actions when the sun changes (from up to down or down to up). Additionally, I wanted to offset the time to exclude twilight hours. If you like the old behavior, you can implement it by undefining IGNORE_TWILIGHT. Oh, and the config notecard is now mandatory, and you need to specify all the positions, including the one that used to default to directly over the rezzer.
Lastly, here’s a link to the butterflies on marketplace. They are only L$10 🙂




