Three Poems

My RL self did National Poetry Writing Month in April; 30 poems in 30 days. I thought I’d post three (at least) of them here, because they have some Virtual World content.

This first one, from the 29th, is notable for having inspired a machinima as noted the other day.

Dactyls are Dharma, too

Here in the midst of the ten thousand thingummies
Hearing the voices of ten million throats,
Feeling compassion for those who have aching knees,
Those who build bridges and those who dig moats.

Sitting in zazen and counting the in-and-out
One and a one and a one and a one,
Mind somehow caught in this insistent rhythm, I
Tick like a clock sitting here in the sun.

Dharma is silent but Dharma is noises and
Dharma is stillness but Dharma is speed,
Why should I think that the circling second-hand
Isn’t precisely the sound that we need?

One commenter (commentor? commentator?) somewhere said they’d learned two new words from it; I’m guessing “dactyl” and “dharma”; both good words to know.

The second one, from the 9th, is very relevant to lil Spennix:

A long way from Kharanos

Well it’s a damn’ long way from Kharanos
To th’ Gate o’ th’ Settin’ Sun,
But the beer is good an’ the beds are soft
When th’ daily slaughter’s done.

I left a dagger in Thermaplugg,
All those long hard years ago,
Took a bit of his gear as a souvenir,
Of Gnomeregan below.

But that crazy old coot was nothin’,
‘gainst the things that they’ve got ‘ere,
Bugs an’ Mogu an’ lizard men,
And hungry ghosts o’ fear.

Someday I’ll go back t’ ol’ Col’ridge,
An’ sit on the porch with ‘em all,
But ’til then I’m out here in the Vale,
Killin’ bugs up on the wall.

Well it’s a damn’ long way from Kharanos
To th’ Gate o’ th’ Settin’ Sun,
But the beer is good and the beds are soft
When th’ daily slaughter’s done.

… and here is an Action Shot of “Killin’ bugs up on the wall”:

Fightin' bugs up on the Wall

(Click through to the shockingly-redesigned flickr for the same picture larger, and in a confusing interface.)

And to close, this one from the 17th. Note that it’s not actually about Second Life, since that has real people in it, not just simulated ones. But still…

Walking Cross-Country

He says he’s writing a computer program
to simulate
walking cross-country
in an unknown place.

Where you might follow a brook upstream
and be surprised by
a forest lake
sparkling in the sun,

And follow a path around it
to a ramshackle house
at the end of a dirt road
where a woman with dark hair and soft eyes
opens the door
and smiles a welcome.

And I say that that sounds cool,
and I also say,
that the real world has surprises like that, too,
and even soft-eyed women,
and he should maybe go for real walks sometimes.

He turns to me,
like he’s about to say something,
but then he just shakes his head
and goes back to the keyboard.

Reflect On This: Dactyls Are Dharma,Too

Reblogged from Digital Rabbit Hole:

  • Click to visit the original post

Where to begin?
I will not make this post too long or long-winded..I really just invite you to scroll down and see the YouTube at the bottom hopefully in HD and Full screen.
I use this little creation as another perfect example of crazy creatives getting together to produce a few minutes of visual and vocal insanity. As those who read my blog regularly know, one of the things I most love about our Second Life, is the possibility to collaborate on artistic projects.

Read more… 205 more words

Y'all know how shy I am and reluctant to blow my own horn :) but I can't resist passing this along. I did National Poetry Writing Month in my RL weblog (maybe I should post them all here too!), and shared some of the results (one poem a day for a month) with a few SL friends. Karima Hoisan (see prior post) liked the rhythm in one of them, and to my enormous surprise she and her frequent collaborator Nat made this extremely neat machinima around it. From little nuts do mighty oak trees grow! :)

I sell houses!

Well, that is to say, I put the Beach shack, one of the houses I was talking about the other day, into my tiny and neglected Marketplace store.
 

Beach Shack Box Cover

 
Is that not exciting?

And I may box up the other three I’ve built lately (the Marketplace doesn’t actually require or even encourage boxing things anymore, but I’m used to it, and used to buying things that way, so I think I’ll keep doing that for now), and maybe even have a Combo Pack of all four at a discount, and even put a tiny vendor or store somewhere on my land, and take part in Hunts, and, and, and…

Or maybe I will just leave this on the Marketplace for a bit and see if anyone buys one. :)

Pricing is so odd in SL; some things of about this same quality are available as freebies, others would probably cost five times as much. I tried to price it so that I might consider buying it myself. Which means it’s at the cheaper end of the scale!

Fantasy Faire!

So I hardly ever go to Organized Events, at least not much; I’m not entirely sure why, maybe because there are so many more disorganized ones :) and I often like them better, and organized events tend to be crowded and/or laggy and/or drama-filled, and in general I have this self-image as being too eccentric and/or 133t to do anything that lots of other people are doing, or…

Whatever. :)

But v good friend Michele has been actively weblogging the 2013 Fantasy Faire this year, and I’ve now been there all of twice, and apparently it’s still going on at least for today (they are having a live auction of various parts of the Faire sims and builds, which seems really cool) and maybe for longer although I’m not sure, and I took a couple of pictures that I like, so here I am weblogging about it myself!

Lotus Valley Dream, harbor

There is the left half (depending on exactly how you’re viewing this) of a picture of me standing looking out at the dragon in the Lotus Valley Dream harbor; click through to see the whole thing, bigger sizes, usw.

And here is a closer-up of the Dragon emself:

Lotus Valley Dream, dragon

(or the left half, depending); enthusiastically friendly, no? Or maybe just hungry…

That’s just two shots from one gorgeous sim in a big collection of gorgeous sims in varying and wonderful styles. While I understand and sympathize with the tendency to use SL to make ourselves into our sort of RL ideals (90210-style, if you will), this is the kind of SL thing that really delights me: going beyond the RL-possible, into fantasy, and dream, and creativity, into worlds and realities beyond the ones that we happen to be born into. And the fact that it’s for a great cause, Relay For Life, just adds to that.

Also dragons are cool. :) Not to mention, shopping!

