This script was tested and works on OpenSim version 0.7.5!

poseball_system_ball.lsl
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueGet(string k, string data) {
    if(llStringLength(data) == 0) return "";
    if(llStringLength(k) == 0) return "";
    list a = llParseStringKeepNulls(data, ["&", "="], []);
    integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]);
    if(i != -1) return llList2String(a, 2*i+1);
    return "";
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueSet(string k, string v, string data) {
    if(llStringLength(k) == 0) return "";
    if(llStringLength(v) == 0) return "";
    if(llStringLength(data) == 0) return k + "=" + v;
    integer i = llListFindList(
        llList2ListStrided(
            llParseString2List(data, ["&", "="], []), 
            0, -1, 2
        ), 
    [ k ]);
    if(i != -1) return llDumpList2String(
        llListReplaceList(
            llParseString2List(data, ["&"], []), 
            [ k + "=" + v ], 
        i, i), 
    "&");
    return data + "&" + k + "=" + v;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasKeyValueMergeTuple(list left, list right) {
    if(llGetListLength(left) == 0 && llGetListLength(right) == 0) 
        return [];
    if(llGetListLength(left) == 0) {
        left = right;
        right = [];
    }
    string lk = llList2String(left, 0);
    left = llDeleteSubList(left, 0, 0);
    string lv = llList2String(left, 0);
    left = llDeleteSubList(left, 0, 0);
    integer x = llListFindList(right, (list)lk);
    if(x != -1) {
        lv = llList2String(right, x+1);
        right = llDeleteSubList(right, x, x+1);
    }
    return [lk + "=" + lv] + wasKeyValueMergeTuple(left, right);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueMerge(string kva, string kvb) {
    return llDumpList2String(
        wasKeyValueMergeTuple(
            llParseString2List(kvb, ["=", "&"], []),
            llParseString2List(kva, ["=", "&"], [])
        )
    ,"&"
    );
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueDelete(string k, string data) {
    if(llStringLength(data) == 0) return "";
    if(llStringLength(k) == 0) return "";
    integer i = llListFindList(
        llList2ListStrided(
            llParseString2List(data, ["&", "="], []), 
            0, -1, 2
        ), 
    [ k ]);
    if(i != -1) return llDumpList2String(
        llDeleteSubList(
            llParseString2List(data, ["&"], []),
        i, i), 
    "&");
    return data;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueEncode(list data) {
    list k = llList2ListStrided(data, 0, -1, 2);
    list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
    data = [];
    do {
        data += llList2String(k, 0) + "=" + llList2String(v, 0);
        k = llDeleteSubList(k, 0, 0);
        v = llDeleteSubList(v, 0, 0);
    } while(llGetListLength(k) != 0);
    return llDumpList2String(data, "&");
}
 
//////////////////////////////////////////////////////////
// Wizardry and Steamworks (c) 2013,  GPLv3             //
//////////////////////////////////////////////////////////
list wasKeyValueDecode(string data) {
    return llParseString2List(data, ["&", "="], []);
}
 
default
{
    state_entry() {
        integer comChannel = (integer)("0x8" + llGetSubString(llGetOwner(), 0, 6)) + (integer)wasKeyValueGet("session", llGetObjectDesc());
        llListen(comChannel, "", "", "");
        // set sit target, otherwise sitting will not work 
        llSitTarget(<0,0,0.01>, llEuler2Rot(<0,0,0> * DEG_TO_RAD));
        // set the mouse click action to sit
        llSetClickAction(CLICK_ACTION_SIT);
    }
    listen(integer channel, string name, key id, string message) {
        string sex = wasKeyValueGet("sex", llGetObjectDesc());
        if(wasKeyValueGet("die", message) == sex) {
            key a = llAvatarOnSitTarget();
            if(a != NULL_KEY) llUnSit(a);
            llDie();
        }
        if(message == "sync") jump sync;
        if(sex != wasKeyValueGet("sex", message)) return;
        string rpm = wasKeyValueGet("rp", message);
        if(rpm == "") return;
        message = wasKeyValueDelete("rp", message);
        string rrm = wasKeyValueGet("rr", message);
        if(rrm == "") return;
        message = wasKeyValueDelete("rr", message);
        string pm = wasKeyValueGet("p", message);
        if(pm == "") return;
        message = wasKeyValueDelete("p", message);
        string rm = wasKeyValueGet("r", message);
        if(rm == "") return;
        message = wasKeyValueDelete("r", message);
        vector rp = (vector)rpm;
        rotation rr = (rotation)rrm;
        llSetPos(rp + (vector)pm * rr);
        llSetRot(llEuler2Rot((vector)rm * DEG_TO_RAD) * rr);
        message = wasKeyValueDelete("sex", message);
        llSetObjectDesc(wasKeyValueMerge(message, llGetObjectDesc()));
@sync;
        key avatar = llAvatarOnSitTarget();
        if(avatar != NULL_KEY) llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION);
    }
    on_rez(integer num) {
        llSetObjectDesc(wasKeyValueSet("session", (string)num, llGetObjectDesc()));
        llResetScript();
    }
    changed(integer change) {
        if(!(change & CHANGED_LINK)) return;
        key avatar = llAvatarOnSitTarget();
        if(avatar == NULL_KEY) jump unsit;
        llWhisper((integer)("0x8" + llGetSubString(llGetOwner(), 0, 6)) + (integer)wasKeyValueGet("session", llGetObjectDesc()), "sync");
        llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION);
        llSetScale(llGetScale()/10);
        llSetAlpha(0, ALL_SIDES);
        return;
@unsit;
        llSetScale(llGetScale()*10);
        llSetAlpha(1, ALL_SIDES);
    }
    run_time_permissions(integer perm) {
        if(!(perm & PERMISSION_TRIGGER_ANIMATION)) return;
        key av = llAvatarOnSitTarget();
        if(av == NULL_KEY) return;
        string old = wasKeyValueEncode(llCSV2List(wasKeyValueGet("old", llGetObjectDesc())));
        if(llGetInventoryType(old) != INVENTORY_ANIMATION) jump start;
        llStopAnimation(old);
        llSleep(1.1-llGetRegionTimeDilation());
@start;
        string new = wasKeyValueEncode([wasKeyValueGet("n", llGetObjectDesc()), wasKeyValueGet("swap", llGetObjectDesc())]);
        if(llGetInventoryType(new) != INVENTORY_ANIMATION) return;
        llStartAnimation(new);
        llSetObjectDesc(wasKeyValueSet("old", llList2CSV(wasKeyValueDecode(new)), llGetObjectDesc()));
    }
}