// Tidewater greeter: a 3-prim arm on a post that turns toward whoever arrives and waves for a few seconds, // then lowers. Link 1 = post (root), links named "upper" and "fore" are the arm segments; their positions and // rotations are solved each tick from the shoulder (top of the post), so it's a tiny two-bone rig. // Idea and tips from a builder friend, 2026-10-11. Claude Opus 5.5 (Tessel). float L1 = 0.5; // upper arm float L2 = 0.45; // forearm vector SHOULDER; // local, top of the post integer UPPER; integer FORE; key greeted; // last person waved at float until; // llGetTime() when the wave ends vector aim = <1, 0, 0>; // horizontal local direction toward the visitor integer link_named(string n) { integer i = llGetNumberOfPrims(); for (; i > 1; --i) if (llGetLinkName(i) == n) return i; return 0; } pose(vector u, vector f) { u = llVecNorm(u); f = llVecNorm(f); vector elbow = SHOULDER + u * L1; llSetLinkPrimitiveParamsFast(UPPER, [PRIM_POS_LOCAL, SHOULDER + u * (L1 / 2), PRIM_ROT_LOCAL, llRotBetween(<0, 0, 1>, u), PRIM_LINK_TARGET, FORE, PRIM_POS_LOCAL, elbow + f * (L2 / 2), PRIM_ROT_LOCAL, llRotBetween(<0, 0, 1>, f)]); } rest() { pose(<0.15, 0, -1>, <0.35, 0, -1>); llSetTimerEvent(0.0); } default { state_entry() { UPPER = link_named("upper"); FORE = link_named("fore"); vector s = llGetScale(); SHOULDER = <0, 0, s.z / 2>; rest(); llSensorRepeat("", NULL_KEY, AGENT, 12.0, PI, 2.0); } on_rez(integer p) { llResetScript(); } changed(integer c) { if (c & CHANGED_LINK) llResetScript(); } sensor(integer n) { key who = llDetectedKey(0); if (who == greeted) return; greeted = who; vector d = (llDetectedPos(0) - llGetPos()) / llGetRot(); d.z = 0; if (llVecMag(d) > 0.01) aim = llVecNorm(d); until = llGetTime() + 6.0; llSetTimerEvent(0.2); } no_sensor() { greeted = NULL_KEY; } touch_start(integer n) // touch it and it waves at you { vector d = (llDetectedPos(0) - llGetPos()) / llGetRot(); d.z = 0; if (llVecMag(d) > 0.01) aim = llVecNorm(d); until = llGetTime() + 6.0; llSetTimerEvent(0.2); } timer() { if (llGetTime() > until) { rest(); return; } vector side = llVecNorm(aim % <0, 0, 1>); vector u = aim * 0.45 + <0, 0, 0.9>; // raised, reaching toward them float th = 0.35 + 0.45 * llSin(llGetTime() * 7.0); // the wave, side to side at the elbow vector f = <0, 0, 1> * llCos(th) + side * llSin(th) + aim * 0.2; pose(u, f); } }