Showing posts with label hintstips. Show all posts
Showing posts with label hintstips. Show all posts

Sit a spell. Or don't

A recent scripting forum post asked for help with Second Life objects we sit on, and listed examples: a prize-awarding chair, a dance pole, and a teleporter. That list reminded me how often in SL we use a "sit" interaction to trigger some wholly unrelated event -- nothing about conventional "sitting" at all -- because scripts get these handy artefacts of the avatar being on a scripted seat assembly.

Teleporting, for example. Scripters have several variants of "sit teleporters" but anybody new to SL must wonder why ever they should "sit" on a thing in order to be transported somewhere else. After a while we get so used to it that we worry that, instead, walk-thru (Experience) portals might "break immersion" -- as if being transported by sitting is somehow more intuitive. We can disguise the "sittingness" of the interaction with llSetSitText() so the right-click menu shows something like "Teleport" instead of "Sit here" but still it involves an explicit right-click gesture. Or, we could make the teleport trigger with a left click with a llSetClickAction of _SIT, but that makes a mouse cursor of a chair -- hardly universal symbol for teleportation!

I have no idea why a prize chair should be a chair. Somebody scripted one that way once, I guess. Maybe it gives a hint of exclusion to others who'd want to claim the prize? Because the sitter is occupying the space while the prize is distributed, so nobody else confuses the process? From the prizewinner's point of view, though, the chair is just weird. Analogue of a throne for coronation? Seems a stretch.

Even though dancing isn't much like sitting, the dance pole is the LEAST artificial of the examples. The real reason to "sit" on a dancepole is to lock the dance animation to the location of a static prop (the pole). Again, using "Dance!" as the sit text makes it a little more intuitive, but a chair -ClickAction mouse cursor is no more evocative of poledancing than of teleporting.

Builders and scripts - particularly those developing with an Experience target - might consider adopting, whenever possible, some more natural interaction, even if it needs to secretly trigger a forced, scripted "sit" behind the scenes, and reserve explicit "sitting" for those special occasions when the user is literally choosing a place to play a real sit animation.
Reporter Qie Niangao
20200605

Geek To The EEP

In an outdoor photo, you can see the weather. In a film, you can FEEL the weather. That's because the dynamic medium represents how the weather CHANGES environmental cues: Clouds move in and the sky darkens, lighting changes, the sea gets heavy.

What if we could give our visitors that feeling in an intentional, _directed_ series of environmental settings? Immerse them in a little program of weather dynamics?

Below is a sample Experience script that demonstrates features of the new Environment Enhancement Project (EEP), to provide just that kind of weather-changing experience, individually for each visitor. As configured, it applies a sequence of four Library environmental "sky" assets to make the weather seem progressively more threatening over about a minute and a half after arrival. (In real use, you might choose longer transition intervals to stretch this out more realistically. And of course you can use other EEP environments in any sequence - perhaps a cheery brightening of the sky as clouds lift.)


/*
Released into Public Domain, 2020, Qie Niangao for Bay City Post
Give visitors an enhanced experience with a SERIES of Environments
So clouds can build, sky can darken, seas roil more over time - or vice versa
(sample Environments in ENV_STAGES below are super primitive, just to demo the concept)
This basic script uses simple passage of time to trigger next stage
Make sure parcel (at least) has the script's Experience enabled
*/

//== USER SPECIFIED CONSTANTS =======================

