Jump to content

llGetSubString - UPDATED almost works


Sari6t
 Share

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

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

Recommended Posts

Hey there,

 

Found a wonderful script written by Rolig Loon, it does mostly what I needed and with my fumbling around I have managed to get it to populate a menu from a NC and then pass that to llMapDestinations and TP. 

 

Sounds like Im done but Im not

Thing is this. The way the script works is it uses llGetSubString and so far it is brilliant if you have a NC with NAME and Vector. Meaning  SIMNAME and <0.0,0.0,0.0>  type thing. 

But I need a location name then sim name and vector. 

so instead of the NC looking like

SimName <0.0,0.0,0.0>

I need

Name / SimName / <0.0,0.0,0.0>

to be parsed and fed along. 

 

So my question is. Can I get there using llGetSubString or do I need to rewrite the whole thing to use something like llList2String etc.

 

Here is a snippit

 dataserver(key qID, string data)
    {
        if (qID == gQuery)
        {
            if (data != EOF)
            {
                integer idx = llSubStringIndex(data,"/");
                if (~idx)
                {
                    Sites += [llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM)];  //Site names from NC
                    Sim += [llStringTrim(llGetSubString(data,idx+1,-1),STRING_TRIM)];  //Sim Name from NC
            //        URLs += [llStringTrim(llGetSubString(data,idx+1,-1),STRING_TRIM)];  //URLs from NC
                    gDlabels += [(string)gCount + ". " +llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM) + " \n"]; //Dialog text
                    gLstMnu += [(string)gCount]; // Button labels
                    ++gCount;
                }
                gQuery = llGetNotecardLine(gCard,++gLine);
            }
            else

The commented out //URLs is the one I need returned and havent yet got it figured out with the +1 -1 stuff.

 

Thanks if you should take this on and thanks for Rolig to have don this in the past, like so many things from years back this person has been a great help.

 

 

Link to comment
Share on other sites

That snippet could have been written with llParseString2List.  It would have worked just as well as finding the divider with llSubStringIndex does.  Because you'll have more than one element in the data string, though, you have no choice.  You have to use llParseString2List, as in

dataserver(key qID, string data)    {        if (qID == gQuery)        {            if (data != EOF)            {                list temp = llParseString2List(data,["/"],[]);                string name = llList2String(temp,0);                string Region = llList2String(temp,1);                vector Whatever = (vector)llList2String(temp,2);                gQuery = llGetNotecardLine(gCard,++gLine);            }        }    }

and so on....

  

 

  • Like 1
Link to comment
Share on other sites

Thank you Rolig, your script is really good btw. I came to the same conclusion just before checking the forum,yay, and now I know exactly how llGetSubString works and I guess more importantly how is doesn't. :)

Its been well worth the effort of being wrong so many times and learning bit by bit. I think I know enough about LSL to be just skilled enough to be bad and that is not a minor thing.  Being able to adapt other scripts I find over the course of many hours and days more usually is rewarding. 

Thanks again for your help. :)

 

Link to comment
Share on other sites

It almost works and maybe someone with a little more knowledge can help me past this last hurdle. 

First let me preface with, this is kind of long and what I have done is comment the heck out of it to try and understand for myself what is going on and where I am struggling. 

Secondly, it's worth noting that I have a working version that uses 2 variable, simName and Vector which is just a minor tweak of Roligs and Voids really great work. 

Ok so onto the issue. The parsing of the NC goes well and the Menu gets populated but it sort of stops there. I CAN by way of using llSay, my debugger of choice lol, find the CHOICE of my menu selection but nothing gets passed to the llMapDestination variables and I think its to do with some msg stuff but I'm really out of my depth at that point.  

Also, and this might just be a side effect of something I did. The menu starts to add the first line to the menu repeatedly , so you end up with a succession of the first selection in the menu. Cool things to learn about as far as I can tell.

 

Anyway , I'll post the code and there is an example NC at the bottom to play with. 