Here’s the group pool for the flickr group for the Faire, where you can see lots more. And assuming I post this in time, you can maybe still go yourself!

Paths through virtuality

So a bag-zillion years ago I weblogged (probably more than once) about an interconnected random adventure in SL, where a friend and I landed in some cool place after skydiving, looked up the picks of the creator of some neat object there, went to their store or something, and so on through various hours worth of fun randomness.

It’s been too long since I went nude skydiving :) but I still have these kinda small adventures all the time, I just don’t weblogify about them as much, because I don’t weblogify about anything as much, because I am lazy person.

But here’s one!

As extremely long-time readers will know, one of my very early living places in SL was a little shack on the PIER sim (which I found in turn from making friends with a bartender at The Elbow Room, which stretches the story back just about to my first months in SL I think), and when that sim shut down I started renting a room in Extropia.

At home in Extropia!

Eventually the Extropians redesigned the sim and didn’t have those little rental rooms available anymore, but I stayed in the Extropians group because it was interesting, and after awhile I started to notice cross-posting in the Extropians group from the Dakini Land / Western Geisha / Companion’s Guild group, see for instance this probably-related video.

I visited the Dakini Land sim somewhere in there, but as I recall I was heavily RL-distracted at the time, and couldn’t really figure out what it was. Then I got a notice about (I think it was) some graduation ceremonies that were going on there, and there was going to be dancing and music and poetry-reading and stuff, so I went, and it was a good time, and the people were very friendly and interesting.

Dakini Land

(I eventually did figure out a little of what was going on, which led me to start watching old episodes of “Firefly” on Netflix, where I was by coincidence already watching old episodes of Buffy; everything connects!)

Probably the performance that struck me most at that ceremony was a live on-voice reading of original poetry by Karima Hoisan. I took her picture and gave her a copy (as I am constantly doing, which is one reason my friends list is so absurdly large), and she looked at my profile and saw a Pick there from New Toulouse, which I had added to replace a Burn2 pick when Burn2 ended, and having connections with New Toulouse herself, she IMd, me and we talked, and continued talking now and then thereafter.

Eventually she and frequent collaborator Natascha Randt were working on this machinima about scripting, and I happened to have a script that fit into it nicely, with the result that some of my LSL code ended up in a machinima, which was extremely cool. (Note that it’s not a dry and geeky machinima, either; you must watch it if you haven’t, it is amazing.)

And then later on, looking around at random things on the web as I constantly do, I came across Karima’s machinima series “The Two”, and realized that I had randomly watched an episode from the middle of it somewhere many months before, but not had enough focus to figure out its context or anything.

Ms. Hoisan wisely suggested that if I wanted the full effect I should first read / listen to / experience her “Colored Dreams” pieces first, and then “The Two” in order.

So I did that, and now at the end of this particular branch of the chain of causality (rather than, say, the one that includes having a lovely tea ceremony on a satellite), I am highly recommending to you my readers that you experience both in that order also:

The Colored Dreams (page one page older to start at the start of Part One)

and

The Two (Also page back one to start at the start)

Don’t expect to consume them all in one sitting :) I found that I wanted to stop for hours or days in between just to sort of let it all sink in. It’s hard to describe or characterize; might be called fantasy or even SF, or a series or dreams, or meditations on the human condition and the nature of power and love and trust, or lots of other things. But really, like all good art, it tends to slip away from any words that you try to tie it up in.

And if you’d like to hear the artist live :) she will be doing another reading this very tomorrow, and I recommend that also, and so we tie the story up to the present day.

So! That’s my path through virtual space for today. Now I will go and find some more. Or maybe I will take a nap…

And speaking of Sn@tch!

I was exploring a store called “POST”, after seeing it mentioned positively over on The Train Wreck Love Life, and as I was camming about (more on that below) I saw a green dot appear near me on the minimap, and thinking it might be (say) the store owner come by to fiddle with things and I could gush about how great the place was, I pulled my camera back, and it turned out not to be the owner of POST, but instead…

Ivey "Murderdoll" Deschanel

it was Ivey “Murderdoll” Deschanel herself, owner of Sn@tch the store I was gushing about in my last post.

Zomg!

So I fanboy’d all over her in IM (well, I tried to be restrained), and she was humorous and friendly. I’ve spoken to a celebrity! :)

The store POST is very neat. Here’s the Marketplace version, but I really liked the inworld one. Both the store and the products are very well and subtly textured, as Emilly says, and there’s a sort of early-1800′s Europe / Russia feel to it all. Lots of good use of mesh in the objects, so they are low-prim, and many of them are art or book related in some way. Prices range from 0L for various random things lying around here and there, to multiple hundreds for more elaborate objects and structures.

Any store that sells (or gives away!) a copy of “Salome” left open face-down on the floor, a copy of Picasso’s “Ma Jolie” for the wall, and an open notebook with sketches from the Voynich Manuscript (as well as nicely worn rugs, sidetables…) is marvelous in my book.

(Tip for Firestorm and probably other viewer users: you can apply a filter and have the Area Object Search show you just things that are, for instance, for sale for between 0 and 50L, and sort them by nearness. Great way to look for bargains!)

Block

Block

There was something otherworldly about it….

(Submission to the Single Frame Stories thing, for the prompt “Block” announced here.)

And yeah, it’s a bit of a geeky in-joke. :)

Flowing Purple Light

Flowing purple light

These gloves and boots are amazing (there’s a corset and a neckpiece also, which I don’t have); a photo can’t really show it, because the amazingest thing is that the lights you see there as sort of purple highlights are flowing, moving across the item in eye-seducing ways. (And there are menus that let you control the rate and direction and color of flow, as well as other things like I think the color of the rest of the object, that I haven’t played with yet).

Also the boots and gloves are both mesh, but fit me and I like them anyway! I am very slowly becoming more of a mesh wearer than I used to be (i.e. not at all).

Boots
Gloves
Inworld store for those and lots of similar

And purple corset set from Rag Dollz sometime a long time ago so good luck finding it. :)

Happy New Year, an’ all!

