Jump to content

Remove all scripts from linkset


SwireD
 Share

You are about to reply to a thread that has been inactive for 1646 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello! how to create a script that would delete all scripts from the link set and then delete itself? I found this script in wiki but it requires some additional action. is there a way to make this easier with a script?

For convenience i post it here:

This one is simple, and works for attachments and rezzed objects. Just drop the script in the linkset (so in the root prim). If the linkset is one single prim, there is nothing else to do. Otherwise, when the script tells you that it is ready, unrez/re-rez the object and set all scripts to running using the menu of the viewer. That's all. An hovertext shows the number of remaining prims to be cleaned up.

integer prims;
integer DELETE;
 
//  remove all other scripts, then this one
remove_scripts()
{
    string thisScript = llGetScriptName();
 
    integer index = llGetInventoryNumber(INVENTORY_SCRIPT);
    string scriptName;
 
    //  start with last script which has the index (numberOfScripts - 1)
    do
    {
        --index;
        scriptName = llGetInventoryName(INVENTORY_SCRIPT, index);
 
        if (scriptName != thisScript)
            llRemoveInventory(scriptName);
    }
    while (index);
 
    //  at last remove this script
    llRemoveInventory(thisScript);
}
 
default
{
    state_entry()
    {
        //  set an ident number code
        DELETE = (integer) ("0x" + (string) llGetOwner() );
        integer link = llGetLinkNumber();
 
        //  the root prim has link number 0 for single prim objects and 1 for linksets
        if (link < 2)
        {
            prims = llGetObjectPrimCount(llGetKey() );        // Get number of prims excluding seated avatars
 
            //  if single prim, else linkset
            if (prims == 1)
            {
                llSay(0, "Done removing scripts.");
                remove_scripts();
            }
            else
            {
                integer n = prims;
                while(n > 1)
                {
                    llGiveInventory(llGetLinkKey(n), llGetScriptName());
                    --n;
                }
                llSay(0, "Please take this object back to your inventory and "
                    + "rez it again. Then edit the object (ctrl+3), go to the menu at the "
                    + "top of your viewer and select BUILD > SCRIPTS > SET SCRIPTS TO RUNNING.");
            }
        }
        else//  not the root prim
        {
            llMessageLinked(LINK_ROOT, DELETE, "", NULL_KEY);
            remove_scripts();
        }
    }
 
    link_message(integer sender_num, integer num, string str, key id)
    {
        //  if the received linkmessage contains the ident number code previously stored...
        if (num == DELETE)
        {
            --prims;
            if (prims == 1)
            {
                llSay(0, "Done removing scripts.");
                remove_scripts();
            }
        }
    }
}

No need for chat and other messages, just deletion...

Edited by SwireD
Link to comment
Share on other sites

As far as I'm aware, there is only one function that can remove inventory items: llRemoveInventory() - but its scope is confined to the prim in which the host script resides. This means the function can't target other prims in the linkset. That is a considerable limitation, but if you reeaaallly want to force it, there may be a workaround. It's not pretty though.

Hypothetically speaking, I suppose you could accomplish this by writing your script in such a way that it would initiate a "delete everything plus myself last" loop when it receives a specific message command. Then use llRemoteLoadScriptPin to inject copy of that script into each linkset of the object. Then send the aforementioned signal (like llMessageLinked or something similar). When all scripts hear the signal, they begin the deletion loop and should in theory, clean themselves up last.

But that's a lot of effort compared to the viewer's menu command. Is there a particular reason why you're aiming for a scripted solution?

Edit: Whoops, I completely misread how llRemoteLoadScriptPin works. See Wulfie's post below.

Edited by Fenix Eldritch
  • Thanks 1
Link to comment
Share on other sites

And that script you posted does the job nicely.  I can't think of an easier way to do the job with a script.  As Wulfie says, though, 

1 hour ago, Wulfie Reanimator said:

Don't use scripts.

Select the object and go to Object > Scripts > Remove scripts from selection

 

  • Thanks 1
Link to comment
Share on other sites

21 minutes ago, Fenix Eldritch said:

But that's a lot of effort compared to the viewer's menu command. Is there a particular reason why you're aiming for a scripted solution?

Hi! Indeed seems very complicated!

my friend used this script, but complained about its inconvenience. I promised that I would try to get rid of the need to do all these operations.

Link to comment
Share on other sites

15 minutes ago, SwireD said:

Hi! Indeed seems very complicated!

my friend used this script, but complained about its inconvenience. I promised that I would try to get rid of the need to do all these operations.

It's not possible because llGiveInventory (which is used to copy the script from the root to every link in the linkset) has this clause:

  • Scripts reach destination disabled (not running, and cannot be made to run unless the destination object is taken to inventory and rezzed again, or the script is recompiled).

That clause has a workaround:

  • To send a running script to a prim, use llSetRemoteScriptAccessPin and llRemoteLoadScriptPin.

But that's not helpful because setting a pin can only be done for the prim the script is in. That means, you must put a script in each link so that they can use llSetRemoteAccessPin.. but you can't do that automatically because of the first clause.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

Generally objects that have a remove scripts option do so by sending a link message to all their scripts, and those scripts remove themselves in response. Not much help to you here, but maybe useful to know for anyone wondering how to incorporate this functionality into something they're making themselves.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

depends on the use case for how simple/complicated this needs to be

a typical use case for deleting scripts is a garment.  We make an inventory copy of the garment.  Wear the garment. Wear the garment texturing HUD.  Use the HUD to texture the garment.  Press a HUD button which deletes all the scripts in the garment

in this case the garment script(s), already has a listen channel open to receive commands from the HUD. On receiving a Delete command from the HUD the garment script deletes itself.  llRemoveInventory(myself).  llDie()

with this approach then our HUD script doesn't need to know anything about the script(s) in the garment or how many there are

next use case is: In what circumstance would we  have to use a script like in OP, because there is no alternative means to do this, either via UI or script

the circumstance would be:  Linkset is No-Modify and No-Copy and the script(s) targeted for deletion is set to Not Running, so the script(s) can't self-delete

a question then is: How likely/often will this circumstance occur.  What is the user circumstance where a No-Copy scripted texture changer would have had the garment script(s) set to Not Running and have a need to delete the scripts in it

 

edit add: what Wulfie and KT said when I was typing this

Edited by Mollymews
  • Thanks 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1646 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...