Jump to content

Ruthven Ravenhurst

Resident
  • Posts

    491
  • Joined

  • Last visited

Posts posted by Ruthven Ravenhurst

  1. A common line break command I've seen used in user input is the pipe character |

    You would then use llParseStringToList to split it using the "|" , and llDumpListToString to make it a string again using "\n" as the spacer

    • Like 2
  2. default
    {
        touch_start(integer total_number)
        {
            integer x;
            for(x = 0; x < total_number; x++)
            {
                if(llDetectedKey(x) == llGetOwner())
                {
                    string InvenName;
                    integer InvenNumber = llGetInventoryNumber(INVENTORY_ALL);
                    list InvenList = [];
                    integer y;
                    string ScriptName = llGetScriptName();
                    for(y = 0; y < InvenNumber; y++)
                    {
                        InvenName = llGetInventoryName(INVENTORY_ALL, y);
                        if(InvenName != ScriptName) 
    					{
    						if(llGetInventoryType(InvenName) != INVENTORY_ANIMATION)
    						InvenList += [InvenName];
    					}
                    }
                    llGiveInventoryList(llGetOwner(), llGetObjectName(), InvenList);
                }
            }
        }
    }

    You'll need to get the inventory type with llGetInventoryType for each item, and compare it against INVENTORY_ANIMATION

    I've edited it above. I also made it so it only uses llGetScriptName before the loop and saves it to a string instead of running the function on every iteration of the loop

    • Like 2
    • Thanks 1
  3. On 12/18/2019 at 8:20 AM, Alyona Su said:

    Serious question: Does it need to be a scripted unpacker? Were I to resell no-copy items, I'd just put it into a box and set the box to give contents on click. Then attach it as a HUD and position it to set that option. Now it works when rezzed or worn as a HUD and will create a folder named the same as the box name, and all inventory will go into that folder with a notice that no-copy items will be moved.

    I'm just wondering, because it seems to me that unpacker scripts are a solution to non-existant problem. :)

    If you are trying to do something special (like creating multiple inventory folders, etc.,) then I do understand. That requires scripting.

    I thought attachments (even huds) couldn't be opened that way? I will have to test that

  4. With advanced lighting and shadows from projectors, you can create a flashing light effect.

    In this example I have just a plain white circle as the projector texture. In front of the light (facing the light source) I have a prim with a texture animation that flickers between solid and full alpha.

    https://gyazo.com/fea61f7438f44b3b5b72bf1ea7b9c2eb

    Can also be used without a projector texture or a wider FOV on the projector to create a flickering light around the whole room

    • Like 2
  5. maybe this?

    http://wiki.secondlife.com/wiki/Attach#Caveats

    • When detaching an object, llGetAttached() returns 0, but the same happens when dropping an object from an attachment point to the ground. No other indicative event is triggered in the latter case; in particular, the on_rez event is not triggered for attachment drops. If you need to distinguish a drop from a detach, a possible hack is to check llGetObjectPrimCount(llGetKey()). If it's zero, it can be assumed that the object is being detached; otherwise, that it is being dropped.
    • Thanks 2
  6. in the on rez event, use llGetAttached to get the attachment point. if it's not attached it will be 0

    default
    {  
        attach(key id)
        {
            llOwnerSay("[ATTACH]");
            if(id != NULL_KEY) // Prevent the next bit to run upon detach.
            {
                // Do stuff
            }
        }
        
        on_rez(integer s)
        {
    	if(llGetAttached() != 0)return;
            llOwnerSay("[ON REZ]");
            // Do different stuff.
        }
    }

     

    • Like 2
    • Thanks 1
  7. I would also suggest a numbered list, with just numbers for the buttons.

    using pantera's script, i added a third list for numbered buttons, and when creating the name list, i had it prepend the name with the number

    list gNames;
    list gKeys;
    list gButtons;
    key gVictim;
    integer gListenerHandle;
    
    stopListener()
    {
        llSetTimerEvent(0);
        llListenRemove(gListenerHandle);
    }
    
    default
    {
    
        state_entry()
        {
            stopListener();
            llSetText("touch me", <1,0,0>, 1.0);
            llTargetOmega(<0, 0, 0>, 0, 0);
        }
    
        on_rez(integer start_param)
        {
            llResetScript();
        }
    
        no_sensor()
        {
            llOwnerSay("cant find targets");
        }
    
        touch_start(integer nd)
        {
            if (llDetectedKey(0) == llGetOwner())
            {
                llSensor("", NULL_KEY, AGENT, 512, PI);
            }
        }
    
        sensor(integer num)
        {
    
            integer i;
            gNames = [];
            gKeys = [];
            gButtons = [];
            key ownerKey = llGetOwner();
    
            if (num > 12)
            {
                num = 12;
            }
    
            for (i = 0; i < num; i++)
            {
                gNames = gNames + [(string)i + ": " +llBase64ToString(llGetSubString(llStringToBase64(llDetectedName(i)), 0, 31))];
                gKeys = gKeys + llDetectedKey(i);
                gButtons = gButtons + [(string)(i+1)];
            }
    
            stopListener();
            gListenerHandle = llListen(6666, "", ownerKey, "");
            llDialog(ownerKey, llDumpList2String(["Select your target"]+gNames,"\n"), gButtons, 6666);
            llSetTimerEvent(60);
    
        }
    
        timer()
        {
            stopListener();
        }
    
        listen(integer channel, string name, key id, string message)
        {
            stopListener();
            gVictim = llList2Key(gKeys, (integer)message-1);
            state stalking;
        }
       
    }
    
    state stalking
    {
    
        state_entry()
        {
            stopListener();
            llSetText("", <0, 0, 0>, 1.0);
            llSetTimerEvent(0.1);
            llSetMemoryLimit(llGetUsedMemory() + 5120);
        }
    
        timer()
        {
            vector position = llList2Vector(llGetObjectDetails(gVictim, [OBJECT_POS]), 0);
            if (position != ZERO_VECTOR)
            {
                position = position + <0, 0, -2>;
                if (position.z < 4096)
                {
                    llSetRegionPos(position);
                }
                integer maxAttemptsPerMove = 25;
                while (llGetPos() != position && maxAttemptsPerMove > 0)
                {
                    --maxAttemptsPerMove;
                    llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, position]);
                }
            }
        }
    
    }

     

    • Like 1
  8. 4 minutes ago, Wulfie Reanimator said:

    Again, it won't work. I specifically tested that to double-check before making a comment on it.

    I see that now, odd, i was able to do it before. Maybe they "fixed" the viewer code to not let dialogs trigger gestures. I had a bingo hud with a "Bingo" button that would pop up a dialog with /bingo to trigger a gesture i had to say "BINGO!" and play a sound. tried it again after not using it for a while, and you are right, it didn't trigger it now, and i checked to make sure the gesture is still active

    • Thanks 1
  9. 3 hours ago, Wulfie Reanimator said:

    The only way to make an avatar say something in chat is with llDialog, but even that won't trigger gestures

    Well you can, sorta. As long as the llDialog is set to channel 0, and the button contains text that will trigger a gesture

    EDIT: Nevermind, it worked for me before, maybe the viewer code changed to ignore llDialog in relation to gestures

    • Like 1
    • Thanks 1
  10. If for any reason the seated avatar doesn't own the vehicle, you could get an agent list, and run a loop using llGetObjectDetails(agent,[OBJECT_ROOT]) to see if their root matches the detected object:

    key agentonobject(key obj, list agents)
    {
        integer len = llGetListLength(agents);
        integer i;
        for(i = 0; i < len; i++)
        {
            key agent = llList2Key(agents,i);
            list details = llGetObjectDetails(agent,[OBJECT_ROOT]);
            key root = llList2Key(details,0);
            if(root == obj)return agent;
        }
        return NULL_KEY;
    }
    default
    {
        state_entry()
        {
            llVolumeDetect(TRUE);
        }
    
        collision_start(integer n)
        {
            key obj = llDetectedKey(0);
            if(llDetectedType(0) & AGENT)//detected a non-seated avatar
            {
                llSay(0, llKey2Name(obj) + " walked or ran through me");
            }
            else//an object passed through
            {
                key agent = agentonobject(obj,llGetAgentList(AGENT_LIST_PARCEL,[]));
                if(agent)
                {
                    llSay(0, llKey2Name(agent) + " is seated on an object that passed through me");
                }
                else
                {
                    llSay(0,"No one was seated on the object that passed through me");
                }
            }
        }
    }

     

    • Like 1
  11. how about doing the llGetInventoryList in the attached event, as well as getting permission to attach. In the touch event, check that it's attached to a hud

    integer attached = llGetAttached();
    if(attached > 30 && attached < 39)//if in the range of 31-38, it's a hud

    if it's not, return. only the owner can touch their hud, so no  need to see if the owner is the one touching.

    i modified it a bit to only work when attached, create the list on attach, and to account for no-copy items.

    In the runtime_permissions, i changed it to check if it's already attached before attempting to attach.

    on attach i also added again the attach perms so it would be able to detach.

    changed the touch command for detach to only check if it has perms then detach.

    Not tested for other buttons, but i didn't mess with anything else anyways

    // Links must begin with http:// or https://
    string link1 = "https://marketplace.secondlife.com/stores/111111";
    string link1_name = "Marketplace";
    
    string link2 = "http://www.facebook.com";
    string link2_name = "Facebook";
    
    string link3 = "http://www.instagram.com";
    string link3_name = "Instagram";
    
    string link4 = "http://www.twitter.com";
    string link4_name = "Twitter";
    
    string link5 = "http://www.youtube.com";
    string link5_name = "Youtube";
    
    // Needed for basic functionality.
    float alpha = 0.5;
    
    key owner;
    integer ocillator;
    list inventory = [];
    list nocopy;
    getitems()
    {
        integer num = llGetInventoryNumber(INVENTORY_ALL);
        inventory = [];
        string script = llGetScriptName();
        while (num--)
        {
            string name = llGetInventoryName(INVENTORY_ALL, num);
            if(name != script)
            {
                integer perms = llGetInventoryPermMask(name,MASK_OWNER);
                if(perms & PERM_COPY)
                {
                    inventory += name;
                }
                else
                {
                    nocopy += name;
                }
            }
        }
    }
    default
    {
        on_rez(integer n)
        {
            if(!llGetAttached())
            {   // If the object is rezzed on the ground, try attaching to owner's HUD.
                llOwnerSay("Please allow me to be on your HUD!");
                llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
            }
        }
    
        run_time_permissions(integer permissions)
        {
            if(permissions & PERMISSION_ATTACH)
            {   // If permission was granted, attach to owner's HUD.
                if(!llGetAttached())//only try to attach if it's not already
                llAttachToAvatar(ATTACH_HUD_CENTER_1);
            }
        }
    
        attach(key id)
        {
            if(id)
            {
                llSetRot(llEuler2Rot(<0,270,270> * DEG_TO_RAD));
                llRequestPermissions(llGetOwner(), PERMISSION_ATTACH);
                owner = id;
            }
        }
    
        touch_start(integer num)
        {
            integer attached = llGetAttached();
            if(attached > 30 && attached < 39)//if in the range of 31-38, it's a hud
            {
    
                integer face = llDetectedTouchFace(0);
                if(face == 1) // When the first (front) face is touched...
                {
                    integer len = llGetListLength(inventory);
                    if(len)
                    {
                       llGiveInventoryList(owner, llGetObjectName(), inventory);
                    }
                    len = llGetListLength(nocopy);
                    if(len)
                    {
                        llOwnerSay("There are no copy items that could not be given in the folder");
                        integer i;
                        for(i = 0; i < len; i++)
                        {
                            string name = llList2String(nocopy,i);
                            llGiveInventory(owner,name);
                        }
                    }
                    // Turn around to show social media buttons.
                    llSetRot(llEuler2Rot(<0,90,90> * DEG_TO_RAD));
                }
                else if(face == 2)
                {
                    if(llGetPermissions() & PERMISSION_ATTACH)
                    llDetachFromAvatar();
                }
                // When the social media buttons are touched...
                else if(face == 7)
                {
                    llOwnerSay("Follow me on ["+link1+" "+link1_name+"]!");
                }
                else if(face == 6)
                {
                    llOwnerSay("Follow me on ["+link2+" "+link2_name+"]!");
                }
                else if(face == 5)
                {
                    llOwnerSay("Follow me on ["+link3+" "+link3_name+"]!");
                }
                else if(face == 4)
                {
                    llOwnerSay("Follow me on ["+link4+" "+link4_name+"]!");
                }
                else if(face == 3)
                {
                    llOwnerSay("Follow me on ["+link5+" "+link5_name+"]!");
                }
            }
        }
    
        state_entry()
        {
            llSetRot(llEuler2Rot(<0,270,270> * DEG_TO_RAD));
            llSetTimerEvent(0.1);
        }
    
        timer()
        {
            // If the alpha has reached a limit,
            //  change which way the alpha changes.
            if(alpha < 0.1 || alpha > 0.9)
                ocillator = !ocillator;
    
            // Increase or decrease the alpha
            if(ocillator)   alpha += 0.05;
            else            alpha -= 0.05;
    
            llSetAlpha(alpha, 0);
        }
    }

     

    • Thanks 1
  12. Link messages is the first thing that comes to mind. You can have one script send a link message to LINK_THIS if you only want scripts in the same prim to receive it. Using the other link message fields to send specific commands, you can send an integer, a message or a uuid, or a combination of them depending on what data you need to send to the other script.

    In the second script you'll have a link_message event that will receive all link messages sent to that prim. Using the data sent from the other script you can tell it what it needs to do

    • Like 1
  13. This is a fun one, and I'm sure something similar to my solution has been used to format llSetText to multiple lines, though the long string i used to test it is too long for llSetText, so it would have to be further broken down into strings with a max length of 255 bytes:

    Given a string s and an integer k, break up the string into multiple lines such that each line has a length of k or less. You must break it up so that words don't break across lines. Each line has to have the maximum possible amount of words. If there's no way to break the text up, then return null.

    You can assume that there are no spaces at the ends of the string and that there is exactly one space between each word.

    For example, given the string "the quick brown fox jumps over the lazy dog" and k = 10, you should return: ["the quick", "brown fox", "jumps over", "the lazy", "dog"]. No string in the list has a length of more than 10.

    Here's my quick solution, which i'm sure could use some optimizing as it only took me about 20 minutes to write:

     

    string texttobreak = "This is an unusual paragraph. I’m curious as to just how quickly you can find out what is so unusual about it. It looks so ordinary and plain that you would think nothing was wrong with it. In fact, nothing is wrong with it! It is highly unusual though. Study it and think about it, but you still may not find anything odd. But if you work at it a bit, you might find out. Try to do so without any coaching.";
    list split;
    string texttoprint;
    integer k = 25;
    integer breaktext()
    {
        if(llStringLength(texttobreak) <= k)return FALSE;
        texttoprint = "";
        split = llParseString2List(texttobreak,[" "],[]);
        integer len = llGetListLength(split);
        integer i;
        list temp;
        string tempstr;
        for(i = 0; i < len; i++)
        {
            string word = llList2String(split,i);
            integer templen = llStringLength(tempstr + " " + word);
            if(templen <= k){tempstr += (" " + word);}
            else{texttoprint += (tempstr + "\n");tempstr = word;}
            if((i+1) == len)texttoprint += tempstr;
        }
        return TRUE;
    }
            
    default
    {
        state_entry()
        {
            if(breaktext())
            {
                llSetText(texttoprint,<0.0,1.0,0.0>,1.0);
                llSay(0,texttoprint);
            }
            else
            {
                llSetText(texttobreak,<1.0,0.0,0.0>,1.0);
            }
        }
    }

     

×
×
  • Create New...