Jump to content

Quistess Alpha

Resident
  • Posts

    3,869
  • Joined

  • Last visited

Everything posted by Quistess Alpha

  1. Surprisingly, DuckDuckGo and google give different but equally interesting results!
  2. you're using msg (which has just been confirmed to have the value "Radio On") as the CURRENT_URL when you probably intend a variable representing the URL.
  3. I'd recommend not using literal faces and links except for basic testing. However, if you don't mind clearing ALL media, try llClearLinkMedia(LINK_SET, ALL_SIDES);
  4. if you're using your code above, "Radio On" doesn't look like a valid URL. . .
  5. https://wiki.secondlife.com/wiki/LlClearLinkMedia should work. Also, I think most viewers ignore the PRIM_MEDIA_AUTO_PLAY setting. It's a helpful suggestion to the viewer, but don't rely on it too heavily.
  6. The sanest way I've found to have LSL 'do something' to MOAP is to make it reload the page (set the media URL to something superficially different*) and send an updated page after receiving the new request. ETA: * exactly what things work for acchieving that vary minutely depending on the script, I think the "most correct" method is to add some unused parameter to the query string of the URL (url+"?value="+(string)(++global_variable)), but for simple cases just adding a new number at the end works too (see my "TV" script in the library).
  7. llSetLinkMedia() PRIM_MEDIA_CURRENT_URL PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERMS_NONE If the URL is set only when the button is pressed, and the media face is turned off otherwise, and the viewer has auto-play enabled. Not necessarily recommended for general use.
  8. This seems pretty much solved, but my own 2 cents: Make sure your elevator has gravity set to 0 (there is a known "bug" where gravity affects how long llMoveToTarget takes), high mass/density, and rotation turned off (see llSetStatus and PhysicsMaterial) Turn physics off when the elevator isn't moving (llSetStatus(STATUS_PHYSICS,FALSE);), turn it on before it does move. I vaguely remember someone complaining that the at_target() event didn't always fire correctly some years ago. the fix is of course a timer and then when you 'should be' at the destination, turn physics off, then llSetRegionPos() to the final destination. IIRC llMoveToTarget speeds up and then slows down as it moves from a to b. For extremely long distances, this can be less than ideal (too slow on the ends (why isn't it moving yet?) and/or too fast in the middle (shaky ride) )
  9. So, a big practical complication is that coordinates can be different depending on which HUD attach point your HUD is attached to. For getting a 'first try' working, make sure your HUD is attached to the "HUD_CENTER" attach point, and set its location to <0,0,0>. Second conceptual hurdle is transforming the 'linguistically obvious' notion of "pointing at" to something that is actionable in LSL. I think the easiest 'pointer' to work with is a half-sliced cone, in which case the actual action would be something like 'move the cone to point A and point the z-axis of the cone at point B' In that case, because a cone is symmetrical about its z-axis, we can use llRotBetween() to find a rotation which will move an object's z-axis from pointing in the z direction, to pointing at any arbitrary vector, for example, the vector pointing from point a to point b which is just (point_b-point_a); <script example when I get a chance to test in-world> ETA: I was going to do a write-up of successive changes to make it work in succssively more 'interesting' cases, but that would take a bit of work. I'll just copy-paste a beginning and ending and note the major differences: 1) Only works when the HUD is at ZERO_ROTATION on the center attach point: //Pointer orientation on a HUD 1: basics. // //Setup: // -Create a box and a cone. // -set the x,y,z size of the box to 0.25, // -set the cone's size ot 0.125,0.125,0.25 and link it to the box. // -make the cone red (for visibility) // -take the box-cone into inventory and attach it to hud->center (or center 2) // -edit the HUD and set the position of the box to 0,0,0, // and the position of the cone to -0.5,0,0 integer gLinkPointer = 2; // link # of the pointer prim. vector gPosPointer = <-1,0,0>; // where is the pointer? vector gPosTarget = <-1,0,0.5>; // where should it point to? integer gMode = 0; // 0: move the base of the pointer. 1: move the pointed ad position. point_at_target() { llSetLinkPrimitiveParamsFast(gLinkPointer, [ PRIM_POSITION, gPosPointer - llGetLocalPos(), PRIM_ROT_LOCAL, llRotBetween(<0,0,1>,gPosTarget-gPosPointer), // there is a bug with PRIM_ROTATION; you should never use it for a child prim. PRIM_SIZE, <0.125,0.125,2*llVecMag(gPosTarget-gPosPointer)> // double the length of the pointer, because it is sliced in half. ]); } default { touch_start(integer n) { vector touch_pos = llDetectedTouchPos(0); gMode=!gMode; if(gMode) { gPosTarget=touch_pos; }else { gPosPointer=touch_pos; } point_at_target(); } } Making things work when it's attached to a different attach point, or when the HUD is in a different orientation, is actually somewhat involved. For other attach points, you need to find an 'offset' between the local coordinates of the HUD and screen coordinates. If the user's window is wider than it is tall (a rather reasonable assumption) the offsets for the top and bottom HUD attach points will be constant, but unfortunately, you can't figure out the width for the offset without some interesting guesswork. that guesswork is easiest to do if the HUD is in a sane orientation (the HUD face is parallel to the screen) and the user is touching the root prim. That calculation (see 'black magic' below) is valid unless/until the HUD is attached to a different attach point, or the user's window size ratio changes. As written, that calculation is a bit 'at odds' with the heuristic values gathered by the attach() even t procedure. I'll leave logic for not overwriting gOffset in the attach event, if it was set while the HUD was attached to the same attach point as an 'exercise' For other orientations, you need (or at least it makes the math and conceptualization actually easier) to abandon llRotBetween() (which is kind of a crutch in any case) and learn about llAtan2, which is basically the only trig function you should ever need in LSL: if you give it x,y coordinates, (the wiki says y,x order, because in math land, people like their clocks with noon facing right and 3pm facing up :P) it tells you in (radian) angles how far around a clock would need to turn to make that angle. 0x,1y = 0 degrees, 0.5x,0.5y = 45 degrees etc. If you zero out the orientation of the root prim, and then turn by the correct angle about an intrinsic axis of the pointer, it should point in a sane direction. //Pointer orientation on a HUD lesson 4: llAtan2 // //Setup: // -Create a box and a cone. // -set the x,y,z size of the box to 0.25, // -set the cone's size ot 0.125,0.125,0.25 and link it to the box. // -make the cone red (for visibility) // -take the box-cone into inventory and attach it to hud->center (or center 2) // -edit the HUD and set the position of the box to 0,0,0, // and the position of the cone to -0.5,0,0 // -set the path cut of the cone to 0,0.5; and texture the (new) open faces green. rotation gRotPointerBase = <0,0,-0.71,0.71>; integer gLinkPointer = 2; // link # of the pointer prim. vector gPosPointer = <-1,0,0>; // where is the pointer? vector gPosTarget = <-1,0,0.5>; // where should it point to? vector gHUDOffset; list gHUDOffsets = // * left&right only valid for 1920x1080 ratio monitors! [ <-0.5,0,0>, // center_2. <-0.5,0.95,-0.5>, // top right <-0.5,0,-0.5>, // top center <-0.5,-0.95,-0.5>, // top left <-0.5,0,0>, // center 1 <-0.5,-0.95,0.5>, // bottom left <-0.5,0,0.5>, // bottom <-0.5,0.95,0.5> // bottom right ]; integer gMode = 0; // 0: move the base of the pointer. 1: move the pointed at position. point_at_target() { vector diff = gPosTarget-gPosPointer; float angle = llAtan2(diff.y,diff.z); // because the pointer starts 'up' it's easier to think in 'clock angles', which, interestingly, are the same as math angles with x,y flipped. llSetLinkPrimitiveParamsFast(gLinkPointer, [ PRIM_POSITION, ( gHUDOffset +gPosPointer-llGetLocalPos() )/llGetLocalRot(), PRIM_ROT_LOCAL, llAxisAngle2Rot(<0,-1,0>,angle)*(gRotPointerBase/llGetLocalRot()), // there is a bug with PRIM_ROTATION; you should never use it for a child prim. // <0,-1,0> is an intrinsic axis of the pointer. PRIM_SIZE, <0.125,0.125,2*llVecMag(gPosTarget-gPosPointer)> // double the length of the pointer, because it is sliced in half. ]); } default { state_entry() { integer point = llGetAttached()-31; if(point<0) { llOwnerSay("Error: I am not atached to a HUD point!"); }else { gHUDOffset = llList2Vector(gHUDOffsets,point); } } touch_start(integer n) { vector touch_pos = llDetectedTouchPos(0); if(ZERO_ROTATION==llGetLocalRot()) {if(4==llDetectedTouchFace(0)) {if(1==llDetectedLinkNumber(0)) { // use black magic to find the user's screen ratio. vector st = llDetectedTouchST(0); vector scale = llGetScale(); vector local_pos = llGetLocalPos(); vector touch_estimate = local_pos + ((<0,-scale.y*(st.x-0.5),scale.z*(st.y-0.5)>)); vector difference = touch_estimate-touch_pos; llOwnerSay("Estimate touch_pos:"+(string)touch_estimate); llOwnerSay("Difference: "+(string)(touch_estimate-touch_pos)); difference.x = -0.5; gHUDOffset = difference; }}} //llOwnerSay((string)touch_pos); //llOwnerSay((string)(RAD_TO_DEG*llRot2Euler(llGetLocalRot()))); gMode=!gMode; if(gMode) { gPosTarget=touch_pos; }else { gPosPointer=touch_pos; } point_at_target(); } attach(key ID) { if(ID) { integer point = llGetAttached()-31; if(point<0) { llOwnerSay("Error: I am not atached to a HUD point!"); }else { gHUDOffset = llList2Vector(gHUDOffsets,point); } } } } ETA2: For a pointer which isn't sliced, you can move it to the middle of the two points and not double the length. The point between 2 points is 0.5*(point_a+point_b);.
  10. If it's just powers of 10, you could convert to a string and pull out the digits with llGetSubString().
  11. Moderate, 70k (15.2 L$/m^2) (I'm not affiliated, just felt like taking a look)
  12. Yes. If you can get your user to have their thing at your store, you can even llRemoteLoadScriptPin() it, without giving them an updater object. And if all "user configuration settings" are stored in LSD, a llRLSP() update should be quite easy, although, I've never had a product I really needed to keep updated...
  13. There's experience KVP, but the caveats are pretty harsh. When llEmail ~does work, you can use it to pass URLs to use HTTP messaging, which is grid wide. URLs (as requested by llRequestURL) are only valid until region reset though, so they can't define a 'permanent' address. If you don't mind haggling your user-base, you could llInstantMessage them a url to feed into their product (or send them a gesture/SLURL containing said URL), and hope they update before the region restarts where your server is. Come to think of it, since rolling restarts are ~rolling, if you have sufficiently many servers in different regions, you could ~possibly work out some kind of networking scheme to keep a bi-directional URL line-of-communication open through the roll. It wouldn't be pretty.
  14. If every link in the object is subject to the visibility/invisibility, you can sometimes set the entire linkset invisible then make just the link you want to be visible, visible: llSetLinkAlpha(LINK_SET,0.0,ALL_SIDES); llSetLinkAlpha(someLinkNumber,1.0,ALL_SIDES);
  15. Red just means it doesn't have a wiki page for that specific constant, either because it's new or doesn't work yet, or in this case, both.
  16. technically you only need to iterate on the last llGetNumberOfPrims() - llGetObjectPrimCount(llGetKey()) links which should be the same as llList2Integer(llGetObjectDetails(llGetKey(),[OBJECT_SIT_COUNT]),0); sitting avatars are always higher link numbers than linked prims/meshes. alternatively, iterate on all avatars you think should be sitting on the object and check whether their OBJECT_ROOT is still the object. (but that wouldn't find someone sitting down, only standing up)
  17. I think the idea is to pop up a llDialog box rather than the usual payment box, or give the item immediately instead of asking for confirmation if the item is 0L$. Any way you slice it, it needs some annoying special handling.
  18. There's a specific group. Sure anyone who owns a group can spoof group tags (and newbies won't know how to check for that), but that's a separate issue.. .
  19. It needs to be a texture, not the low shininess setting. I recommend TEXTURE_BLANK and setting the color parameter of the shininess map to a dark grey, like 64,64,64.
  20. I have a few 'ethical' small area lands if you want to borrow some. there are a lot of absurdly priced 16m2 s but there are(used to be? 199L$ for a 16m2 underwater was too good to pass up >.<) also a handful of low priced small small parcels, mostly from land-cutters.
  21. More applied rotation things: fudging Omega and 'real' orientations to play nice with each-other for a car's wheels: // this script expects a linkset with 2 links: a cube root prim, and a cylinder prim wheel. controls by touching the faces of the cube. // for the rest of this script and comments, 'roll' means what a wheel does when going forward or backwards , 'turn' means what a wheel does when moving left or right, not around its main axis. //current wheel state: float gSpeedRoll = 0.0; // how fast the wheel is turning forwards or backwards float gAngleTurn = 0.0; // in radians: how far the wheel is turned left or right. // wheel intrinsic parameters: // llGetLinkPrimitiveParams(wheel,[PRIM_ROT_LOCAL]); when the wheel is facing forward in default 'rest position': rotation gWheelRotIntrinsic = <-0.5,0.5,0.5,0.5>; // with 'snap: local' checked in the edit window, and with the root prim (or the entire linkset) selected, this axis points left (from the perspective of the vehicle/object): vector gAxisRoll = <0,1,0>; // when selected as above, this axis points directly up at the sky: vector gAxisTurn = <0,0,1>; set_speed(float s) { llSetLinkPrimitiveParamsFast(2, [ PRIM_OMEGA, gAxisRoll*llAxisAngle2Rot(gAxisTurn,gAngleTurn), s, 1.0 ]); } set_turn(float r) { llSetLinkPrimitiveParamsFast(2, [ PRIM_ROT_LOCAL, gWheelRotIntrinsic* llAxisAngle2Rot(gAxisRoll,estimate_theta())* // attempt to fix wheel not rolling while turning. llAxisAngle2Rot(gAxisTurn,r), PRIM_OMEGA, gAxisRoll*llAxisAngle2Rot(gAxisTurn,gAngleTurn), gSpeedRoll, 1.0 ]); } float gTheta; // angle of how much the wheel has rolled. float estimate_theta() { gTheta += llGetAndResetTime()*gSpeedRoll; gTheta -= TWO_PI*llFloor(gTheta/TWO_PI); // wrap to [0 thru TWO_PI) return gTheta; } default { state_entry() { llSetLinkPrimitiveParamsFast(2, [ PRIM_ROT_LOCAL, gWheelRotIntrinsic, PRIM_OMEGA, <0,0,1>, 0.0, 0.0 ]); llMinEventDelay(0.2); // to make the touch() event behave performantly. } touch_start(integer total_number) { integer face = llDetectedTouchFace(0); estimate_theta(); // reset theta before changing gSpeedRoll if(2==face) set_speed(gSpeedRoll+=0.25); else if(4==face) set_speed(gSpeedRoll-=0.25); } touch(integer n) { integer face = llDetectedTouchFace(0); if(3==face) set_turn(gAngleTurn+=0.125); else if(1==face) set_turn(gAngleTurn-=0.125); } } see
  22. True, but Omega for rolling might behave oddly when combined with left and right 'turning' which requires directly setting the rotation in any case. I might give it a test next I get in-world though. ETA: Making Omega and turning work together is non-trivial. The main issues to grapple with are that Omega's axis parameter is in the coordinate space of the root prim; setting the rotation while omega is active continues to rotate in object-local coordinates which leads to wobble; setting both the rotation and omega at the same time can lead to the spin of the wheel jumping back to zero (the wheel 'stops spinning' while it's turning left or right) All of those issues are manageable, but not easy to work around if you don't have a decent understanding of rotations. see:
  23. This is kind of off-topic, but the 'point' of the wiki isn't necessarily to be directly helpful for certain situations, but to give an accurate and as-complete-as-is-reasonable description of the functionality. If it's going to suggest a method of circumventing some problem, it should mention all such methods. Adding a blank shininess or normal texture might be more appropriate for some use-cases (like, if your key-framed thing needs to be a torus for some reason) And in-fact, in many cases, setting the physics shape of non-essential child prims to physics-type none would probably be more appropriate.
  24. Bigger idea is that to set the orientation of an object in-world, one of the most useful paradigms to keep in mind is that orientation*change causes a change based on global axes, but change*orientation causes a change based on local axes. Consider: rotation r; default { state_entry() { r = llAxisAngle2Rot(<0,0,1>,15*DEG_TO_RAD); // 15 degree rotation about z axis. llSetRot(<llFrand(1.0),llFrand(1.0),llFrand(1.0),llFrand(1.0)>); // randomize orientation. } touch_start(integer total_number) { // use one of the following: llSetRot(llGetRot()*r); // global rotation //llSetRot(r*llGetRot()); // local rotation } }
×
×
  • Create New...