Jump to content
Sign in to follow this  
Mollymews

Experience Permissions: Managing multiple agents

Recommended Posts

complete example of managing multiple agents using Experience permissions

2 scripts: Console script which manages the agent script(s). Agent script(s) which manages each agent's permissions

/*
   Console

   manages upto 100 agent scripts
   see companion script; Agent

   example of using a console to manage the engagement of multiple agents, each with 
   their own experience permissions script

   the example use case is an automated dance arena accessed thru a collision portal/door
   
   console (as wrote) does not need to be saved/compiled with Use Experience
   
   placed in the Public Domain by Molly (mollymews) October 2019

*/   

integer aidx; 
integer alen;
integer alive;
string  anim;
list    anims;
list    agents;

engage(key id)
{   // act on agent's engaged state
    integer i = llListFindList(agents, [id]);
    if (~i) 
    {   // agent is engaged, so stop
        // 0 is the stop action. FE is console. i is agent script identity
        llMessageLinked(LINK_THIS, 0x0FE00 + i, "", id);
    }
    else  
    {   // agent is not engaged, find an agent slot for them
        i = llListFindList(agents, [0]);
        if (~i)
        {   // mark the slot as engaged
            agents = llListReplaceList(agents, [id], i, i);
            // message the assigned agent script
            // 1 is the start request action. FE is console. i is agent script identity                   
            llMessageLinked(LINK_THIS, 0x1FE00 + i, anim, id);
        }
        else
            llRegionSayTo(id, 0, "Agency is full. Please try again soon.");
    }
}

default
{
    state_entry()
    {
        // set arena gateway to phantom collision detect 
        llVolumeDetect(TRUE);
          
        // build list of agent script slots. Cap at 100
        integer n = llGetInventoryNumber(INVENTORY_SCRIPT) % 101;
        while (--n) agents += [0];
        
        // build index list of engagement animations. Set start animation. Cap 100
        alen = llGetInventoryNumber(INVENTORY_ANIMATION) % 100;
        n = alen;
        while (n) anims += [--n];
        anim = llGetInventoryName(INVENTORY_ANIMATION, 0);
          
        if (alen && llGetListLength(agents))
        {  // setup is good, so go to main loop 
            state main;
        }
        else
            llOwnerSay("Error: Either no engagment animation files or no agent scripts"); 
    }
    
    on_rez(integer start)
    {
        llResetScript();    
    }

    changed(integer change)
    {
        if (change & CHANGED_INVENTORY)
            llResetScript();
    }
    
}

state main
{
    on_rez(integer start)
    {
        llResetScript();    
    }

    changed(integer change)
    {
        if (change & CHANGED_INVENTORY)
            llResetScript();
    }
    
    collision_start(integer num)
    {   // act on the agent's engaged state
        while(~--num) engage(llDetectedKey(num));        
    }

// uncomment to act on touch 
/*
    touch_start(integer num)
    {   
        while(~--num) engage(llDetectedKey(num));        
    }
*/
    
    link_message(integer sender, integer addr, string msg, key id)
    {
        if ((addr & 0xFF) != 0xFE) 
        {   // message is not for me. My identity is OxFE
            return;
        }
       
        integer action = (addr >> 16); 
        if (action == 1)
        {   // start request granted
            if (++alive == 1) 
            {   // start the engagement timer changer when at least 1 agent engaged/alive
                llSetTimerEvent(30.0);
            }
        }
        else // action is 0
        {   // remove agent id from the assigned agents slot, mark as available
            integer from = (addr >> 8) & 0xFF;
            agents = llListReplaceList(agents, [0], from, from);
            if (!--alive) 
            {   // stop the engagement timer changer when is no agent engaged/alive
                llSetTimerEvent(0.0);
            }
        }
    }

    timer()
    {
        if (!aidx)
        {   // randomize the engagement animations to play in a full cycle
            anims = llListRandomize(anims, 1);
            if (llGetInventoryName(INVENTORY_ANIMATION, llList2Integer(anims, 0)) == anim) 
            {   // swap to end of cycle to not have an engagement play twice in a row
                anims = llDeleteSubList(anims, 0, 0) + ([llList2Integer(anims, 0)]);
            }
        }
        
        // get and send next animation in cycle to the agent scripts
        anim = llGetInventoryName(INVENTORY_ANIMATION, llList2Integer(anims, aidx));
        aidx = (++aidx) % alen; 
        if (anim != "") 
        {   // send message only when animation exists 
            // 1 is action. FE is console. FF is to all agent scripts      
            llMessageLinked(LINK_THIS, 0x1FEFF, anim, NULL_KEY);
        }
    }    
}
/*
   Agent

   managed by companion Console script
   needs to be saved/compiled as Use Experience

   example of using a console to manage the engagement of multiple agents, each with 
   their own experience permissions script

   the example use case is an automated dance arena accessed thru a collision portal/door

   dragcopy to object contents as many copies as desired. Capped by console to 100 agents
   dragcopy will autonumber the agent scripts, from which the script identity number is derived

   placed in the Public Domain by Molly (mollymews) October 2019

*/   

