Jump to content

Wandering Soulstar

Resident
  • Posts

    421
  • Joined

  • Last visited

Posts posted by Wandering Soulstar

  1. 1 hour ago, Wulfie Reanimator said:

    The reset is there only because the value returned by llGetOwner won't change when the owner changes, unless the script is reset. 

    To be clear, when ever you call llGetOwner() it will return the current owner of the object where the script resides, you do not need to reset your script. If you have the Owner Id stored in a variable, listens set to the owner, etc., you will need to reset these on ownership change (detected in the change event). In the above script I do not see any reason why the script needs to be reset on ownership change.

    I do see how this confusion can arise from the initial parts of the Wiki, as the wording is a bit ambiguous. Buit if you go the last example in the Notes, you'll see that the problem is not with the funtion llGetOwner, rather elsewhere.

    • Like 1
  2. @Sunbleached .. it is quite clear that you do not know how to code, and are simply searching for someone to modify this script for you. IF you knew anything about coding, you would either not be asking these questions, or at least after @Rolig Loon gave you such kind instructions in the other thread (where you double posted the question) you would be able to do this. Like I said above . this Forum is not a Free Script Modification/Customisation/Creation source.

    • Like 1
  3. Hi All,

    Had a snippet of code that was driving me mad .. got it fixed but I do not understand what was going on ... here is what I had (redacted for clarity)

    integer num = 8;
    integer found = FALSE;
    while (num -= 2 >= 0 && !found)
    {
    	//do something to check found
    }

    What was hapening was that with the code was running through the loop SEVEN times, as opposed to the four that I would expect, going from 7 to 1.

    I got it to work by enclosing the 'num -= 2' in parenthesis. FIne, undertand about forcing the calculation prior to the conditional check or whatever ... what I do not get though is the behaviour seen without the parenthesis. Why would it do a -1 of num?

  4. Hi Millie .. sounds interesting .. but also sounds like it needs an off-world system for storing the information, do you have something for that (i.e. off-world server) or expect that to come with the design ... also you mention a couple of other systems that you have running that would need to interface .. are these open to you so that the scripter would have access to the APIs?

     

  5. ha ha ha .... actually @Wulfie Reanimator 's suggestion gave me the answer .. using the Build>Script>Set Scripts to Running option .. it at least gives me the name of the object that the script is in .. and if that is something I recognise I can get to the object .. otherwise it's just the remove option

    2 minutes ago, Wulfie Reanimator said:

    A pretty complex and overkill method is possible. You'd have to insert a script into every link so that each of them can check if there is another script in there, and report back to you in chat.

    ha ha .. by doing that I'm going to each link anywayby hand .. so can dlete the offending scripts while I'm there

    In this case deleting them all was the best optin as I only needed  one script in the root prim

    Thansk both of you for the prompt response!

  6. Hi all .. is there anyway (other than checking the prim) to identify prims that have scripts in them? I have a linked piece, with 183 parts.. and somewhere in there is a script that is no copy .. which is making it difficult to package the house for sale 🙂

  7. 6 hours ago, ItHadToComeToThis said:

    That would be so useful if you use the same custom function in multiple scripts

    Come pretty close with the Firefox Preprocessor ... have you looked into that? Since I discovered it has changed my life 😉

     

    • Thanks 1
  8. Hi All,

    Have a question that I cannot get in-world to check for sometime, and was hoping someone knew the answer to ... or could test 😄

    When we turn any prim in a linkset to Phantom .. the whole linkset goes Phantom. Reading the definition of PRIM_PHYSICS_SHAPE_TYPE - PRIM_PHYS_SHAPE_NONE it seems that with this we can get around that limitation ... i.e. have a particular prim in a linkset go 'phantom' without affecting the rest ... just wondering if that is true as it would simplify some code I'm on at the moment.

  9. @TalistoriaThe reason that the items were returned when you deeded the 1024 was because the other (4096) parcel still belonged to you, whilst the1024 parcel belonged to the group. Therefore the Li count from the 1024 was no longer available to the 4096 ... li count is only shared in-sim between parcels of the same owner. So suddenly the 4096 only had available it's Li count. You won't have a problem deeding the 4096 from that perspective.

    The only thing I'm not certain on is in regards to auto-return ... I have never deeded land after putting things down on it, so not certain if the items taht are rezzed will automatically get set to the group ... or what .. that needs someone with a more varied experience to me to chime in.

  10. @Richardc1980 You have got the wrong forum. This forum is for posting/sharing completed scripts. The other scripting forum is for questions around scripting ... to find a particular script that someone has created for sale or a scripter to create it .. try the Wanted or InWorld Employment forums

    • Like 2
  11. @animats Thanks for the feedback .. I'll tackle your points one by one:

    Quote

    Shouldn't the timer event reset the timer to the time to the next event on the timer queue? It looks like queuing a big delay followed by a small delay will not work right.

    Not quite sure what you mean. The idea is that it should always be setting as the time the next shortest one in the queue. This is so that the timer event fires (as close as possible) when it should based on when the user interacted. What I mean by this is: User A gets a dialog (30 second timer), then 10 seconds later user B does a touch on a door and holds (0.75 sec timer). User B's timer should fire, then the remaining time on User A's timer is set (30 - 10 - 7.5) .. does that make sense?

    Quote

    llGetTime() returns a 32-bit float, with a 24-bit mantissa and an 8-bit exponent. It will take a while, but after 195 days, the resolution of the time will only be 1 second. After about a year, 2 seconds. Two years, 4 seconds. Two years downstream, your users will be puzzled at the ways this breaks. If you use llGetTime(), you have to use llResetTime() once in a while. Maybe clear the queue and timer each time the sim restarts. I've had something that needed 20ms time resolution break that way. For 20ms, four days is enough to cause trouble

    I had read about this .. but did not think it would really matter, and do not understand how this affects things .. the queue is going to be clear 95% of the time . and most cases may only have one current item in it, which will clear when done. Understand that  for a more generic version this might be needed .. but in the end nothing is in the queue for more than 30 secs .. and all the time comparisons are off llGetTime(). Or are you saying that a year in if I get the time and then 10 secs later get the time again .. it will not be 10 secs difference but rather +-2 secs from 10?

    Quote

    More efficient to keep the list in-order than to sort it on every timer event to find the one to remove. Only matters if you have a lot of items queued

    I thought about this .. but I thought that walking the list to find the position and then inserting would be more onerous ... I'd guess again that for a more generic version of the code that would probably be the better solution to cover more scenarios.. but in a house with only 15 doors involved llSort should be ok.

  12. Thanks @Rolig Loon .. I had gone into that particular thread but did not see an answer to my particular situation. Once I have tested and as well heard any feedback will definitely post to that/the library .. making it more generic so as to be not so particular to my solution.

    • Like 1
  13. Hi all,

    In my current project I found myself with a problem. I had created a script that would manage all the doors in the house I was building, so that would only need one script as opposed to in door scripts. After slogging through how I would keep track of what way they needed to move, how far, etc. I thought that I was done .. until I hit the 'extras'. First off my doors include a security check, which calls a central access script to determine if the user can open of not the door. Next, since these were sliding doors, with multiple panels I had added in a 'feature' where if you did a hold touch on the door, a menu would pop up for you to select how many panels you wanted open, and if you wanted this applied to the paired door (if any). Now each of these things:, the hold touch, the access check, the dialogs, all had timers associated with them. And worse I realised that multiple things could be happening at once from different doors in the house.

    So the challenge was how could I manage an unknown number of multiple timers, of different duration, which had some data associated with them (user at the least). I've spent most of the afternoon thinking it through, with a few starts and restarts, but I think I have come up with an answer, and I'd appreciate any feedback, suggestions, pointers as to where it might not work .. fail. I've pasted the code below, the first section is the basic timer stack code .. there are a few specifics to my house solution, but these can be readily changed .. and then following is an example of how this is implemented .. again here with a number of specific functions to my solution .. most of which (functions etc) are not included.

    So fire away 🙂

    string EMPTY_STR = "";
    string FUNC_SEP = "|";
    string DATA_SEP = "^";
    
    //stack ids
    string ST_ACCESS = "acc";
    string ST_DIALOG = "dia";
    string ST_TOUCH = "tch";
    
    //list of the timer lengths associated with the stack_id
    list TIMER_LENGTHS = [ST_ACCESS, 5.0, ST_DIALOG, 30.0, ST_TOUCH, 0.75];
    
    //strided list that holds the data of timer items in the stack
    //end_time, stack_id, user_key, data
    //end_time: when the timer event should fire
    //stack_id: what called for a timer, in this case ST_DIALOG, ST_ACCESS, ST_TOUCH
    //user_key: key of the AV involved in the event
    //data: list of relevant data that needs to be stored with the timer call, seperated by ^ (DATA_SEP)
    list gStack;
    
    add_stack(string stack_id, key user, list data)
    {
        //stack_id = ST_DIALOG, ST_ACCESS, ST_TOUCH
        //data = ST_DIALOG:set, type, action; ST_ACCESS:set, group, type; ST_TOUCH:set, group
        //type = ST_DIALOG:DT_MAIN, DT_SECOND; ST_ACCESS:AT_MENU, AT_OPEN
        
        //do the action as required by the type
        //these return data with a listen handle added and relevant data removed (dialog removes type, access removes group)
        if (stack_id == ST_DIALOG){data = show_dialog(user, data);}
        else if (stack_id == ST_ACCESS){data = check_access(user, data);}
    
        //get my end and current time
        float time = llGetTime();
        float end = llGetTime() + (float)llList2String(TIMER_LENGTHS, llListFindList(TIMER_LENGTHS, [stack_id]) + 1);
        float set = 0;
    
        //if the stack is empty .. its my timer to start
        if (llGetListLength(gStack) == 0){set = (end - time);}
        //or if next end is > my end reset timer to my end
        else {if (end < (float)llList2String(llListSort(gStack, 4, TRUE), 0)){set = (end - time);}}
        if (set > 0){llSetTimerEvent(set);}
    
        //finally add me to the stack
        gStack += [end, stack_id, user, llDumpList2String(data, DATA_SEP)];
    }
    
    
    list clear_stack(string stack_id, key user)
    {
        //stack_id = ST_DIALOG, ST_ACCESS, ST_TOUCH
        //return stack_data
        //stack_data = ST_DIALOG:set, action; ST_ACCESS:set, type; ST_TOUCH:set, group
    
        //clear any active timer
        llSetTimerEvent(0.0);
        //find me 
        integer posit = llListFindList(gStack, [stack_id, user]);
        //get data to return
        list data = llParseString2List(llList2String(gStack, posit + 2), [DATA_SEP], [EMPTY_STR]);
        //if a dialog or access we need to remove the listen
        if (stack_id == ST_DIALOG || stack_id == ST_ACCESS){llListenRemove(llList2Integer(data, 2));}
        //remove me from the stack
        gStack = llDeleteSubList(gStack, posit - 1, posit + 2);
        //finally if there is still something in the stack reset the timer
        if (llGetListLength(gStack) != 0){llSetTimerEvent((float)llList2String(llListSort(gStack, 4, TRUE), 0) - llGetTime());}
    
        //return data, dropping handle if there
        return llList2List(data, 0, 1);
           
    }
    
    //checks to see if the user has a touch event in the stack, used to short-circuit the touch_end event
    //#define touch_active(user) ~llListFindList(gStack, [ST_TOUCH, user])
    integer touch_active(key user)
    {
        //return t/f if user has an active touch
        return ~llListFindList(gStack, [ST_TOUCH, user]);
    }
    
    //gets the current event which has caused the timer event to fire
    //#define get_active() llList2List(llListSort(gStack, 4, TRUE), 1, 2)
    list get_active()
    {
        //return flag, user for most recent
        return llList2List(llListSort(gStack, 4, TRUE), 1, 2);
    }
    
    //############ END Stack Functions ########################
    
    //example of how to use
    default
    {
        listen(integer channel, string name, key id, string message)
        {
            if (channel == ACCESS_RETURN_CH)
            {
                list results = llParseString2List(message, [FUNC_SEP], [EMPTY_STR]);
                key user = (key)llList2String(results, 0);
                
                list data = clear_stack(ST_ACCESS, user);            
                if(llList2Integer(results, 1))
                {              
                    if (llList2String(data, 1) == MENU){add_stack(ST_DIALOG, user,[llList2String(data, 0), MAIN, EMPTY_STR]);}
                    else{move_door(llList2String(data, 0), EMPTY_STR, FALSE);}
                }
                else
                {
                    llRegionSayTo(user, PUBLIC_CHANNEL,  "Sorry, you do not have keys");
                }
            }
            else if (channel == DIALOG_CH)
            {
                //set, action
                list data = clear_stack(ST_DIALOG, id);
                if (message == OPT_THIS || message == OPT_BOTH)
                {
                    move_door(llList2String(data, 0), llList2String(data, 1), (message == OPT_THIS));
                }
                else if (message != OPT_CANCEL)
                {
                    add_stack(ST_DIALOG, id, [llList2String(data, 0), SECOND, message]);
                }
            }        
        }
        
        touch_start(integer total_number)
        {
            while (total_number-- > 0){add_stack(ST_TOUCH, llDetectedKey(total_number), [llDetectedLinkNumber(total_number), llDetectedGroup(total_number)]);}        
        }
    
        touch_end(integer total_number)
        {
            //if the specific user key(s) have not had their touch ended .. continue
            integer x;
            while (total_number-- > 0)
            {
                key user = llDetectedKey(total_number);
                if (touch_active(user))
                {
                    list data = clear_stack(ST_TOUCH, user);
                    //check to see if this AV can open door
                    if (user == OWNER_ID || gLockState == OPT_UNLOCK){move_door(llList2String(data, 0), EMPTY_STR, FALSE);}
                    else {add_stack(ST_ACCESS, user, data + [OPEN]);}
                }
            }
        }
    
        timer()
        {
    
            list active = get_active();
            key user = (key)llList2String(active, 0);
            string flag = llList2String(active, 1);
            list data = clear_stack(flag, user);
            
            if (flag == ST_TOUCH)
            {
                if (user == OWNER_ID){show_dialog(user, [llList2String(data, 0), MAIN, EMPTY_STR]);}
                else {add_stack(ST_ACCESS, user, data + [MENU]);}  
            }
            else if (flag == ST_ACCESS)
            {
                llRegionSayTo(user, PUBLIC_CHANNEL, "Sorry, the access server is not working, cannot allow you to open the door");
                llInstantMessage(OWNER_ID, "Access server failed when " + llKey2Name(user) + " tried to open a door");
            }
            else if (flag == ST_DIALOG)
            {
                llRegionSayTo(user, PUBLIC_CHANNEL, "Dialog timed out");
            }        
        }    
    }

     

    • Like 1
  14. might it be that they are using offsets in the texture .. simple example .. all the actual textures you see are on one uploaded texture .. so one face .. but by changing the scale and offset we have different parts of the texture show. I've started to do this quite a lot lately .. So for example have a deck with mulitple wood boards .. with a texture that has 8 different board styles in it my mesh can have but one face, but have set different offsets to each individual board.

  15. Good Morning All,

    Have a question for all in general .. and hopefully will be an interesting discussion and stays on track 😉

    What is your preference in the following option for readability compared to possible efficiency:

    //readability
    
    integer x;
    integer len = llGetListLength(gSomeList);
    
    for (x = 0; x < len; x++)
    {
        //lines and lines of code
        integer worker;
        //do a bunch of stuff with worker
    }
    //efficiency
    
    integer x;
    integer len = llGetListLength(gSomeList);
    integer worker;
    
    for (x = 0; x < len; x++)
    {
        //lines and lines of code
        //do a bunch of stuff with worker
    }

    My assumption in regards to the efficiency example is that it is somewhat faster to instantiate worker once, outside the loop, rather than be instantiating (and destroying) the variable n times inside the loop. That said ... if there is a lot of code from the start to where we first encounter worker we have lost in readability.

    So .. is there a real gain in efficiency that we would notice? Would this on the macro scale, i.e. sim wide, make a difference if 'everybody' coded like this? Is it worth the loss of readability?

     

×
×
  • Create New...