Thanks in advance, I'm actually learning. No really I am :)

 

// llMapDestination from parsed notecard// Notecard format  LocationName/SimName/<128.0,22.0,22.0>//URL Chooser -- Rolig Loon -- February 2011// Reads web site information from a notecard in the format   Site name = http://www.a_great_URL.com// and presents result in a URL prompt.// Multipage dialog function uDlgBtnLst by Void Singer ( http://community.secondlife.com/t5/LSL-Scripting-Library/Dynamic-Multi-page-Dialog-AKA-Pagination/m-...list uDlgBtnLst( integer vIntPag ){    integer vIdxBeg = 10 * (~-vIntPag);          //-- 10 * (vIntPag - 1), enclose "~-X" in parens to avoid LSL bug    integer vIdxMax = -~(~([] != gLstMnu) / 10); //-- (llGetListLength( gLstMnu ) - 1) / 10 + 1    list vLstRtn =      llListInsertList(        llList2List( gLstMnu, vIdxBeg, vIdxBeg + 9 ), //-- grab 10 dialog buttons        (list)("  <<---(" + (string)(vIntPag + (-(vIntPag > 1) | vIdxMax - vIntPag)) + ")"), //-- back button        -1 ) + //-- inserts back button at index 9, pushing the last menu item to index 10      (list)("  (" + (string)(-~((vIntPag < vIdxMax) * vIntPag)) + ")--->>"); //-- add fwd button at index 11       return //-- fix the order to L2R/T2B      llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) +      llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 );}//--                       Anti-License Text                         --//*///     Contributed Freely to the Public Domain without limitation.     //*///   2009 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*///  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*///--list gLstMnu;integer gLine;string gCard;integer gDChan;integer gDLisn;key gQuery;integer gCount;list Sites;list URLs;list Sim;list gDlabels;string simName;vector tpDest;vector lookAt = ZERO_VECTOR;default{    state_entry()    {        if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0)        {            gCard = llGetInventoryName(INVENTORY_NOTECARD,0);            gQuery =llGetNotecardLine(gCard,0);            gCount = 1;        }        else        {            llOwnerSay("No URL notecard detected.");        }    }        changed (integer change)    {        if (change & CHANGED_INVENTORY)        {            llResetScript();        }    }      /*         // Original code to use NC with http:// style urls from menu as explained above        dataserver(key qID, string data)    {        if (qID == gQuery)        {            if (data != EOF)            {                integer idx = llSubStringIndex(data,"/");                if (~idx)                {                    Sim += [llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM)];  //Site names from NC                    URLs += [llStringTrim(llGetSubString(data,idx+1,-1),STRING_TRIM)];  //URLs from NC                    gDlabels += [(string)gCount + ". " +llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM) + " \n"]; //Dialog text                    gLstMnu += [(string)gCount]; // Button labels                    ++gCount;                }                gQuery = llGetNotecardLine(gCard,++gLine);            }            else            {                llSay(0,"Initialized.");                state running;            }        }    }       */                  // Use notecard with location/SimName/<128.0,128.0,0.0> format for menu and llMapDestination Teleport       dataserver(key qID, string data)    {        if (qID == gQuery)        {            if (data != EOF)            {                {                    //Parse the NC . First read it (data) and look for ["/"] to know what the separators are.                     list temp = llParseString2List(data,["/"],[]);                    string Sites = llList2String(temp,0);  // This says that the list called "Temp" and the first data blob is 0                    string Sim = llList2String(temp,1);  // This is the same as above but now its the second bit, but we start at 0 so it's 1                    vector URLs = (vector)llList2String(temp,2); // Etc. But the URLs is a vector so you need to say so.                               gDlabels += (string)gCount + ". " + llList2String(temp,0) + " \n"; //Dialog text.Read "temp,0" to get the location name                    gLstMnu += [(string)gCount]; // Button labels. make some buttons with the information above                    ++gCount; // g for Global. Count em up.                                       // Check with llSay if that all works so far?   YES PARSING CORRECTLY          //      llSay(0, "Dest:  "+(string)Sites + "  SimName: "+ (string)Sim+" Coord: "+(string)URLs + " \n ");                       }                                 gQuery = llGetNotecardLine(gCard, ++gLine); // Gets the Notecard from inventory and I assume since gLine is an integer and there is ++ attached it incremtally counts through it.            }            else            {                llSay(0,"Initialized.");        // Once all the above is done say its "Initialized" .. thats a good thing.                 state running;  // Then we change states. Like NY to Cali or something.....not really. but sort of             }        }    }}                state running{    changed (integer change)  // Did anything change and if it did reset.     {        if (change & CHANGED_INVENTORY)        {            llResetScript();        }    }        touch_start(integer num)  // Touch the prim    {        llSetTimerEvent(100.0);  // Set a timer because ...timer        gDChan = (integer)("0xF" + llGetSubString(llDetectedKey(0),0,6)); // Not a clue. guessing it's smart person code for a Listener channel.        gDLisn = llListen(gDChan,"","",""); // Then this listens to the above thing and I suspect partly this is where it goes wrong.                               string temp = "";    // fill in the blank, which will be menu items shortly        integer i;          // no code can exist with out an i                //Display the first 10 sites for our Menu        for (i=0;i<10;++i)    // See, must have an i thing to add up things. Thats what this does.        {            temp += llList2String(gDlabels,i);  // make those menu buttons from the code up above where gDlabels lives        }        llDialog(llDetectedKey(0),"Which site do you want to visit? \n"+ temp, uDlgBtnLst(1) ,gDChan);  // Here is where I think I have a problem too with the gDChan not getting what I selected or something.    }        listen (integer channel, string name, key id, string msg)   // Ok get yer ears on.     {        llSetTimerEvent(0.0);         llListenRemove(gDLisn);          // Has the user clicked either the ">>" or "<<" button?        if (!llSubStringIndex( msg, "  " ))  //-- detects 2 (hidden) leading spaces        {            llSetTimerEvent(10.0);            gDLisn = llListen(gDChan,"","","");            string temp = "";            integer menu =  (integer)llGetSubString( msg, -~llSubStringIndex( msg, "(" ), -1 );   // Maybe this is part of the issue too             integer i;            for (i=(10*(menu-1));i<(10*menu);++i)            {                temp += llList2String(gDlabels,i);            }            llDialog( id, "Which site do you want to visit? \n"+ temp, uDlgBtnLst(menu), gDChan );   // And here is the gDChan again. ??        }        else // If user has clicked a numbered button        {            integer Choice = (integer) msg -1;                    llSay(0, (string) Choice); // Returns the # of my selection and thats all                                    simName = llList2String(Sim,Choice); // Here is my monkey work. So this works using Roligs version with Sim Name, Vector                    tpDest = llList2Vector(URLs,Choice);  // Its just defining  a pair to be plugged into the llMapDestination below                          state Tele_state;              // Change states again to finally TP                    }    }       timer()       // A timer for the Dialog Menu    {        llSetTimerEvent(0.0);        llWhisper(0,"Timeout. Please close the dialog box on your screen.");        llListenRemove(gDLisn);    }      } state Tele_state     // And now we can TP to our destination{    state_entry(){        llSetTimerEvent(20);    // Close things if you forget why you did this     }    timer(){        llSetTimerEvent(0);              llListenRemove(gDLisn);    state default;    }    touch_start(integer num_detected){                llMapDestination(simName, tpDest, lookAt);   // After all that we finally get to two variables and lookAt which is a constant more or less. And if it all works you have a cool NC reading simple to update grid wide Teleporter that is a neat basis for making it even more interesting. Like separating it out to a control and say a magic mirror with animations or whatever.        llListenRemove(gDLisn);    state default;    }} // End    //////////////////////////////NoteCard Example ////////////////////////  /* Help Island/Help Island Public/<128.0,128.0,24.0>Space Station/Raglan Galaxy/<132,157,627>Lelutka /LeLutka/<125, 98, 22>3D TREES/zen island/<216, 149, 21>   */  
Link to comment
Share on other sites

