Jump to content

Filter list using llGetSubString


testgenord1
 Share

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

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

Recommended Posts

Hi!
I'm trying to write a script in which a sensor puts objects' names on a list.
However, I only want to use objects starting with a particular beginning, e.g. "voc" (for "vocabulary").
These objects are supposed to be used for other purposes.

This means either:
- only objects with such a beginning are put on the list
or
- only objects with such a beginning on the list are used.

This is the step I haven't been able to achieve.
(I tried llGetSubString, but unsuccessfully.)

How can I filter a list in such a way that only objects beginning with "voc" are used in the script later on?

Here is my script so far (it works so far):

list lnames;

default
{
    state_entry()
    {
        llSensor("","",PASSIVE,96.0,PI);
    }
    sensor(integer num)
    {
        integer i;
        for(i = 0; i < num; ++i)
        lnames = lnames + llDetectedName(i); //all object names found by the sensor are put on the list.
        integer j;
        for(j = 0; j < num; ++j)
        llSay(0,llList2String(lnames,j)); //the object names on the list are used.
    }
}

Thank you very much in advance!
 

Edited by testgenord1
Link to comment
Share on other sites

Thank you very much for your quick reply.
After casting the list into a string using llList2String, I was able to find the index of the first word starting with "voc" (, which was 0), as you described.
However, some of my problems still remain:

- I could only find one word starting with "voc" in the resulting string, but not the other ones.

- What do I do with the index I've found so I can eventually use the object's complete name from the list?

The problem is further complicated by the fact that the words are on a list and not in a string, at first.

Link to comment
Share on other sites

I have been there myself, and the solution is actually rather simple. 
 

list lnames;

default
{
    state_entry()
    {
        llSensor("","",PASSIVE,96.0,PI);
    }
    sensor(integer num)
    {
        integer i;
        for(i = 0; i < num; ++i)
        {
        	if(llToLower(llGetSubString(llDetectedName(i)), 0, 2) == "voc") lnames = lnames + llDetectedName(i); //only object names starting with "voc" are put on the list.
        	integer j;
        	for(j = 0; j < num; ++j)
            {
        		llSay(0,llList2String(lnames,j)); //the object names on the list are used.
            }
        }
    }
}

although if I were to allow myself to modify the script to my own style, it would look like this:

list lnames;

default
{
    state_entry()
    {
        llSensor("","",PASSIVE,96.0,PI);
    }

    sensor(integer num)
    {
        integer i;
        for(i = 0; i < num; ++i)
        {
          	string DetName = llDetectedName(i); // I use variables for recurring functions. Makes code look less
          										// like spaghetti to me. Just personal preference.
        	if(llToLower(llGetSubString(DetName), 0, 2) == "voc") //only object names starting with "voc" are processed. I have DetName changed to lower case before comparing so it will also find "VOC", "vOc", Voc", "vOC", etc.
            {
            	lnames = += DetName; // Works the same as lnames = lnames + DetName, only more efficient in tests.
            }
        }
      	// This part is reached when the entire list is populated.
      	llOwnerSay(llList2CSV(lnames)); // Spit out a comma-separated list of the values in lnames.
    }
}

Although I changed quite a bit, the most important is the if(llToLower(llGetSubString(DetName), 0, 2) == "voc") part, this will check to see if a name starts with voc, and if so, adds it to the lnames list. If it does not start with "voc", it skips it.

  • Like 2
Link to comment
Share on other sites

Thank you so much for your help!
This seems to have done the trick.
I think there was a very little typo, which is, the line

if(llToLower(llGetSubString(llDetectedName(i)), 0, 2) == "voc") lnames = lnames + llDetectedName(i); //only object names starting with "voc" are put on the list.

probably has to be

