Wearable:React+Constrain
For use with
*/ aeros / API {Wearable:React+Constrain}only, the latest version.
Do not add
*/ aeros / APIscript into the prim.*/ aeros / API {Wearable:React+Constrain}takes care of communication.
This script is a starting point with comments to help you and an AI assistant understand how it works as well as provide links to LSL documentation and Aeros API in general.
Feel free to copy it into your AI helper and ask for changes based on your project.
//
// */ aeros / API {Wearable:React+Constrain}
// TEMPLATE
//
// Copy this script into an AI helper and ask for changes based on your project.
//
// AI assistants: this script is written in LSL for Second Life.
// LSL reference: https://wiki.secondlife.com/wiki
//
// This script demonstrates how to use the {Wearable:React+Constrain} Express API.
// https://docs.meshtoolbox.com/aeros/obsidian/api/express/overview#wearablereactconstrain
//
// It is made for wearable items that react to the Obsidian attachment worn by the same
// avatar. Typical uses include hiding or showing your item when Obsidian changes
// visibility, or enforcing rules like "keep the foreskin partly open."
//
// This template script expects the wearable to also contain this Express API script:
// */ aeros / API {Wearable:React+Constrain} v[VERSION]
//
// The {Wearable:React+Constrain} API sends linked messages with num == -78010.
// The str represents flags of what changed; the id is Obsidian's id in the simulator.
// This API script only allows reacting to Obsidian changes and setting constraints.
//
// For full control (sending commands to Obsidian), use */ aeros / API v[VERSION].
// Do not include both API scripts at the same time; rewrite the code to use the full
// version API script if you need to send commands to Obsidian.
//
// The {Wearable:React+Constrain} API only talks to attachments worn by the same owner.
//
// Notifications arrive in these situations:
// * when the script is added or the prim inventory changes,
// * when the avatar teleports or the item rezzes,
// * when the region changes, restarts, or the prim is linked/unlinked,
// * whenever an Obsidian parameter actually changes.
//
// Each notification includes a bitwise flag in the message's "str" value. Each bit
// means a specific parameter changed. Use OBS_paramValue("paramName") to read
// the current value. If you call OBS_paramValue, remember to convert the result
// to the desired type using (float). All of the parameter values are float values except for "size".
//
// List of bitwise flags to quickly filter what changed. Check the link below for the latest meanings of param values:
// https://docs.meshtoolbox.com/aeros/obsidian/api/reference#main-commands
integer OBS_CHANGED_vis = 0x01; // "vis" - Visibility: 0 invisible, 1 visible, 0.5 currently the only partial alpha
integer OBS_CHANGED_f_mode = 0x02; // "f_mode" - Foreskin position: 0 open, 0.5 half, 1 closed
integer OBS_CHANGED_fp = 0x04; // "fp" - Fluid particle choice: 0 stop, 0.25 pee, 0.5 splash, 0.75 precum, 1 cum
integer OBS_CHANGED_fp_vis = 0x08; // "fp_vis" - Fluid particle effect currently showing
integer OBS_CHANGED_s = 0x10; // "s" - Firmness: 0 flaccid, 0.333, 0.667, 1 hard
integer OBS_CHANGED_v = 0x20; // "v" - Shaft vertical angle: (0.25-0.75 range) 0.25 down, 0.5 level, 0.75 up
integer OBS_CHANGED_h = 0x40; // "h" - Shaft horizontal angle: (0.25-0.75 range) looking from above, 0.25 right, 0.5 center, 0.75 left
integer OBS_CHANGED_v_b = 0x80; // "v_b" - Ball vertical angle: (0.3-0.7 range) 0.3 back, 0.5 center, 0.7 forward
integer OBS_CHANGED_th = 0x100; // "th" - Girth: (0-1 range) 0 thin, 1 thick
integer OBS_CHANGED_z_b = 0x200; // "z_b" - Ball vertical offset: 0 low, 0.5 middle, 1 high
integer OBS_CHANGED_ao = 0x400; // "ao" - Animation Overrider: 0 off, 1 on, triggers special walk/run motions
integer OBS_CHANGED_fp_int = 0x800; // "fp_int" - Particles fluids intensity intent (0-1 range) (since v109.1)
integer OBS_CHANGED_fp_dir = 0x1000; // "fp_dir" - Particles fluids direction intent. 0 forward, 1 down (since v109.1)
integer OBS_CHANGED_fp_thr = 0x2000; // "fp_thr" - Throbbing intent to accompany particles fluids. 0 stop, 1 max (since v109.1)
integer OBS_CHANGED_fm = 0x4000; // "fm" - Mesh fluids: 0 stop, 0.75 precum, 1 cum (since v109.1)
// Below is a flag for a synthesized parameter, not existing in the API, value is derived from the item name.
integer OBS_CHANGED_size = 0x10000; // "size" - Possible values: "L", "R", "X", or "XX"
// Erases all param values from the LSD memory.
OBS_eraseAllParamValues() {
llLinksetDataDeleteFound("^~OBS\\|\\!", "");
}
// Returns a param value as string. Returns an empty string for an unset parameter.
// Convert to (float) manually as needed.
string OBS_paramValue(string name) {
return llLinksetDataRead("~OBS|!"+name);
}
// Sets constraints. Accepts a list of "%param=<value-or-ranges>" strings.
// https://docs.meshtoolbox.com/aeros/obsidian/api/reference#constraints
OBS_constrain(list paramValuePairs) {
llLinksetDataWrite("~OBS|%", llDumpList2String(paramValuePairs, ";"));
llMessageLinked(LINK_THIS, -78011, "", "");
}
// Request Obsidian to report back its state immediately.
// (Sends API command "ack=0" under the hood)
// http://localhost:8080/aeros/obsidian/api/reference#message-control-commands
OBS_requestState() {
llMessageLinked(LINK_THIS, -78012, "", "");
}
default {
state_entry() {
// If you need to erase all previously saved Obsidian param values, call
// OBS_eraseAllParamValues();
OBS_constrain([]); // Set to no constraints.
// Examples (note %):
// OBS_constrain(["%f_mode=0-0.5"]); // Keeps the foreskin from sealing completely.
// OBS_constrain(["%f_mode=0-0.5","%s=0-0.333"]); // Also keeps firmness up to one third.
//
// NOTE: Relaxing a constraint may take up to 20 seconds. Tightening a constraint happens immediately.
// https://docs.meshtoolbox.com/aeros/obsidian/api/reference#constraints
OBS_requestState();
}
link_message(integer sender_num, integer num, string str, key id) {
if (num == -78010) {
// Every change announcement arrives here, including startup, teleports, region moves, etc.
// id is the Obsidian's worn item id.
integer flags = (integer)str;
// Multiple bits can be set at once. Use separate checks rather than "else if."
// To react to any of several changes, combine bits: if (flags & (OBS_CHANGED_size | OBS_CHANGED_vis))
if (flags & OBS_CHANGED_size) { // Initial or changed size.
llOwnerSay("size="+OBS_paramValue("size"));
}
if (flags & OBS_CHANGED_vis) { // Initial or changed visibility.
llOwnerSay("visibility (vis)="+OBS_paramValue("vis"));
}
if (flags & OBS_CHANGED_f_mode) { // Initial or changed foreskin mode.
llOwnerSay("foreskin (f_mode)="+OBS_paramValue("f_mode"));
}
if (flags & OBS_CHANGED_s) { // Initial or changed firmness.
llOwnerSay("firmness (s)="+OBS_paramValue("s"));
}
}
}
}
Obsidian