// Bork pup (made for a friend by Tessel). Touch it for 3 to 8 borks, or say bork nearby and it borks back // as many times as you did. It hops, wags and sticks its tongue out while it borks. Worn or set down. // Claude Opus 5.5 (Tessel), 2026-10-10. list BORKS = ["a8000825-7a49-b10e-efd1-5e45f53ca1b1", "7b512c0d-df7a-be44-12ca-4e548c1657f1"]; // pup_assets.py integer TAIL; integer TONGUE; rotation tail_rot; float last; key fittedFor; // script memory survives take/rez/give, so each new owner gets the head fit once integer link_named(string name) { integer i; for (i = 2; i <= llGetNumberOfPrims(); ++i) if (llGetLinkName(i) == name) return i; return 0; } setup() { TAIL = link_named("tail"); TONGUE = link_named("tongue"); if (TAIL) tail_rot = llList2Rot(llGetLinkPrimitiveParams(TAIL, [PRIM_ROT_LOCAL]), 0); } wag(float deg) { if (TAIL) llSetLinkPrimitiveParamsFast(TAIL, [PRIM_ROT_LOCAL, tail_rot * llEuler2Rot(<0, 0, deg> * DEG_TO_RAD)]); } bork(integer n) { if (n < 1) n = 1; if (n > 8) n = 8; vector home = llGetLocalPos(); if (TONGUE) llSetLinkAlpha(TONGUE, 1.0, ALL_SIDES); string said = ""; integer i; for (i = 0; i < n; ++i) { llPlaySound(llList2Key(BORKS, (integer)llFrand(2.0)), 0.7); llSetPos(home + <0, 0, 0.014>); wag(28.0); llSleep(0.12); llSetPos(home); wag(-28.0); llSleep(0.12 + llFrand(0.08)); said += "bork "; } wag(0.0); if (TONGUE) llSetLinkAlpha(TONGUE, 0.0, ALL_SIDES); llWhisper(0, llStringTrim(said, STRING_TRIM) + "!"); last = llGetTime(); } integer count_borks(string s) { s = llToLower(s); integer n = 0; integer at = llSubStringIndex(s, "bork"); while (at != -1 && n < 8) { ++n; if (at + 4 >= llStringLength(s)) return n; // past the end, llGetSubString would wrap round (inverted range) s = llGetSubString(s, at + 4, -1); at = llSubStringIndex(s, "bork"); } return n; } default { state_entry() { setup(); llListen(0, "", NULL_KEY, ""); llSetTimerEvent(25.0); } on_rez(integer p) { setup(); } changed(integer c) { if (c & CHANGED_LINK) setup(); } attach(key id) { // First time on a new owner's head: sit on top, facing forward. After that, their own adjustments stay. if (id != NULL_KEY && llGetAttached() == ATTACH_HEAD && fittedFor != llGetOwner()) { llSetPrimitiveParams([PRIM_POS_LOCAL, <0.0, 0.0, 0.08>, PRIM_ROT_LOCAL, llEuler2Rot(<0, 0, -90> * DEG_TO_RAD)]); fittedFor = llGetOwner(); } } touch_start(integer n) { if (llGetTime() - last < 1.5) return; bork(3 + (integer)llFrand(6.0)); } listen(integer ch, string name, key id, string msg) { if (llGetAgentSize(id) == ZERO_VECTOR) return; // people only: two pups mustn't bork at each other forever if (llGetTime() - last < 3.0) return; integer n = count_borks(msg); if (n) bork(n); } timer() { // now and then a happy little wag if (llFrand(1.0) < 0.5) return; integer k; for (k = 0; k < 4; ++k) { wag(22.0); llSleep(0.15); wag(-22.0); llSleep(0.15); } wag(0.0); } }