MLPV2 Ball Script with more flexible parameters

From Second Life Wiki
Revision as of 23:46, 23 February 2016 by ErikoLeo Resident (talk | contribs) (Added the missing </source> tag, removed the </lsl> and </LSL> obsolete(?) ones. The whole script now displays correctly.)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


// ~capture Script V1.01
// drop into a ball
//
//MLPV2.4z9
//Chaz edit 2012 to give control over (1) how visible adjusting beams are, (2) how high up balls rez, and (3) and over floating text on balls
//that's the only change, to make these parameters easily accessible and put them all in one section near top of script


// MLPV2 Version 2 by Learjeff Innis.  Based on
// MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License)

// To make ball phantom, put "*" as the first character in the ball's description
// or just make the ball phantom (which really works better for HUDs).
// The rest of the description, if any, is used for the sit pie menu and floating text.
// To make this take effect, use STOP to unrez the balls, and then select any pose.

// v2.4j - cancel old listen on rez
// v2.4m - handle control keys! To enable, begin ~ball description with a plus sign ("+"), following "*" if any.
// v2.4p - page up & down to enable/disable adjustment
// v2.4x - moved SitTarget to top.

//chaz adjustable parameters start
float AdjustBeamTransparency = 0.4; //0.1 is practically invisible; 1.0 is solid (0.0 <= alpha <= 1.0) 
string BallFloatingText = "";//any floating text to display above the balls
vector  SitTarget       = <0.,0.,-.5>;   // Change this to <0.,0.,-.15> or lower, to raise balls above cushion
//chaz adjustable parameters end


vector  SitTargetRef    = <0.,0.,.1>;   // Don't change this, unless you're replacing earlier versions
                                        // with a custom SitTarget.  In that case, set to match SitTarget.

integer ADJUSTABLE  = FALSE;
float   DELTA       = 0.01;        // cm to move
float   EPSILON     = 0.005;       // cm position error tolerance, should be about half delta
vector  Offset;
vector  BallPos;
rotation BallRot;

key     NullKey = NULL_KEY;

integer Chan;
integer Group;
integer visible = TRUE;
integer Adjusting;
key     Avatar;
string  Name;
integer ListenHandle;

integer ControlsActive;

// 15 color support, thanks to Liz Silverstein
// Color is passed as a string by object chat (from menu via poser*)
    
list colors = [ <0.0,0.0,0.0>,          // 0 = HIDE
                <0.835,0.345,0.482>,    // 1 = PINK
                <0.353,0.518,0.827>,    // 2 = BLUE
                <0.635,0.145,0.282>,    // 3 = PINK2 - Dark pink
                <0.153,0.318,0.627>,    // 4 = BLUE2 - Dark blue
                <0.128,0.500,0.128>,    // 5 = GREEN
                <1.000,0.000,1.000>,    // 6 = MAGENTA
                <1.000,0.000,0.000>,    // 7 = RED
                <1.000,0.500,0.000>,    // 8 = ORANGE
                <1.000,1.000,1.000>,    // 9 = WHITE
                <0.0,0.0,0.0>,          // 10 = BLACK
                <1.0,1.0,0.0>,          // 11 = YELLOW
                <0.0,0.8,0.8>,          // 12 = CYAN
                <0.5,0.0,0.0>,          // 13 = RED2
                <0.0,0.5,0.5>,          // 14 = TEAL
                <0.0,0.25,0.25>];       // 15 = GREEN2



handle_control(key id, integer level, integer change) {

    if (Avatar == NullKey) {
        return;
    }
    
    if ((level & CONTROL_UP) && (level & CONTROL_DOWN)) {
        ControlsActive = ! ControlsActive;
        if (ControlsActive) {
            control_active();
        } else {
            control_ready();
        }
        return;
    }
    
    if (!ControlsActive) {
        return;
    }


    if (level & CONTROL_UP) {
        Offset.z += DELTA;
    } else if (level & CONTROL_DOWN) {
        Offset.z -= DELTA;
    } else if (level & CONTROL_LEFT) {
        Offset.y += DELTA;
    } else if (level & CONTROL_RIGHT) {
        Offset.y -= DELTA;
    } else if (level & CONTROL_FWD) {
        Offset.x += DELTA;
    } else if (level & CONTROL_BACK) {
        Offset.x -= DELTA;
    } else {
        return;
    }

    llSetPos(BallPos + Offset * BallRot + SitTargetRef - SitTarget);
}

// enter "control ready" state.
control_ready() {
    ControlsActive = 0;
    integer controls = CONTROL_UP | CONTROL_DOWN;

    llTakeControls(controls, TRUE, FALSE);
    llInstantMessage(Avatar, "Allow adjusting your position by pressing Pgup and Pgdn keys at the same time");
}

control_active() {
    integer controls = CONTROL_UP | CONTROL_DOWN | CONTROL_LEFT | CONTROL_RIGHT | CONTROL_FWD | CONTROL_BACK;

    llTakeControls(controls, TRUE, FALSE);
    llInstantMessage(Avatar, "Adjust your position using Pgup/Pgdn, Up/Down arrow, and shift-left/right arrow keys\nDisable by pressing Pgup and Pgdn keys at the same time");
    BallPos = llGetPos() + SitTarget - SitTargetRef;
    BallRot = llGetRot();
}



