Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llDialog and scripts in prim inventory... help

Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-22-2007 13:26
Hello,

I am fairly new to scripting and I am grasping the concepts of it all thanks to a massive jump start From Newgate Ludd.

I have a question. I wanted to use a script that would open a menu using llDialog display options that the user can select and the script will in turn remember that script and execute it.

So for example I want the object attached to me to say different things when I teleport (Depending on what I choose from the menu). So in a seperate script I would put something like:

scriptyay
CODE

changed(integer change) // something changed
{
if (change & CHANGED_TELEPORT) // and it was a Teleport change
{
llSleep(0.5);
llOwnerSay("I Teleported YAY!!");
}
}


In the primary script I would put the llDialog piece that I could select on touch from a menu the scriptyay script.

The primary script would generate a list of scripts in the prims inventory and put them in my menu to select when i click the prim.

So in the prims inventory:
scriptyay
scriptboo
scriptharahh

How and what would I need to script the main script to search its inventory upon click and give me a list of options depending on the scripts in it and store it so that whenever I teleport it allways uses the Script I chose in the options menu?

If you need me to explain it better let me know.

Thank you for your time
-Lady Cherry
Hg Beeks
llGetElement(80);
Join date: 13 Apr 2006
Posts: 134
05-22-2007 17:14
To get the list of scripts in the prim:
CODE

int count = llGetInventoryNumber(INVENTORY_SCRIPT) //Gets the number of scripts in the file.
list names;
integer i;
for (i = 0; i =< count; i++)
{
if (llGetInventoryName(INVENTORY_SCRIPT, i) != llGetScriptName()) //Makes sure it's not the script it's in that's being called.
{
names += llGetInventoryName(INVENTORY_SCRIPT, i); //if not, adds the script name to the list.
}
}

The dialog could use the list created, and save the returned value as a string. However, there's no way to activate or find out what the activation in a script is via another script, so unless you program in the activation mechanism for each script, there's no way to call the specific scripts.
Kode Forager
llDie();
Join date: 23 Nov 2006
Posts: 2
llDialog
05-23-2007 08:01
Not sure if using different script will work in this situation. What would happen is 3 (or however many script you had in the object) CHANGE events would fire each time you teleported. You could probably do it with different states, but i don't think that is really necessary.

Here is something that may work for you, unless I'm completely missing your question.
Basically, it uses 2 lists to store your "sayings" in. One is for the llDialog menu - so the options don't get truncated. The other list is the actual sayings.

Owner touches, is presented with dialog to choose which saying to use when teleporting - and the variable 'selected' is set by the index of the selected menu option.

Adding new saying is as simple as adding the menu display to the 'menu' list, and the appropriate saying in the 'sayings' list, making sure thier placement in the list are the same.

Haven't tested the code, but it might give you an idea.

CODE

//********************************************************************
list menu = ["Yaay", "Boo", "Harahh"];
list sayings = ["I Teleported YAY!!", "Oh Booo!", "Harahh! I TP'd"];
integer selected = 0;

integer listen_handle;
integer listen_channel = -5443;
integer timeout = 30;