integer AGENT_SCOPE = AGENT_LIST_PARCEL; // or AGENT_LIST_PARCEL_OWNER or AGENT_LIST_REGION
// but if they're on land without the Experience, there will be errors
list ENV_STAGES = // sequence of (SAMPLE) Environment UUIDs and durations (in seconds)
[ "d15d3fb0-7e14-4af8-203e-33b85346f3f1", 20 // "Neutral" Library sky
, "cd880f86-53c7-1a91-532c-2797f517a35f", 20 // "Daytime shadows" Library sky
, "07899451-b3d8-9f5c-563b-14b89eda481d", 30 // "Dusty" Library sky
, "2a000d12-e692-da2a-9e08-0cbda70bc0bf", 30 // "PaperSnow" Library sky
]; // These use unnaturally short durations for demo & testing)
float AVATAR_SCAN_INTERVAL = 10.0; // in seconds.
// Not a real sensor, but still some list manipulation, so keep it as long as tolerable
// A new arrival may wait UP TO this interval, so just half this time on average
integer MAX_IGNORED_AGENTS = 20; // after which, forget the oldest (prevent memory leak)
integer MAX_STARTING_AGENTS = 3; // most we'll wait to reply to permissions request (prevent leak)

//== SCRIPT-MANAGED VARIABLES =======================

list tAvStages; // avatar UUIDs in scope, index of their Env.stage, preceded by time to move through stage
list ignoredAgents; // don't spam these with more exp perm requests
key parcelID;
list agentsStarting;

debugOut(string outStr) {
// llOwnerSay(outStr);
}

default
{
state_entry()
{
if ([] == llGetExperienceDetails(NULL_KEY))
{
llWhisper(DEBUG_CHANNEL, "Script \""+llGetScriptName()+"\" is not associated with an experience. Exiting.");
return;
}
// trivial, impossible to match sensor, just set a repeating no_sensor interval:
llSensorRepeat("NO SUCH NAME", llGetKey(), AGENT, 0.01, 0.01, AVATAR_SCAN_INTERVAL);
parcelID = llList2Key(llGetParcelDetails(llGetPos(), [PARCEL_DETAILS_ID]), 0);
}
on_rez(integer start_param)
{
llResetScript();
}
no_sensor()
{
list newAgents = llGetAgentList(AGENT_SCOPE, []);
// any already-staged agents need removing?
integer oldAgentIdx = llGetListLength(tAvStages) - 2;
while (0 <= oldAgentIdx)
{
key oldAgent = llList2Key(tAvStages, oldAgentIdx);
if (-1 == llListFindList(newAgents, [oldAgent]))
tAvStages = llDeleteSubList(tAvStages, oldAgentIdx-1, oldAgentIdx+1);
oldAgentIdx -= 3;
}
// any newly-arrived agents need request to add?
integer newAgentIdx = llGetListLength(newAgents);
while (0 <= --newAgentIdx)
{
key newAgent = llList2Key(newAgents, newAgentIdx);
integer scopeIdx = llListFindList(tAvStages, [newAgent]);
if (-1 == scopeIdx) // agent not yet in list of agents with managed environments
if ((-1 == llListFindList(ignoredAgents, [newAgent])) // agent didn't deny us in past
&& (-1 == llListFindList(agentsStarting, [newAgent]))) // and not already being invited
{
if (!llAgentInExperience(newAgent)) // agent new to this Experience: greet & invite
llRegionSayTo(newAgent, 0, "Greetings "+llGetDisplayName(newAgent)
+" and welcome! You're being invited to an Experience, \""
+ llList2String(llGetExperienceDetails(NULL_KEY), 0) // script's Experience name
+"\" that demonstrates dynamic personal Environment settings."
+" We hope you'll agree to participate."
+" (If you don't grant permissions, this script will try not to ask again for a while.)");
agentsStarting += newAgent;
if (MAX_STARTING_AGENTS < llGetListLength(agentsStarting))
agentsStarting = llList2List(agentsStarting, 1, -1);
llRequestExperiencePermissions(newAgent, "");
}
}
}
experience_permissions_denied(key agentId, integer reason)
{
integer agentStartingIdx = llListFindList(agentsStarting, [agentId]);
if (-1 != agentStartingIdx)
{
if (XP_ERROR_NOT_PERMITTED == reason)
{
if (-1 == llListFindList(ignoredAgents, [agentId]))
{
ignoredAgents += agentId; // don't spam after first request
if (llGetListLength(ignoredAgents) >= MAX_IGNORED_AGENTS)
ignoredAgents = llList2List(ignoredAgents, 1, MAX_IGNORED_AGENTS);
}
}
agentsStarting = llDeleteSubList(agentsStarting, agentStartingIdx, agentStartingIdx);
}
else
if (XP_ERROR_NOT_PERMITTED_LAND != reason)
// ignore _LAND perm error because it's raised every time agent moves to non-XP parcel
llWhisper(DEBUG_CHANNEL, "Experience permissions denied, reason #"+(string)reason
+": "+llGetExperienceErrorMessage(reason));
}
experience_permissions(key agentId)
{
integer agentStartingIdx = llListFindList(agentsStarting, [agentId]);
if (-1 != agentStartingIdx)
{
tAvStages = [llGetUnixTime(), agentId, 0] + tAvStages;
llSetTimerEvent(0.1);
agentsStarting = llDeleteSubList(agentsStarting, agentStartingIdx, agentStartingIdx);
return;
}
// else handle timer-triggered requests (process the tAvStages queue)
integer now = llGetUnixTime();
if (now >= llList2Integer(tAvStages, 0))
{
key agent = llList2Key(tAvStages, 1);
integer envIdx = llList2Integer(tAvStages, 2);
key env = llList2Key(ENV_STAGES, envIdx);
integer transition = llList2Integer(ENV_STAGES, envIdx + 1);
debugOut("process env "+(string)env+" for agent "+llKey2Name(agent)
+"\n\t with tAvStages = "+llDumpList2String(tAvStages, " | "));
integer envErr = llReplaceAgentEnvironment(agent, (float)transition, env);
if (0 > envErr)
llWhisper(DEBUG_CHANNEL, "Error in llReplaceAgentEnvironment : "+(string)envErr);
envIdx += 2; // advance agent to wait for next stage
integer nextTime = now + transition;
if (envIdx >= llGetListLength(ENV_STAGES))
nextTime = 2147483647; // Final env stage should last for rest of stay (MAXINT)
tAvStages = llListReplaceList(tAvStages, [nextTime, agent, envIdx], 0, 2);
}
tAvStages = llListSort(tAvStages, 3, TRUE); // lazy
float timeTo = (float)(llList2Integer(tAvStages, 0) - now);
if (0.0 >= timeTo) timeTo = 0.1;
llSetTimerEvent(timeTo);
}
timer()
{
llSetTimerEvent(0); // set again in exp_perms event
if (llGetListLength(tAvStages)) // any Avs left?
llRequestExperiencePermissions(llList2Key(tAvStages, 1), "");
}
}

