// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Crank and piston study // Not compiled or tested in-world // Setup: Put in root with exactly one child named crank_marker and one piston. The illustration uses root-local XY; both should be small. Owner-touch starts/stops. // 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. Uses a slider-crank relation with crank radius 0.2 m and connecting-rod length 0.6 m. No physics constraints or collisions are simulated. // License: see LICENSE in this distribution. // Original Incoprea. MIT. Not compiled or tested in-world. integer crank; integer piston; list home; integer active; default { state_entry() { integer i; integer hits; for(i=2;i<=llGetObjectPrimCount(llGetKey());++i) { string name=llGetLinkName(i); if(name=="crank_marker") { crank=i; ++hits; } if(name=="piston") { piston=i; ++hits; } } if(hits!=2||!crank||!piston) { crank=0; piston=0; return; } home=llGetLinkPrimitiveParams(crank,[PRIM_POS_LOCAL])+llGetLinkPrimitiveParams(piston,[PRIM_POS_LOCAL]); } touch_start(integer n) { if(llDetectedKey(0)!=llGetOwner()||llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)||!crank||!piston)return; active=!active; if(active) { llResetTime(); llSetTimerEvent(0.15); } else { llSetTimerEvent(0.0); llSetLinkPrimitiveParamsFast(crank,[PRIM_POS_LOCAL,llList2Vector(home,0)]); llSetLinkPrimitiveParamsFast(piston,[PRIM_POS_LOCAL,llList2Vector(home,1)]); } } timer() { if(llGetLinkNumber()>1||llGetStatus(STATUS_PHYSICS)) { llSetTimerEvent(0.0); active=FALSE; return; } float a=llGetTime()*0.5; float y=0.2*llSin(a); float x=0.2*llCos(a); float slider=x+llSqrt(0.36-y*y); llSetLinkPrimitiveParamsFast(crank,[PRIM_POS_LOCAL,]); llSetLinkPrimitiveParamsFast(piston,[PRIM_POS_LOCAL,]); } changed(integer change) { if(change&CHANGED_LINK) { llSetTimerEvent(0.0); active=FALSE; crank=0; piston=0; llOwnerSay("Links changed; reposition and reset before reuse."); } } }