Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

What's wrong with this?

Dire Graves
Registered User
Join date: 3 Sep 2007
Posts: 51
09-14-2007 19:09
I made a script that will take the names of the 16 prims which makeup a link set, loop thru them to figure out the link numbers. The script is used for changing the colors of the faces of each prim. Right now the prims are changing the wrong colors and I cant figure out why. I'm pretty sure the problem is in one of these 2 functions....any ideas?

The names of the prims are just a number 1 to 16

list PrimLinkNums;

GetLinkNumbers() {
integer i = 1;
PrimLinkNums = [];
for(; i < 16; ++i) {
PrimLinkNums += [(integer)llGetLinkName(i)]; // Prim Name
PrimLinkNums += ; // Link Num
}
//Sort list by Link name
PrimLinkNums = llListSort(PrimLinkNums, 2, TRUE);
}

//Convert Link Name to Link Number
integer N2L(integer LinkName) {
return llList2Integer(PrimLinkNums, LinkName * 2);
}
Day Oh
Registered User
Join date: 3 Feb 2007
Posts: 1,257
09-14-2007 19:26
Greetings Dire Graves... first,

From: someone
for(; i < 16; ++i) {


If you have 16 prims, you probably want to go from 1 to 16, so would want to change the comparison to i < 17

Second,

From: someone
return llList2Integer(PrimLinkNums, LinkName * 2);


The list elements are referenced beginning with 0, so you may want to try (LinkName - 1) * 2

And good luck (:
_____________________
Dire Graves
Registered User
Join date: 3 Sep 2007
Posts: 51
09-14-2007 20:11
Thanks... I'll try that. :-)
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
09-15-2007 01:02
I have two versions for you, depending on your needs,

I agree that the for loop needs to start from 1, and go while i <= 16, as 1 is the lowest link number in a linked set (only unlinked prims are link 0). Question though, is the root prim one of the numbered prims in the set, or are there actually 17 prims? Your script could be more generalized and robust if it used the function llGetNumberOfPrims() to check ALL the prims in the link set for a nonzero nuimber, instead of coding for just 16.

I believe your main problem with wild behavior is the second function, in how it addresses the strided list. To address the second element of a stride (in your case the actual link number stored AFTER each prim name), you need to add 1 to (index * 2) to actually get the link number which you stored. Your function was returning the Prim Name number. Since it's 1-based, this means your access has to subtract 1 from the prim name (for 1-based numbering), multiply by 2 for the stride, then add 1 more to reach the second element in the stride:

return llList2Integer(PrimLinkNums, ((LinkName - 1) * STRIDE) + 1);


Here's a bit of a rewrite to demonstrate the above suggestions:

CODE


integer STRIDE = 2;
list PrimLinkNums;

GetLinkNumbers() {

integer i = 1;
integer total = llGetNumberOfPrims();

PrimLinkNums = [];
for(; i <= total; ++i) {
integer primnum = (integer)llGetLinkName(i);
if(primnum > 0) { // non-zero number found for name
PrimLinkNums += [primnum]; // Prim Name
PrimLinkNums += ; // Link Num
}
}
//Sort list by Link name
PrimLinkNums = llListSort(PrimLinkNums, STRIDE, TRUE);
}

// Convert Link Name to Link Number
// assumes that LinkName is 1-based
// assumes that LinkName < (llGetListLength(PrimLinkNums) / 2);
integer N2L(integer LinkName) {
return llList2Integer(PrimLinkNums, ((LinkName - 1) * STRIDE) + 1);
}



Now I can see some assumptions which can cause the code to fail if any of the prims do NOT have a nonzero number in them, and will also fail if any two prims have the same number. You don't really need a strided list to handle this if you make an empty list of 16 zeros and plug in the link numbers where you find them. If you wish to check for duplicate prim names, you can simply test the slot for a non-zero number which was previously filled in. Here's a rewrite using a non-strided list:

I convert the prim name to a zero-based number to simplify access to the link number list. Having the prim name strings be 1-based is good, this helps you to detect if a number was actually found in the cast to integer, (a name which is just Object or any other non-numeric string will cast to 0)

CODE

list PrimLinkNums;

GetLinkNumbers() {

integer i = 1;
integer total = llGetNumberOfPrims();

// create empty list
for(i = 1; i <= total; ++i) {
PrimLinkNums += 0;
}

// this will ONLY store the link numbers for prims named with a number
for(i = 1; i <= total; ++i) {
integer primnum = (integer)llGetLinkName(i);
if(primnum > 0) { // non-zero number found for name
--primnum; // convert to zero-based
// test to double-check we dont have a duplicate prim name
if(llList2Integer(PrimLinkNums, i) == 0) {
PrimLinkNums = llListReplaceList(PrimLinkNums, , primnum, primnum);
}
// error complaint for debug purposes
else {
llOwnerSay("Error, prim name " + llGetLinkName(i) +
" found in prim #" + llList2String(PrimLinkNums, i) +
" as well as prim #" + (string)i);
}
}
}
}

// Convert Link Name to Link Number
// assumes that LinkName is 1-based
// assumes that LinkName < llGetListLength(PrimLinkNums);
// returns 0 on failure
integer N2L(integer LinkName) {
return llList2Integer(PrimLinkNums, LinkName - 1);
}



Remember, while bbcode is disabled on this board, you can still copy the text with formatting by hitting the Quote button to see the original posts's formatting, and copy that out with the spacing intact. Then just hit your browser's back button without posting to return to the thread.
Dire Graves
Registered User
Join date: 3 Sep 2007
Posts: 51
09-15-2007 02:30
Thanks for your reply!

I liked your idea of not using a strided list so I gave it a try. It definitely looks a lot closer to being correct then what i had before although for some reason i get...

[2:21] 7: Error, prim name 14 found in prim #3 as well as prim #5
[2:21] 7: Error, prim name 16 found in prim #1 as well as prim #6
[2:21] 7: Error, prim name 15 found in prim #2 as well as prim #7
[2:21] 7: Error, prim name 11 found in prim #4 as well as prim #12

This doesn't make any sense to me. I checked all the prim names and there are no duplicates (just 1 to 16). I'm going to keep playing around with it, just thought you might see something I don't. Thanks again for your help. I think I'm definitely on the right track now.

I added llOwnerSay(llGetLinkName(i)) to where it created the list of 16 zeros and got..

[2:33] 7: 7
[2:33] 7: 8
[2:33] 7: 6
[2:33] 7: 13
[2:33] 7: 14
[2:33] 7: 16
[2:33] 7: 15
[2:33] 7: 5
[2:33] 7: 4
[2:33] 7: 3
[2:33] 7: 10
[2:33] 7: 11
[2:33] 7: 12
[2:33] 7: 9
[2:33] 7: 1
[2:33] 7: 2

Just so you don't think I'm crazy..lol
Dire Graves
Registered User
Join date: 3 Sep 2007
Posts: 51
09-15-2007 18:46
ok... found the problem...

The part where it says if(llList2Integer(PrimLinkNums, i) == 0) { should be if(llList2Integer(PrimLinkNums, primnum) == 0) {

I still have a couple of faces that are wrong but I think that is just my fault from when I was writing down the colors for each face. Thanks again for your help...both of you :-)
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
09-16-2007 01:04
Quite right, my bad, sorry about that. I'm glad you got back on track now.