// ===================================================================== // Hover Text Sign // skimi3d script library // https://grid.skimi3d.com/scripts/hover-text-sign // // Floating words above a prim. The label on a door, the name of a // shop, the price on a stall, the arrow that says which way the // landing point is. // // It can also read its words out of the object's Description, which is // the trick worth knowing: one script, twenty signs, and you change // each one from the build tool without ever opening the code. // // Plain LSL. // ===================================================================== // --------------------------------------------------------------------- // Settings // --------------------------------------------------------------------- // The words, one line per entry. Keep it short: hover text is read at a // glance and there is a hard limit of about 254 characters in total. list LINES = [ "The Old Forge", "open to visitors" ]; // Take the words from the object's Description instead of from the list // above. Use a vertical bar to separate lines: Ferry|leaves on the hour // // This is how you run twenty signs off one script. Drop the same script // into all of them and give each one a different Description. integer READ_FROM_DESCRIPTION = FALSE; // Colour of the text, and how solid it is. vector COLOUR = <1.0, 1.0, 1.0>; float ALPHA = 1.0; // Make the prim itself invisible, so the words hang in the air on their // own. The prim is still there and can still be clicked. integer HIDE_THE_PRIM = FALSE; // --------------------------------------------------------------------- // Everything below here is the machinery // --------------------------------------------------------------------- // Hover text is cut off past roughly this many characters, and the cut // is silent. Better to say so than to let somebody wonder where the // last line went. integer LIMIT = 254; write() { string text = ""; if (READ_FROM_DESCRIPTION) { string d = llGetObjectDesc(); // A brand new prim says "(No Description)" in some viewers and // nothing in others. Neither is a sign. if (d == "" || d == "(No Description)") { llSetText("", COLOUR, ALPHA); llOwnerSay("My Description is empty, so I have nothing to say. Put the words in the Description, and use | between lines."); return; } text = llDumpList2String(llParseString2List(d, ["|"], []), "\n"); } else { text = llDumpList2String(LINES, "\n"); } if (llStringLength(text) > LIMIT) { llOwnerSay("My text is longer than a sign can hold, so the end of it will not show. Around " + (string)LIMIT + " characters is the whole budget, newlines included."); } llSetText(text, COLOUR, ALPHA); } default { state_entry() { if (HIDE_THE_PRIM) llSetAlpha(0.0, ALL_SIDES); write(); } changed(integer what) { // A sign that changes hands should read itself again, because // the new owner's Description is the one that counts. if (what & CHANGED_OWNER) write(); } touch_start(integer total) { // THERE IS NO EVENT FOR A CHANGED DESCRIPTION. Editing it in // the build tool tells the script nothing at all, and a sign // that polled its own Description every few seconds would be // twenty signs polling for ever to catch an edit that happens // twice a year. So: change the Description, then touch the // sign. Owner only, because a visitor touching a sign should // not be able to set it working. if (llDetectedKey(0) != llGetOwner()) return; write(); } on_rez(integer start) { llResetScript(); } }