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);
}
}
}
}