2012 Seasonal Card

Continuing the occasional tradition! :) I spammed this out to all 450+ people on my Friends list earlier today. (If you don’t get one and would have expected to, let me know; I’m not sure I entirely trust SL to have done that perfectly.)

Image uses the techniques (and the little HUD device) from Dale Meets Dale. Once I had two images that I liked (which took awhile!) it was easy.

Wow, I haven’t posted here much lately, have I? I have a somewhat more developed and usable version of the script from the automatic walking post, that lets you increase and decrease (and even reverse) the force that makes you walk, and it gets along okay with jumping and flying. So you can arrange for really Superman jumps, and you can fly along at whatever speed cross-country you want without having to hold down a key, and so on.

I’m still not entirely happy with the turning behavior; or maybe I’m just too lazy to make a Wiki page so far. :) But when I do I will post here about it. Or vice-versa.

Otherwise doing pretty much the usual stuff. Good SL friend and prominent photographer and DJ Calli had a Seventh Rezday party last night (with fireworks!). That was a lot of fun. Next year I’ll be turning seven myself; pretty neat! :)

Automatic walking (and the invisible stranger)

So very poetic friend Karima flatteringly chose my avatar following script as some context for a new poem of hers lauding scripters (she even used some of the code in the poem, and although this sounds like it couldn’t possibly work it certainly does, and you should go read it).

This reminded me of a related script that I have been too lazy to work on forever and ever, and I now have a rough draft. It may stay a rough draft for some time :) since LSL makes it hard to do in a really polished way, but in any meantime here it is. When you’re using it, once you start walking you keep walking, more or less forward unless you use the side-arrow keys to turn, until you tap backward or etc to stop. (Works best on or over flat ground; see the page for details!)

If I ever like it enough I’ll put it into the Library.

Here is a picture of me walking with the automatic walker. Note that this is a hard sort of picture to get in general, because you have to walk and cam around to looking at yourself from the front at the same time, but the walker makes it relatively simple!

(Well, okay, and without any special scripts you can also cheat by just playing a walking anim and not actually walking. :) But this would let you make a video of yourself walking! A bit, anyway…)

In other news, I noticed that for a long time (like, weeks) there had been a green dot over in an adjacent parcel on the Rise, and whenever I went over to look it was the same AV name in the title floating there, but with no visible person, and they never answered chat or IMs.

Feeling whimsical the other day, I’d nudged the invisible person (who turned out to be nudgeable) over into my land, and built a little protective envelope of colorful devices around them. I figured I’d keep them around as a decoration until my conscience got the better of me, and then send them home (since they were on my land, and I could now do Teleport Agent Home).

But then not long after that I logged into the Rise, and there they were again, standing invisible and unresponsive at the same place in the empty field next door. (And yeah I’ve checked high and low and Highlight Transparent; I suppose they are probably wearing a full-transparent body alpha, or something subtler.)

Most puzzling! What process moved them back there again, to stand again invisible and unresponsive?

But that’s why we love the mainland. :)

Update: the llSetForce() version of this seems to work just awesomely! I am now playing with a version where you stop by pressing Back, and each time you press Forward it speeds you up a bit. Enormous fun so far!

Um, soooo….

Is there an Official Name for this general AV and clothing style in SL:

Um, sooo...

This is a random picture from a vendor board at Zombiepopcorn, but if you’ve been out and about in the fashion-caring parts of SL lately you’ve probably seen the style. On people, even!

It’s characterized by a sort of pouty-frowning mouth-shape, a smallish and widish body shape, and (um) an unusually wide space between the thighs.

I first saw something vaguely like this shape on someone who was I think doing it out of creativity, and generally paired it with an animal head or frog feet rather than fashion accessories. But now it seems to have Caught On enough that various people have been expressing reservations about it. (To say the least.)

I don’t find it especially attractive, myself. On the other hand I am deciding that I like the fact that it exists. It’s a rather NPIRL fashion trend, after all, something that’s possible only because we can fiddle so extensively with our bodies. And it doesn’t cater to or reinforce the usual beauty clichés, and that’s a plus. Of course in that it’s a new beauty cliché itself, it may be that it’s similarly being used mostly sell product. :) But that’s okay, really, as long as it doesn’t lead people who look other ways to feel inferior.

But anyway, what’s it called? And I don’t mean what amusing epithets does Alicia have for it. :) What do the people who actually design for it / wear it / not run screaming away from it call it? If anything?

Combat System Scripting V: our first combat meter

I have suddenly remembered this here series of combat scripting posts that I was doing the other Geological Epoch!

So I will do another one. A pretty simple, but important one; our first Combat Meter.

Now as I didn’t explain in the first post but probably should have, when it comes to people (AVs) taking “damage” in Second Life, there are two distinctly different ways that can work. There is a notion of “health” and “damage” that are built directly into the world (but as far as I can tell very seldom used, because they’re inflexible and kind of silly), and then there’s “health” and “damage” as enforced by scripts in things that you wear.

(In a way this is like the difference between vendors that let you buy using “buy”, and those that let you buy using “pay”, as explained in my extremely thorough post on the subject. “Buy” is built into the world whereas “Pay” enables scripting, just like Linden Damage is build into the world whereas Scripted Damage is scripted. Not that there is anything all that significant about the analogy. :) )

Many, even most, Residents probably don’t even know that every AV is always at some state of Health, and that if that Health goes to zero, we “die”, in the sense that we are suddenly teleported Home, just as though we’d hit control-shift-h or whatever.

The reason that people don’t know this is that the vast majority of SL land has the “damage enabled” flag turned off, so you’re always at 100% health, and the viewer doesn’t normally even bother displaying the health meter in that case.

But if you stop by my Park in the center of Hughes Rise, or various other places, and then look carefully, you’ll be able to find a little heart on the screen, probably with a “100%” next to it. It you fly or teleport a few dozen meters into the sky and let yourself fall, or fly at high speed into a tree, or other amusing things, the number may go down from 100% (and then rather quickly go back up again). If you lose enough health fast enough, you may even hear your AV make a little supposedly gender-appropriate pained-grunt sort of noise.