Note that Experience permissions are required by llReplaceAgentEnvironment, the EEP function that makes this possible, so the script will need to be compiled to an Experience that's enabled on the land where it runs. And visitors have to grant the permissions requested when the script invites them to participate.

At the moment, EEP is only visible in the Linden viewer, but soon it'll be supported in popular third party viewers too. Although the script sequences the effect individually for each viewer, it manipulates what's called the "Shared Environment" -- so it can be overridden by users who specify their own environment or time-of-day.

Passage of time needn't be the only thing to trigger a change of EEP environment. Should one particular room or area have different lighting? Such a script would track where visitors roam and update their environments accordingly. Or maybe trigger environments by level in an in-world game, or in response to some scripted role-play interaction.

Another possible extension: _Sound_ is powerfully evocative of weather: wind, thunder, bird song, waves, etc: llPlaySound() in a HUD is heard only by the wearer; llAttachToAvatarTemp() could transparently attach a sound-emitting HUD to experience participants.
Reporter Qie Niangao
200504

Where Is Everybody?

Your second day in Second Life, you walk around, see houses, clubs, roads, waterways and you see nobody!
Even when you turn on the mini-map you find yourself in an empty area.
You discover some green dots, you search very hard to find them, in the sea, and they do not respond to anything. Not to chat, not to IM's, they appear being dead.

WHAT IS GOING ON???

