2

I would like to create an object that, when clicked by a specific person and only that person, it will animate the wearer of the object. When clicked a second time, the animation stops. I already have a script which animates on touch but now I need to implement some kind of permission system. I have effectively no scripting experience so I just find scripts others made or haphazardly tinker. In this case, I am not finding solutions.

Here's the script I currently have:

integer playing;

default
{
    state_entry()
    {
        playing = FALSE;
    }
    touch_start(integer start_param)
    {
        if(playing == FALSE)
        {
            llRequestPermissions(llDetectedKey(0),PERMISSION_TRIGGER_ANIMATION);
        }
        else if(playing == TRUE)
        {
            llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
            playing = FALSE;
        }
    }
    run_time_permissions(integer perm)                                  
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION)
        {
            playing = TRUE;
            llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
        }
    }    
}

If I implement a permission system, how would I do that? Where in the code should I put it? Also, if I wanted the object to say or whisper something when clicked by the permitted person, how can I do that? I am also open to being directed to alternative scripts that get closer to what I want, if available and preferably modifiable.

Thanks in advance for any assistance.

Vigos
  • 21
  • 1
  • 3

1 Answers1

2

This is very simple, actually.

One error you've made is that you ask for permission to animate from one who touched the object. That means that, no matter whether this object is worn by somebody or not, it will ask permission to animate from a toucher, not a wearer. So, your variant can be used as a dance machine that is attached to someone. But you want only the wearer to be animated, so you need to use llGetOwner() instead, because the wearer is always the owner of the object.

To make only the 'toucher' be "heard" by the touch event, simply put whatever there is in it into if(llDetectedKey(0) == TOUCHER) statement. And don't forget the brackets.

So, the working code is

    //specify the key of the agent that you want to be the 'TOUCHER'
key TOUCHER = "a6e50f98-cacf-4442-814b-cdf0a5554648";

integer playing;

default
{
    state_entry()
    {
        playing = FALSE;
    }
    touch_start(integer start_param)
    {
        if(llDetectedKey(0) == TOUCHER)
        {
            if(playing == FALSE)
            {
                llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
            }
            else if(playing == TRUE)
            {
                llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
                playing = FALSE;
            }
        }
    }
    run_time_permissions(integer perm)                                  
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION)
        {
            playing = TRUE;
            llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
        }
    }    
}

And a general recommendation. No need to write it

if(playing == FALSE)
            {
                llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
            }
            else if(playing == TRUE)
            {
                llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION,0));
                playing = FALSE;
            }

because "else" already means that whatever condition is in if is not true. So, in this case, else already means "if(playing == TRUE)", so there is no need to specify it again. Moreover, if you're working with so-called "boolean" values (LSL has no true booleans, only integers. But those are integers that you only give the values of TRUE (1) or FALSE (0) ), it is much easier and shorter to put it that way:

if(playing){} is the same as if(playing == TRUE) if(!playing){} means "if not playing" or the same as if(playing == FALSE)

And if I go even farther, there is a way you may get rid of playing variable and setting it manually everywhere. Script can detect whether a certain animation (with a certain key) is being played on the wearer via llGetAnimationList( llGetOwner() );. It returns a list of all animations (as keys, not names!) that are being played on the wearer right now.

Then you may simply check whether your animation is on that list via if(llListFindList(anims, [llGetInventoryKey(animation)]) == -1)

The final code is like this. I'm not sure if it works completely, and if it is the best way to do it, but worked for me. 8)

//specify the key of the agent that you want to be the 'TOUCHER'
key TOUCHER = "a6e50f98-cacf-4442-814b-cdf0a5554648";

//stores the key of an inventory animation to be played
string animation;

default
{
    state_entry()
    {        
        animation = llGetInventoryName(INVENTORY_ANIMATION,0);
    }

    touch_start(integer start_param)
    {
        //check if the allowed avatar touched the object
        if(llDetectedKey(0) == TOUCHER)
        {     
            llRequestPermissions(llGetOwner(),PERMISSION_TRIGGER_ANIMATION);
        }
    }

    run_time_permissions(integer perm)                                  
    {
        if (perm & PERMISSION_TRIGGER_ANIMATION)
        {
            //get all animations being played on the owner of the object as keys
            list anims = llGetAnimationList( llGetOwner() );

            //if the animation is NOT being played, start it. Else, stop it
            if(llListFindList(anims, [llGetInventoryKey(animation)]) == -1)
            {
                llStartAnimation(animation);
            }
            else
            {
                llStopAnimation(animation);
            }
        }
    }    
}
Highstaker
  • 1,015
  • 2
  • 12
  • 28