render() {
    if (!visible || (Avatar != NullKey && !Adjusting)) {
        // hidden
        llSetScale(<0.01,0.01,0.01>);
        llSetAlpha(0.0, ALL_SIDES);
        llSetText(BallFloatingText,<1.0,1.0,1.0>,0.0);    
    } else if (Avatar != NullKey && Adjusting) {
        // sitting and adjusting
        llSetAlpha(AdjustBeamTransparency,ALL_SIDES);
        llSetText("Adjust",<1.0,1.0,1.0>,1.0);
        llSetScale(<0.1,0.1,5.0>);
    } else {
        // shown
        llSetAlpha(1.0, ALL_SIDES);
        llSetScale(<0.2,0.2,0.2>);
        if (Adjusting) {
            llSetText("Adjust",<1.0,1.0,1.0>,1.0);
        } else {
            //chaz edit
            llSetText(BallFloatingText,<1.0,1.0,1.0>,1.0);
        }
    }
}

show() {
    visible = TRUE;
    render();
}

hide() {
    visible = FALSE;
    render();
}

default {
    on_rez(integer channel) {
        Name = llGetObjectDesc();
        if (Name == "" || Name == "(No Description)") {
            //chaz edit
            Name = "";
        } else {
            if (llSubStringIndex(Name, "*") == 0) {
                llSetPrimitiveParams([PRIM_PHANTOM, TRUE]);
                Name = llGetSubString(Name, 1, -1);
            }
            if (llSubStringIndex(Name, "+") == 0) {
                ADJUSTABLE = TRUE;
                Name = llGetSubString(Name, 1, -1);
            }
            if (Name == "none") {
                Name = "";
            }
        }
        llSitTarget(SitTarget, ZERO_ROTATION);
        if (Name != "") {
            llSetSitText(Name);
        } else {
            llSetSitText("");
        }
        Avatar = NullKey;
        Chan = channel;
        Group = 0;
        
        if (ListenHandle) {
            llListenRemove(ListenHandle);
            ListenHandle = 0;
        }

        if (Chan != 0) {
            ListenHandle = llListen(Chan,"",NullKey,"");
            // start timer unless ball was dragged from inv
            llSetTimerEvent(180.0);
        }
        
        if (llGetObjectDesc() == "ADJUSTABLE") {
            ADJUSTABLE = TRUE;
        }
    }

    changed(integer change) {
        if (change != CHANGED_LINK) return;
        Avatar = llAvatarOnSitTarget();
        if (Avatar != NullKey) {

            if (Group) {
                if (!llSameGroup(Avatar)) {
                    llUnSit(Avatar);
                    llWhisper(0,"no permission to use poseball");
                    return;
                }
            }
            if (ADJUSTABLE) {
                llRequestPermissions(Avatar, PERMISSION_TAKE_CONTROLS);
            }
        }
        llSay(Chan+8,(string)Avatar);     //requests perm, sets animation
        render();
        
    }

    listen(integer channel, string name, key object, string str) {
        integer ix;
        ix = llSubStringIndex(str,">");    
        if (ix != -1) {
            BallPos = (vector)llGetSubString(str,0,ix);
            BallRot = (rotation)llGetSubString(str,ix+1,-1);
            llSetPos(BallPos + SitTargetRef - SitTarget);
            llSetRot(BallRot);
        } else if (str == "0") {    //HIDE
            hide();
        } else if (str == "SHOW") { //SHOW
            show();
        } else if (str == "ADJUST|1") {
            Adjusting = TRUE;
            render();
        } else if (str == "ADJUST|0") {
            Adjusting = FALSE;
            render();
        } else if (str == "SAVE") {
            llSay(Chan+16,(string)(llGetPos() + SitTarget - SitTargetRef)+(string)llGetRot());
        } else if (str == "GROUP") {
            Group = 1;
        } else if (str == "ALL") {
            Group = 0;
        } else if (str == "DIE") {
            llSay(Chan+8, (string)NullKey);    //msg to poser (don't reanimate after STOP)
            llDie();
        } else if (str == "LIVE") {
            llSetTimerEvent(180.0);
            // llSay(Chan+8,"ALIVE");    //msg to poser -> to menu
        } else {
            list ldata = llParseString2List(str, ["|"], []);
            integer colorIx = (integer) llList2String(ldata,0);
            string ballIx = llList2String(ldata,1);
            Adjusting = (integer) llList2String(ldata,2);
            if ((colorIx > 0) && (colorIx < 16)) { // this must be a color setting  
                llSetColor(llList2Vector(colors, colorIx),ALL_SIDES);     //pull the color out of the list
                render();
                llSetObjectName("~ball" + ballIx);
                BallPos = llGetPos() + SitTarget - SitTargetRef;
                BallRot = llGetRot();
            }
        }
    }

    timer() {                       //not heard "LIVE" from menu for a while: suicide
        llDie();
    }

    run_time_permissions(integer perm) 
    { 
        if (llKey2Name(Avatar) == "") {
            return;
        }
        if (Avatar != llGetPermissionsKey()) {
            return;
        }

        if (perm & PERMISSION_TAKE_CONTROLS) {
            control_ready();
        }
    }

    moving_end() {
        vector newpos = llGetPos() + SitTarget - SitTargetRef;
        if (llVecMag(newpos - (BallPos + Offset)) > EPSILON) {
            // we didn't move it, someone else did.  Deal with it.
            BallPos = newpos;
        }
        BallRot = llGetRot();
    }

    control(key id, integer level, integer change) {
        handle_control(id, level, change);
    }
}