And if you get the little number next to the heart down to 0%, you will suddenly be teleported home.

Now that sounds like a useful basis for a combat system, but it really isn’t, because it’s relatively easy to script up an object that instantly kills anyone it’s pointed at, and being teleported home isn’t a very flexible way to implement defeat (for instance it’s tough to script a scoreboard of “kills” or anything, just for one example), and healing is always exactly the same over time (no way to make “medikits” or “health potions” or anything), and it doesn’t apply to non-AVs (targets, monsters, robots, etc) and so on and so on.

So basically no one uses the built-in health and damage system for actual combat. What they use instead is Scripted Damage, which works by having the combatants wear some sort of attachment or other, that somehow finds out when they are “damaged” by “weapons”, or “healed” by whatever, and does whatever the system designer thought appropriate when they “die”.

The things that you wear that keep track of your damage generally have some sort of indicator of how healthy you are right now, in Scripted Damage terms, and are therefore generically called Damage Meters.

In today’s posting here, we will make a Damage Meter. Or, actually, we will discover that we’ve Already Got One!

(“Oh, yes, it’s very nice.“)

Already got one with a few modifications, that is; because it turns out that our self-healing target, from the self-healing target post, makes a very nice basis for an AV damage meter.

This is because of this Very Important Fact: when something hits your AV, all of your attachments see the collision event.

(I understand that this may not be true in OpenSim, or in some OpenSims, in which case damage meters there will have to work in some entirely other way of which I amn’t aware; I may explore that at some point too.)

So for instance if you were to take our self-healing target into inventory, and attach it to the center of your HUD say, and stand in front of the auto-popgun, you would see the health value above it go gradually down; and then if you step aside out of the stream of pellets, it will go slowly up again.

The only problem with it is that when it gets down to zero nothing useful happens. The script does an “llDie()” at that point, which you might think would cause the attachment to Cease To Be, or to detach or something, but in fact (another Interesting Fact) llDie() does nothing at all in attachments, so nothing actually happens.

This is easy to change, though. For now let’s just have the meter say something amusing when you “die”, to demonstrate that it is working. We will just change the process_collision routine so that it does something slightly different when health is zero, as in:

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        show_health(health,MAX_HEALTH);
        if (health<=0) {
            llSay(0,"Arg! "+llKey2Name(llGetOwner())+
                    " has been defeated!");
        }
        llSetTimerEvent(HEAL_SECONDS);
    }
}

(We also took out the “pow” and “clunk”, because we’re confident enough that things are generally working that we don’t need them anymore.)

So modify the target script as above, put it into a prim, wear that prim somewhere appropriate on your HUD, and stand in front of the auto-popgun or have a friend shoot at you, and you will find yourself being “damaged” and eventually being “defeated”.

Combat! Shazam!

Some other stuff one might want to do:

  • Support “medikits” or “health potions” or whatever, that heal you when, say, you walk (run) across them (I have code for that!),
  • Cause you to, say, fall down and stop running around when you “die” (I have code for that too!),
  • Remove your ability to use your own weapons while you are “dead” (I don’t have code for that yet, but I might talk about various approaches).

(The other thing I’m currently playing with, which I haven’t quite scripted up yet, is to have the targets, the “monsters”, be “lootable”, so that once you’ve defeated one you can touch it or something and get I dunno some kind of reward. If anyone knows of a sim or a system of scripts that does this sort of WoW-like lootable-monsters thing, let me know; I’d like to take a look!)

So that’s all for this time. Pew pew! :)

Welcome to Brown, 2003!

Some discussion somewhere on some weblog led me to go exploring off to Brown. As reflected in Lalo Telling’s great SL History postings, Brown is one of the “Color Sims”; not the very first sims created in the Grid, but still some of the oldest.

There are all sorts of interesting and touching and nostalgic sorts of things to be seen on Brown, giving insight of various kinds to the thoughts of the early Lindens and Residents about how the world might go, and how things have changed, and not changed, since then.

There are all these little pedestals with spinning hands scattered about, and touching one gets you this notecard from 2003, that’s worth posting in its entirety.

Brown
=====

Welcome to Brown! Brown is a controlled building community. A small suburban area, Brown is the perfect place to build your home if you’re looking for a nice, quiet region without the stores and looming towers you might find building elsewhere.

Here are some helpful guidelines to help maintain Brown:

You can own as much land as you want, but your build in Brown MUST be a conventional residence that might be seen in a suburb. This means that stores, dance clubs, sheep farms, and any other non-house builds are not permitted within Brown.

Builders are no longer limited to using the Mini-House-in-a-Box. But it’s available at the supply stores located around the perimeter of this region.

**Note: the following zoning regulations will be enforced:
* No terraforming. The land stays the way it is.
* No buildings taller than 15 meters. All buildings must be attached to the ground.
* You must build within your own property lines.
* No objects for sale, except within the stalls in the center of the region.
* No signs permitted.
* Noisy or flashing textures, particles, excessive and/or looping sounds, or any script that puts unnecessary strain on the region will be removed.

This region is located within a PG-Rated territory. All applicable rules, laws and community standards apply.

***Open Air Market***

This area in the middle of the region has been set up for people to sell or trade goods. The following rules apply.

* Only one 8 x 13 parcel per resident per sim.
* You can sell anything within the PG guidelines but it must be displayed within the stall.
* You can buy more land in the sim to support more objects in the market.
* Don’t delete the stall walls.

For some reason I especially love “Builders are no longer limited to using the Mini-House-in-a-Box”.

How far we’ve come! :)

Wind and Rotations

So I must apologize for (A) having gotten distracted from the combat-system scripting by thinking about the details of sailboat physics, and (B) posting some stuff here that is really just for me, but I thought it might someday be useful to someone else to, and besides this was a handy place to jot it down.

There are an annoying number of ways to write down rotations and directions and things in LSL, and different parts of the word want different ones. (And this is just, for the moment, talking about rotations in two dimensions!)