At any given time there are about 50,000 avatars on-line. Sometimes more, sometimes less.
An unknown portion of those are the ocean dwellers, the semi dead green dots in the water. My guesstimate is that those pollute the numbers about 50%. So, take it from me, 25,000 avatars are hanging around somewhere, one of those is you (if you are on-line that is).

The ocean dwellers are avatars that serve no real purpose except to pollute the oceans. Forget about them. The more experienced people have opinions about them and these are not very positive.

Before I (try to) help with finding people let me explain why everything is empty.

It's no glitch, not a failure or a fault, that everything is empty.

This is Second Life, not meat life.

We are just hanging around and are having fun! 
That is the true purpose of Second Life.
Life is good to us.

The houses and clubs, parked boats and cars, are not real.
We don't sleep in a bed, eat bread and milk when we wake up, we don't travel to work, we don't have to work long hours in the prim mines to bring home some L$.
The houses don't serve a purpose at all!
Ok, it serves a few purposes. It's nice to log-in at a place that looks familiar, it's nice to have a bed that has various functions that don't include sleeping. But that's about it.

It's decoration!

It's like your Facebook page that you make look good so that you look good. Nice profile picture, interesting CD collection, interesting pictures, amazing interests. The same is with that house you see in Second Life. It reflects something about the owner, it's character, desires, loves and hates.

Most houses (visible from the ground) are free to enter because most like to show how nice they can decorate. When the owner arrives, apologize for being there and compliment about the decorations.
Same goes with the parked cars and boats. Decoration, but it does tell something about the owner.
The clubs, with flashing lights and disco floors, you can find all over the place are most often also just decoration, though sometimes the owners throws a party and invites friends over. The empty bars, same.

It all is decoration, because we like to be surrounded by things we like and love. Also a car costs less then high quality shoes. (yes ladies, good shoes are expensive. A wig cost less then a full furnished house) In this world we can own a house that is impossible to afford in the real world and call it home.

Nobody is there but it all tells a story about the owners.
It's a big profile page you can walk through.

Once you figure it all out you will understand, and you will purchase a plot of land and decorate it to your liking so that everybody can see what a nice person you are, because you are.

I have already explained where half the population is, those are the ocean dwellers (feel free to hate them). But where is the rest??

Well... Second Life is BIG! It's HUUUGE! It's gigantuously BIG!
If you zoom out the map to the max it still doesn't fit the screen.

So the 25,000 avatars are scattered around there somewhere.

To find them, use Search. One place to look is the Destination Guide, not a guarantee to meet people though but you'll find nicely decorated places and things to do.
Another place to Search is Events. Live Music is a great way to meet people.

Once you figure it out, you can always find people you will like. Trust me.
Reporter Vick Forcella
200406

Fair Winds

Second Life sailors will have noticed that boats move according to wind patterns that vary over time and across the continents. That's possible because the Second Life simulation includes wind. In a recent Forums thread, https://community.secondlife.com/forums/topic/451524-sl-wind-variance-between-sims , we explored a bit more about how that wind simulation behaves.

Although all regions have wind that varies over time, it seems that some have wind that also varies over the region at any instant -- and some don't. The thread shows a few scripters figuring why some regions have wind that varies across the region, and it's a good example of loose but effective teamwork investigating the phenomenon. (It turns out that isolated island regions, surrounded by void, do not get the spatially-varied wind, and the ones that do are seeing patterns that propagate across region borders, covering whole continents of connected regions.)

There are several little scripts in the thread showing approaches to quick-and-dirty data collection, interspersed with digging into dusty scrolls in the Forums archive, the jira, the wiki, and old release notes.

It's not exactly Indiana Jones or a Dan Brown novel, but it kinda makes me want to dress my avatar as Holmes -- or maybe Watson.

Besides sailboats and the beautiful particle effect that introduced the thread, SL wind also affects ambient sound in the viewer, flexiprim movement, and scripted things like windsocks and weather vanes. It used to be an option to see Linden trees moving according to wind conditions but we found that was removed in early 2012 to reduce viewer lag. I've also used wind as a sort of whimsical "switch" for a space heater that turns on when it's "windy" -- the SL "weather" simulation doesn't include temperature... or anything else except wind.