Managed to fix part of it. I need to reset things after making a selection and that stopped the menu form adding to itself.

 

So Im realy only left with why in the parsed version the selection doesnt go through and in the llGetSubString it works perfectly.

 

Every bit of script is the same with the exception of the dataserver section.

This one works with the format SimName/<0.0,0.0,0.0> in a NC

    dataserver(key qID, string data)    {        if (qID == gQuery)        {            if (data != EOF)            {                integer idx = llSubStringIndex(data,"/");                if (~idx)                {                    Sim += [llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM)];  //Site names from NC                    URLs += [llStringTrim(llGetSubString(data,idx+1,-1),STRING_TRIM)];  //URLs from NC                    gDlabels += [(string)gCount + ". " +llStringTrim(llGetSubString(data,0,idx-1),STRING_TRIM) + " \n"]; //Dialog text                    gLstMnu += [(string)gCount]; // Button labels                    ++gCount;                }                gQuery = llGetNotecardLine(gCard,++gLine);            }            else            {                llSay(0,"Initialized.");                state running;            }        }    }   

and this one populates the dialog menu but thats it with the format of the NC being  DesName/SimName/<0.0,0.0,0.0>

 dataserver(key qID, string data)    {        if (qID == gQuery)        {            if (data != EOF)            {                {                                        list temp = llParseString2List(data,["/"],[]);                    string Sites = llList2String(temp,0);                      string Sim = llList2String(temp,1);                      vector URLs = (vector)llList2String(temp,2);                               gDlabels += (string)gCount + ". " + llList2String(temp,0) + " \n";                     gLstMnu += [(string)gCount];                     ++gCount;                                             }

 

Link to comment
Share on other sites

If nothing else, I suggest that you continue to lop off any leading and training blank spaces with llStringTrim.  Of course, if you suspect that's where your problem lies, the very first thing to do is to insert llOwnerSay diagnostic messages in the notecard reader to show you exactly what those input variables look like, as opposed to what you think they look like.

Link to comment
Share on other sites

Yes yes 1000 times yes, that is it . Totally works. 

 

ty ty ty ty ty a millions times.

 

Now I can carefully read and learn what you did. Thank you so much for sharing. This is really s ohelpful to now have it working and compare and learn. SL rocks when we share like this.

Thank you ...super hugs.

 

Link to comment
Share on other sites

i dunno if i accidentally deleted my post?

anyways, here it is again ...

string NC;key kQuery;integer iLine;integer len;list gLstMnu;string txt;key id;integer chan ;integer handle;integer idx;list uDlgBtnLst( integer vIdxPag ){    list vLstRtn;    if ((gLstMnu != []) > 9)    {   integer vIntTtl = -~((~([] != gLstMnu)) / 9);                                 //-- Total possible pages        integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 9;              //-- first menu index        string  vStrPag = llGetSubString( "                     ", 21 - vIdxPag, 21 ); //-- encode page number as spaces            vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 8 ),         (list)(" «" + vStrPag), vIdxBgn + 9 ) + "CLOSE" + (list)(" »" + vStrPag);    }    else    {  vLstRtn = gLstMnu + [" ", "CLOSE"," "]  ;    }    return //-- fix the order for [L2R,T2B] and send it out      llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) +      llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 );}    init(){       SiteNames = [];        SimNames = [];        SimCoords = [];         chan = 0x80000000 | (integer)("0x"+(string)llGetOwner()); // channel based on owners key                  if (llGetInventoryNumber(INVENTORY_NOTECARD) )          { NC = llGetInventoryName(INVENTORY_NOTECARD,0);            //  llSay(0,"Loading.....");            kQuery = llGetNotecardLine(NC, iLine);              txt = "\n \nMain Menu\n"  ;                     }          else          { llOwnerSay("No URL notecard detected.");          }                   llSetText("click to choose Destination ", <1.0, 1.0, 1.0>, (float)TRUE);            } list SiteNames;list SimNames;list SimCoords;string simName ;vector tpDest;vector lookAt = ZERO_VECTOR;default{    state_entry()    {   init();    }    on_rez(integer param)    { init();    }    touch_start(integer total_number)    {   id = llDetectedKey(0);        llDialog( id, txt, uDlgBtnLst( 0 ), chan );        handle = llListen(chan,"","","");        llListenControl(handle, TRUE);         llSetTimerEvent(20);    }     dataserver(key query_id, string data)     {        if (query_id == kQuery)        {                          if (data == EOF)             {                     iLine = 0;                 //  llSay(0,"Destinations Loaded");                gLstMnu = SiteNames;                        }            else             {   if(data != "")                {                          list temp = llParseString2List(data,["/"],[]);                    string Site = llList2String(temp,0);  // This says that the list called "Temp" and the first data blob is 0                    Site = llGetSubString(Site, 0, 23) ;                    string Sim = llList2String(temp,1);  // This is the same as above but now its the second bit, but we start at 0 so it's 1                    vector URL = (vector)llList2String(temp,2); // Etc. But the URLs is a vector so you need to say so.                                         // add to each list so the indexes will match                    SiteNames += Site;                    SimNames += Sim;                    SimCoords += URL;                               }             ++iLine;             kQuery = llGetNotecardLine(NC, iLine);             }        }    }     listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg )    {        if (!llSubStringIndex( vStrMsg, " " ))        {  llDialog( vKeySpk, txt,                      uDlgBtnLst( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ),                      vIntChn );           llSetTimerEvent(20);                   }                 else if (vStrMsg == "CLOSE")        {   llSetTimerEvent(0.5);             llSay(0,"Turning  off... " );        }               else        {              integer index = llListFindList(SiteNames, [vStrMsg]);             simName = llList2String(SimNames,index);            tpDest = llList2Vector(SimCoords,index);            llSetText("click to teleport to\n '" +  vStrMsg + " : " + simName + "'", <1.0, 1.0, 1.0>, (float)TRUE);                           state Tele_state;            }    }    timer()    {   llListenControl(handle, FALSE);               llSetTimerEvent(0);          }    changed(integer change)    {        if (change & (CHANGED_REGION_START | CHANGED_OWNER | CHANGED_INVENTORY) )        {   llOwnerSay("Resetting...");            llResetScript();        }    }    } state Tele_state     // And now we can TP to our destination{    state_entry(){        llSetTimerEvent(20);    // Close things if you forget why you did this     }    timer(){        llSetTimerEvent(0);              llOwnerSay("Timed Out");        state default;    }    touch_start(integer num_detected){                llMapDestination(simName, tpDest, lookAt);               llSetText("click to choose Destination ", <1.0, 1.0, 1.0>, (float)TRUE);            state default;    }}
Link to comment
Share on other sites

lol, well I don't know what happened there but thanks again.

Thanks to you I was able to extend this to FINALLY finish this more RP based llMapDestination gateway project.

It seems fairly easy to use now for someone else, just add the destinations you like and drop it in. The rest just happens.

I've managed to break it out into three compontents now as well. So it is very RP based.

You can imagine a person with a set of contorls in a room (Menu), they walk to a lever and pull it(Sets and sends to the gateway) and before them a magical gateway appears that is persistant, allowing them and their freinds to follow. 

Its very cool. Well I think so lol.

 

I wouldn't have been able to figure out how to do that however if it were not for your generous work. It was a months worth of education for me. Thank you so much. 

 

 

 

 

 

 

Link to comment
Share on other sites

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

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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...