Rope Constraint

This is a nifty little script that simulates a rope between two objects

Place the script in an object, duplicate the object, and make one physical. This script is not perfect, if bumped right the object will go swinging out of control and fly off-world.

// Pseudo-Realistic Rope Constraint by Comrade Podolsky
// Free for non-commercial use.
// If used commercially, if possible please notify me of what use you found for it. (Besides tether-ball.)

integer lockon = FALSE;
float rope_length = 1.0; // Obviously, the length of the simulated rope. (It will stretch slightly longer than this, though)
float dampening = 0.04; // This dampens a fraction of the object's velocity every 0.1 seconds, if the rope is stretched.
float bouncing = 1; // How much the object "bounces" back after stretching the rope to the limit of its length. This applies if the rope is stretched suddenly. 0.4 means it will bounce back with  40% of its original velocity. Setting this to below 0 will make the constraint act more stretchy than ropes normally do. Setting this to above 1 will make it unstable and dangerous.
float constant = 16.0; // The force constant of the rope. This applies when the rope is stretched slowly - in which case, it acts sort of like a spring.
key target;
vector ropecolor;
list rope_effect = [];

default
{
    state_entry()
    {
        llListen(12345,"","","TEST123");
        llSetTimerEvent(5.0);
    }

    timer() { if ( !lockon ){llWhisper(12345,"TEST123"); } } // Automatically locate "other" objects

    listen(integer chan, string name, key id, string msg)
    {
        if (!lockon)
        {
            lockon = TRUE;
            llWhisper(12345,"TEST123");
            llSetTimerEvent(0.0);
            target = id;
            llSensorRepeat("", target, SCRIPTED, 20.0, PI, 0.1); // This part may get rather resource-consuming. For slower-moving objects, and objects roped to something static, range may be decreased and delay may be increased.
            //Sensor range must be at least twice the length of the rope. Stretching the rope farther will cause it to act like it breaks, but it will restore itself if the objects are moved back together.

            rope_effect = // This is the particle effect representation of the rope. Change the colors, alphas, scales, and textures however you like. I can't say how it will affect the effect if you change anything else.
            [
                PSYS_PART_FLAGS,            PSYS_PART_FOLLOW_SRC_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_TARGET_LINEAR_MASK | PSYS_PART_TARGET_POS_MASK,

                PSYS_SRC_PATTERN,           PSYS_SRC_PATTERN_DROP,
                PSYS_SRC_TARGET_KEY,        target,

                PSYS_PART_START_COLOR,      ropecolor,
                PSYS_PART_END_COLOR,        ropecolor,
                PSYS_PART_START_ALPHA,      1.0,
                PSYS_PART_END_ALPHA,        1.0,
                PSYS_PART_START_SCALE,      <0.05,1.0,1.0>,
                PSYS_PART_END_SCALE,        <0.05,1.0,1.0>,
                PSYS_SRC_TEXTURE,           "",

                PSYS_PART_MAX_AGE,          0.5,
                PSYS_SRC_BURST_RATE,        0.001,
                PSYS_SRC_BURST_PART_COUNT,  1
            ];

            llParticleSystem(rope_effect);
        }
    }

    sensor(integer num_detected)
    {
        vector i_pos = llGetPos();
        vector u_pos = llDetectedPos(0);

        if (llVecMag(u_pos-i_pos)>rope_length)
        {
            llSetForce(constant*llGetMass()*llVecNorm(u_pos-i_pos)*(llVecMag(u_pos-i_pos) - rope_length),FALSE); // This is how an ideal spring would behave under these conditions. Without this statement, the rope would stretch slowly but indefinitely. Ropes do not work that way.
            llApplyImpulse( llGetMass() * llGetVel() * dampening * -1.0 , FALSE ); // This dampens the motion of the object, preventing buildup of excess kinetic energy through oscillation.
            vector wrongway = llVecNorm(i_pos - u_pos); // The direction in which the object should NOT be moving
            float wrongmag = ( llGetVel() - llDetectedVel(0) ) * wrongway; // The velocity with which the object is apparently moving, against the pull of the rope.
            if ( wrongmag > 0.0 ) { llApplyImpulse( llGetMass() * ( ( -1.0 - bouncing ) * ( wrongway * wrongmag ) ) , FALSE ); } // Stop the object from stretching too much farther than rope length.
        }
        else { llSetForce( ZERO_VECTOR, FALSE ); } // If the two objects are closer than rope length, the rope doesn't do anything.
    }

    no_sensor()
    {
        llSetForce( ZERO_VECTOR, FALSE );
    } // If the other object is nowhere to be seen, this object stops doing stuff.
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License