// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Child wind vane // Not compiled or tested in-world // Setup: Use a child arrow whose front is local +X. Owner-touch starts wind tracking once per two seconds. // Stop / restore: Owner-touch to stop and restore the captured starting pose before removing, resetting, or relinking. // Notes: Use a small nonphysical rezzed build with clear space. Actual prim transforms change. Original poses live only in script memory. Do not change physical status or link topology during use. Converts a world direction into the root-local frame. Calm wind keeps the last meaningful orientation; the root never rotates. // License: see LICENSE in this distribution. // Original Incoprea. MIT. Not compiled or tested in-world. vector home; rotation rest; integer active; integer valid=TRUE; default { state_entry() { home=llGetLocalPos(); rest=llGetLocalRot(); } touch_start(integer count) { if(llDetectedKey(0)!=llGetOwner()||!valid||llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS))return; active=!active; if(active) { llResetTime(); vector wind=llWind(ZERO_VECTOR); wind.z=0.0; if(llVecMag(wind)>0.01) { vector local=llVecNorm(wind)/llGetRootRotation(); llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]); } llSetTimerEvent(2); } else { llSetTimerEvent(0.0); llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_POS_LOCAL,home,PRIM_ROT_LOCAL,rest]); } } timer() { if(llGetLinkNumber()<2||llGetStatus(STATUS_PHYSICS)) { llSetTimerEvent(0.0); active=FALSE; return; } vector wind=llWind(ZERO_VECTOR); wind.z=0.0; if(llVecMag(wind)>0.01) { vector local=llVecNorm(wind)/llGetRootRotation(); llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,llRotBetween(<1.0,0.0,0.0>,local)]); } } changed(integer change) { if(change&CHANGED_LINK) { valid=FALSE; active=FALSE; llSetTimerEvent(0.0); llOwnerSay("Links changed; stopped without restoring. Reposition and reset before reuse."); } } }