if(llToLower(llGetSubString(llDetectedName(i), 0, 2)) == "voc") 
{
  lnames = lnames + llDetectedName(i); //only object names starting with "voc" are put on the list.

and likewise also in the second script?

The scripts are awesome.
Thank you so much for your support!

  • Like 1
Link to comment
Share on other sites

2 hours ago, testgenord1 said:

I think there was a very little typo, which is, the line


if(llToLower(llGetSubString(llDetectedName(i)), 0, 2) == "voc") lnames = lnames + llDetectedName(i); //only object names starting with "voc" are put on the list.

probably has to be


if(llToLower(llGetSubString(llDetectedName(i), 0, 2)) == "voc") 
{
  lnames = lnames + llDetectedName(i); //only object names starting with "voc" are put on the list.

and likewise also in the second script?

Ah yes, missing a closing bracket was bound to happen with my habit of making typos, but you caught it and fixed it. LOL

It's what I get for not taking the script in-world to check to see if it works :D 

 

 

Link to comment
Share on other sites

part 2:
(I hope I'm not annoying you too much.)
In order to reduce script count, I'm using a slight variation using a linkset and detecting the parameters of the child prims instead of the sensor.

What I would like to do now is the following:
The prims (i.e. their location vectors) of the respective linkset
can be individually used by touch_start as long as they are on the list (lprimpos).

However, each prim is only supposed to be used once.
This means, once it has been touched,
it should to be taken off the list.

I tried to do that but got stuck,
when it comes to the list.
The vectors on the list are being correctly named by (llList2String(lprimpos,n).
But I cannot take them off the list.
(When I check by touching if a vector is on the list,
the result is negative (although it was named right before as being on the list by llList2String).)

Maybe one of you can see why deleting the vectors from the list is not possible?
Thank you very much in advance!

vector vprimpos;
list lprimpos;
integer primnum;
//key id;
//string region;
vector vtouchedprim;


default
{
   state_entry()
   {
     //region = llGetRegionName(); 
     primnum = llGetNumberOfPrims();
     integer i;
     for (i=1; i <= primnum; i++) //link numbering in linksets starts with 1
        {
            lprimpos=llGetLinkPrimitiveParams(i,[PRIM_POSITION]);
            integer n;
            for(n=0; n<=primnum; n++)
            llOwnerSay(llList2String(lprimpos,n)); //check what elements are on the list.
        }
    } 
     touch_start(integer num)
     {
         //id = llDetectedKey(0);
         integer itouchedprim = llDetectedLinkNumber(0);
         llOwnerSay("link number touched: " + (string)itouchedprim); //check which linked prim has been touched.
         vtouchedprim = llList2Vector(llGetLinkPrimitiveParams(itouchedprim,[PRIM_POSITION]),0);
         llOwnerSay("position of touched: " + (string)vtouchedprim); //check position vector of the prim touched.
         {
            integer idxprimpos = llListFindList(lprimpos, vtouchedprim);
            llOwnerSay((string)idxprimpos); //check whether vector of prim touched is on the list.
            if(llListFindList(lprimpos, vtouchedprim) != -1) //if vector is on the list ...
            lprimpos = llDeleteSubList(lprimpos, idxprimpos, idxprimpos); //delete vector from the list.

            integer m;
            for(m=0; m<=primnum; m++)
            llOwnerSay("new list: " + llList2String(lprimpos,m)); //check elements on the new list.
            }
        }
}

 

Edited by testgenord1
Link to comment
Share on other sites

there is quite a lot missing in your latest code

like in state_entry is: lprimpos = when it should be lprimpos += appending the linked prim positions to the list

doing this tho won't always do what you want, when prims have the same referenced property values. Which is to remove a linked prim from the list when it is touched.  What we can do is save the link numbers in the list,  use the link number to reference the prim's properties, then finally, remove the link number from the list

example

list lprims;

default
{
   state_entry
   {
      integer numprims = llGetNumberOfPrims();
      integer linknum;
      for (linknum = 1; linknum <= numprims; linknum++)
         lprims += [linknum];
   }

   touch_start(integer detected)
   {
       
       integer linknum = llDetectedLinkNumber(0));
       integer listidx = llListFindList(lprims, [linknum]);
       if (~listidx) // found in lprims list
       {
           .. do something with prim (linknum) ...
           .. like gets its position ...

           // finally, remove linknum from lprims list using its listidx
           lprims = llDeleteSubList(lprims, listidx, listidx);
       }
   }
}

 

 

Edited by Mollymews
same referenced property values
  • Like 1
Link to comment
Share on other sites

Thank you so much for your quick reply and working through my script.
Your suggestion seems to have done the trick.
The list showed up empty after several clicks.
So thank you very much for your help, again!🙂

edit:
In order to show you what I wanted to do with the script,
I'm posting a slightly different version of the script below.
It teleports an avatar to a different prim in the linkset through saying the name of that prim.
It seems to work. I hope it stays that way.

(In that version, the vector does not need to be taken off the list.
Besides, It is made for OpenSim and so there is no experince permission for the teleporter, which would have to be added in SL.)

I'm posting the script below.
The script certainly has more room for improvement,
and so feel free to comment further.
Thank you very much for your ideas, once again.

integer primnum;
list lprimpos;
string region;
key player;
integer imessage;

default
{
   state_entry()
   {
       llSetClickAction(CLICK_ACTION_TOUCH);
    }
    touch_start(integer num)
    {
        player = llDetectedKey(0);
        llSetClickAction(8);
        llListen(0,"","","");
        llSetTimerEvent(10.0);
        llRegionSayTo(player,0,"Please write the name of the next station into the chat and press 'Enter'.");
   }
   listen(integer channel, string name, key id, string message)
   {
       region = llGetRegionName();
       primnum = llGetNumberOfPrims();
       integer i;
       for (i=1; i <= primnum; ++i) //link numbering in linksets starts with 1
       {
            lprimpos = llGetLinkPrimitiveParams(i,[PRIM_NAME,PRIM_POSITION]);
            lprimpos = llListSort(lprimpos, 2, TRUE);     //  sort strided list by ascending name (name used because it comes before vector [DetName,vpos]); TRUE means ascending order.
            imessage = llListFindList(lprimpos,message);
            if(imessage != -1)
            {
                vector pos = llList2Vector(lprimpos,imessage+1);
                //llOwnerSay((string)pos);
                osTeleportAgent(id,region,pos,<0.0,0.0,0.0>);
                llResetScript();
                }
            }
        }
    timer()
    {
        llRegionSayTo(player,0,"Click to start again.");
        llResetScript();
    }
}


 

Edited by testgenord1
adding new script version
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 1531 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...