There could be an opportunity here if anybody can think of a product that could benefit from a semi-randomly fluctuating property that varies over time and space.
Reporter Qie Niangao
200406

Slow Inventory Saves a Step

Perhaps you, like me, find yourself copying the contents of one object into another, for example to move a whole bunch of animations from one piece of furniture into a new one. Out of habit, I've always done this by first copying everything into my own Inventory, then back out to the other object. This is really slow and prone to failure. Some third party viewers have a way to make it a little more reliable, but it's still pretty painful.

Thanks to particularly sluggish Inventory services I recently realized that this was a silly extra step: All I really need to do is copy the contents directly, object to object. So here's a script that does that (read the comments for some caveats and options about how it works):

/*
Simple little script to copy the contents of this prim to another, identified by key in textbox
To get the key to put in that textbox, can use Firestorm's "Copy Keys" button in the Build Tool editor or drop this trivial script into the target object:

default { state_entry() { llOwnerSay((string)llGetKey()); } }

Unfortunately (and weirdly) I don't know a way for a script to get the permissions on a rezzed object, so this will try to copy to anything the toucher owns, which won't work for no-mod targets. This expects both the sending and recipient objects to be owned by the toucher.

Some special cases might make sense with other owners, but lots of ways for that to cause trouble, too. Can theoretically use something like this to give contents to an avatar
but as written it would wait 2 seconds between items. Some TPVs have built-in means of doing this reliably.

Could use llGiveInventoryList() to make it faster, but that can't work at all for no-copy,
which would mean a hybrid approach, much like product unpacking scripts.
*/

integer COPY_SCRIPTS = FALSE;

// Scripts would arrive confusingly NOT running (use TRUE to copy them anyway, including THIS script,

// but then will need to either recompile them or take target object into inventory and re-rez it.)

integer MOVE_NO_COPY_CONTENTS = FALSE;

// It could damage the sender; use TRUE to do it anyway, but that won't work if copying to an attachment

integer listenHandle;



default

{

touch_start(integer num_detected)

{

key toucher = llDetectedKey(0);

if (llGetOwner() != toucher)

{

llRegionSayTo(toucher, 0, "You need to own this object to copy its contents");

return;

}

llListenRemove(listenHandle);

integer chan = -1000000000 - (integer)llFrand(1000000000);

llListen(chan, "", toucher, "");

llTextBox(toucher, "Key (UUID) of recipient object?", chan);

}

listen(integer channel, string name, key id, string text)

{

key target = (key)text;

if (NULL_KEY == target)

llRegionSayTo(id, 0, "Sorry, that's not a valid key");

else

if (id != llGetOwnerKey(target))

llRegionSayTo(id, 0, "Sorry, you don't own that object");

else

{

integer inv = llGetInventoryNumber(INVENTORY_ALL);

while (--inv >= 0)

{

string invName = llGetInventoryName(INVENTORY_ALL, inv);

if (COPY_SCRIPTS || (INVENTORY_SCRIPT != llGetInventoryType(invName)))

{

if (! (PERM_COPY & llGetInventoryPermMask(invName, MASK_OWNER)))

if (MOVE_NO_COPY_CONTENTS)

llGiveInventory(target, invName);

else

llRegionSayTo(id, 0, "Skipping no-copy contents: "+invName);

else

llGiveInventory(target, invName);

}

}

llRegionSayTo(id, 0, llGetScriptName()+": Done");

}

}

}
Reporter Qie Niangao
200302

Hopeful: Embedded MP4s, Hopeless: Measuring visitor script times

