// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Paced notecard caption show // Not compiled or tested in-world // Setup: Add captions with one short caption per line. Owner-touch starts or stops. Each caption stays eight seconds. // Stop / restore: Touch to stop and restore original hover text. At EOF the script restores automatically. // Notes: No endless reread loop. A request timeout stops the show; the notecard should contain only text intended for public display. Keep example captions and notecard lines short, preferably ASCII. Character clipping is not UTF-8 byte-budget clipping: multibyte text may reach hover-text or chat limits sooner and be truncated. // License: see LICENSE in this distribution. // Original Incoprea. MIT. Not compiled or tested in-world. integer active; integer line; integer waiting; key request; list saved; stop() { active=FALSE; waiting=FALSE; request=NULL_KEY; llSetTimerEvent(0.0); llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXT]+saved); } fetch() { waiting=TRUE; request=llGetNotecardLine("captions",line); llSetTimerEvent(15.0); } default { state_entry() { saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXT]); } touch_start(integer n) { if(llDetectedKey(0)!=llGetOwner())return; if(active) { stop(); return; } if(llGetInventoryType("captions")!=INVENTORY_NOTECARD)return; active=TRUE; line=0; fetch(); } dataserver(key id,string data) { if(!active||id!=request)return; request=NULL_KEY; waiting=FALSE; if(data==EOF) { stop(); return; } ++line; llSetText(llGetSubString(data,0,220),<0.9,0.95,1.0>,1.0); llSetTimerEvent(8.0); } timer() { if(waiting) { stop(); llOwnerSay("Caption read timed out."); } else if(active) { if(llGetInventoryType("captions")!=INVENTORY_NOTECARD) { stop(); return; } fetch(); } } changed(integer change) { if(change&CHANGED_INVENTORY)stop(); } }