// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Armed owner gesture receiver // Not compiled or tested in-world // Setup: Put in a child with gesture. Name the root gesture_controller. Owner-touch arms and explicitly grants animation permission; root code 7920 and message play triggers it. // Stop / restore: Owner-touch disarms/stops; each trigger also stops after four seconds. Use Stop Animating Me if interrupted. // Notes: Stop before renaming or removing animation assets. An animation asset may also be used by another controller: do not run competing controllers for the same asset. Validates root name, code, message and owner permission. Only one configured inventory animation is accepted; no arbitrary animation UUID is executed. // License: see LICENSE in this distribution. // Original Incoprea. MIT. Not compiled or tested in-world. integer armed; integer pending; integer playing; integer permitted() { return (llGetPermissions()&PERMISSION_TRIGGER_ANIMATION)&&llGetPermissionsKey()==llGetOwner(); } stop() { if(playing&&permitted())llStopAnimation("gesture"); playing=FALSE; llSetTimerEvent(0.0); } default { touch_start(integer n) { if(llDetectedKey(0)!=llGetOwner())return; if(armed) { armed=FALSE; stop(); return; } if(pending)return; pending=TRUE; llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION); } run_time_permissions(integer p) { if(!pending)return; pending=FALSE; armed=permitted(); } link_message(integer sender,integer code,string s,key data) { if(!armed||!permitted()||sender!=1||llGetLinkName(1)!="gesture_controller"||code!=7920||s!="play"||llGetInventoryType("gesture")!=INVENTORY_ANIMATION)return; stop(); playing=TRUE; llStartAnimation("gesture"); llSetTimerEvent(4.0); } timer() { stop(); } changed(integer change) { if(change&CHANGED_OWNER)llResetScript(); else if(change&CHANGED_LINK) { armed=FALSE; stop(); } } }