There's excellent news from the Lab about plans to eventually support embedded MP4s. This has been a problem because many videos, notably including those hosted on Vimeo, use this format that does not work with out-of-the-box Chromium Embedded Framework, the basis of parcel and shared ("Media on a Prim") media as well as viewer browsers. Although there's no schedule yet, it's an encouraging development compared to a previous statement in the Jira that the Lab did NOT plan to support the format. (This may affect plans for hosting SL-related video content and for displaying that content.)

On an unrelated topic, there have long been devices that measure visitor scripts with the goal of controlling the lag they might cause. In a recent forums thread ( https://community.secondlife.com/forums/topic/448580-avatar-script-count-limit-on-homestead/) some of us took a deeper dive into what such devices might do to be useful, and what they very often do that is useless -- or worse. To summarize:

Scripts worn by visitors can lag other scripts but generally do not contribute to the most common forms of lag experienced by avatars in a busy region. That's because scripts are the lowest priority of sim processes, so a lot of avatars in a region will tax *other* sim resources, squeezing out scripts (and making script-on-script lag more severe). It can be annoying that scripts don't get much time to run, but that's rarely best addressed by reducing the script load itself.

That said, reducing the load of the most over-scripted visitors can improve responsiveness of other scripts (such as vendors), and griefers can take over-scripting to such an extreme that it hurts overall sim performance.

To efficiently find script offenders, what to measure? Turns out that the simplest metric -- count of running scripts -- is probably the best option. That's because, as detailed in the cited thread, both Script Memory and Script Time are actually measuring something very different from what the names imply. Script Time in particular is almost impossible to use responsibly because the more a region is having performance problems, the less accurately Script Time can be measured in the region and the longer it takes (20 minutes or more) to settle into a potentially useful metric.

Worse, the *direction* of inaccuracy is also a function of time and sim load: when an avatar first arrives in a busy region, their Script Time measure will be (hugely) *over*-estimated compared to a less busy region, but later when the measure stabilizes, the same scripts will show *lower* Script Times than when the sim is less busy. Indeed an avatar's Script Time depends less on their scripts than on the performance of the region and the time since the avatar arrived.
Reporter Qie Niangao
200206

Using Second Life to "Extend the Rafters"

Anyone finding themselves near Ottawa Canada between now and 5 April 2020 may want to arrange a special trip to the National Gallery of Canada to experience "Àbadakone | Continuous Fire", a very special exhibit of international Indigenous art with a wide array of amazing works from around the world. 
Of particular relevance to Second Life is "Teiakwanahstahsontéhrha’ / We Extend the Rafters" by Kanyen'kehà:ka (Mohawk) artist Skawennati.
Central to the work is a machinima, "The Peacemaker Returns", constructed and recorded in Second Life. The entire work also includes wampum belts (deer hide, sinew, plastic beads), LED lights, and an aluminum structure.

An earlier (2017) exhibition of the work explains the title of the piece: "The bilingual title of the exhibition—in Kanien’kéha (Mohawk) and in English—refers to the action of 'extending the rafters' of a longhouse. 
These traditional Indigenous structures would be lengthened to make room for new generations or even other families." 
As shown, the "rafters" of the aluminium structure extend into the futuristic machinima itself, which also includes virtual wampum belts echoing the real beaded belts in the museum exhibit space.

The artist outlines the significance of the work and details the Second Life effort involved in its development in a fascinating background video.
Reporter+Image Qie Niangao
191202

A Hoverlogo And Other Sprites

Particles are two-dimensional images situated in 3-D space. They (except still-rare "ribbon" particles) have the special property of always facing the camera: they're "sprites" is the parlance of computer graphics. This is fine for many purposes, but in other situations can challenge immersion: there's no real world analogue of a surface that's always facing you regardless of how your view moves around it.

Well, there's the optical illusion of eyes in paintings such as the Mona Lisa that appear to follow as the viewer moves around the room, but particle sprites really do face the cam.

That's similar to hovertext which, too, is always drawn facing the cam; one big difference is that hovertext doesn't scale with distance from the emitter whereas particles do.

In SL, things that aren't realistic may break immersion -- or they may appear magical. Here we have what I prefer to see as magical: a "hoverlogo" that always shows the circular logo image head-on, regardless of whence it's viewed:

default
{
state_entry()
{
llParticleSystem(
[ PSYS_PART_FLAGS, 0
| PSYS_PART_EMISSIVE_MASK
| PSYS_PART_FOLLOW_SRC_MASK
, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_DROP
, PSYS_SRC_TEXTURE, "422ed2fa-482d-b9fd-1bd7-eef1611a1dbf"
, PSYS_PART_START_SCALE, <0.5, 0.5 , 0.0>
, PSYS_PART_MAX_AGE, 30.0
, PSYS_SRC_BURST_RATE, 3.0
]);
llSetText( "Visit the\nBay City Post", <1.0, 1.0, 1.0>, 1.0);
}

touch_start(integer total_number)
{
llLoadURL(llDetectedKey(0), "Visit the Bay City Post online",
"https://baycitypostsl.blogspot.com/");
}
}

This example is intended to go inside a fully transparent 0.5 m sphere so it can be activated by touch. Of course for another logo you'll want to change the texture UUID and hovertext as well as the prompting text and URL that's loaded when touched. If no touch-response is desired, the particle system will continue to show the logo after the script is removed, saving a tiny bit of simulator resources.

I've also used this approach to create an analogue "hoverclock" that shows the time from all sides, perched on top of teleport domes on major Virtual Railway Consortium sites around the SLRR. (The reader is invited to ponder the mystery of how the hands move around the face of those hoverclocks.)
Reporter Qie Niangao
191104

Experiencing a Bug, and BoM Obscurities

Some folks with their own Experience scripts may have noticed a particularly nasty bug that's a real head-scratcher when first encountered. It seems that with some recent server update, all rezzed-in-world scripts compiled to any Experience lost record that they were compiled to that Experience. The scripts keep running using the Experience for which they were compiled, but they can't be recompiled (nor shift-drag copied, etc.) unless re-introduced to that Experience.

Turns out this doesn't really affect that many end-user scripts because most folks just use whatever Experiences are already compiled, and a lot of Experience scripts (such as the AVsitter auto-attach scripts I often praise) are usually embedded in object inventories, not rezzed-out on their own, so they weren't affected.

New objects don't seem to be affected now, but currently it's not clear whether there's any way for the Lab to fix the already damaged objects. If you're interested you can watch developments at https://jira.secondlife.com/browse/BUG-227526 for updates.
Much wider attention is on the new "Bakes on Mesh" (BoM) feature for attached mesh bodies and heads. This enables direct wearing of skin-tight textures and alpha masks, just as the old system avatars used, rather than the much more complex and limited "applier" scripts and "alpha cuts" HUDs that mesh attachments needed until now.

Much has been said about BoM already, but some things I think have been under-reported. First, in addition to the oft-cited improvement in rendering efficiency, the feature overcomes a constant source of user frustration and support problems: the unpredictable interaction of multiple layers of blended alpha textures. This comes up all the time when people try to wear makeup and tattoos, say, on overlapping layers of their attached mesh. All those problems go away when those overlapping transparent layers are simply baked on top of each other into a single displayed surface texture.

This also completely eliminates a problem inherent to how Advanced Lighting is implemented, limiting how many projected light sources affect a blended alpha surface. If you've ever noticed make-up, for example, looking weirdly coloured depending on where it is in a scene with complicated lighting, you've seen the problem -- which you WON'T see anymore with baked-on textures.

Finally, a note about BoM and Materials: if creators of BoM skin, make-up, tattoos, clothing, etc. want to include "Materials" effects, they should simply supply the normalmaps and/or specularmaps directly with their products, so folks can manually compose their combined normal- and specularmaps for the baked surface layer. These assets have zero value as "stolen" content, so the creator loses nothing by doing so, however much they may have been trained to "protect IP" at all cost. Mesh avatar makers understand this and provide a way to apply those manually composed material maps (at least this applies to Slink, which was "first out the gate" with BoM so I could test the existing built-in Materials applier on the skin layer, and a single-layer Omega applier for Materials will also work).

The reason this process still involves manual composition is that there's no simple rule for combining the "bumpiness" of normalmaps layered on top of one another. An under-shirt might be tight enough to reveal skin-layer bumpiness, but its own ribbed collar may not be revealed under a tight jacket, for example. It's still up to the user to decide which bumps should show through, and that means combining the normalmaps individually. (Most end-users may not want to do this themselves but creators of quality assembled outfits will surely follow this process for their customers.)
Reporter Qie Niangao
190902

Bump 'n' Go: A simple Experience teleporter

I like to think it's useful for readers to learn about Experiences because Bay City has a high concentration of landowners, and landowners can enable Experiences on their parcel. There are also a large share of Premium subscribers, and they're eligible to define and use their very own custom Experiences.

Before enabling a custom Experience on your parcel, it must first be created -- an easy process, well documented in the knowledge base: https://community.secondlife.com/knowledgebase/english/experiences-in-second-life-r1365/#Section__4

One thing you can do with your own custom Experience is to make a simple collision-driven teleporter. Of course you could instead use other events besides collisions to trigger teleportation, but it's a neat trick to just walk through a fake door or fall through a "hole" in the floor and end up in a totally different place. So let's take the simplest collision-triggered Experience teleporter script as an example:

_______________

vector destiny = <56, 15, 2222>;
vector facing = <50, 15, 2222>;

default
{
state_entry()
  {
llVolumeDetect(TRUE);
  }
collision_start(integer num_detected)
  {
key collider = llDetectedKey(0);
if (ZERO_VECTOR == llGetAgentSize(collider))
return;
llRequestExperiencePermissions(collider, "");
  }
experience_permissions(key agent)
  {
llTeleportAgent(agent, "", destiny, facing);
  }
experience_permissions_denied(key agent, integer reason)
  {
if (17 != reason)
llRegionSayTo(agent, 0, "NO PERMS, reason: "+llGetExperienceErrorMessage(reason));
  }
}
_______________

That script would be placed in an object that, when the avatar steps into it, will teleport that avatar to a particular point in the same region (the "destiny" coordinates) oriented towards the "facing" coordinates when they arrive. So first you'll scope out where you want the avatar to go and which direction she should look on arrival, and change those two vectors to fit your situation.

(HINT: Don't set a "destiny" that's the EXACT same location of another teleporter because then you might arrive, collide with that teleporter, and be immediately teleported somewhere else -- or right back where you started. If BOTH ends specify each others' exact locations, it can be tricky to escape without relogging somewhere else.)

There are lots of ways to elaborate on this theme. For example, if this will serve the uninitiated, it wouldn't hurt to check first whether they're already enrolled in the Experience (llAgentInExperience), and if not, give them a little pep talk in chat before requesting experience permissions of them.

This form of teleporting also works for destinations in remote regions, but if you're unlucky, the destination region might be offline at the time. (There's also a separate step for finding the global coordinates of the remote region, and some trickiness with how the "facing" parameter is used, as well as a built-in "flyslow" animation that may need to be stopped.)

If there are a bunch of origin-destination pairs on a region, they might be networked to discover each other. (ADVANCED: They can even discover each other on very distant regions, using the "Key-Value Pair" persistent storage built-in to Experiences; that's how a network of walk-thru teleportation orbs work on Virtual Railway Consortium sites around the SLRR.)
Reporter Qie Niangao
190805

Calendar



Park Plaza Hotel

Park Plaza Hotel
Please visit our Sponsor!

Luxury Living in Bay City


Park Plaza residents enjoy beautiful views, fine dining, and a roof top patio with hot tub; all this near route 66, and within walking distance to Hairy Hippo Fun Land and aquarium. Rates start at 55L a week for studios, and 185L a week for full size apartments. Free furnishings available. Contact Roc Plutonium for more information!

Archive