// ============================================================ // [HappyBums] HoverText v1.1 // Optional floating text display for the HappyBums system. // // This is a SEPARATE wearable from the main Diaper HUD. // Wear on skull attachment point for best text positioning. // The root prim attaches to skull; child prim (link 2) displays // the floating text and can be repositioned up/down. // // Compatible with both HappyBums and HappyBumsPlus. // Mess state is only displayed when HappyBumsPlus sends it. // // Communication: // Listens on a private channel derived from owner UUID. // Main Diaper HUD sends commands on the same channel. // // Commands received: // STATE:wetness_index|display_name|wet_state_name[|MESS:mess_index|mess_state_name] // TOGGLE:0 / TOGGLE:1 // HEIGHT:+0.1 / HEIGHT:-0.1 / HEIGHT:0 // // Storage (root prim description): // on=1,h=0.5 // ============================================================ integer g_channel = 0; integer g_listen = 0; integer g_enabled = 1; float g_height = 0.5; // Colour map for wetness index 0-4 vector wetColor(integer idx) { if (idx == 0) return <0.0, 1.0, 0.0>; // Dry - green if (idx == 1) return <1.0, 1.0, 0.0>; // Damp - yellow if (idx == 2) return <1.0, 0.5, 0.0>; // Wet - orange if (idx == 3) return <1.0, 0.3, 0.3>; // Soaking - light red return <0.8, 0.0, 0.0>; // Leaking - dark red } // Colour map for mess index 0-3 vector messColor(integer idx) { if (idx == 0) return <0.0, 1.0, 0.0>; // Clean - green if (idx == 1) return <1.0, 1.0, 0.0>; // Soiled - yellow if (idx == 2) return <1.0, 0.5, 0.0>; // Messy - orange return <0.8, 0.0, 0.0>; // Blowout - dark red } saveSettings() { llSetLinkPrimitiveParamsFast(LINK_ROOT, [PRIM_DESC, "on=" + (string)g_enabled + ",h=" + (string)g_height]); } loadSettings() { string desc = llList2String(llGetLinkPrimitiveParams(LINK_ROOT, [PRIM_DESC]), 0); if (desc == "") return; list pairs = llParseString2List(desc, [","], []); integer i; for (i = 0; i < llGetListLength(pairs); i++) { string pair = llList2String(pairs, i); integer eq = llSubStringIndex(pair, "="); if (eq < 1) jump skip; string k = llGetSubString(pair, 0, eq-1); string v = llGetSubString(pair, eq+1, -1); if (k == "on") g_enabled = (integer)v; else if (k == "h") g_height = (float)v; @skip; } } clearText() { llSetLinkPrimitiveParamsFast(2, [PRIM_TEXT, "", <0,0,0>, 0.0]); } applyPosition() { llSetLinkPrimitiveParamsFast(2, [PRIM_POS_LOCAL, <0.0, 0.0, g_height>]); } // mIdx < 0 means HappyBums (wetting only) — no mess fields present applyText(integer wetIdx, string displayName, string wname, integer mIdx, string mname) { if (!g_enabled) { clearText(); return; } applyPosition(); string label; vector col; if (mIdx >= 0) { // HappyBumsPlus — combined wet + mess display if (wetIdx == 0 && mIdx == 0) label = displayName + "'s diaper is clean and dry"; else label = displayName + "'s diaper is " + wname + " and " + mname; // Use the colour of whichever state is worse if (mIdx >= wetIdx) col = messColor(mIdx); else col = wetColor(wetIdx); } else { // HappyBums — wetness only label = displayName + "'s diaper is " + wname; col = wetColor(wetIdx); } llSetLinkPrimitiveParamsFast(2, [PRIM_TEXT, label, col, 1.0]); } default { state_entry() { g_channel = -1 - (integer)("0x" + llGetSubString((string)llGetOwner(), 0, 6)); loadSettings(); applyPosition(); if (!g_enabled) clearText(); if (g_listen != 0) llListenRemove(g_listen); g_listen = llListen(g_channel, "", NULL_KEY, ""); llOwnerSay("[HappyBums HoverText] Ready."); llOwnerSay("[HoverText] Hover channel: " + (string)g_channel); } on_rez(integer param) { llResetScript(); } attach(key id) { if (id != NULL_KEY) llResetScript(); } listen(integer channel, string name, key id, string message) { if (channel != g_channel) return; if (id != llGetOwner() && llGetOwnerKey(id) != llGetOwner()) return; if (llGetSubString(message, 0, 5) == "STATE:") { string body = llGetSubString(message, 6, -1); list parts = llParseString2List(body, ["|"], []); integer wIdx = (integer)llList2String(parts, 0); string dname = llList2String(parts, 1); string wname = llList2String(parts, 2); // Check for optional mess fields (HappyBumsPlus only) integer mIdx = -1; string mname = ""; if (llGetListLength(parts) >= 5) { string messTag = llList2String(parts, 3); if (llGetSubString(messTag, 0, 4) == "MESS:") { mIdx = (integer)llGetSubString(messTag, 5, -1); mname = llList2String(parts, 4); } } applyText(wIdx, dname, wname, mIdx, mname); return; } if (llGetSubString(message, 0, 6) == "TOGGLE:") { g_enabled = (integer)llGetSubString(message, 7, -1); saveSettings(); if (!g_enabled) clearText(); else llOwnerSay("[HappyBums HoverText] Enabled."); return; } if (llGetSubString(message, 0, 6) == "HEIGHT:") { string val = llGetSubString(message, 7, -1); if (val == "0") g_height = 0.5; else g_height += (float)val; // Clamp to reasonable range if (g_height < -2.0) g_height = -2.0; if (g_height > 3.0) g_height = 3.0; saveSettings(); applyPosition(); return; } } }