Wednesday, December 28, 2016

CSD Noise-Canceling Headset

The NCH is up on Marketplace at last, and will be in the vendors shortly.  There seems to be debate over the correct spelling of "canceling" - whether it should have one or two 'l's, so I'll continue to refer to it as the NCH.(which could also be an acronym for "No Chat or Hearing").

Stand-alone use

Out of the box, the NCH acts very much like any other SL restraint - clicking on it gives a menu to the wearer or to the avatar named as the NCH's "owner", and a helpful message (but no menu) to anyone else.  The wearer's and owner's menus are very similar, except that only the owner's menu allows for resizing the headset, and for changing the owner (if the NCH isn't locked on).  The bulk of both menus is for setting restrictions.

The supported restrictions on communication are:
  • Silent - wearer may not speak in local
  • IM block - wearer may not use IM
  • Deaf - wearer may not hear local chat
  • Lock - The headset may not be removed
If an owner has been set, then the owner is exempt from the IM block and Deaf restrictions - you can always hear your owner's speech or IMs.  Both the wearer and the owner can set restrictions.  The wearer can remove restrictions they have set themselves, but they cannot remove restrictions set by the owner.

The headset can be set to be invisible.  Headset visibility is considered a restriction, so if the owner has selected "Visible", the wearer cannot make the headset invisible;  if the owner makes the headset invisible, the wearer can make it it visible or invisible at will.

The Resize button allows the wearer to make the headset larger or smaller, either across the head, or up and down.  "Std Height" and "Std Width" will reset the height and width to their initial values.

In addition, the NCH can relay chat spoken by the wearer in local to either IM to their owner, or to Mesmerizer chat (if a network-enabled Mesmerizer is worn) even if the Silent restriction is in effect..  When relaying is enabled, the LED on the earpiece that holds the microphone boom will light, and the color will indicate whether the wearer's chat is being relayed to IM (red), to Mesmerizer chat (blue), or to both (green).  Relaying to IM and to Mesmerizer chat are also considered restrictions, so they can be enabled by either the wearer or the owner, but the wearer cannot disable them if they were enabled by the owner.


Control via a Mesmerizer

If the wearer uses a CSD CHAOS Mesmerizer, then all the controls described above can be accessed from the Mesmerizer (which acts as if it were the owner, in the sense that the wearer will not be able to remove a restriction set via the Mesmerizer).  In addition, the Mesmerizer can change the Owner setting of the NCH (this operation is not available to an owner via the menu).  All these operations use the pansend or pansendpars Mesmerizer commands.

The NCH will identify itself as a PAN station called "headset".  The Mesmerizer pandir command will show the stations currently logged on to the PAN.

The following Mesmerizer commands are used to control the NCH:

CommandDescription
pansend headset lockLock the headset
pansend headset unlockUnlock the headset
pansend headset showMake the headset visible
pansend headset hideMake the headset invisible
pansend headset silentApply the Silent restriction; prohibit the wearer from speaking in local
pansend headset nosilentRemove the Silent restriction; allow the wearer to speak in local
pansend headset imrelayRelay the wearer's local speech via IM to their owner
pansend headset noimrelayStop relaying the wearer's local speech via IM
pansend headset mesrelayRelay the wearer's local speech to Mesmerizer chat
pansend headset nomesrelayStop relaying the wearer's local speech to Mesmerizer chat
pansend headset blockimPrevent the wearer from using IM (except to their owner)
pansend headset noblockimPermit the wearer to use IM
pansend headset deafPrevent the wearer from hearing local chat
pansend headset nodeafAllow the wearer to hear local chat
pansend headset noownerRemove the owner
pansendpars headset owner <key>Set the avatar whose key is <key> as the owner
pansendpars headset status <key>Tell avatar <key> the current state of the headset
pansendpars headset help <key>Send help on the headset commands to avatar <key>


Since the Mesmerizer can be configured to work grid-wide, using the NCH with a Mesmerizer allows the NCH to be controlled from anywhere on the grid (or even from the web). This means that you can force-wear your sub's NCH remotely, and then have it apply whatever restrictions you like.


Uses

The headset's main purpose is to impose controls on a sub when you're not present, reinforcing your control over them.  However there are a number of other interesting use-cases.

If you have a number of subs who share a single Communications Hub (or whose different Hubs are bridged together via The Enforcer), then the NCH can be serve as an easy-to use way for the subs to communicate with one another, simply by enabling Mesmerizer chat relay.  This will allow all subs to hear one another's speech in local.  Turning on the Silent restriction will mean that their speech is redirected to Mesmerizer chat as opposed to being copied there, allowing the subs to communicate with one another relatively privately.  This use-case is something that the sub may want to employ for their own convenience.

Setting IM Relay, Silent and Deaf restrictions together provides for an interesting "isolation" effect.  The sub will be able to communicate with you in chat (they will be able to hear your chat, and you will receive anything they try to say as an instant message).  However, nobody around will hear what the sub is saying, and the sub will not be able to hear anyone but you.



Thursday, December 15, 2016

Mesmerizer 0.99e

I was expecting the next release of the Mesmerizer to be focused on the new RLVa features, but a nasty bug cropped up, for which I want to get a fix out as soon as possible.  The bug is in the Mesmerizer initialization, and the vast majority of people never encounter it.  However, a small number of users have found that their brand new Mesmerizer issues an error message during initialization and then refuses to work.  I have had three reports of this, and it turns out to be a timing bug. 0.99e contains a fix for it.  Now, the Mesmerizer initializes itself the very first time its worn, and usually has no reason to re-initialize, so if your Mesmerizer is working, then you've avoided this bug.

There is one piece of new functionality in 0.99e.  In a post in January of this year, I introduced the textcolor command, which allows you to specify the color that the text command will use for on-screen text.  I added this command because my testing found that some colors are more readable than others, but which colors are best varies tremendously from person to person.  So allowing you to set your preferred color was my first stab at improving readability.  However, whatever color you pick is going to be hard to read against a similar colored background.  So 0.99e has made a slight enhancement to the textcolor command - as an alternative to specifying a color (either by name or as an RGB vector) you can now specify the keyword cycle, which will make the text rapidly cycle through a number of colors, which should make it stand out against any relatively static background.  Along with the color cycling, the text command has been enhanced to allow for multi-line text, with line-breaks indicated by a "\n" character sequence (backslash followed by "n").  While this may seem a minor tweak, the use of vertical spacing can be quite effective in trances.  With the new ability to "stack" text vertically, I have also significantly extended the time for which displayed text remains on-screen.  If you want it to disappear earlier, just use either use the text command again with an empty string as a parameter: text "", or you can use the clear command, which will also remove any images that are being displayed.

This work actually came out of another product I have under development, the Focus Couch, which I'll describe in a post in the near future.  Mesmerizer 0.99e should be in vendors and on Marketplace tomorrow, and going out to previous purchasers at the same time.

12/23 Edit to the above - Mesmerizer 0.99e is in the vendors and up on Marketplace, but I've decided not to push it out to previous purchasers.  The bugfix, while important, only affects initialization, and I've already given replacements for anyone who ran into that.  The new functionality around the text command, while nice, isn't worth bothering everyone with an update.  If you have an earlier version and want to upgrade to 0.99e, just send me an IM or notecard and I'll get a replacement out to you, otherwise wait until the next update, which should be much more significant.


Sunday, November 6, 2016

Mesmerizer Release 0.99d, and New Product Preview

The Mesmerizer release mentioned in the previous post is now up in vendors and on Marketplace, and existing customers should have received an automatic update.  As described earlier, this release adds Named Triggers (intended to allow triggers to be added automatically without creating multiple copies) and the updated PAN protocol.  I expect the next Mesmerizer release to support some more of the RLVa 2.0 features.

As I mentioned in the previous post, I have made a minor update to the PAN protocol.  The Mesmerizer PAN is a communications protocol that's designed to make it easy for the Mesmerizer to communicate with other worn attachments.  Accessing the PAN from the Mesmerizer is fairly easy - there are commands to send messages, and you can create an internal trigger to receive messages.  But why would you want the Mesmerizer to talk to other attachments?  Well, all the Mesmerizer's features are available remotely (if the Mesmerizer's connected to a Communications Hub), so any device that communicates with the Mesmerizer via the PAN is also potentially available remotely.  As a concrete demonstration of this, I will soon be releasing a new mini-product - The CSD Noise-Canceling Headset.   Here's a picture of the pre-release version:

Just like the real-world version, the Noise-Canceling Headset (henceforth referred to as "NCH") can prevent extraneous sounds from reaching the wearer's ears, rendering the wearer unable to hear local chat.  However, the CSD version can also cancel noise generated by the wearer - preventing them from speaking.  It can also be set to block IMs.

However, it's not all restrictive.  It can also be set to relay anything the wearer says (or tries to say, if speech is blocked) to an IM to their "owner", or to Mesmerizer chat.  The wearer gets to turn any of these features on or off, unless their owner has turned the feature on (in which case it stays on until the owner switches it off).

While the CSD NCH can be used stand-alone, it can also be controlled via the PAN by a Mesmerizer, using the pansend and pansendpars commands.  All features of the NCH can be controlled through the PAN, which means that the headset can be completely remotely controlled, just by connecting the user's Mesmerizer to a Hub, or can be voice-controlled via appropriate trigger definitions.

Going forward, I expect to release further PAN-connected accessories, and possibly plug-ins for third-party products.

Tuesday, October 11, 2016

October 2016 Update

The new Mesmerizer release promised back in August is very nearly ready.   As described in an earlier post, this contains the signal command, used to signal user-defined events to The Enforcer:

Command Parameters Description
signal 2 signal an event named <p1>, passing <p2> as a parameter

So if a Mesmerizer executes the command signal myevent "my parameters", and it is connected to a Hub that has an Enforcer connected to it, then inside that Enforcer, an event named myevent will be triggered, with the user and sim as parameters.  So The Enforcer will execute the first of these notecards that it finds in its inventory:

myevent:<username>:<sim-name>
myevent:<username>:*
myevent:*:<sim-name>
myevent:*:*

In addition to the regular variables defined for an event, the string given as <p2> to the signal command will be stored in a variable called data, to allow the event handling code to make use of it.  This command allows you to define custom events within one or more Mesmerizers, and push them to The Enforcer for processing centrally.  I imagine a future variant of the signal command taking a more structured <p2> parameter, resulting in setting multiple variables within the event handler, but for now a simple string is all there is.


This release also introduces the new named trigger concept.   A named trigger is exactly what it sounds like - a trigger that happens to have a name.  A regular trigger is defined with a command like:

sleep now $rpname = hypnotize

A similar named trigger would be defined like this:

sleep now $rpname == trance hypnotize

The use of a double-equals "==" symbol identifies this as a named trigger definition, and the name is the word immediately following the ==, in this case "trance".   Any scope specifier (me, subject, etc) would appear between the name and the trigger action:

sleep now $rpname == trance me hypnotize

Named triggers behave differently from regular triggers in that the definition of a named trigger will replace an existing definition with the same name, if one exists.  A regular trigger will always be added.  The main purpose of this is so that triggers can be added "idempotently" (a fancy word that simply means doing it multiple times has the same effect as doing it once), which allows for triggers to be set automatically by things like The Enforcer, the MesmerX or the HoloTrainer.  A regular trigger definition would always add the trigger, resulting in duplicate triggers if the sub ran a trance or event more than once.

The following new commands that relate to named triggers are defined:

Command Params Description
ntdel 1 Delete a trigger named <p1>
ntadd 2 Give trigger number <p1> the name <p2>
ntren 2 Rename trigger named <p1> to <p2>

I have tried to make these commands play well with regular un-named triggers too.  You should be able to use either a number ("1") or a # followed by a number ("#1") to identify an existing trigger, whether or not it is named.  This means, for instance, that the ntdel command can be given a number as a parameter (e.g. ntdel 3) to delete trigger number 3.  Obviously this means that you can't use a number (or a "#" followed by a number) as a trigger name, and the Mesmerizer should ignore any attempt to use such a name.


The other major enhancement in this release is an overhaul of the PAN protocol.  The Mesmerizer creates a "Personal Area Network" or PAN that other attachments worn by the Mesmerizer's wearer can connect to, to send and receive data from the Mesmerizer (or from one another).  A developer's script to interface to the Mesmerizer's PAN is available on request.

Each attachment that connects to the PAN is termed a "Station", and is identified by a station name.  There is nothing to prevent multiple attachments from using the same station name, and they will all receive messages directed to that station name, but this situation should be avoided if possible.

These commands relate to the PAN.  The first two are existing commands; the third is new in this release.  If a * is given as the first parameter to pansend or pansendpars, then all stations on the PAN (except for the sender) will receive the message.

CommandParamsDescription
pansend2Send message <p2> to PAN station <p1>
pansendpars3Send message <p2> with parameters <p3> to PAN station <p1>
pandir0List all stations on the PAN.

If <p3> of pansendpars is used to pass multiple parameter values, they should by convention be separated by colons.

Receiving PAN messages in a Mesmerizer is done by declaring an on-pan internal trigger, which will be fired whenever the Mesmerizer receives a PAN message.  Within this trigger, the following variables are defined:

VariableContents
sourceSending station-name
pancmdThe message that was received
pan0First parameter
pan1Second parameter
pan2Third parameter
pan3Fourth parameter

pan0 through pan3 are obtained by splitting the received parameters at colons.  A future release may add a pars variable which will contain the entire parameters as a single string.


Why the focus on the PAN in this release?  I am about to release a small toy that, while it can operate stand-alone, can also be controlled through the Mesmerizer, via the PAN.  This is intended as a demonstration of the ability of the Mesmerizer to control any compatible attachment, which in turn will allow such attachments to be controlled remotely, grid-wide or from the web, simply by connecting the Mesmerizer to a Hub.  More details to come in another post.


Thursday, August 4, 2016

The Enforcer - Programming


Programming the Enforcer is fairly simple.  First you decide which event you want to respond to, and then you create a notecard that specifies the action(s) to perform when that event fires.  Let's assume you have a Hub called "Hub_A", and you want to have the Enforcer send an email to you when Hub_A changes its address.  First you create a notecard containing the action(s) you want to perform, in this case sending an email.  Here's what the contents of that notecard might look like:

Hub_A address is $hubAddress
!mailto you@yourEmail.com::New web address for Hub_A::Use this URL to connect to the hub:\n $hubAddress



There are two lines in the notecard, although they may wrap in your browser.   Each line is an action, and they are executed in order.  Actions come in several flavors: announcements, comments, calls, local commands and Mesmerizer commands.  The first character of the line is used to determine which flavor the action is.  Local commands begin with an exclamation point (!), comments begin with a hash or pound sign (#), Mesmerizer commands begin with an up-arrow (^), a call begins with an at-sign (@) and anything else is an announcement.  So in this example, the first action is an announcement, and the second is a local command.  Let's take them in order.

First we have the announcement: Hub_A address is $hubAddress.
Announcements are simply sent verbatim as instant messages to the Enforcer's owner.  The intent is that, for debugging, you can write your action notecards with every action as an announcement, and then when the event occurs, you'll see the commands that would be executed, without them actually doing anything.  Once you're happy that they appear correct, you can add the appropriate "action character" at the start of each line to make them function.  So the first line will send the Enforcer's owner an instant message saying something like:

 Hub_A address is https://sim123.agni.lindenlab.com:12043/cap/12345678-1234-5678-9abcdef01234 

Note that $hubAddress has been replaced by the address of the Hub.  This is an example of variable substitution, and is similar to how the Mesmerizer expands variables.  Each event is executed with a number of predefined variables, and additional variables can be set via a local command.  The "Address" event, which is what the notecard we are creating will respond to, sets the hubAddress variable prior to invoking the notecard.  Variables are expanded before the action is processed further.

The second line begins with an exclamation point, and it is therefore a local command.  The command is mailto, and it takes three parameters, which are separated from one another by double-colons (::).  The first parameter specifies the destination email address, in this case "you@yourEmail.com", the second is the subject-line of the email "New web address for Hub_A", and the third parameter is the body of the email "Use this URL to connect to the hub:\n $hubAddress".  As in the previous line, "$hubAddress" will be expanded to the actual URL of the Hub.  Note that the mail body parameter includes a "\n" sequence, which means "newline".

Now that we have the notecard, we need to make it be triggered by an Address event from Hub_A.  We do than simply by putting the notecard into the inventory of the Enforcer, and naming it "Address:Hub_A".  Whenever the Enforcer receives an "Address" event from Hub_A, it will execute the "Address:Hub_A" notecard.

That's fine, but what if you have lots of Hubs - you don't want to have to create a notecard for each of them.  And you don't - instead what you can do is modify the notecard slightly so that it's more generic:

Hub: $hubName address is $hubAddress
!mailto you@yourEmail.com::New web address for hub $hubName::Use the following URL to connect to the hub:\n $hubAddress



Instead of explicitly saying "Hub_A" in the actions, we've used another variable expansion, $hubName, to provide the Hub's name.  Any event signaled from a Hub will define the hubName variable.

Then, instead of naming the notecard "Address:Hub_A", we name it "Address:*".  In this context, "*" is a wild-card that will match any hub-name.  So when processing the Address event for Hub_A, the Enforcer will first look for a notecard called "Address:Hub_A" and if it doesn't find that, it will look for one called "Address:*".  This process always tries the most-specific match first, and once a notecard is found, it is executed and no further searching is done.

Logon and Logoff events (which are Hub-generated) are similar, except that the second "field" in the action notecard name is the legacy username of the user who logged on or off.   For example, if Mesmerizer user "John Smith" logs in wearing a Mesmerizer connected to Hub_A, their Hub will signal a Logon event and the Enforcer will look for a notecard named "Logon:John Smith", and then if that isn't found it will look for one called "Logon:*". 

Mesmerizer-generated events are handled in a similar way, with the most significant difference being that the name of a notecard to respond to a Mesmerizer event has three "fields":  the event-name, the avatar legacy name, and the sim they're in.  For example, if John Smith teleports to the Lochme sim, their Mesmerizer will signal an event to their Hub, which will send a "Location" event to the Enforcer, which will then look for a notecard named "Location:John Smith:Lochme".  If that isn't found, it will then look for a notecard named "Location:John Smith:*", and if that isn't found, it will look for "Location:*:Lochme".  Finally if none of those notecards are found, it will look for "Location:*:*".  This process allows you to create generic responses for Location events, and over-ride them for particular users and/or particular sims.

Here is the complete list of pre-defined events:

Event Name Parameter(s) Description
Logon Username User logs on to a Hub
Logoff Username User logs off a Hub
Address Hub-name Hub changes its address
Location Username, Sim-name User moves to a new sim or changes position within a sim
Update Username, Sim-name Periodic "keepalive" event


Additional user-defined events may be signaled from a Mesmerizer with the new signal command.  This Mesmerizer command takes two parameters:   the name of the event, and a "parameter" string that is used by the Enforcer to set a variable prior to dispatching the event.  In the Enforcer, the event will be dispatched with the two standard parameters: Username and Sim-name.


Now that we have a feel for how a response notecard is picked for a given event, let's look in more detail at what such a notecard can contain.  We've already covered announcements.  Comments - lines starting with a # - are simply ignored.  Mesmerizer commands - introduced by an up-arrow (^) - can be any channel 99 command, and are sent to the Mesmerizer that caused the event to be generated, as if they came from the user who owns the Enforcer and Hub.  So they can only be used in events that originate at a Mesmerizer - they won't work, for example, in an Address event.  Calls - lines starting with an @ - cause a new notecard to be invoked.  When that notecard finishes executing, either by running out of actions or by executing an action that performs a "return", any subsequent actions in the original notecard  will be executed.  Local commands - introduced by a ! - are the most complex (other than Mesmerizer commands, which, being standard channel 99 commands, are already documented elsewhere in this blog).

The table below gives the available local commands:

 

Command Parameter(s) Description
!mailto Address :: Subject :: Body Send an email to the specified address.
!sendim RecipientKey :: Message Send an IM to the specified avatar.
!setvar Variable :: String Set the variable to the String
!setvarex Variable :: Expression Evaluate an expression and set a variable to the result
!exit Return from a called notecard
!exitif Expression Return from a called notecard if the expression evaluates to True
!if Expression Start a condition. See text for description
!delay Float Delay for the specified number of seconds

Conditionals

The Enforcer supports two types of conditional.  The simplest is a conditional return: exitif.  This is used within a called notecard (called via @), and will cause execution to return to the calling notecard if the expression evaluates to true.

The more general conditional form is the if ... then ... else ... fi.  The following is the general form of the conditional:

!if expression
do_something
do_another_something
...
!else
do_something_else
...
!fi

Note that each keyword (if, else, fi) is an individual command, and must therefore appear on a notecard line by itself. An if must always have a terminating fi, but the else and the lines between it and fi are optional.

A note on variable substitution

Variable substitution is distinct from expression evaluation.  As with the Mesmerizer, expressions are only permitted in a few places: In the second parameter of a setvarex command and the condition of an if or exitif.  Variable substitution is performed on all actions.  If you want to use an expression in some other context, you should use setvarex to evaluate the expression and assign the result to a variable, and then use variable substitution to insert the value of the evaluated expression where you want it.

Variable substitution is requested by preceding a variable name with a $-symbol.  The name can be ended with any non-alphanumeric character, but using a semicolon is most flexible since a terminating semicolon will be removed as part of the substitution, allowing you to butt the variable expansion up against following text if you wish.


Wednesday, July 20, 2016

Announcing the CHAOS Enforcer

The long-promised CHAOS Enforcer is finally ready for its initial release.  Like the entire CHAOS range, it's under active development, so I'm releasing it as a "beta", with the intent that feedback I receive from early adopters will be rolled into the final stable release (which beta customers will, of course, receive as a free update).

The CHAOS Enforcer is a central management console for multiple CHAOS Communications Hubs and their associated CHAOS Mesmerizer user communities, and the functionality it provides can be conceptually divided between Hub Management and Event Processing.

A single Enforcer can manage multiple Hubs.  All managed Hubs have to be owned by the owner of the Enforcer, and they also have to be in the same region as it.  Unlike the Hubs, you aren't required to leave the Enforcer rezzed; however if it's not rezzed it can't respond to user or Hub events.

The Hub management features include displaying the users registered with each hub and showing those currently logged in, and also "bridging" of commands and Mesmerizer chat between Hubs.  Bridging allows for two Hubs to be temporarily connected together so that they behave as if they were a single Hub - in other words messages sent to one Hub in a bridged pair will be received by users logged in to either of the Hubs.

Event Processing is the major feature provided by the Enforcer.  An event is some action performed by either a connected Hub, or by a user of a connected Hub.  For example, when a Hub allocates a new Web address (e.g. after a restart of the sim hosting the Hub), it will generate an event that the Enforcer can respond to, typically by sending an email to users who use the Hub's Web interface.  This allows for long-term use of the Hub Web interface without having to log in to SL whenever the hosting sim is restarted to find the Hub's new address.

Mesmerizers also generate events that the Enforcer can respond to.  Most of these events are generated automatically, as a normal part of the communication between a Mesmerizer and its Hub.  For example, the Mesmerizer contacts the Hub on login, and after each TP or region change, and in addition sends a 'keepalive" message every few minutes to let the Hub know that the Mesmerizer is still operating.  If this keepalive message is not received for at least 10 minutes, the Hub assumes that the user has logged out.  Each of these situations generates an event that the Enforcer can be programmed to respond to.  It's likely that I will add additional events in response to suggestions received during the beta period.

Finally, as of version 0.99, Mesmerizers can generate custom Enforcer events via the new signal command.  Since Mesmerizers have their own handlers for local events detected within the Mesmerizer, one use for signal is to allow any of these local events to be passed to the Enforcer for central processing.


The details of programming the Enforcer will be covered in a separate post, but it basically consists of creating a notecard for each event or class of events that you want the Enforcer to respond to, and listing the response actions in the notecard.  If desired, responses can be limited to a specific user and/or sim.  This makes it easy to do things like:
  • Force-TP or force-sit a user upon login 
  • Apply or remove RLV restrictions when a user enters or leaves a sim
  • Impose a curfew on a specific user
  • Enforce "ban lists" of sims that a given user may not enter

I expect the Enforcer beta to be up on Marketplace and in vendors this week.

Update (8/4/2016):   The Enforcer didn't go out as planned.  The day after I posted this note, my test system, which had been running without problems for several months, crashed.  It was an out-of-memory situation that was triggered by an abnormally large number of users' Mesmerizers sending updates simultaneously.   Some code restructuring has significantly increased the headroom, and before the final release I may do a little more refactoring to make memory issues much less likely to occur.  Note that I've decided to release The Enforcer as a copiable system, and since multiple Enforcers can connect to a single Hub, it would be possible for someone who runs into memory issues to simply create another Enforcer, and divide the events to be processed between them.

I am presently boxing up the new (fixed) Enforcer and hope to make it available this week.

Update 2 (8/18/2016):   It's been a long road to get here.  After the memory hiccup that delayed the original release, I ran into a situation where the PC I use to make vendor images wouldn't boot.  I eventually had to restore things from backup to be able to complete the listings, but as of a few minutes ago, The Enforcer is finally up on Marketplace and in the vendors, at an initial (beta) price of L$299.

Friday, June 24, 2016

CSD Stasis Tube Version 3

The Stasis Tube is the oldest CSD product that's still available, and it's been a decent seller over the years.  It's a pretty simple device - it's a tube that can capture an avatar and apply various RLV restrictions.  Its notable features are fairly flexible access control and that it announces restrictions as it applies them, to let the prisoner know exactly what abilities are being stripped from them.  It's also fairly aggressive at capturing and recapturing, as it's intended to support holding a prisoner long-term.  It's not much to look at - just a simple glass tube.  When role-playing with it, I generally mention an (unseen) "Stasis Field Generator" with the implication that this field is what's holding the captured avatar motionless.  The advantage to the simple look of the tube is that it has a Land Impact of just 1 prim, so it's feasible to have a wall full of them, which makes an impressive display, especially if they're all occupied.

I had considered the Stasis Tube to be a stable product, and wasn't planning an update.   There have been occasional requests for enhancements - a timer being the most popular one - but my focus for quite a while now has been on the CHAOS range, so I'd given little thought to enhancing the tube.  I think the last update was to support long usernames, which shows how long ago that must have been.

A little while ago, however, I met someone who I guess liked the concept of the Stasis Tube rather more than the execution, Dusty Hays-Tegan, who one day presented me with a mesh model for a brand new tube.  It looked magnificent, but it had an LI of 8, which we both felt was too high.  Thus began a series of refinements and tests, the end result of which is pictured here.


It's a composite mesh/sculpt/prim object with an LI of 3, which is more than the original tube, but in my own set-up, where I have a wall of 20 tubes, each one is paired with a 3-prim display light, whereas the new tube has lighting built in, so effectively I'm saving a prim per tube.  The model is all Dusty's but getting down to a LI of 3 also required that I rewrite the scripts from scratch, so that everything fitted into just 2 scripts.  My scripting has improved quite a bit since I created the original tube, and I found I had room to add both on-line and off-line timers, as well as building in the "externalizer" functionality so that it's compatible with the CHAOS HoloTrainer out of the box.  It also supports a few additional RLV restrictions that have been added to RLV since the original tube debuted, which taken together make it rather more secure than the original against various escape devices, as well as making it suitable for self-bondage.  With the original tube, the tube's owner could always escape.  That's still the default, but if you want to use the tube for self-bondage you can set a restriction to prevent you from touching the tube, which will make it impossible to get a "Release" button.  Finally, the tube now intelligently handles restrictions and timers for multiple captives.  The need for this was a major part of the reason I had resisted adding a timer until now.

This is a problem that's common to any capture device with a timer.  Assume you have a capture device, and you've just caught "Alice" in it, and set a 3 hour on-line timer.   The intent of that is that the device should keep Alice prisoner for a total of three hours.  If she were to log out after an hour, and then log in again the following day, she should still have 2 hours of her sentence to run.  That doesn't seem hard to do, but what happens if Bob sits on the device and gets captured by it while Alice is offline?  It doesn't seem right that Bob should use up Alice's timer - if the device has a timer enabled by default, then Alice and Bob should each get their own independent timer instance.  So the device really should be able to handle multiple instances of the timer - a different one for each captive avatar.

The stasis tube has a quirk of its own.  Since one intended use of it is for long-term storage, it has the concept of being "reserved" for a specific prisoner.  This doesn't mean that it can't be used for storing another captive, but it will only actively grab the intended target - for anyone else to be caught, they have to sit on the tube.  And in the new version, if the "reserved" avatar logs in while the tube is occupied, this will cause any current prisoner to be released, so that the tube can re-capture the real target.  This means that any RLV restrictions that were set for the reservee should be restored when they log in, even if different restrictions had been applied to another avatar in the interim.  Both this and the requirement to have per-avatar timers mean that the stasis tube has to maintain multiple contexts, where a context is a pair of timers (on-line & real-time) and a set of RLV restrictions, and apply the appropriate context when an avatar is recaptured.

The new version of the stasis tube maintains a default context, which is used as a template to create "active" contexts when an avatar is first captured.  Once the avatar is explicitly released, their context is deleted, but it is kept if they simply log out while captured, and will be re-applied if they are recaptured.  To avoid the possibility of running out of memory, the tube only retains up to five contexts for non-reserved users, plus one for the reserved user.  If more than five additional avatars sit and log out, only the most recent five are preserved.

The new model has a base that houses the "stasis field generator", which glows dimly when waiting for the target to appear, and brightly once an avatar is captured.  When I used the original tube to grab someone, I would generally describe the field as "reaching out and enveloping them, then pulling them into the stasis chamber".  I took the opportunity of the script re-write to make it actually do this during capture, as this picture shows.


The stasis field color and initial default restrictions can be set by editing a Config notecard.  I did it this way rather than add menu options as this way you can set the options once, and have them apply to any copies of the tube you make, rather than having to set each tube individually if you have more than one rezzed.  Finally, the new version of the stasis tube will be copiable, so that creating a wall of them isn't too expensive in terms of either prims or Lindens.

The new tube should be on Marketplace and in the vendors this evening, and will be available as a free upgrade to prior purchasers of any version of the stasis tube.

Saturday, June 18, 2016

Brief Update

It's been a while since my last post, but I haven't been idle.  The Enforcer is very nearly ready for release - it has been running continuously now for several months, letting me know when my Hubs' addresses change, so I can maintain Web Access after a sim restart without having to log into SL to find the Hubs' new address.  I've also used the bridging capability on a number of occasions.  There are one or two more features I want to add, but I don't think I need to hold up the initial release for those.

I've been somewhat side-tracked with a major update to the CSD Stasis Tube.  I'll go into the details of this in another post, but it's a significant improvement in functionality coupled with a huge cosmetic improvement.  This should be released soon too, and will be available as a free upgrade to purchasers of the original tubes. 

There is a Mesmerizer update in the works too.  As mentioned earlier, this will have the new signal command, which allows a Mesmerizer trigger to generate an Enforcer event.  It will also include a feature I've been intending to add for a while, but hadn't got around to until it was requested recently by a user.  This allows Mesmerizer triggers to be defined by devices like the HoloTrainer and the Enforcer.  You can do this today, but they will be added - so if you create a HoloTrainer trance that adds a trigger, and someone runs that trance more than once, they will end up with multiple instances of the trigger defined in their Mesmerizer.  The new update of the Mesmerizer will allow for an alternative syntax for defining triggers that allows the trigger to be given a name, and adding a named trigger will replace any existing trigger with that same name.  You will eventually also be able to delete named triggers by name and to name or rename existing triggers, although that capability may not make it into the next update.

Tuesday, March 29, 2016

Spirals

You don't need a Mesmerizer of your own to place a sub in trance using their Mesmerizer - all you need are the appropriate access permissions as described in the previous post,  This means that you may not have an easy way to see what options are available for spirals.   I have some ideas about how I might provide this information automatically, but for now I'll just show the standard spirals here in this post.

A "spiral" is the eye-focus image that's displayed to the sub while they are in trance, and is typically a rotating spiral.  It doesn't have to be a spiral, and it doesn't even have to rotate - it can also be a sequence of frames to make up an animation loop. You can select a particular spiral with the setspiral command, which takes an integer parameter, currently ranging from 1 to 7, with the initial value being set to 1.   The spiral selection is persistent across logins, so if the sub finds one of the provided spirals particularly effective, you can set that as their standard image.

Shown below are the 7 standard spirals, as of version 0.98.  Note that all of these are displayed with an alpha of somewhat less than 1, so the sub can see through them.  Spirals that appear static below will be displayed by the Mesmerizer as rotating clockwise.  The direction of rotation (or of animation, for frame sequences) can be reversed by using a negative number.  For example, setspiral "-1" will show spiral number 1 below, rotating counter-clockwise.

setspiral 1

setspiral 2

setspiral 3

setspiral 4
setspiral 5

setspiral 6

setspiral 7

Friday, March 25, 2016

Mesmerizer Access Control

Specifying who can access your Mesmerizer can be a little complicated.  The most important thing you should be aware of is that if someone can put you into a trance, they can execute any Mesmerizer command and place triggers for themselves or others to use in the future.   So, unless you permit only people you trust to activate a trance, it's worth keeping either yourself or someone you do trust as an owner, so that you can review and remove any undesirable triggers that might be implanted.

There are basically three types of access that someone can have to a sub's Mesmerizer, each of which is controlled differently:
  • Channel 99 command access
  • Placing the sub in a trance
  • Triggering post-hypnotic suggestions
Channel 99 command access is the simplest.  Channel 99 access allows someone to issue Mesmerizer commands without the sub necessarily being aware of it.  It is also required for someone to be able to control the sub's Mesmerizer remotely, through a Communications Hub.  This type of access is reserved for owners - people listed in an owners= line in the Mesmerizer's Access notecard.

If someone places the sub in a trance, then, for the duration of the trance, they have access that's equivalent to owner-level access, except that instead of using channel 99, they will be given a random channel to use.   They cannot use this access remotely - only true Owners can use the sub's Mesmerizer without being within earshot of it (and only if the sub has enrolled in a Hub the owner controls).  There are three ways in which someone might place a sub into a trance:
  • If they have channel 99 command access and use the hypnotize, hypnotizeac or spiral commands.
  • If they use the default "sleep now <name>" trigger.
  • If they use a custom re-induction trigger.
The default "sleep now <name>" trigger is equivalent to a custom trigger-rule of the form:

     sleep now $name = other hypnotizeac

The rule is defined using the other keyword which means that it's triggerable by anyone except the sub.  The trigger rule invokes the hypnotizeac command, or "hypnotize with access control".   This command will use the access control lists to determine whether the person tying to hypnotize the sub is permitted or prohibited from doing so.  The access control lists are initialized from the Access notecard.  If the would-be hypnotist is not found in either list, then the sub will be asked if they will allow the hypnosis attempt.  They can respond "yes" or "no", or they can choose "never" (which will reject the attempt and add them to the "Denied" list) or "always" which will allow the attempt, and add them to the "Allowed" list.

A custom trigger using the hypnotizeac command will operate in the same way.  However, the hypnotize and spiral commands do not check access, so a trigger using these commands will allow even someone on the denied list to induce trance, if they are permitted to use the trigger.   In general, therefore, use the hypnotizeac command in public trigger-rules, and keep the hypnotize and spiral commands for use as manual commands, or in trigger-rules restricted to specific people.

As stated above, the access control lists are initialized from the Access notecard.  This is a typical Access notecard:

reset
Owner=abcd1234-b9a1-423b-1235-c2128b4af803
Allow=7f1cfe79-71ae-4855-b766-754ec2e38bd7
Deny=*


The "reset" keyword clears the current lists when the Access notecard is read.  Without this, entries from the notecard will be added to the existing lists, rather than replacing the existing lists.  In general, you should start the notecard with "reset" until you are happy with your access permissions, and then remove it, so that permissions added subsequently via the hypnosis permission popup will not be discarded whenever something is added to the Mesmerizer's inventory (which causes the Access notecard to be re-read).

The above notecard specifies one Owner, and one other avatar who will be able to use the default sleep now trigger.  An attempt to use the default trigger by anyone else will be rejected, because of the deny=* line.  If the deny=* line were omitted (or identified a few specific avatars instead of using a wildcard), then when anyone else attempted to use the default sleep now trigger, or any trigger that runs the hypnotizeac command, the Mesmerizer would prompt the sub as to whether or not they were willing to succumb to the attempt.

Saturday, March 19, 2016

The Enforcer - Progress Report

I've been making good progress on the Enforcer, so I thought I should give an update.  But first, time for a confession. 

The current published version of the Mesmerizer is 0.98m, not the 0.98l that I intended.  The day after I released 0.98l, I needed an expression evaluation function for use in the Enforcer.  Partly because I'm lazy, but mostly to ensure consistency between the Mesmerizer and the Enforcer, I decided to reuse the expression evaluation code from the Mesmerizer in The Enforcer.  This has the big advantage that you'll only have to become familiar with one syntax for Reverse Polish expressions, as the expressions are almost identical between the Mesmerizer and the Enforcer (the only difference being that the Enforcer doesn't implement the isdefined operator).  For my first test of the ported expression code I had it add 1 and 1 - and to my surprise I found it couldn't do it.  It turns out that I'd omitted the plus and minus operators in the original Mesmerizer code.  Perhaps adding and subtracting aren't things that a trigger rule needs to do very often, but it was still embarrassing to discover they weren't there.  Adding them was trivial, and so I re-issued the Mesmerizer as 0.98m with the fixed code.  I took the opportunity to rationalize (and update this blog to correctly document) a couple of operators whose argument order was the reverse of what you'd expect.  I've sent out the 0.98m update to people who bought from vendors;  I'm in the process of updating Marketplace purchasers.

Now onto the good news - the Enforcer is coming on well.  For those of you who haven't waded through this blog, the Enforcer is a device that connects to one or more CHAOS Communications Hubs and provides two distinct functions - management of the Hubs and programmable control of users.  The Hub management features include providing a single point where users can be viewed across all your Hubs, and the ability to "bridge" Hubs together so that chat and/or command traffic on one Hub can be forwarded to another Hub, linking the user communities of the two Hubs.  The user control aspects are somewhat similar to event triggers within a Mesmerizer - the differences are that they are stored in and executed out of the Enforcer, so a given event response can be shared by multiple users, and can be defined or changed even when the affected user(s) aren't logged in.

Event rules in the Enforcer can:
  • issue Mesmerizer commands, by default to the Mesmerizer that generated the event, although you can specify a different recipient
  • send instant messages to specified users
  • send email
  • set and use variables, which  can be either global and long-lasting, or transient and exist only for the duration of the event.
  • call other event rules
  • contain conditional logic
Most events are triggered by a Mesmerizer connected  to one of the Hubs associated with the Enforcer.  There are a few standard events - logon, logoff and location change, but I recently decided to add custom events.  This requires a new "signal" Mesmerizer command to signal an event, so the Enforcer release will be accompanied by another Mesmerizer update.  There are a few events that are triggered by things other than a remote Mesmerizer - a Hub web address changing generates an event, for example, so that an Enforcer rule can be defined  to send an IM and/or email to interested web users to inform them of the new address.  I will probably allow for custom events to be locally-generated too, so that Enforcer rules can be used to automate multiple-command sequences that would otherwise have to be manually typed into a Communicator.

I don't yet have a launch date, but I don't expect it to be much later than the end of April.

Idioms: silent self triggers and gestures; facial expressions

The Mesmerizer offers a lot of functionality that isn't necessarily tied to controlling the sub.   For example, the express command can be used by the sub to adopt various facial expressions.  It takes a single parameter, which is a comma-separated list of expression names to be activated, or, if the name is preceded by "no", to be deactivated.  Any expressions that are already playing will continue to play if they are not mentioned.  "all" is used to indicate all possible expression animations; it's mostly used to cancel all expression animations: express noall.

If the sub isn't listed as an owner in their Mesmerizer's Access notecard, they can't issue commands directly, but an owner can define triggers for them that will do this.  Since the sub won't want to accidentally fire an expression trigger in regular speech, you should make the trigger-phrase something that they are unlikely to say except when they want to fire the trigger, for example "se1" (short for 'set expression 1') for, say, a smile expression:

se1 = subject express smile

Note the use of the subject keyword at the start of the trigger-action.  This keyword means that this trigger will fire only when spoken by the sub.  Now, whenever the subject says "se1" in local, they will smile.  You should probably define a trigger to let them stop making faces too:

se0 = subject express noall

Speaking incantations like "se1" in open chat would be a little distracting to the people around the sub, so the Mesmerizer will also accept self-triggers spoken on channel 98.  So to smile without saying anything strange in local chat, the sub would do "/98 se1".

Finally, the sub could create gestures that issue these channel-98 commands, allowing them to define a keystroke to cause them to smile.  Since gestures can include wait steps, it's easy to define one that will start to smile by issuing a "/98 se1", wait for a few seconds, and then return to a neutral expression with "/98 se0".

Gestures and channel 98 can be used to link any self-trigger to a keystroke.  So you could create, for example, a "panic button" that uses the tpto command to teleport the sub to a safe location.

Sunday, February 28, 2016

Idioms: Notification of incoming messages

If you use Mesmerizer chat, incoming messages will appear in the same place as local chat.   Unlike IMs, they won't cause a persistent flag to appear, so they can be easy to miss.   One way to make them more noticeable is to have a notification sound play when one arrives.   This is simple to do, using a trigger-rule fired by the on-commlink-message event, like this:

   on-commlink-message = internal play "Pling"

"Pling" is an included sound;  if you prefer to use a different sound, you can use the sounds command to list the built-in sounds, or you can use a key of any full-perm sound (for example, one in your inventory).

Friday, February 26, 2016

Idioms: freeze-play

Freeze-play - where a trigger causes the subject to suddenly become unable to move - is commonly used in genuine erotic hypnosis, often as a convincer, and also as a "stage", allowing you to build other effects on top of a frozen subject.  The Mesmerizer's freeze command is probably poorly named, as it doesn't actually stop the sub's avatar from moving, but merely disables the movement controls.   So while they won't be able to go anywhere, their AO will still continue to animate them in-place.

If you're using the Mesmerizer for RP, a suddenly motionless avatar is a lot more visually effective than one that continues to move, but just isn't covering any horizontal distance.  And if you're using the Mesmerizer as an adjunct to genuine hypnosis, having the subject see their avatar frozen in response to your freeze trigger can be a powerful reinforcement of their own trigger.

So rather than use the freeze command, it's better to have your freeze trigger fire a static animation with the play command.   Since play already disconnects the subject's movement controls, there's no need for an additional freeze.  I like to use the built-in "Attention" animation for this, so a typical freeze trigger would be:

   freeze $rpname = play "Attention"

You may want to define a second trigger that fires the stop command to release them from a frozen state.

Idioms: Triggering multiple subs

If you have multiple subs, it's a good idea to have a standard set of triggers that they all share.  The trigger-rules can still be individually tailored, but having a common set of trigger phrases minimizes confusion.  If you do this, it's usually a good idea to include the sub's name in the trigger phrase, so you can direct a trigger to a specific sub if more than one are present.  For example, consider a trigger that will cause the sub to kneel.  A good trigger rule might be:

   kneel $rpname = play "kneel"

Note the use of $rpname as a template for any of the sub's role-play names (names defined individually for each sub via addname or setname).  This lets the same trigger work for three subs with role-play names of Anna, Beth and Cindy:  for example, "Kneel, Beth" will fire only Beth's instance of the trigger-rule.

It's useful to give each sub an additional "collective name", for example "girls", so that the roleplay names of, for instance, Anna would be "anna" and "girls".  This allows you to trigger her either individually:  "Kneel, Anna", or collectively with Beth and Cindy, if they are present:  "Kneel, Girls".

Wednesday, February 24, 2016

Idioms: Wearing #RLV items by name

I mentioned this in the post on the 0.98l update, but it's worth calling out again. 

Access to the #RLV folder was one of the areas where I was concerned that a command interface would be harder to use than a typical menu-based UI.  However, in practice I find it much quicker to use the commands, in part because they allow much faster navigation between different folders that a menu-driven system, especially if the folders contain more subfolders than would fit in a single menu.

One situation where the Mesmerizer's approach shines is when you you know the sub has a particular item, but you don't know where it is in her #RLV subtree.  For example, assume I know that she owns a set of RR Vixen Leather Cuffs, but I can't remember where she keeps them.  The following sequence would usually let me put them on her:

/99 find vixen
/99 wearoverall "$rlvpath"

This works because the find command (as of 0.98l) sets the variable rlvpath with the results of its search.

Monday, February 22, 2016

Idioms: force-sitting

This is hopefully the first of a series of short posts that will cover some Mesmerizer idioms that might be useful.  I'll use the tag "idioms", both as a label and in the post title to identify such posts.


To get the ball rolling, let's assume that you have a sub who has a particular cage or display case that you want to put them into regularly.  Also, assume that it's the type of case that they would get inside by "sitting on" it.  The conventional way to make the sub get into the case would be to force-sit them, and a Mesmerizer trigger that would do that looks like this:

into your case=sit <key> where <key> is the key of the case.

However, it is much more effective to have them walk over to the case before getting inside it:

into your case=moveto <key> sit <key>


Binds and Modes

This post is about bound poses, or Binds, how the Mesmerizer implements them, and how to add your own.

A Bind is the term the Mesmerizer uses for a combination of a pose and some sort of chaining.  The 0.98l version of the Mesmerizer ships with a single Bind;  as mentioned in a previous post, I intend to add more in the final release.  But you can easily add your own, and this post will describe how to do that.

Binds are an extension of Modes - the Mesmerizer's term for its mini-AO that will over-ride the sub's own AO while the mode is active.  Modes are intended for things like doll play, where you may have created a trigger that puts the sub into "doll mode" for a period, and want their movements to reflect that.   The Mesmerizer ships with two Modes - "doll" and "ballet".  Use the setmode command to activate a Mode, for example setmode doll.  You can cancel a Mode and revert to the sub's AO by using setmode with a mode-name of "-":  setmode -.  On canceling a Mode, the sub may have to make a small movement in order for their AO to notice that it has control again.  A Bind is simply a Mode plus a list of the LockGuard points that should be linked together to make it look as if the chains or ropes are holding the sub in the pose.

At first glance, it might seem that Binds should be more like semi-static poses - in other words animations as run by the play command - than Modes, which generally allow the sub to move around.   In fact, most real tie ups wouldn't prevent the sub from moving (unless they were tied to something fixed), although movement would be hindered.   For example, even if hogtied, the sub would likely still be able to move, albeit slowly, by squirming and wriggling.  This is why the Mesmerizer chooses to build Binds on top of Modes, rather than on top of static poses.

The 0.98l release introduces Binds, but there is more functionality that needs to be added before they're complete.  This post will describe the current state of Binds, and I'll update it as more functionality is added.

Modes and Binds are both defined in the Modes notecard in the Mesmerizer's inventory.  Here is the shipping contents of that notecard as of 0.98l:

Mode=Doll
Stands=DollStand1,DollStand2
Walks=~DollWalk3
Mode=Ballet
Stands=Ballerina1
Walks=~BallerinaWalk1
Bind=Hogtied
Desc=Hogtie, knees apart
Stands=Hogtie
Unlink=*
Link=lwrist rankle, rwrist lankle


It consists of a number of sections, each introduced by either a "Mode=" or "Bind=" line.  The default file therefore defines two modes (doll and ballet) and a single bind (hogtied).  Note that mode names are not case-sensitive, but the case used in this notecard will be what's used in Mesmerizer messages, and an initial capital works best with those messages.

We'll look at the mode definitions first, "Doll" in particular.  A mode specifies the animations used for various activities.   Doll-mode only defines animations for standing and walking, although the Mesmerizer also supports the following activities or animation states: stands, walks, runs, turning left, turning right.  I may support more states in the future.  All of these allow the specification of multiple animations, with the expectation that one will be chosen at random, although in 0.98l, only the first in each list is used.

Note that the name of the animation used for the Doll-mode walks, ~DollWalk3, begins with a tilde character.   If you were to play a walk, the sub would walk in place which would look strange;  the leading tilde in the animation name "hides" the animation from the anims command, which is used to see what animations are available to be played.

Doll and Ballet Modes are followed by the definition of the "Hogtied" Bind.  Like Modes, Binds can specify animations for the various animation states.  Unlike Doll and Ballet modes, Hogtied only specifies a stand - there is no walk animation.  Binds (and Modes) that omit a walk are considered "in-place" binds or modes, and no movement is permitted.


The "desc=" line is intended for a brief description of the Bind or Mode, to be shown in an extended version of the listbinds or listmodes commands.  Currently it's not used.

The "Unlink=" and "Link=" lines define the LockGuard chaining to be used, and apply only to Binds, not Modes.  Unlink gives a comma-separated list of LockGuard points that should be unlinked prior to drawing new ones; "Unlink=*" means unlink all points.  Link gives a comma-separated list of pairs of LockGuard points, and will cause a chain or rope to be drawn from the first member of each pair to the second.  Choice of chain or rope is made by a preceding lgropes or lgchains command; chains are used by default.

So when activating the Hogtied bind, with the bind hogtied command, first, any existing chains or ropes will be removed, and then new ones will be drawn from the sub's left wrist cuff to their right ankle cuff, and from their right wrist cuff to their left ankle cuff.  You can edit this notecard to draw other bonds if you prefer to tie a hogtie differently.


As I said earlier, Binds are a work in progress.  In particular, walking (or squirming) in a Bind is still under active development.  I expect that the next update will complete this feature.

Adding Custom Animations

It's very easy to add a custom animation to the Mesmerizer - simply dragging it into the Mesmerizer's inventory will make it available to the play and anims commands.  There are a few constraints on the types of animations that are suitable though.

Animations should be looped - that is, they should not stop by themselves.  This is always true of static poses (which in SL are simply looped single-frame animations), but some non-static animations may stop by themselves when they've finished.  The play command assumes that it is playing a looped animation, and will restart it if it stops, which will likely look strange with a non-looped animation that has played to completion.  I may add a playonce command that doesn't automatically restart, but as of 0.98l you should only used looped animations.

Secondly, animations whose names start with a tilde ("~") will not be displayed in the list of animations returned by the anims command.  This is to avoid cluttering the list with animations that are intended to be only used with a mode or bind (such as walks).  So the names of animations intended for use with the play command should not begin with a tilde.

Finally, the animation should ideally be full-permission.  The Mesmerizer needs to determine the key of an animation in order to properly manage it, and it currently cannot do this for animations that have restricted permissions.  You may add animations that aren't full-permission, but if you do, you will need to carry out an extra step to tell the Mesmerizer the key of your animation.  This can be determined with a device that's included with the Mesmerizer - the "Animation Tester".  To use this, rez the Animation Tester - it will ask for permission to animate you the first time you use it - and simply drag your animation into its inventory.  It will tell you the key of the animation in local chat.   Once you have the key of the animation, you can drag the animation into the Mesmerizer's inventory and edit the AnimFixup notecard to tell the Mesmerizer the key of the animation.  To supply the key for an animation, add a line of the form animation-name|key, for example:

Jump Up|ea54436b-7625-b93f-05dc-2e0a2ba1aa29

In general, you should try to avoid spaces in animation names, and keep them in lower case.   This will let you avoid having to enclose the name in double-quotes in a play command: play "Jump Up".

The AnimFixup notecard also allows you to specify a height offset to be used with the animation, and an optional delay before applying the offset.   See the notecard for more details.

I expect to build the Animation Tester functionality into the Mesmerizer before the final release, so that installing an animation, regardless of permissions, will be drag and drop.

Friday, February 19, 2016

The Mesmerizer as an outfit manager

It's quite easy to set up the Mesmerizer so that it operates as a simple outfit manager, to let you change your sub's entire outfit with a single command.

For the sake of simplicity, we'll assume that the sub has three outfits, and you want to be able to switch them into any of these outfits at will.   The simplest way to do this is to create an "Outfits" folder in the #RLV folder, and put each of the three outfits into its own folder within "/Outfits".  Recall that the Mesmerizer uses "/" as a separator between folders in a path from the #RLV folder, and that a leading "/" means that the path starts at the #RLV folder itself.  We'll assume that the outfits are imaginatively named "Outfit 1", "Outfit 2" and "Outfit 3", so we'll put them in "/Outfits/Outfit 1", "/Outfits/Outfit 2" and "/Outfits/Outfit 3".  We'll further assume that, at the start, the sub is wearing "Outfit 1".

The goal is to create triggers that will make the sub change into one of the other outfits.  For example, we want to define a trigger "wear outfit 2" that will cause them to do exactly that.  As a first cut at a solution, you might define the trigger action to be something like wearreplaceall "/Outfits/Outfit 2".  We use a replace-style wear so that the new outfit will replace the old one, and an all-style wear so that if there are sub-folders inside the "Outfit 2" folder, then the sub will wear them too.

The problem with this is that wearreplace doesn't replace entire outfits - it replaces individual clothing items.  So if Outfit 1 (the one that the sub is initially wearing) includes something worn on, say the left lower leg attachment point, and so does Outfit 2, then the correct thing will happen - the new left lower leg attachment from Outfit 2 will replace the old one from Outfit 1.  However, if Outfit 2 didn't include anything on the left lower leg, then there would be nothing to "knock off" the attachment from Outfit 1, so the sub would end up with a mixture - all of Outfit 2, plus any bits of Outfit 1 that don't have corresponding items in Outfits 2.

What we really want to do is have the trigger-rule first take off Outfit 1 and then put on Outfit 2 - something like this: detachall "/Outfits/Outfit 1" wearoverall "/Outfits/Outfit 2".  Note the use here of wearoverall (as opposed to wearreplaceall).   This allows Outfit 2 to contain things that might want to be worn at the same point as some object that's really part of the sub's base avatar, rather than a specific outfit.  For example, the sub's hair might not be included in each outfit, but Outfit 2 might include something else worn on the skull - wearoverall allows the new object to be added without knocking the sub's hair off.

This almost works, but what we've actually defined is a trigger that will switch from Outfit 1 to Outfit 2.  It won't work if the sub happened to be wearing Outfit 3.  What we want is to detach anything that's part of any of the outfits before putting on the one we want.  Doing the detachall at the /Outfits level will do that, and the complete trigger definition is:

wear outfit 2 = detachall "/Outfits" wearoverall "/Outfits/Outfit 2" 

Similarly:

wear outfit 1 = detachall "/Outfits" wearoverall "/Outfits/Outfit 1"
wear outfit 3 = detachall "/Outfits" wearoverall "/Outfits/Outfit 3"

In a future version of the Mesmerizer, I may support parameterized triggers that would allow these three triggers to be specified as a single rule, but I think this is the best you can do today.