Jump to content

Quistess Alpha

Resident
  • Posts

    3,801
  • Joined

  • Last visited

Everything posted by Quistess Alpha

  1. llOrd seems a bit superfluous, as it's not that hard to write as a user function i I'm understanding its intended use correctly: string uInt2Ordinal(integer n) { if(n==1) return "1st "; if(n==2) return "2nd "; if(n==3) return "3rd "; if(n<10) return (string)n+"th "; if(n<20) return (string)n+"th"; string ret=(string)n; string last=llGetSubString(ret,-1,-1); if(last=="1") return ret+"st"; if(last=="2") return ret+"nd"; if(last=="3") return ret+"rd"; return ret+"th"; } Actually looking back at that there might be some problems numbers 111 thru 120 and such. could use a bit of improvement, but it's not a hard function to write.
  2. While a "Full-time job" isn't really a thing on SL to my knowledge, unless you're self employed or somehow work for a big-name creator; I think there are plenty of jobs that expect you to be at a certain place at a certain time, even if that place and time is negotiated in advance.
  3. With the first link Rowan listed, I might mention that assuming the uv map and material faces are sane you can probably make whatever faces invisible you need to, and put a 'U-shape' and a 'L-shape' box together for a 5-sided cube.
  4. both vecMag(a-b) and vecDist(a,b) are equivalent. because we're not doing this test repeatedly on a quick timer there's not much reason to use a more efficient version, but for refference, the most efficient version would be something like: integer IsWithinRange(float pfMaxRange, vector pvAvatarPos) { vector diff = llGetPos() - pvAvatarPos; return diff*diff <= pfMaxRange*pfMaxRange); } as is mentioned at the bottom of that wiki page. Edit: For maximum efficiency, you would drop the function call and do the test in-line.
  5. Seems pretty straight forward. gChannelAnnounce = -47; gChannelTeleport = -48; gChannelDialog = -49; list gDestinations; list gDestinationNames; default { state_entry() { llListen(gChannelAnnounce,"",NULL_KEY,""); llListen(gChannelTeleport,"",NULL_KEY,""); llListen(gChannelDialog ,"",NULL_KEY,""); llRegonSay(gChannelAnnounce,(string)llGetKey()); } touch_start(integer n) { llDialog(llDetectedKey(0),"Select a teleport destination:",gDestinationNames,gChannelDialog); } listen(integer Channel,string Name,key ID,string Text) { if(Channel==gChannelAnnounce) { gDestinations+=[ID]; gDestinationNames+=[Name]; llRegionSayTo(ID,gChannelAnnounce,(string)llGetKey()); } else if(Channel==gChannelTeleport) { llRequestExperiencePermissions(ID, ""); } else if(Channel==gChannelDialog) { integer index = llListFindList(gDestinationNames,Text); if(index==-1) llRegionSayTo(ID,0,"ERROR, destination not found!"); else llRegionSayTo(llList2Key(gDestinations,index),gChannelTeleport,(string)ID); } } experience_permissions(key av) { vector pos = llGetPos(); llTeleportAgent(av, "", pos+<1,0,0>*llGetRot(), pos); } } It's a bit brittle, and I haven't tested it so it might have a few bugs. All of your teleporters with this script should be named something less than 12 letters long to fit into a dialog button, and it doesn't have any way of removing a teleport destination, unless you reset scripts in all of the teleporters. Also only supports up to 13 teleporters, again due to dialog limitations, and will throw an error (due to trying to give a dialog menu with empty button list) if there's only one teleporter.
  6. Is there any reason you can't use a prim or a couple of prims?
  7. Firstly, in order to get the functionality you want, you would probably need to make a slight adjustment to the main script; an addon script probably wouldn't be able to do much. Secondly, your API script seems pretty useless. Unless you have some good documentation on what kinds of link_messages and chat commands the main script expects to send and receive, writing an addon script is almost impossible. Now, if you had access to the main script, you would just have to add a line or two to the touch_start and or touch_end events : touch_start(integer i) { if(llVecMag(llDetectedPos(0)-llGetPos()) > 3.0) return; // the rest of the touch event code goes here. } where 3.0 in this example is the maximum distance (in meters) the object can be touched from.
  8. doing a double take, I think my logic might have been a bit flawed. you probably need something more like: timer() { integer typing = llGetAgentInfo(llGetOwner()) & AGENT_TYPING; if(typing+on !=1) return; // do nothing if the typer is in the correct state. on = !on; llSetLinkAlpha(LINK_SET, (float)on, ALL_SIDES); if(on) { if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0)); } else { if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION,0)); } }
  9. Instead of a scripted camera, for things that you sit on (like cars' seats) you can change the prim default camera position: http://wiki.secondlife.com/wiki/LlSetLinkCamera More directly to the original question, you can try and see if an invisiprim works for your needs / graphics settings: http://wiki.secondlife.com/wiki/Invisiprim a lot of people are adamant that they don't work with ALM, but they work just fine if you turn off deferred rendering.
  10. From what I understand the Topology doesn't have to match as long as you can map it in a way that doesn't look too distorted. I'm not really a modeling expert, but the way I would go about it would be to create a mesh head from scratch, then, create a UV map and tweak it until applying a skin template to your head looks similar enough to the same template applied to the default SL head.
  11. An interesting factoid about client-side interpolation: if you have the object selected in edit mode when the snap happens you'll see the object snap rather than interpolate, at least in in any of the viewers I've used.
  12. Animation is a bit trickier because you need to ask the avatar for permission to animate them (which in the case of a worn object like a typer would be automatically granted, but you still need to ask for it) integer on=FALSE; default { state_entry() { llSetTimerEvent(0.1); } attach(key ID) { if(ID) { llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); } } timer() { if (!on && llGetAgentInfo(llGetOwner()) & AGENT_TYPING) { llSetLinkAlpha(LINK_SET, 0.0, ALL_SIDES); on=TRUE; if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStartAnimation(llGetInventoryName(INVENTORY_ANIMATION,0)); } else if(on) { llSetLinkAlpha(LINK_SET, 1.0, ALL_SIDES); on=FALSE; if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) llStopAnimation(llGetInventoryName(INVENTORY_ANIMATION,0)); } } } That should work, I added a global variable 'on' as well to avoid triggering the animation multiple times.
  13. You'll also probably want to convert the group key into something a human can use. One easy way to do that is to use the group's key as part of an SLURL. key kObjectKey = llGetKey(); // use this object just as an example key kGroupKey = llList2Key(llGetObjectDetails(kObjectKey, [OBJECT_GROUP]),0); llSay (0, "This object's group is: secondlife:///app/group/"+(string)kGroupKey+"/inspect ."); http://wiki.secondlife.com/wiki/Viewer_URI_Name_Space
  14. Hmm, that has me wondering if the 32 bits of the rez parameter is enough to encode a local position offset with reasonable precision. . . EDIT: 10 bits each for X, Y, Z Euler angles could give you slightly better than 1 degree accuracy, if you wanted to use a direction to fire in rather than a position. could be made more accurate if you only allow the missile to fire in a 90 degree cone.
  15. my 2 cents. If I were to code something like this the sequence of events would go as follows: - the Rezzor script receives a target key from the user (or HUD) and stores it in a global variable(there are various ways of doing this some of which are more user-friendly than others, I'll skip over the details because I think you already have this down.) presumably the rezzor will refuse to rez missiles before this. -the Rezzor script receives a command to fire a missile. (again, details depend on implementation) -the Rezzor script opens a listener on a random channel, (and stores the handle of that listener as a global variable) and rezzes the missile with that channel as its rez parameter. - the missile script opens a listener on the channel it gets from its rez parameter, and sends a message on that channel. -the Rezzor script receives the message from the missile script, and replies with the key of the target the missile is supposed to fire at. it then removes the listener. -the Missile script receives the key from the Rezzor and fires itself at the target, deleting itself after impact or after some amount of time (guardin against the case in which the target cannot be found)
  16. Speaking as someone who's decent at programming but not really a professional, reading the commented version really gave me motivation to understand the code, and while I probably could have come up with a similar algorithm had I thought about it enough, or parsed the non-commented code if I really put my mind to it, reading a verbal description (the comments) got me thinking about the problem enough to check that your code actually does what it says it does.
  17. Yeah looks like LL is smart enough to not allow HTML additions to marketplace listings, and there's not really many places you could add even plaintext to your marketplace page. I second @Chic Aeon : Thank goodness! You could always add your soundcoud or whatever link wherever you can add text. . . disturbing music
  18. Turns out the forums really don't like returns. for future reference, seems you have to open the file in a document editor like Libreoffice or Word before copy-pasting to get it to look right. I still had to fix the returns manually in vim though. // Modified Hover Text Script -- Rolig Loon -- June 2015 // Adapted from "100% Menu Controlled Hover Text" by Lankarion Lock (posted at https: //community.secondlife.com/t5/LSL-Library/100-Menu-Controlled-Hover-Text/m-p/2942411) // This version simplifies dialog options by refering to a strided list gColors and removing user functions. It also adds an option to remove the script when the owner has finished with it. list gColors = [ "Blue",<0,0,0.8>, "Green",<0,225,0>, "Yellow",<1,0.863,0>, "Orange",<1,0.522,0.106>, "Red",<225,0,0>, "Purple",<0.694,0.051,0.788>, "White",<1,1,1>, "Black",<0,0,0>, "Pink",<0.941,0.071,0.745> ]; string hoverText = "Touch To Set Text And Color"; //Default text goes between the parentheses vector hoverColor = <1.0,1.0,1.0>; // set color default from predefined vectors or use any RGB color vector float hoverAlpha = 1.0; // Sets the text's transparency, 1.0 being opaque, while 0.0 would be transparent list dialogButtons = ["Reset","Close Menu","Set Text","Set Color","No Hover","Kill Script"]; //Defines dialog menu buttons list colorButtons = ["Yellow", "Orange", "Pink","Red","Green","Purple","White","Black","Blue"]; integer dialogChan; integer txtlisten; integer dialogHandle; default { state_entry() { llSetText(hoverText, hoverColor, hoverAlpha); } touch_start(integer num) { key toucher = llDetectedKey(0); if (toucher == llGetOwner()) { dialogChan = (integer)llFrand(DEBUG_CHANNEL)*-1; dialogHandle = llListen(dialogChan, "", toucher, ""); llDialog(toucher, "\nSelect An Option", dialogButtons, dialogChan); llSetTimerEvent(30.0); } } listen(integer chan, string name, key toucher, string msg) { llSetTimerEvent(0.0); // Message received in time. Kill timer. if (msg == "Set Text") { txtlisten = llListen(dialogChan - 1,"",toucher,""); //Set TextBox to listen on an offset to dialogChan llTextBox(toucher,"\nWrite what you would like your hover text to say. Then click \"Submit\".",dialogChan - 1); llSetTimerEvent(30.0); } else if (chan == dialogChan - 1) { hoverText = (string)msg; llSetText(hoverText, hoverColor, hoverAlpha); llListenRemove(txtlisten); llDialog(toucher, "\nSelect An Option", dialogButtons, dialogChan); //Return to main menu llSetTimerEvent(30.0); } else if (msg == "Set Color") { llSetTimerEvent(30.0); llDialog(toucher,"\nPlease select what color you would like your hover text to be.",colorButtons,dialogChan); } else if (msg == "Close Menu") { llListenRemove(dialogHandle); } else if (msg == "Kill Script") // Script no longer needed. Remove. { llRemoveInventory(llGetScriptName()); } else { if (msg == "Reset") { hoverColor = <1.0,1.0,1.0>; hoverAlpha = 1.0; hoverText = "Touch To Set Text And Color"; } if (msg == "No Hover") { hoverAlpha = 0.0; } else { integer idx = llListFindList(gColors,[msg]); hoverColor = (vector)llList2String(gColors,idx+1); hoverAlpha = 1.0; } llListenRemove(dialogHandle); llSetText(hoverText, hoverColor, hoverAlpha); } } timer() { llSetTimerEvent(0.0); llListenRemove(txtlisten); llListenRemove(dialogHandle); llOwnerSay("The dialog menu has timed out."); } }
  19. NVM might have misunderstood the intent of the code.
  20. http://wiki.secondlife.com/wiki/LlGiveInventoryList ^^ a few good ones there, you could change it a bit to suit your taste, perhaps chage touch_stert to on_rez, and add both llDie() and llDetach() to the end of the event to cover the case where it's rezzed in-world and the case when it's attached.
  21. Another confusing thing about quaternion rotations, is that like vectors, they can be thought about in (at least) two seemingly different ways: just like a vector can either intuitively represent a spot in 3d space (a place on your region) or a transformation of the origin to another location (a velocity and heading an object could be moving) , a quaternion can represent either a static orientation an object can be in (rather useful to think of the quaternion in its vector-angle formulation in that case https://eater.net/quaternions/) or a transformation from one orientation to another rotation (turn 90 degrees to the right with respect to your z axis).
  22. Perhaps a useless question, but is there any reason to use addition ('+') in this sort of branchless programming structure rather than bitwise or ('|')? assuming the options are mutually exclusive bitwise, wouldn't | avoid having to deal with the possibility of carrys that won't happen?
  23. Just to add to the confusion, I'll add my 2cents. Well, maybe more than 2: - The first important thing to understand about rotation is that there are 2 major kinds: client side, and server side, although a rotation can often be a mix of the two, it's useful to keep the distinction in the back of your head. For situations where you need a very specific rotation, you will snap the objects to specific positions server-side, and the client will interpolate. - The second important thing is that how easy/hard it is to get the rotation working will depend on if the mesh was conveniently prepared for rotation, and how slow you want the rotation; if the defined center (where the arrows/gimble are when you select the object in SL) of the thing you want to rotate (the lid) is along the axis of rotation (the hinge) it will be easier and smoother to rotate, because you will only have to rotate it, and not move it. keeping point one in mind, if you only need the rotation to be a short quick one, you can get away with snapping the object (lid) directly from its start position to its end position, and your client will interpolate that into a somewhat smooth looking rotation for you. if on the other hand you want the chest to open very slowly, the script needs to do some math to calculate the intermediate rotations, and move the object (lid) to each one in sequence after a delay. In conclusion, your script will depend not only on what you want to do, but how you want to do it, and how well your build was designed for it.
×
×
  • Create New...