For instance, llWind() returns a vector representing the wind direction. Wind is (I believe!) always flat (parallel to the ground) in SL, so we can ignore Z. But what exactly are X and Y?

Well, Rule 1 (which I always forget and have to try out again) is that X is East and Y is North. So if for instance I am standing at 117, 119, 117 in Hughes Rise, on the walkway in the Park, and I walk one meter due North, I’ll be at 117, 120, 117. See how Y got bigger? And if I walk one meter due West from there, toward the stairs, I’ll be at 116, 120, 117; X got smaller.

So if llWind returns < 5, 0, 0 > for instance, that means the wind is blowing at five meters per second toward the East (and therefore is called a West wind, ’cause winds are called by where they are coming from, just to be confusing).

Now say you have a sail, and you want to know the angle between the sail and the wind. Well, the sail’s trim is represented as a rotation, which can be represented in LSL either as an actual rotation object (which has four components, corresponding to the four components of the corresponding quaternion, where a quaternion is of course an element of a four-dimensional associative normed division algebra over the real numbers), which is mathematically wonderful but not too useful for actually thinking about, or as a three-element vector, each element representing a rotation about the corresponding axis.

So for instance if your sail is flat in the X dimension, it will be facing head-on to winds coming from the east or west. If you then rotate it ninety degrees (which is a rotation of pi/2, or PI_BY_TWO, in radians) about the Z axis (the up-and-down one), it will be facing head-on to winds coming from the north or south.

To represent a rotation of pi/2 radians as a vector in LSL, we write < 0, 0, PI_BY_TWO >. Now the fun part! If I know the X and Y parts of the wind speed from llWind, and I have the rotation of my sail as a rotation about the Z axis, how do I figure out the angle at which the wind is hitting my sail?

Now I pause to think and experiment a little, so as to have an answer to write down in the next paragraphs. :)

Well, first of all notice that by using a symmetrical sail and a rotation of pi/2, I’ve sort of cheated; in particular, I didn’t have to figure out whether rotations are clockwise or counterclockwise (anticlockwise). This is probably obvious to smart people of various kinds, but I can never remember it (some Right Hand Rule or something is probably involved) so I have done the experiment and will write down Rule 2: Rotations are counterclockwise, or, to be precise and therefore meaningful, if you’re looking down at something that is not rotated, and you rotate it positively about the Z axis, it moves around anticlockwise.

This surprised me. :)

It makes sense, though, if we think back to like Trig 101 or whatever that was; X is East (i.e. to the right on the map), and Y is North (upward on the map), which is just how the graphs were all done on the board, and if you start out with a line running from the origin to < 1,0 >, say, and “rotate it” by some small angle theta, it goes up a bit into th’ ol’ First Quadrant there, which means it’s moved anticlockwise.

(Whoever designed clocks must have skipped that class or something.)

So we can represent wind direction as a rotation-about-Z by drawing it on the board there using the X and Y that we got from llWind(), and straightforwardly figure out what angle we would have to rotate that origin-to-1,0 line through to get it there, and it turns out to be (unless I’m wrong) llAtan2(Y,X); that is, the angle whose tangent is y over x.

So we have two rotation amounts, the amount that our sail’s been rotated and the amount that the wind’s been “rotated”, and we can just subtract them from each other to get the angle between them. If they’ve been rotated the same, the difference is zero, and our sail is getting (basically) all of the benefit of the wind. If they are ninety degrees apart, the sail is edge-on to the wind, and getting no benefit at all. Because we suspect there is probably something trigonometric going on here, we will note that llCos(0) is 1.0, and llCos(PI/2) is 0.0, and decide that we can do, say:


vector wind = llWind(ZERO_VECTOR); // The wind right here
float windrotz = llAtan2(wind.y,wind.x);
vector sailrot = llRot2Euler(llGetLocalRot());
float sailrotz = sailrot.z;
float rot_difference = windrotz - sailrotz;
float wind_effect_on_sail = llCos(rot_difference);

and so wind_effect_on_sail will be 1 if the wind’s blowing right onto the sale, will be 0 if the wind is blowing edge-on onto the sail (luffing!), and will be inbetween in between. (It will also be negative, I think, if the wind is blowing on the wrong side of the sail, but I haven’t thought about that yet.)

And some similar calculation can be used to get the angle between the sail and the hull (or, really, the keel), to figure out how much of the wind’s effect on the sail then contributes to the forward motion of the boat. But that’s a little later. :)

Combat System Scripting IV: the auto-popgun

Before we continue in our series from targets to personal combat-meters, it will be convenient to have something that shoots.

So far we’ve been using whatever projectile weapons happen to be in inventory to shoot at targets, but as soon as we want something to shoot back, we’re going to need either a patient and/or interested friend (but those aren’t always available at short notice), or something that will shoot on its own.

And to avoid the complexities of bullets and all, we’re going to cheat. :)

Here’s what you do to get our project for today, the auto-popgun:

  1. Search inventory for “popgun”,
  2. Find the last one that shows up; it should be in the library rather than your personal inventory, and be called something like “Popgun (drag onto yourself)”,
  3. Don’t drag it onto yourself, but just onto the ground.
  4. Edit it, rename it to say “autopopgun”, set the rotations to 354, 0, and 0 (so it’s pointing down a little), and raise it up a bit off the ground.
  5. Go into Contents, open the Popgun script in there, and replace all the text with the script below.

It should then sit there shooting a little ball every second or so, and the little balls should vanish on their own, just as if you were shooting it yourself.

You can rez one of the targets we made earlier in its path, or rez a target and then rotate and move the gun so it’s pointing at it, and observe how the target satisfyingly gets damaged and vanishes, just like you’d expect.

Here’s the autopopgun script:

float SPEED         = 18.0;   //  Speed of bullet in meters/sec
integer LIFETIME    = 7;      //  How many seconds will bullets live 
float DELAY         = 1.0;    //  Delay between shots

