User:Daemonika Nightfire/Scripts/Single Pose Sitter

From Second Life Wiki
Jump to navigation Jump to search

*DS* Single Pose Sitter

Dieses Script ist das Ergebnis unseres Unterrichts. Es eignet sich ideal fuer einzelne Moebel die fuer 1 Avatar gedacht sind. Des weiteren verfuegt dieses Script ueber saemtliche bis dato aktuellen Funktionen, also es ist technich auf dem neusten Stand (Juli. 2024).

Das Format der Notecard um die Animationen zu verwalten sieht wiefolgt aus.
AnimationsName|VectorPosition|VectorRotation

Warum haben wir uns bei der Rotation fuer den Vector entschieden?
Ganz einfach, den Vector kann man im freihant editieren und das Script rechnet es selbst in ein Quaternion um.
/*
    *DS* Single Pose Sitter by *DS* Script-Schule
    
    Single Pose bedeutet 1 Avatar pro Link_Set.
    Weitere Avatare mit zusaetzlichen Scripten werden nicht beruecksichtigt.
    Im Gegenteil, es kann zu irretationen fuerhren.
    
    Dieses Script kann bis zu 9 verschiedene Posen nutzen.
    Jede Pose kann individuell angepasst und gespeichert werden.
    Bei bedarf kann man die entsprechende Einstellung ebenfalls in die Notecard uebertragen.
    
    Es sind 9 Button-Namen fuer die jeweiligen Posen vorgegeben.
    Die Liste dieser Button passt sich automatisch der Anzahl Posen an.
    Werden also nur 2 Posen aus der notecard gelesen, erhaeltst du nur die Button [ one ] & [ two ].
*/

// Notecard auslesen.
string nc_name = "posen";
key read_nc;

// Avatar Key, Status & Berechtigung.
key Avatar = "";
integer Sitting = FALSE;
integer Permission = FALSE;

// Grund-Einstellungen fuer den SitTarget.
integer LinkTarget = LINK_THIS;
vector Position = <0.00, -0.00, 0.43>;
vector Rotation = <00, 00, 00>;

// Auswahl der Animationen inclusive individueller Vectoren.
list button_index = ["one","two","three","four","five","six","seven","eight","nine"];
list posen = [];
string Animation = "";
integer avi_link;
vector avi_pos = <0,0,0.65>;
vector avi_rot = <0,0,90>;

// Menue mit dynamischen Channel.
integer menu_handler;
integer menu_channel;
menu(key user,string title,list buttons)
{
    llListenRemove(menu_handler);
    menu_channel = (integer)(llFrand(1) * -DEBUG_CHANNEL);
    menu_handler = llListen(menu_channel,"","","");
    llDialog(user, title, buttons, menu_channel);
    
    llSetTimerEvent(60);
}

// Anpassbare Vectoren fuers Einstellungs-Menue.
list pos_step_button = ["1cm", "5cm", "25cm"];
list pos_steps = [0.01, 0.05, 0.25];
integer pos_counter = 0;
float pos_step = 0.01;
postion_menu(key uuid)
{
    menu(uuid, "\nPositioning\n", ["Main",llList2String(pos_step_button, pos_counter),"Save","Pos x-","Pos y-","Pos z-","Pos x+","Pos y+","Pos z+"]);
}

list rot_step_button = ["1°","6°","30°"];
list rot_steps = [1.0, 6.0, 30.0];
integer rot_counter = 0;
float rot_step = 1.0;
rotation_menu(key uuid)
{
    menu(uuid, "\nOrientation\n", ["Main",llList2String(rot_step_button, rot_counter), "Save","Rot x-","Rot y-","Rot z-","Rot x+","Rot y+","Rot z+"]);
}

// Ausfuehrung der individuellen Vectoren.
string current_animation;
integer index = 0;
Change(key uuid)
{
    list parsed = llParseString2List(llList2String(posen, index), ["|"],[]);
    current_animation = llList2String(parsed, 0);
    avi_pos = (vector)llList2String(parsed, 1);
    avi_rot = (vector)llList2String(parsed, 2);
    
    llStartAnimation(current_animation);
    if(current_animation != Animation)
    {
        llStopAnimation(Animation);
    }
    Animation = current_animation;
    llSetLinkPrimitiveParamsFast(avi_link, [PRIM_POS_LOCAL, avi_pos, PRIM_ROT_LOCAL, llEuler2Rot(avi_rot * DEG_TO_RAD)]);
    menu(uuid, "\nChoose your options.\n", ["Position","Rotation","Close"] + button_index);
}