key     agent = NULL_KEY;
string  anim;
integer console;
integer identity;

integer perms()
{   // exhaustive permissions check
    if (!llAgentInExperience(agent))
        return FALSE;
    if (llGetAgentSize(agent) == ZERO_VECTOR)
        return FALSE;
    if (llGetPermissionsKey() != agent)
        return FALSE; 
    if (!(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION))
        return FALSE;
    if (anim == "")
        return FALSE;
    return TRUE;
}
        
stop()
{
    llSetTimerEvent(0.0);
    if (perms())
    {
        llStopAnimation(anim);
        llRegionSayTo(agent, 0, "You have stopped engaging.");
    }
    // 0x00000 is action stopped + console address     
    llMessageLinked(LINK_THIS, 0x00000 + console, "", agent);
    agent = NULL_KEY;
    anim = "";
}

default
{
    state_entry()
    {
        // get my unique identity number from my script name. Cap range to 0..99
        // as capped, more than 100 agent scripts will result in duplicate identity numbers 
        identity = (integer)llList2String(llParseString2List(llGetScriptName(), [" "], []), -1) % 100;
        // prepend identity to the console script identity (message address: from-me-to-you)
        // 0xFE is the identity of the console script
        // from-me-to-you addressing helps scripts to uniquely communicate 
        console = (identity << 8) + 0xFE;
    }
    
    link_message(integer sender, integer addr, string msg, key id)
    {
        if (addr == 0x1FEFF)
        {   // Ox1FEFF is action 1 from console FE to all agents FF
            if (perms())
            {
                if (msg != anim)
                {
                    llStartAnimation(msg);
                    llStopAnimation(anim);
                    anim = msg;
                }     
            }
            else
                stop();
            return;
        }
                
        if ((addr & 0xFF) != identity)
        {   // message is not for me
            return;
        }
        
        // who message is from ?
        integer from = (addr >> 8) & 0xFF;
        if (from == 0xFE)
        { // is from console
            integer action = (addr >> 16);
            if (action == 1)
            {   // request start
                anim = msg;
                agent = id;
                // set a timeout for when user blocks/ignores perms request dialog
                // as waiting for denied can take up to 5 minutes
                llSetTimerEvent(30.0); 
                llRequestExperiencePermissions(id, ""); 
            }
            else // action is 0
                stop();
        }
    }
    
    experience_permissions(key id)
    {
        if (perms())
        {
            llStartAnimation(anim);
            llRegionSayTo(agent, 0, "You are engaged!");
            llSetTimerEvent(0.0);
            // 0x10000 is perms request granted + console address
            llMessageLinked(LINK_THIS, 0x10000 + console, "", agent);        
        }
        else
            stop();
    }
    
    experience_permissions_denied(key id, integer reason)
    {
        // check that agent hasn't already been stopped by timer 
        if (agent != NULL_KEY)
            stop();    
    }
     
    timer()
    {
        // check that agent hasn't already been stopped by denied
        if (agent != NULL_KEY)
            stop();    
    }
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...