default
{
    state_entry() {
        llSetTimerEvent(DELAY); 
    }
    
    on_rez(integer param) {
        llSetTimerEvent(DELAY);
    }
    
    timer() {
        string bullet_name = llGetInventoryName(INVENTORY_OBJECT,0);
        vector vel = <0,SPEED,0>*llGetRootRotation();
        vector pos = llGetPos()+vel/SPEED;      
        llRezObject(bullet_name, pos, vel, ZERO_ROTATION, LIFETIME); 
    }
  
}

Pretty simple script, boiled down from the original popgun script by taking out all of the user-interaction stuff. Basically, once a second, in the timer() event, it figures out the name of the first object in inventory, figures out which way it (the gun) is pointing, and rezzes one of those objects moving in that direction at the given speed SPEED.

It passes the LIFETIME number along to the objects that it rezzes, and as it happens the bullets in the popgun read that number and delete themselves after that many seconds. But we don’t have to worry about any of that, because we cheated and didn’t have to do the bullet scripting ourselves! We are so lazy… :)

Next time, or some time after, or something: our first personal combat meter, so we can stand in the way of the popgun and be shot and take damage!

NeoVictoria Photo Contest

So I got a note about this awhile back, but I am lazy and/or busy so now of course it is almost over, but not quite! And anyway this is a steampunk sort of place that I hadn’t run across before, and those are always fun.

Click through the poster above there for details, or go to the page via this link here.

Combat System Scripting III: target, heal theyself

Okay, short one! No picture! :)

Starting with the final script from last time, as usual, the simplest way to allow our targets to gradually heal themselves over time, is to just stick in a little timer that will increase health back up to maximum:

  timer() {
    if (health<MAX_HEALTH) {
      health += 1;
      show_health(health,MAX_HEALTH);
    }
  }

and add something to, say, state_entry(), that starts the timer, so that state_entry() would now look like this:

    state_entry() {
        show_health(health,MAX_HEALTH);
        llSetTimerEvent(HEAL_SECONDS);
    }

with HEAL_SECONDS set to like 2.0 or something at the top.

And if you do that and play with it, you’ll find that it works. You may also notice that once in awhile when you shoot the target, it will instantly heal again, which is annoying.

To fix that, we can make sure that the timer is running only when there is actually damage to heal, by moving the “start the timer” line to the place where the target notices damage, and adding a “stop the timer” line to the timer itself, whenever it’s at full health.

And so tonight’s final result looks like this:

integer MAX_HEALTH = 20;
integer health = MAX_HEALTH;
float HEAL_SECONDS = 2.0;

vector color_for(integer h,integer max) {
    float ratio = (float)h/(float)max;
    if (ratio>0.666) return <0,1,0>;   // Green
    if (ratio>0.333) return <1,1,0>;   // Yellow
    return <1,0,0>;  // Red
}

show_health(integer h,integer max) {
    llSetText((string)h+"/"+(string)max,color_for(h,max),1);
}

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        show_health(health,MAX_HEALTH);
        if (health<=0) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"pow");
        }
        llSetTimerEvent(HEAL_SECONDS);
    } else {
        llSay(0,"clunk");
    }
}
default {
    state_entry() {
        show_health(health,MAX_HEALTH);
    }
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
    timer() {
        if (health<MAX_HEALTH) {
            health += 1;
            show_health(health,MAX_HEALTH);
        } 
        if (health>=MAX_HEALTH) llSetTimerEvent(0.0);
    }
}

We make such progress! :)

Combat System Scripting II: slightly buffer target

Ah, now I remember! Before going on to other things besides the basic target, I was first going to make the basic target a little less basic.

In this posting, we’ll make the targets a little more robust, so it takes more than one collision to make them Cease To Be (or, in more violent language, more than one shot to kill them).

We’ll also, by the end, stick some nice color-changing floaty text over them, so you can tell how many collisions away from Ceasing to Be they are. (I’m sort of swerving between showing how a combat system might work, and giving little lectures on programming style, here, but it’s my weblog and I can do what I want! Feedback welcome if you’d like to see it go faster or slower or whatever, although I don’t promise to necessarily do what any feedback might suggest.)

The nice simple target script from last time was this:

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        llSay(0,"boom");
        llDie();
    } else {
        llSay(0,"clunk");
    }
}
default {
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
}

To make the target a little harder to kill, we’ll add a “health” variable to keep track of just how many more hits it has left, and update process_collision to count that variable down, and do the Cease to Be thing only when it reaches zero. Other hits will just make some I dunno “pow” noise. So:

integer health = 20;

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        if (health<=0) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"pow");
        }
    } else {
        llSay(0,"clunk");
    }
}

The rest of the script (the collision_start() handler in the default state there) stays the same.

So play with that a little. It’s very nice, but it’s lacking some indication of how damaged the target is. We’ll add the floaty-text for that. It’ll require a new event handler in the default state to initialize the floaty text in the first place, and then some new code in process_collision to update the text when it’s hit.

That gets us to something like this:

integer health = 20;

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        llSetText((string)health+"/20",<1,1,1>,1);
        if (health<=0) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"pow");
        }
    } else {
        llSay(0,"clunk");
    }
}
default {
    state_entry() {
        llSetText("20/20",<1,1,1>,1);
    }
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
}

This works nicely, but it is Evil because very similar llSetText() calls appear in two different places, and the “20″ appears in four different places, which means that if I decided to change it to only take 10 hits, say, I would be sure to miss at least one of them.

With the maintainability improved, it does exactly the same thing, but looks nicer:

integer MAX_HEALTH = 20;
integer health = MAX_HEALTH;

show_health(integer h,integer max) {
    llSetText((string)h+"/"+(string)max,<1,1,1>,1);
}

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        show_health(health,MAX_HEALTH);
        if (health<=0) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"pow");
        }
    } else {
        llSay(0,"clunk");
    }
}
default {
    state_entry() {
        show_health(health,MAX_HEALTH);
    }
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
}

Much better.

And for one final touch, we can make the floaty text be green or yellow or red depending on how damaged the thing is, by just changing the <1,1,1> in show_health(), which causes it to always appear white, to a call to yet another function that will calculate the right color for us.

The final form for today, then:

integer MAX_HEALTH = 20;
integer health = MAX_HEALTH;

vector color_for(integer h,integer max) {
    float ratio = (float)h/(float)max;
    if (ratio>0.666) return <0,1,0>;   // Green
    if (ratio>0.333) return <1,1,0>;   // Yellow
    return <1,0,0>;  // Red
}

show_health(integer h,integer max) {
    llSetText((string)h+"/"+(string)max,color_for(h,max),1);
}

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        health = health - 1;
        show_health(health,MAX_HEALTH);
        if (health<=0) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"pow");
        }
    } else {
        llSay(0,"clunk");
    }
}
default {
    state_entry() {
        show_health(health,MAX_HEALTH);
    }
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
}

Isn’t Nature Wonderful?

Next time, maybe: target, heal thyself!

Combat System Scripting I: intro and our first target

As foreshadowed previously, we will now begin a series of posts about the Combat System Scripting we have been doing, because (a) it will be fun, and (b) it might be interesting.

What I’ve done so far, and hope to get to in this series, includes:

  • Stationary targets to shoot at,
  • Moving targets that shoot back,
  • A combat HUD that keeps track of your “damage” and makes you fall down when you take too much,
  • A “medikit” that makes you be less damaged when you walk through it.

Which is enough to have fun battles with your friends and/or Daleks. :) We’ll talk about just that first one in this episode.

A couple of notes:

  • If you just want to have a working combat/RP system to play with, and don’t want to learn scripting of it from first principles, take a look at Myriad Lite (Preview 4) on the Second Life wiki; lots of neat features (and a certain amount of complexity) there.
  • I’m going to assume here that you know how to rez a cube, and how to get a script into one. Not much more than that, though!
  • Loose design goals of the project will include compatibility with various existing things (e.g. it would be good to be able to shoot at stuff with any normal sort of SL weapon), and a preference for less inter-object communication over more, where that’s possible (to reduce lag and complexity).
  • I’m not going to worry too much about preventing ‘cheating’ of various kinds; this is mostly to play with, not to organize serious combat RP with untrusted others around.

Okay, off we go!

The first thing we’ll make is a simple target. Here’s probably the simplest possible target script:

default {
    collision_start(integer n) {
        llSay(0,"clunk");
    }
}

This says, basically, “whenever something collides with you, say ‘clunk’”. (You can change that line to ‘llOwnerSay(“clunk”);’ if you don’t want anyone else to hear the object talking for whatever reason.) Technically the stuff inside “collision_start” is an event-handler, and in this case the event is something hitting the prim that the script is in.

So make a cube, put that script into it, and walk into the cube. It will say “clunk”. Amazing!

Of course walking into things is sort of boring, so let’s get out a weapon and shoot at the cube bang bang. Any weapon that fires actual projectiles will do; if you don’t have one, or aren’t sure of what you have, you can use the simple popgun that is in the standard SL library (the lower part of your inventory, where many people never go; there’s some pretty good stuff in there).

Find the popgun, wear it, go into Mouselook (via the Mouselook button, or pressing M, or whatever), mouse so the little crosshair is on the box (the popgun has weightless projectiles, so you don’t need to compensate for any drop), and click. A thing will emerge and hit your cube (with some amusing colors and sounds and bubbles), and the cube will say “clunk”; huzzah!

Just saying “clunk” is good to be able to tell that you’ve actually hit it, but if we’re going to do Combat we want the target to explode into a flaming ball of gas. Well, or at least to Cease To Be, since I’m not going to figure out a particle-system for a Flaming Ball of Gas today.

So here’s another script:

default {
    collision_start(integer n) {
        llSay(0,"boom");
        llDie();
    }
}

Replace the original one with this one, make a copy of the prim, and then walk into it or shoot at it, and it will say “boom” (which sounds more final than “clunk”), and Cease To Be (quite thoroughly Cease To Be, not in your trash or Lost and Found or anything, which is why I suggested you make a copy of the prim).

You can use shift-drag (or just rez a bunch of copies) to make a whole row of these, and either run along it or go into mouselook and pop them one at a time, boom boom boom boom.

Not bad for a six-line script!

Now it’d be better if the target didn’t actually Cease To Be if someone just casually bumped into it. There are various ways to try to tell casual bumps from official Weapon Projectiles; we’ll use one of the simplest: speed. If somehthing is moving more than, say, fifteen meters per second (which is about as fast as it’s possible for a lone AV to move in normal circumstances), we’ll assume it’s a Weapon Projectile (or maybe a car; getting hit by a speeding car counts); but if it’s moving slower than that, it isn’t. So:

default {
    collision_start(integer n) {
        if (llVecMag(llDetectedVel(0))>15) {
            llSay(0,"boom");
            llDie();
        } else {
            llSay(0,"clunk");
        }
    }
}

The only new complexity here is the “llVecMag(llDetectedVel(0))” bit, which just means “the scalar magnitude of the velocity vector of the thing that hit us” which is to say, how fast it was going.

The (0) means “the first of the N things that hit us”, where N is almost always 1 (so it looks at the first and only thing that hit it), but in some situations, especially when there are lots of bullets flying about, two or more things can collide with the cube so quickly that they’ll both get reported in the same collision event.

If we were just saying “clunk” that wouldn’t matter too much, but if (say) a slow bump happened at the same time as a fast projectile impact, we wouldn’t want to look at just the slow bump. So we’ll add a loop that looks at each of the things that hit us, in case there’s more than one.

default {
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) {
            if (llVecMag(llDetectedVel(i))>15) {
                llSay(0,"boom");
                llDie();
            } else {
                llSay(0,"clunk");
            }    
        }
    }
}

Relatively straightforward.

And then, and finally for this episode, just because I like to keep blocks of code simple wherever possible, we’ll pull out the bit of code that gets done for each colliding thing in to a subroutine of its own, and call it from the event handler:

process_collision(integer index) {
    if (llVecMag(llDetectedVel(index))>15) {
        llSay(0,"boom");
        llDie();
    } else {
        llSay(0,"clunk");
    }    
}
    