default
{
    state_entry()
    {
        llLinkSitTarget(LinkTarget, Position, llEuler2Rot(Rotation * DEG_TO_RAD));
        
        if(llGetInventoryNumber(INVENTORY_ANIMATION) > 0 && Animation == "")
        {
            Animation = llGetInventoryName(INVENTORY_ANIMATION, 0);
        }
        read_nc = llGetNumberOfNotecardLines(nc_name);
    }
    
    dataserver(key request, string data)
    {
        if(request == read_nc)
        {
            integer count = (integer)data;
            integer i;
            do
            {
                string line = llGetNotecardLineSync(nc_name, i);
                if(line == NAK)
                {
                    llSay(0, "---NAK---\nNotecard are missing or not readable.");
                }
                else if(line == EOF)
                {
                    // An dieser Stelle wird die Liste mit den 9 Button an die Laenge der Liste Posen angepasst.
                    // Hier wird lediglich jeder weitere unnoetige Button einfach geloescht.
                    integer bl = llGetListLength(posen);
                    button_index = llDeleteSubList(button_index, i, -1);
                    llSay(0,"---EOF---\n" + (string)bl + " poses loaded.\n" + (string)llGetUsedMemory() + " bytes memory in use.");
                }
                else
                {
                    posen += line;
                }
            }
            while(++i <= count);
        }
    }
    
    touch_start(integer total_number)
    {
        key agent = llDetectedKey(0);
        if(agent == Avatar)
        {
            menu(agent, "\nChoose your options.\n", ["Position","Rotation","Close"] + button_index);
        }
    }
    
    listen(integer channel, string name, key id, string message)
    {
        list temp = llParseString2List(message, [" "], []);
        string cmd = llList2String(temp, 0);
        string data = llList2String(temp, 1);
        
        if(cmd == "Close")
        {
            llSetTimerEvent(0.0);
            llListenRemove(menu_handler);
        }
        else if(cmd == "Main")
        {
            menu(id, "\nChoose your options.\n", ["Position","Rotation","Close"] + button_index);
        }
        else if(~llListFindList(button_index, [cmd]))
        {
            integer i = llListFindList(button_index, [cmd]);
            if(i != -1)
            {
                index = i;
                Change(id);
            }
        }
        
        // Positions-Einstellungen
        else if(cmd == "Position")
        {
            postion_menu(id);
        }
        else if(~llListFindList(pos_step_button, [cmd]))
        {
            pos_counter++;
            if(pos_counter == llGetListLength(pos_steps))
            {
                pos_counter = 0;
            }
            pos_step = llList2Float(pos_steps, pos_counter);
            postion_menu(id);
        }
        else if(cmd == "Pos")
        {
            if(data == "x-")      { avi_pos.x -= pos_step; }
            else if(data == "x+") { avi_pos.x += pos_step; }
            else if(data == "y-") { avi_pos.y -= pos_step; }
            else if(data == "y+") { avi_pos.y += pos_step; }
            else if(data == "z-") { avi_pos.z -= pos_step; }
            else if(data == "z+") { avi_pos.z += pos_step; }
            
            llSetLinkPrimitiveParamsFast(avi_link, [PRIM_POS_LOCAL, avi_pos, PRIM_ROT_LOCAL, llEuler2Rot(avi_rot * DEG_TO_RAD)]);
            postion_menu(id);
        }
        
        // Rotations-Einstellungen
        else if(cmd == "Rotation")
        {
            rotation_menu(id);
        }
        else if(~llListFindList(rot_step_button, [cmd]))
        {
            rot_counter++;
            if(rot_counter == llGetListLength(rot_steps))
            {
                rot_counter = 0;
            }
            rot_step = llList2Float(rot_steps, rot_counter);
            rotation_menu(id);
        }
        else if(cmd == "Rot")
        {
            if(data == "x-")      { avi_rot.x -= rot_step; }
            else if(data == "x+") { avi_rot.x += rot_step; }
            else if(data == "y-") { avi_rot.y -= rot_step; }
            else if(data == "y+") { avi_rot.y += rot_step; }
            else if(data == "z-") { avi_rot.z -= rot_step; }
            else if(data == "z+") { avi_rot.z += rot_step; }
            
            llSetLinkPrimitiveParamsFast(avi_link, [PRIM_POS_LOCAL, avi_pos, PRIM_ROT_LOCAL, llEuler2Rot(avi_rot * DEG_TO_RAD)]);
            rotation_menu(id);
        }
        
        // Speichern der Einstellungen
        else if(cmd == "Save")
        {
            string store = "\n" + Animation + "|" + (string)avi_pos + "|" + (string)avi_rot;
            posen = llListReplaceList(posen, [store], index, index);
            llOwnerSay(store);
        }
    }
    
    changed(integer Change)
    {
        if(Change & CHANGED_LINK)
        {
            if(!Sitting)
            {
                Avatar = llAvatarOnLinkSitTarget(LinkTarget);
                if(Avatar)
                {
                    Sitting = TRUE;
                    integer prims = llGetNumberOfPrims();
                    integer i = 0;
                    do
                    {
                        string name = llGetLinkName(i);
                        if(name == llKey2Name(Avatar))
                        {
                            avi_link = i;
                        }
                    }
                    while(++i <= prims);
                    
                    if(Animation != "")
                    {
                        llRequestPermissions(Avatar, PERMISSION_TRIGGER_ANIMATION);
                    }
                }
            }
            else if(Sitting)
            {
                if(Permission)
                {
                    if(llKey2Name(Avatar) != "")
                    {
                        llStopAnimation(Animation);
                    }
                    Permission = FALSE;
                }
                Sitting = FALSE;
                Avatar = "";
            }
        }
        else if(Change & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
    
    run_time_permissions(integer Permission)
    {
        if(Permission & PERMISSION_TRIGGER_ANIMATION)
        {
            llStopAnimation("sit_generic");
            llStopAnimation("sit");
            Change(Avatar);
        }
    }
    
    timer()
    {
        llSetTimerEvent(0.0);
        llListenRemove(menu_handler);
    }
    
    on_rez(integer Dae)
    {
        llResetScript();
    }
}