Jump to content

Wulfie Reanimator

Resident
  • Posts

    5,738
  • Joined

Everything posted by Wulfie Reanimator

  1. Considering that the installer is barely a megabyte, it's obviously downloading the actual client before installing it. Even if your initial download/install will take a while, but as updates come around it'll be considerably smaller.
  2. War never changes. Also SL helped me understand programming, the ease of tweaking scripts and seeing the results in 3D has been a huge help.
  3. Few more useful things, a little more complicated: A HUD with 3 buttons on it -- each button should send a different message on a non-zero channel Then make an object that is listening for the messages from your HUD, and do something based on them. Many things come with HUDs to control them, knowing how to make one is about as essential as understanding llListen. A cube that follows you around by floating above your avatar's head Bonus points if you can tell the cube which avatar to follow via chat commands. This'll teach you to search for avatars and get information about other objects in general, and you'll have to keep position offsets in mind or you'll end up pushing the avatar. Item giver/vendor Put any items you want (like colored prims) into an object, then use a script to give one (any) of the items to anyone who touches the object. As a bonus task you could let the user select which item they want, without having to look into the object.
  4. Have you already read up on the basics of LSL? Do you know what types, global and local variables, states, and events are? You should read up on those before you try to script, otherwise you'll be in an even bigger world of confusion. If you have though.. A "light" that you can turn on/off with a single touch Learning how to toggle things is very useful in a very wide variety of ways. It doesn't have to be actual light, you could just use llOwnerSay to say either 1/0, or on/off. A cube that changes its color randomly (touch or timer) It'll teach you a little bit about vectors, random values, and primitive parameters. A link set where each prim changes their color randomly -- different color for each prim This builds on the previous task by needing a loop and having to figure out a proper structure for your code. An object that repeats what is said in local chat. llListen is something very commonly used in scripts as well. Knowing how to use it is essential. An object that reads a notecard and says each line in chat. This can seem very complicated at first, and it's fine to skip, but notecards enable you to process a lot of information and since script memory is reset with the script, notecards can be used to keep things persistently in memory -- although scripts can't write into a notecard.
  5. I need this in my life, even if alpha textures would break it. I'm willing to sacrifice some alphas.
  6. Imagine that your avatar is facing forward (arbitrary direction in global coordinates), and there is a straight vertical wall to your left. You run towards the wall and jump onto it. A ray is repeatedly being cast from the center of the avatar and 45 degrees to its left. As the ray hits the wall, it gets a position near the wall and places the avatar there. As you keep running forward, your avatar keeps "wall-running" parallel to the wall, not climbing up or slipping down. That's the basic idea here; Check for surface, attach to it, move along it but only along the X and Y axes in global coordinates regardless of the surface's orientation. Edit; After a bit of fiddling I think I've achieved what I wanted. I simply removed the rotation around the X and Y axes, so the offset position from the wall will only ever be rotated around the Z axis. Here is some example code (following the above wall-run example) you can put into a cube, it would probably help to make another cube to represent a wall as well (even though this example shows no raycast). rotation RotHz() { vector v = llRot2Euler(llGetRot()); return llEuler2Rot(<0, 0, v.z>); } rotation RotNormal(vector normal, rotation rot) { vector left = llVecNorm( normal % llRot2Fwd(rot) ); vector forward = left % normal; return llAxes2Rot(forward, left, normal); } default { state_entry() { vector surface_normal = <-1, 0, 0>; vector contact_position = <100, 100, 10>; llOwnerSay( "start: " + (string)contact_position ); vector wall_offset = <1, 0, 0>; // from the wall vector forward_offset = <2, 0, 0>; // from the current position vector running_position = wall_offset * RotNormal(surface_normal, RotHz()); llOwnerSay( "initial offset: " + (string)running_position ); running_position += forward_offset * RotNormal(surface_normal, RotHz()); llOwnerSay( "with forward offset: " + (string)running_position ); vector final_position = contact_position + running_position; llOwnerSay( "final: " + (string)final_position + "\n " ); } }
  7. I've not tested to see if that's still actually the case, but I'll take your word for it and if it is true, it's a rare edge-case similar to "what if there are no attachments?" You could ignore it (I might) based on the probability of it happening being very low, or you could cover that base for the sake of it. The performance difference is negligible just as well.
  8. All attachments have the same group (the avatar's active group), there's no reason to loop through them all.
  9. Using the function you wrote, I was able to set it my script up just fine, but.. Could you explain the math in words a little bit? I'm glad it works but I feel uneasy because of the fact that I'm not sure why (or more specifically how), lol. Edit; After some more careful testing, I want to reiterate that I'd like horizontal movement only, currently if the object is tilted up or down, it will drift accordingly.
  10. What's wrong with checking the object's own group with OBJECT_GROUP? An object will rez under the group that the avatar has active at the time of rezzing, so if the object's group is the "family group," the rezzer MUST to be in the group. But if you want to check it the moment someone sits on the object and not before, just do this: default { changed(integer change) { if(change & CHANGED_LINK) { // Get last person to sit on the object key target = llGetLinkKey(llGetNumberOfPrims()); // Get their attachments, you only really need one. list attachments = llGetAttachedList(target); // Get the group of the first attachment list ugh = llGetObjectDetails(llList2Key(attachments,0), [OBJECT_GROUP]); // And now you have the avatar's active group. key avatar_group = llList2Key(ugh, 0); } } } The group of all attachments are updated as soon as the active group is changed. P.S. CHANGED_LINK will also trigger when an avatar unsits, so the target will be the object's own link, which will be NULL_KEY. This isn't a problem.
  11. I'm using llCastRay with RC_GET_NORMAL to get a vector (normalized) that is perpendicular to the surface it hits, always pointing "out" of the object. What I want to do is then get a position that is a certain distance away from the surface, and then add another distance to move parallel to the surface. Getting the initial distance from the wall is easy enough, it can be done like this: vector contact_position = <100, 100, 10>; // example, surface facing towards negative global X axis vector surface_normal = <-1, 0, 0>; rotation surface_rot = llRotBetween(<1,0,0>, surface_normal); // forward axis of surface_normal llOwnerSay( (string)(llRot2Euler(surface_rot) * RAD_TO_DEG) ); // <0, 0, 180> vector offset = <1, 0, 0>; // 1 meter "forward" (from the surface) vector final_position = contact_position + (offset * surface_rot); llOwnerSay( (string)final_position ); // <99, 100, 10> Now, the movement should be based on the source object's rotation (that cast the ray) and the surface can face "any" direction, but movement will always be horizontal. In the above example, movement should happen on the Y axis, which would be parallel with the surface. How do I go about this?
  12. Thanks, I spent some time reading through it and trimming it down to just the essentials and renaming things a bit. Here's what I ended up with: UpdateTargeter(integer link, key target) { if (target) // Is valid { vector targetPos = llList2Vector(llGetObjectDetails(target,[OBJECT_POS]), 0); vector childPos = Region2HUD(targetPos, llGetCameraPos(), llGetCameraRot()); if (childPos != <-999, -999, -999>) { vector hudLocal = llGetLocalPos(); hudLocal = <hudLocal.x, hudLocal.y, hudLocal.z>; llSetLinkPrimitiveParamsFast(link,[ PRIM_POSITION, childPos - hudLocal, PRIM_COLOR, ALL_SIDES, <1,1,1>, 1]); } else llSetLinkPrimitiveParamsFast(link,[ PRIM_POSITION, <0.02, 0, 0>, PRIM_COLOR, ALL_SIDES, <1,1,1>, 0]); } else // Target not a valid key. { llSetLinkPrimitiveParamsFast(link,[ PRIM_POSITION, <0.02, 0, 0>, PRIM_COLOR, ALL_SIDES, <1,1,1>, 0]); } } // The root prim has to be attached to Center with ZERO_ROTATION vector Region2HUD(vector targetPos, vector camPos, rotation camRot) { targetPos = (targetPos - camPos) * (ZERO_ROTATION / camRot); targetPos = <-targetPos.y, targetPos.z, targetPos.x>; float FOV = 1.7320508075688774; float posX = (targetPos.x * FOV) / targetPos.z; if (posX > -3 && posX < 3) { float posY = (targetPos.y * FOV) / targetPos.z; if (posY > -1 && posY < 1) { float posZ = (targetPos.z - 2) / targetPos.z; if (posZ > -1 && posZ < 1) return <0, -posX/2, posY/2>; } } return <-999, -999, -999>; } And now it's as simple as doing: timer() { UpdateTargeter(2, target); } I added a link number because I want multiple links to hover near specific targets.
  13. If you absolutely don't want to deal with a user-defined function, you could easily cram everything on a single line, or if you only ever need the rounding in one place, handle the process there instead. (At least I assume you meant user-defined functions, because you have to use regular functions to display anything at all anyway.) llSetLinkPrimitiveParamsFast(1, [PRIM_TEXT, "FC\n" + llGetSubString((string)value, 0, 2+llSubStringIndex((string)value, ".")), <1, 1, 1>, 1]); Just change the "2" into anything between 1 and 6. (Though this is truncation only. But likewise Rachel's function makes small rounding errors.) And I know I'm roughly 3 days late, but I'm tired and wanted to pass the time before bed.
  14. I have a HUD that's only two default prims linked together (and attached to Center), the root is placed at <0,0,0>. In-world, I have a target that I'm tracking. I want the child prim to be placed exactly over the target as I see it on my screen, but I'm struggling with it. Here's what I have so far: key target = "ec85be1f-21b6-d989-6412-db165e53d5e7"; vector target_pos; default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TRACK_CAMERA); } run_time_permissions(integer perm) { if(perm) { target_pos = llList2Vector( llGetObjectDetails(target, [OBJECT_POS]), 0); llSetTimerEvent(0.1); } } timer() { rotation camera_rot = llRotBetween( llRot2Fwd(llGetCameraRot()), target_pos - llGetCameraPos()); vector hud_pos = <1,0,0> * camera_rot; llSetLinkPrimitiveParamsFast(2, [PRIM_POSITION, hud_pos]); } } Sadly, this doesn't work. The placement isn't very accurate at any point, and if you turn your camera to face towards anything but the positive global X axis, the HUD's child prim either barely moves (while perpendicular), or moves in the reverse direction on the attachment's Z axis (while facing towards the negative global X axis). Here is an image while perpendicular: http://puu.sh/wIwLU/94651c9ffd.png And opposite: http://puu.sh/wIwKj/1d393a073b.png And facing towards positive X: http://puu.sh/wIwN5/1b7e639472.png The purple square is the HUD's root, at <0,0,0> The yellow sphere is the HUD's child.
  15. Here's my take on the "multiple timers" problem. All you really need is two variables, I think using linked messages is unnecessarily complex -- and resource heavy, just like sensors. float timer1_start = 5; float timer1_duration = 5; float timer2_start = 10; float timer2_duration = 3; default { state_entry() { llSetTimerEvent(0.1); } timer() { llSetText((string)llGetTime(), <1,1,1>, 1); if(llGetTime() >= (timer1_start + timer1_duration)) // first ends in 10s { llOwnerSay("timer 1 ended!"); timer1_start = llGetTime(); // restart timer immediately, ends in 5s } if(llGetTime() >= (timer2_start + timer2_duration)) // first ends in 13s { llOwnerSay("timer 2 ended!"); timer2_start = llGetTime(); // restart timer immediately, ends in 3s } } } If you copypaste the script into a box, you'll see the script's internal timer as hovertext, and the chat output will be something like this: [00:00:10] Obj: timer 1 ended! [00:00:13] Obj: timer 2 ended! [00:00:15] Obj: timer 1 ended! [00:00:16] Obj: timer 2 ended! [00:00:19] Obj: timer 2 ended! [00:00:20] Obj: timer 1 ended! [00:00:22] Obj: timer 2 ended! [00:00:25] Obj: timer 1 ended! [00:00:25] Obj: timer 2 ended! [00:00:28] Obj: timer 2 ended! [00:00:30] Obj: timer 1 ended!
  16. What you're talking about can't be done with just a script. You would have to create a large set of animations for the head to appear to be tracking the object, and scripts cannot turn an avatar directly.
  17. I guess you can think of it exactly like a door script for uncut prims like you said, the differences being that the "door" is more like a pole that can change its length and the hinge is at one end of the pole. But I'm having trouble following the script you posted, mainly in state_entry where you assign the offset for the first time.
  18. I actually do that whenever I can, it's extremely useful for indirectly optimizing scripts. However, sometimes path cuts are not an option, for example when trying to rotate flexi prims at the base. (Flexi cannot be sliced from beginning/end.) This is actually one of the cases I'm dealing with.
  19. The three rotations shown in the image are only examples. The rotation could be anything between 0-359 on each axis at once. I also understand that the object's position has to change in addition to its rotation, but the math of it goes way over my head.
  20. They're usually called just "clicky" or "clickable" scripts.
  21. Here's a little visual for what I'm about to ask (I lied, there's only going to be a single picture): 1: First rotation at <0,0,0> (euler) 2: Second rotation 3: Third rotation Black dot: Object center White dot: Center of rotation Grey circle: Projected location for object center given any angle around the X axis. Given a prim (box/cylinder) with an abitrary size with one axis being longer and able to change its length while the script is running, how do I set an object's rotation while keeping one end "anchored" in its place? (Rotating around an offset point.) There's an example on the SL Wiki, but it results in relative rotation. For example, running the same code twice would cause two rotations with the same angle size. What I want to do is set the rotation in global coordinates so that running the same code twice would cause one rotation and no change the second time. In short, I want to know/understand the math required for this. I can script, I just can't do the math. Additional notes for context: - The rotation can be around multiple axes at once. (<45,90,30> euler) - The center of rotation or "anchor point" is known. - The prim is part of a link set and worn as an attachment. - The length of the Z axis can be anything above 0.1 and max prim size.
  22. You cannot have an event (timer) inside of a conditional (if) or another event (like state_entry). If you're trying to turn the timer on and off, you can either: 1. Use llSetTimerEvent(x) to turn the timer on (x is seconds between each time the timer event happens) and then llSetTimerEvent(0) to turn the timer off, or.. 2. Use an on/off variable and an "if" check inside of the timer event to check whether or not a scan should happen.
  23. Aren't dialogs just predetermined messages shown via UI, and sent to a "hidden" channel by the viewer? I say "hidden" because the channel is actually communicated to the viewer and it can be snooped. (Not via scripts though.) If you receive a script dialog and you know the channel, you don't have to click the buttons. You can manually type the message. Although, in the end, this does not help you script something that would call a dialog from another script and detect what messages can be sent.
  24. From what I understood, he wants the same particle to move between several points during its path before disappearing. If that is the case, it's not possible, but what you could do in that situation, is create a particle effect with the flag PSYS_PART_FOLLOW_SRC_MASK and then move the source object through a set of coordinates.
  25. You're already doing a good job at formatting your code properly! I'm noticing that you use all-caps for "constant" variables, which aren't meant to be changed. If you're using the Firestorm viewer, you could enable the pre-processor (Gears icon above the code area > Enable LSL preprocessor) in order to not spend memory assigning global variables that only ever have one value. Basically, you'd do this instead: #define BIANCO <1.0, 1.0, 1.0>#define GRIGIO <0.667, 0.667, 0.667>#define BLU <0.0, 0.0, 0.851>#define OPAQUE 1.0integer gSwitch = TRUE; // Switch is on.default[...] This way, whenever you type BIANCO into your code, the pre-processor replaces it with the text <1.0, 1.0, 1.0>. You can read more about it here if you're interested, it has even more helpful uses, but that would be most fitting for you: http://wiki.phoenixviewer.com/fs_preprocessor P.S. This is completely optional and nothing you need to concern yourself with as a beginner.
×
×
  • Create New...