default {
    collision_start(integer n) {
        integer i;
        for (i=0;i<n;i++) process_collision(i);
    }
}

And there you have it! A nice target that can be bumped into with impunity, but that goes away with a boom when shot (or when run into at high speed in a Chevy, I expect, although I haven’t tested that… yet).

Next time, hm, I dunno… maybe the Combat HUD or something…

UGCFTW5!

Well, the news has somehow leaked out that today is my fifth rezday; it’s been five years since I joined Second Life (presumably on 22 November, 2006).

I remember some time back (must have been quite awhile) I was lucky enough to attend a Fifth Rezday Party for Washu Zebrastripe (the inventor of prim hair!), and we were all astounded that anyone could have a Fifth Rezday Party. Of course, as I recall, this was shortly before SL5B, and for a Resident to be older than the world itself is pretty amazing.

I can’t claim that distinction. :) But I do have a last name (or a dot in my name, depending how you look at it), and I remember when the Grid used to go down like every Wednesday (at the very least), and when we had real lag, not these tiny slowdowns that youngsters complain about these days. (We didn’t have none o’ these “sculpties”, either; flexi-prims were new and shiny enough for us!)

I thought I would take a few minutes’ break from the fireworks and parades in my honor and so on to say how great I still find SL, and scribble down my thoughts on some of the reasons why.

It’s very significant, I would say, that I’ve just starting taking a serious look at PvE combat and combat scripting in the last couple of weeks. And similarly that I just started breeding my first breedables in the last few months. Two things, each of which have been around for a long time, each of which are The Big Thing about Second Life to a significant number of people, and yet it’s taken me Five Years to get around to them. And there are still more things waiting for me that I haven’t tried at all yet; probably haven’t even heard of yet.

On the other hand I haven’t played World of Warcraft in weeks (months, maybe); because I’ve done everything that I want to (one 85 DPS, one 85 healer, one 85 tank, all the raiding experience I felt like getting). I may get lured back in for awhile to play a Pandaren, and to get my main toons up to level 90, but then I will probably get bored again.

And dearly as I love Glitch for its humor and quirkiness and art, I haven’t been doing any more recently than poking my head in, tending my little garden, squeezing my chicken and milking my butterfly, maybe gathering a few beans from the nearest bean-trees, and leaving again. There’s a complete encyclopedia of everything there is to do there, and I’ve either done, or decided not to bother doing, just about all of it. I know the devs will be adding stuff, eventually, and then maybe I’ll come back to look at it.

I occasionally get messages from other virtual worlds I’ve tried, like Blue Mars and Twinity and all, about how a new shopping mall has been added, or how they’ve added a new beach where there’s a vehicle you can drive around. And these make me laugh, because they’re so trivial. Can you imagine getting a piece of mail every time someone made a new model of car or motorcycle in SL, or opened up a new shopping mall or public beach? Talk about information overload!

The reason, the only reason that Second Life has been able to hold my interest for five years, is that users can create stuff.

(The people I’ve met there also hold my interest, but that’s interest in the people, which could have been maintained via Skype or email or even (gasp) actual visits, even without SL.)

So this is going to be another post like my original UGC FTW post (three years ago, I see!), only somewhat less organized. :)

User-generated content instantly gives Linden Lab a huge staff of unpayed (and for that matter of paying) content developers, who produce the content that keeps people coming back to the world, and keeps them wanting to live there, and keeps there being brand-new stuff all the time, driven by the Invisible Hand of the Market to cater to users’ wants. User-generated content isn’t just about the creators; in fact it’s not even primarily about the creators. It’s primarily about the people who see or get or buy or otherwise experience the work of the creators, and thereby find the world an interesting and enjoyable place.

(I say it’s “primarily” about the content consumers rather than the content creators because, with a few exceptions, we all consume more content than we create; we all enjoy more stuff that other people make than we make ourselves. I create lots of content that I like and that I hope other people like, but I experience orders of magnitude more content created by others.)

I think this is the key thing that most of the people tossing around the weird little milkshake analogy lately are missing. (The original article, headlined as it is “Why Second Life Failed”, of course seems to me to be coming from some Zone of Deep Cluelessness, since as far as I’m concerned SL is doing just fine thank you.)

All of this “milkshake” thing seems to boil down to saying that you can figure out which products are going to succeed by figuring out what they are for, and then seeing if that is something that people want. (Deep, eh? I wish I could think of deep stuff like that and then write books about it and all.)

I think this is actually wrong and/or stupid in many cases; I would argue that most innovations have been potentially able to do lots of different things, and the reason they succeeded is that their owners were able to figure out pretty quickly which of those things people actually wanted, and bend them in those directions. (In fact even the original milkshake example shows that, if you consider the product to be the store and its services as a whole, rather than just the milkshake line.)

And that’s exactly the right way to think about Second Life. It’s not designed to provide one specific thing; it’s designed to let people create and provide to each other whatever it is they want (within the capabilities of the platform). That general approach can’t lose. The platform has to have good enough affordances for people to actually use it, it has to have good mindshare and stability and so on, it has to be sufficiently funded to survive dry times, and so on; but the general principle is just pure win.

From this point of view, it would be exactly wrong to try to figure out what Second Life is, or should be, designed to do, except for the very high level “to enable people to create and experience stuff that they want to create and experience”. As we (and the Lab) notice some kinds of things that people are using it to create and experience right now, we can definitely make sure that the world is, and stays, good at those things. But that doesn’t mean we can decide that those are The Things, and focus only on those. Enabling User-Generated Content in general, and keeping the world good at that, in general, is in my very strong and pronounced opinion the right way forward. If Linden Lab doesn’t do that, someone else will; and whoever does do it will win.

(And that will eventually mean lots of money, as I’ve observed before.)

So anyway. :) Those are my Fifth Rezday Thoughts on why it is that I’m having a fifth rezday at all, and why and how Second Life has held my interest for all this time, and how it can keep doing that, for the Good of All.

Now, back to the cake!

Follow

Get every new post delivered to your Inbox.

Join 50 other followers