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:
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)
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.