default
{
touch_start(integer total_number)
{
integer i;
for (i=0; i < total_number; i++)
{
if (llDetectedKey(i) == llGetOwner())
{
llDialog(llDetectedKey(i),"Select Teleport Message",menu,listen_channel);
listen_channel = llListen(listen_channel, "", llDetectedKey(i), "");
llSetTimerEvent(timeout);
}
}
}

listen(integer channel, string name, key id, string message)
{
selected = llListFindList(menu, [message]);
llListenRemove(listen_handle);
llSetTimerEvent(0);
}

changed(integer change)
{
if (change & CHANGED_TELEPORT)
{
llSleep(0.5);
llOwnerSay(llList2String(sayings,selected);
}
}


timer()
{
llListenRemove(listen_handle);
llSetTimerEvent(0);
}
}
//*******************************************************
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-23-2007 13:15
Ok I have a little bit of a handle on things now.

The way I wanted to go about it was have a main menu.

On the main menu you have two choices TP or VN

after you select one of those choices like TP It will load the prims inventory of all the scripts that start with the word tp- and display them as choices (Like: tp-sample1 tp-sample2)

Also same would be true if you chose VN in stead (vn-sample1 vn-sample2)

Then lets say you choose one of the tp-sample1 one from the menu. The script would then deactivate all the other scripts that start with tp- and only activate the one you chose.

Same would be true for what you chose in VN.

I have two things the menu system and a partial script put together and I have 2 issues.

one when I select TP from the menu it shows all scripts including the VN ones.

How would I go about merging them with my dialog script also?

Thank you for your time.

Basic Dialog script
CODE

integer channel = 159;

list summon;

list mainmenu =
[ "Sum. Effects",
"Van. Effects"
];

string maintext =
"
This is the Main Menu\n
Hey there This is wonderful!
";


default
{
state_entry()
{

}

touch_start(integer total_number)
{
key id = llDetectedKey(0);


llDialog(id, maintext, mainmenu, channel);
llListen(channel,"",id,"");
}

listen(integer channel, string name, key id, string message)
{
if (message == "Sum. Effects")
{


llSay(0,"You selected " + message);
llSetScriptState(message, TRUE);
}

}
}






Main Script:

CODE


list scripts;

default
{
state_entry()
{
llSay(0, "Hello, Avatar!");
}

touch_start(integer total_number)
{
key id = llDetectedKey(0);
integer count = llGetInventoryNumber(INVENTORY_SCRIPT);
scripts = [];
while(--count >= 0)
{
string name = llGetInventoryName(INVENTORY_SCRIPT, count);
// if(name != "")
if (name != llGetScriptName())
{
if (llSubStringIndex(name, "tp-") == 0)
{
llSetScriptState(name, FALSE);
}
if (llSubStringIndex(name, "vn-") == 0)
{
llSetScriptState(name, FALSE);
}
scripts = (scripts = []) + scripts + [ name ];
}
}
llDialog(id,"Which Script?",scripts, 43);
llListen(43,"",id,"");
}

listen(integer channel, string name, key id, string message)
{
// llSay(0,"You selected " + message);
llSetScriptState(message, TRUE);

}

}

Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-24-2007 01:08
From: Cherry Hotaling
Ok I have a little bit of a handle on things now.

The way I wanted to go about it was have a main menu.

On the main menu you have two choices TP or VN

after you select one of those choices like TP It will load the prims inventory of all the scripts that start with the word tp- and display them as choices (Like: tp-sample1 tp-sample2)

Also same would be true if you chose VN in stead (vn-sample1 vn-sample2)

Then lets say you choose one of the tp-sample1 one from the menu. The script would then deactivate all the other scripts that start with tp- and only activate the one you chose.

Same would be true for what you chose in VN.

I have two things the menu system and a partial script put together and I have 2 issues.

one when I select TP from the menu it shows all scripts including the VN ones.

How would I go about merging them with my dialog script also?

Thank you for your time.

build your lists on rez (or inventory change), filtering by name and discard any that dont match the required criteria.
On first rez Turn them all off and then clear the current item name.
When a new one is chosen turn off the old one before turning on the new one and remember its name.

Also remember to turn off your listens.
_____________________
I'm back......
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-24-2007 06:36
SO the example above would be a problem because its constantly searching the prims inventory?

How would you write it for an on rez event that will seperate the 2 types in a list?

Also by listens you mean the listens in the main script? Would it be required to remove the listens due to lagg?

Thanks
-Lady Cherry
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-24-2007 08:13
From: Cherry Hotaling
SO the example above would be a problem because its constantly searching the prims inventory?

How would you write it for an on rez event that will seperate the 2 types in a list?

Also by listens you mean the listens in the main script? Would it be required to remove the listens due to lagg?

Thanks
-Lady Cherry


You should always remove listens that you no longer need. Each time you call llListen a new listen is added and will start adding to lag. Also when it gets to 64 it will give a script error. By removing them when you no longer need them you are being more efficient.

The system isnt a problem for constantly searching, it bypasses the need for having an on changed event, but it is inefficient. If the contents hasnt changed why keep rereading it?

Code Fragment
CODE

list tpscripts;
list vnscripts;
integer maxtpscripts;
integer maxvnscripts;
string currenttpscript;
string currentvnscript;

ReadScripts()
{
// Empty the lists
tpscripts = vnscripts = [];
// get the number of scripts to check
integer count = llGetInventoryNumber(INVENTORY_SCRIPT);
// Iterate the list of scripts
while(--count >= 0)
{
string name = llGetInventoryName(INVENTORY_SCRIPT, count);
// Check its not us
if (name != llGetScriptName())
{
if (llSubStringIndex(name, "tp-") == 0)
{
// Add to list of tp scripts
tpscripts = (tpscripts = []) + tpscripts + [ name ];
// Dont disable it if its currently selected
if(name != currenttpscript)llSetScriptState(name, FALSE);
}
else if (llSubStringIndex(name, "vn-") == 0)
{
// Add to list of vn scripts
vnscripts = (vnscripts = []) + vnscripts + [ name ];
// Dont disable it if its currently selected
if(name != currentvnscript)llSetScriptState(name, FALSE);
}
}
}
maxtpscripts = llGetListLength(tpscripts);
maxvnscripts = llGetListLength(vnscripts);
}
_____________________
I'm back......
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-24-2007 11:03
So the

ReadScripts section should go under an on rez event so that it loads its inventory upon rez or should I create an if statement upon inventory change?

-Lady Cherry
Milambus Oh
Registered User
Join date: 6 Apr 2007
Posts: 224
05-24-2007 11:20
From: Cherry Hotaling
So the

ReadScripts section should go under an on rez event so that it loads its inventory upon rez or should I create an if statement upon inventory change?

-Lady Cherry


You want to call it from both places... when it originally loads, then any time the inventory is changed. Thats why he gave you a function which can be called from both events.
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-24-2007 12:04
I understand that now. Putting it on_rez and changed_inventory.

Im getting an error at the moment.

If I put the ReadScripts under an on_rez event I get a syntax error.

Is there something the ReadScripts required before this?

Thanks

-Lady Cherry
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-24-2007 12:39
Ack Never mind the ReadScripts() function needs to go before the default state.
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-24-2007 12:58
I have a question on how a line reads.

What does this line actually say in lamen terms?:

tpscripts = (tpscripts = []) + tpscripts + [ name ];

Also how does the script know what the currenttpscript or currentvnscript string is. Or is that part not listed in the script above that newgate has posted?

How would I tie that to a llDialog Function?

Thanks you as im new to this trying to get an understanding of it all and appreciate your patience with me!

-Lady Cherry
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-25-2007 00:17
From: Cherry Hotaling
I have a question on how a line reads.

What does this line actually say in lamen terms?:

tpscripts = (tpscripts = []) + tpscripts + [ name ];

Also how does the script know what the currenttpscript or currentvnscript string is. Or is that part not listed in the script above that newgate has posted?

How would I tie that to a llDialog Function?

Thanks you as im new to this trying to get an understanding of it all and appreciate your patience with me!

-Lady Cherry


Cherry,

The tpscripts line is a memory reclaim hack. It basically just adds name to the list.

As I said the code I posted was a fragment, i.e. incomplete so you could add it to your own script.

If you want a full script here it is:

CODE

list MainMenu = ["TP Script", "VN Script" ];
string MainTitle = "Please Select an Option.";
string TpTitle = "Please Select a TP Option.";
string VnTitle = "Please Select a VN Option.";

list tpscripts;
list vnscripts;
integer maxtpscripts;
integer maxvnscripts;
string None = "None";
string currenttpscript;
string currentvnscript;

string BACK = "BACK";
integer CHANNEL; // Channel on which Dialog listens
integer Listening = 0; // Active Listen Handle
integer first; // First entry to be displayed on Dialog
integer pagesize = 9; // Number of Items per Dialog
list Choices; // Current Dialog Choices
// --------------------------
CancelListen()
{
if(Listening > 0) llListenRemove(Listening);
Listening = 0;
llSetTimerEvent(0);
}
// --------------------------
UpdateListen(key id)
{
CancelListen();
CHANNEL = 0 - (integer)llFrand(2147483647);
Listening = llListen(CHANNEL,"",id,"");
llSetTimerEvent(20);
}
// --------------------------
ShowMainMenu(key id)
{
UpdateListen(id);
llDialog(id, MainTitle, MainMenu, CHANNEL);
}
// --------------------------
ShowTPMenu(key id)
{
Choices = [ "<<" , BACK , ">>" ];
// Now add the items
//len = llGetListLength( tpscripts );

integer i;
for(i = 0;i < pagesize;i++)
{
integer j = (i + first);
string strname = llList2String(tpscripts,j);
if( llStringLength(strname) > 0)
{
Choices += [ strname ];
}
}
// finally show the dialog
UpdateListen(id);
llDialog(id, TpTitle + "\nCurrent Item is " + currenttpscript , Choices, CHANNEL);
}
// --------------------------
ShowVNMenu(key id)
{
Choices = [ "<<<" , BACK , ">>>" ];
// Now add the items
//len = llGetListLength( vnscripts );

integer i;
for(i = 0;i < pagesize;i++)
{
integer j = (i + first);
string strname = llList2String(vnscripts,j);
if( llStringLength(strname) > 0)
{
Choices += [ strname ];
}
}
// finally show the dialog
UpdateListen(id);
llDialog(id, VnTitle + "\nCurrent Item is " + currentvnscript , Choices, CHANNEL);
}
// --------------------------
ReadScripts()
{
// Empty the lists
tpscripts = vnscripts = [];
// get the number of scripts to check
integer count = llGetInventoryNumber(INVENTORY_SCRIPT);
// Iterate the list of scripts
while(--count >= 0)
{
string name = llGetInventoryName(INVENTORY_SCRIPT, count);
// Check its not us
if (name != llGetScriptName())
{
if (llSubStringIndex(name, "tp-") == 0)
{
// Add to list of tp scripts
tpscripts = (tpscripts = []) + tpscripts + [ name ];
// Dont disable it if its currently selected
if(name != currenttpscript)llSetScriptState(name, FALSE);
}
else if (llSubStringIndex(name, "vn-") == 0)
{
// Add to list of vn scripts
vnscripts = (vnscripts = []) + vnscripts + [ name ];
// Dont disable it if its currently selected
if(name != currentvnscript)llSetScriptState(name, FALSE);
}
}
}
maxtpscripts = llGetListLength(tpscripts);
maxvnscripts = llGetListLength(vnscripts);
}
// --------------------------
default
{
state_entry()
{
currenttpscript = None;
currentvnscript = None;
ReadScripts();
}

touch_start(integer total_number)
{
// Show the MainMenu
key id = llDetectedKey(0);
ShowMainMenu(id);
}

listen(integer channel, string name, key id, string message)
{
// Cancel the existing Listen as its no longer needed
CancelListen();
// verify dialog choice
integer index = llListFindList( MainMenu, [ message ] );
if(0 == index)ShowTPMenu(id);
else if(1 == index)ShowVNMenu(id);
else if("BACK" == message)ShowMainMenu(id);
else if("<<" == message)
{
first -= pagesize;
if(first < 0)first = 0;
ShowTPMenu(id);
}
else if(">>" == message)
{
first += pagesize;
if(first >= maxtpscripts)first = maxtpscripts - pagesize;
ShowTPMenu(id);
}
else if("<<<" == message)
{
first -= pagesize;
if(first < 0)first = 0;
ShowVNMenu(id);
}
else if(">>>" == message)
{
first += pagesize;
if(first >= maxvnscripts)first = maxvnscripts - pagesize;
ShowVNMenu(id);
}
else
{
// Check for a tp script name
index = llListFindList( tpscripts, [ message ] );
if(index >= 0)
{
if(message != currenttpscript)
{
if(None != currenttpscript)llSetScriptState(currenttpscript, FALSE);
currenttpscript = message;
llSetScriptState(currenttpscript, TRUE);
}
}
else
{
// Check for a vn script
index = llListFindList( vnscripts, [ message ] );
if(index >= 0)
{
if(message != currentvnscript)
{
if(None != currentvnscript)llSetScriptState(currentvnscript, FALSE);
currentvnscript = message;
llSetScriptState(currentvnscript, TRUE);
}
}
}
}
}

timer()
{
// Cancel the Listen if the timer expires
CancelListen();
}

changed(integer change)
{
// Change in Inventory so check if any scripts have been added or deleted
if(change & CHANGED_INVENTORY) ReadScripts();
}
}


The above doesn't check the string lengths being added to the dialog.
_____________________
I'm back......
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-25-2007 05:58
Incredible Newgate!

I was actually going to ask about pagination and how that might be done.

This simply amazes me. I have alot to learn still it seems.

I have two questions. When you say "The above doesn't check the string lengths being added to the dialog."
YOu mean the script doesn't check for the length of the name of the script?

Also what listener event would I put in the main script to do this:
A linked message from another prim on channel 23(Just an example channel) says "alloff" Which will turn all tp- and vn- scripts except for the main script to non running?

Thanks again newgie, again thanks for being patient with me showing, doing, and explaining things.

-Lady Cherry
Milambus Oh
Registered User
Join date: 6 Apr 2007
Posts: 224
05-25-2007 06:20
http://lslwiki.net/lslwiki/wakka.php?wakka=llDialog

I believe he is referring to these bits:
"# Entries in buttons cannot be longer than 24 characters. Attempting to pass llDialog a list with entries longer than 24 characters will result in the object saying the message "llDialog:Button Labels can not have more than 24 characters.", and then fail to show the dialog box.
# While actual button width is fixed (three buttons to a line), the amount of text that will fit on a button is limited and varies with character width. ("O" is wider than "i", for example.) If the button label is too long to be viewed, it will be cut off and "..." will be appended. However, the chat output will still contain the full string."
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-25-2007 09:15
From: Cherry Hotaling
Incredible Newgate!

I was actually going to ask about pagination and how that might be done.

This simply amazes me. I have alot to learn still it seems.

I have two questions. When you say "The above doesn't check the string lengths being added to the dialog."
YOu mean the script doesn't check for the length of the name of the script?

Also what listener event would I put in the main script to do this:
A linked message from another prim on channel 23(Just an example channel) says "alloff" Which will turn all tp- and vn- scripts except for the main script to non running?

Thanks again newgie, again thanks for being patient with me showing, doing, and explaining things.

-Lady Cherry


Milambus has already answered your first question so i will skip over that one.
|As for your second (more like 200th to me! :) ) you wouldnt use a listen, rather a link_message handler instead.
_____________________
I'm back......
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-25-2007 16:36
So how would that code look like?

*Knows she has to ask you before you show her*

Thanks in advance!
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-26-2007 03:55
From: Cherry Hotaling
So how would that code look like?

*Knows she has to ask you before you show her*

Thanks in advance!

For someone who purports to want to learn for herself you do like being spoon fed.
You should really should try reading the wikki !!!!

At its simplest something like this would do :
CODE

link_message(integer sender_num, integer num, string str, key id)
{
if(ALL_OFF == num)
{
currenttpscript = None;
currentvnscript = None;
ReadScripts();
}
}
/php]

Personally I'd look at factoring out common code into a function.
_____________________
I'm back......
Cherry Hotaling
Registered User
Join date: 25 Feb 2007
Posts: 86
05-27-2007 07:34
And that would go into the main script or each individual script?

Thanks

-Lady Cherry
Newgate Ludd
Out of Chesse Error
Join date: 8 Apr 2005
Posts: 2,103
05-28-2007 03:00
From: Cherry Hotaling
And that would go into the main script or each individual script?

Thanks

-Lady Cherry


Just the main one.
_____________________
I'm back......