Jump to content

Fenix Eldritch

Resident
  • Posts

    771
  • Joined

Everything posted by Fenix Eldritch

  1. Can confirm: even though the UUID changes, the creation time doesn't appear to update with it. I'm guessing that's intentional...
  2. Just tested inworld, and the changed event will fire if you edit and save a notecard in the object's inventory. And given that the notecard will result in having a new uuid, you can extrapolate whether that was the specific cause of the inventory change. //started demo with notecard named "test" already in the object default { state_entry() { llOwnerSay("pre-edit uuid:"+(string)llGetInventoryKey("test")); } changed(integer change) { if (change & CHANGED_INVENTORY) { llOwnerSay("post-edit uuid:"+(string)llGetInventoryKey("test")); } } } //[17:48] Object: pre-edit uuid:e9c6a95c-e0e0-1c7b-895a-c8a4b18d1c5a //[17:48] Object: post-edit uuid:031621e6-da7f-6bc9-ceee-bab341944677
  3. I know you've gotten past it already, but I figured I'd just expand on this and explain why you were told one thing, and then told another. Molly's initial post was presenting you with the documentation for the input list. That typically includes variable types - but that is just for our knowledge/benefit. The function that takes the list as input already expects each element to be of a certain type and doesn't need it to be redefined. Thus the expectation is that you omit the types when actually writing it out . You only include variable types when declaring variables: which can include standalone local/global variables, and also the parameter variables of event and function handlers.
  4. Yes, it's entirely possible, that's what functions like llSetLinkPrimitiveParams and llSetLinkPrimitiveParamsFast are for. They allow you to modify any linked prims in the linkset. In your case, you would want to modify the local rotation of the top section of the phone. And it would be advisable to have the top part not be the root prim. Here is a very quick demonstration script: // Demo script rotation open = <0.438371, 0.0, 0.0, 0.898794>; //example open rotation rotation close = <0.999312, -0.0, -0.0, 0.037077>; //example closed rotation integer toggle = FALSE; integer top_part; //link number default { state_entry() { integer x; for(x=1;x<=llGetNumberOfPrims();x++) //scan all links in the linkset { if(llGetLinkName(x) == "top") //check if it's the top prim by looking for a name of "top" { top_part = x; //store the link number of the top part } } llSetLinkPrimitiveParamsFast(top_part,[ PRIM_ROT_LOCAL, close ]); //start in closed rotation } touch_start(integer total_number) { if(toggle = !toggle) { llSetLinkPrimitiveParamsFast(top_part,[ PRIM_ROT_LOCAL, open ]); } else { llSetLinkPrimitiveParamsFast(top_part,[ PRIM_ROT_LOCAL, close ]); } } } For your purposes, you'll need to supply the local rotations for the top part in its closed and opened orientations. You can do this by linking everything together and manually editing the top to be in the orientation you want and then adding a diagnostic command to the touch_start event of your script to report the part's current local rotation. Something like: llOwnerSay((string)llGetLinkPrimitiveParams(top_part,[ PRIM_ROT_LOCAL ])); where "top_part" is a global variable which contains the link number for the top part of the phone. Make a note of what is reported and repeat the process for the other orientation. Once you have both, plug them into the demo script above. I noticed that the phone appears to have a hinge prim, which suggests the top part of the phone doesn't have its origin in an optimal location. This isn't a huge problem, it just means you'll need to also update the top part's local position as well. The process for discovering that is identical to the above, just use PRIM_POS_LOCAL for the get and set functions respectively. You can also combine using the local rotation and local position at the same time.
  5. Scripts cannot play animations locally. Any animation started by a script will display for all to see. Regarding the other half of your question, yes I think it should be possible to create a HUD that you wear, but can animate other avatars. However, that HUD would need to request PERMISSION_TRIGGER_ANIMATION from that avatar, and they would need to explicitly grant that request via a popup dialog box. And a script can only hold permissions for one avatar at a time. Alternatively, you could make additional attachments which would be worn by the avatars you want to animate. Said attachments would contain the animations and a script that would communicate with your HUD. This would enable your HUD to send commands to the other attachment which in turn could animate the avatar wearing them. Of course, be sure to clearly explain your intent to any avatars you want to do this with - as attempting to animate them without their knowledge or permission would constitute as abuse and get you reported.
  6. It will detect both, but I suspect the script as currently written might only be processing one. The integer seen in a collision's event handler* is an index into a table of all targets that collided with it on that frame. You need a loop to iterate through them all to process them. default { collision_start(integer num) { llOwnerSay("total collisons detected in this event: "+(string)num); integer x; for(x=0;x<num;x++) { llOwnerSay(llDetectedName(x)); } } } Rez a prim and resize it to have a large horizontal area. Drop the above script into it. Then, rez two more prims above the first, making sure they are at the same elevation. Give them unique names and then turn both physical. Let them drop - they should hit the first prim at the same time and demonstrate the effect. *and it's not just collision events, this is used for others as well, like touch. Edit: You can probably set up a similar test with your existing gates, even if you don't have access to the script. Orient the gate horizontally so that you can position and drop two prims through it from the same height. If you don't get two signals, then it's likely that it wasn't scripted to handle multiple simultaneous collisions.
  7. Replicating what is essentially a game of inventory hot potato poses an interesting problem: namely once an object is given to an avatar, it's effectively off any detectable radar. Scripts cannot see into an agent's inventory, nor can they run while their host object is in an inventory. There's also the matter of scripts not being able to cause a worn object to drop on the ground - which would be necessary if you wanted the object itself to jump from one avatar's possession to another (nevermind permissions or blocking/ignoring of requests). If every participant was wearing a HUD, that would simplify things. Firstly, the dispenser would have easy access to a list of everyone who joined the game. And you could have the game scripted in such a way as to pass the object not to an avatar, but to their HUD instead. Though to do this, you'd need to write logic for letting avatars pick targets through their HUD instead of just dropping inventory onto a random target. This target selection could take into account the active players known to the dispenser as well as filter out those who are away/busy. Going one step further, the HUD could instead be the worn prop, temp attached and invisible until the owner is chosen to be the current "it". At that point, all you need is a communication protocol between the attachments for letting one effectively "tag" someone else. This would also allow you to work around edge cases where someone is tagged, but they remove the attachment or leave the area while still being "it". You could have the attachment send out a short signal to the dispenser which would in turn randomly pick a new person from its internal list. You can also have a failsafe timer where if no action happens within a set time, the system automatically tags a new person.
  8. It's not you, a number of images have been broken on the wiki for years. The source images are actually still there, but those previews to them broke long ago.
  9. When you log in, all your attachments have to rez, because they are new instances of those objects. So it is as Ruthven said. This bit here is the culprit: on_rez(integer s) { llResetScript(); } Either remove it, or comment it out. That will stop your script from being reset upon login. Again, this is because when you login, all of your attachments have to be recreated and that counts as being freshly rezzed, which in turn would trigger the on_rez event. In fact, the same holds true for simply attaching an object from your inventory. That also counts are a fresh rez and will also trigger the on_rez event.
  10. Hope everything went ok for you! Next window to try again is on 2222-02-22
  11. The point of Lucia's script is that it alters the linkset such that avatars can no longer right-click sit on the object anymore. If they try to do so, the action fails and they get a system message telling them there was no place to sit. That's an excellent way to prevent people from trying to cheat their way past barriers and the like via sitting on stuff. Regarding Rolig's suggestion, her code is a self-contained event. You would place it alongside the other events in your default state.
  12. So close.... 2022-02-22T22:22:22.222821Z I've left it rezzed outside my workshop at http://maps.secondlife.com/secondlife/Bay City - Moloch/54/88/26
  13. This is a good example where indentation can be extremely helpful. Whenever you have a new { it is advisable to further indent whatever follows until you close that off with the }. This helps keep track of the scope of things in nested code blocks. And if you go to close a section and things don't line up, that'll give you a hint that you might have missed something. For example, using the code snippet you posted above, indenting can make the nested blocks look something like this. I think it helps visually organize what scope contains what, with each block being more indented the deeper the nesting goes. else if(option == "RLV...") { listen(integer channel, string name, key id, string message) { if (message == "Next Level") { llMessageLinked(LINK_THIS, 0, message, kToucher); } } } else if(option == "Reins...") However... aside from that, it looks like you're defining a listen event within another code block - and that is not valid. Events are only allowed to be by themselves within the state scope level, not lower. You can't define an event within another event. (Unless this is something special for RLV, which I am not knowledgeable about at all.)
  14. Echoing what Rolig and KT have said above, be careful in the assumptions you make: the issue might not actually be unbalanced brackets. There are many different kinds of syntax errors. Also... I neglected to mention that simply balancing the brackets isn't enough. Their placement is equally important. Take this example below. We have the proper amount of opening and closing brackets, but one of them is placed in a bad location which will cause a syntax error. // Syntax error demo. default { state_entry() { if(TRUE) { llSay(0,"True!"); // there should be a closing bracket "}" here to properly encapsulate this code block else { llSay(0,"Not true!"); }} //This is incorrect. Even though we balanced the brackets, this is not the right spot for one of them. } }
  15. States, events, user defined functions, and even multi-lined if-then-else and loop code blocks all need to be flanked with brackets. Think of them as bookends that are used in defining different sections of code. I'd recommend reading through the Getting Started with LSL page on the wiki. The Dissecting "Hello, Avatar!" section in particular gives some visuals and commented examples regarding the use of brackets. One of the most important things is to keep them balanced. Whenever you use an open bracket of any kind, you must always close it with its counterpart: every { needs a corresponding }. One helpful way to visually keep track of brackets is to follow a consistent indentation style. See the top of the Basic LSL Tutorial page for more on this. Edit: Also in regards to syntax errors, the compiler will give you a line and column number where it thinks the problem is. Double clicking on that error message will put the cursor there. Depending on the error, it may not be the exact location, but is generally a good place to start looking to see if anything is out of place.
  16. It's worth mentioning that there is built-in functionality in the form of a media control bar that hovers over the prim's media face when active. You can choose between two types: one with the url bar, and another without. Both cases contain a home button that will navigate the media to a home url if specified in the media params list. You can include PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI in the list to enable the control bar without a url bar. That will allow you to prevent users from navigating to arbitrary addresses, but still have access to buttons like forward, back, and home. Or if you'd rather not use the built-in one and prefer to have prim home buttons as you stated in your OP, then you can accomplish the task by having the prim button invoke the command to set the media params again, but only specify the PRIM_MEDIA_CURRENT_URL and the accompanying home url. The wiki page for the prim media function states that any unspecified parms will not be changed, so issuing the command again with only a new current url will update only that and leave the rest intact. Below is a short demo. Link to prims together and drop this script into it. Clicking the 2nd link will mimic a sort of home button // Prim Media manual home button demo. // Link 2 prims together and drop this script into the root. default { state_entry() { llSetLinkMedia(LINK_ROOT, 0, // Link and side to display the media on. [PRIM_MEDIA_AUTO_PLAY,TRUE, // Show this page immediately PRIM_MEDIA_CURRENT_URL,"http://google.com", // The url currently showing PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE // Set so the control bar is not visible to anyone ]); } touch_start(integer total_number) { if(llDetectedLinkNumber(0) == 2) { llOwnerSay("home prim button clicked"); // sets new current url, mimicking a home button llSetLinkMedia(LINK_ROOT, 0, [PRIM_MEDIA_CURRENT_URL,"http://duckduckgo.com"]); } } }
  17. So the ultimate goal is to telegraph to the driver whether other approaching racers are already a lap or more ahead of them? If so, I can think of a simpler system that might achieve the same result without the need for much cross communication. Keep your rearward facing sensor, but instead of scanning for avatars, scan for the cars themselves. Have the cars all be named the same, so you can keep the sensor filter tight (this is crucial because a sensor can only detect 16 results per sweep). I presume the cars somehow know what lap they are on, correct? Store that information in the car's root prim description field, perhaps along with the name of the driver too. That way, when your car scans behind itself and detects other cars in range, it can check those car's description field and compare their lap counter to your own. If theirs is grater than yours, display the flag and driver name as before. By storing the lap counter and driver name in the car's root description, you make it easy for other cars to query that data immediately using llGetObjectDetails, as soon as they get the car's uuid from the senor. As opposed to having to bounce between sensor and listen events to process the data fully. Being able to do everything quickly in one event and then exit makes life much easier, especially in time sensitive scenarios like a race. And using a lap counter as opposed to say, total distance driven would be preferable I think, as it would only need to be updated once each lap.
  18. I'm assuming the intent here is to have a HUD that when clicked, speaks the chat command which would trigger a gesture? If so, then it is as Wulfie already said: scripted objects can't trigger gestures. The chat commands only work if they are typed out directly by you. A script saying "/hello" would not be able to trigger that gesture. You can, however, bind gestures to shortcut keys. You can assign any of the F2 - F12 keys to trigger a gesture (and you can combine Ctrl or Shift with them to get a total of 33 potential shortcuts for use). Check out the Knowledge Base article.
  19. Then it is as I said previously: child prims have their omega on a local axis - which is relative to the orientation of the root prim of the linkset. The 2nd main bullet point would apply to your current scenario. In this case the vector axis you specify in the llTargetOmega (or SLPPF) command will not refer to the global axis, but rather the local axis relative to the root prim's orientation. Setting your entire object to be at a zeroed out rotation will be helpful while you experiment to find an appropriate value for the axis vector to supply to your llTargetOmega call. To help illustrate this, take your linkset as it is now and get the linked rotor spinning. Now, open the edit tool and enable the "Edit Linked" checkbox. Select the root of your linkset and change its rotation in the edit tool. Observe how the spin of the linked rotot changes as soon as you confirm the root's new orientation. This is what you're experiencing. Your object's root is at some arbitrary rotation, so when you attempt to apply llTartetOmega to one of the child links, it is affected by the current rotation of the root. Try a supplying a vector that uses a different axis, either <0.1, 0.0, 0.0> or <0.0, 0.0, 0.1>. Or, build your linkset such that the root's orientation is all zeros for XYZ rotation in the edit window. That might help show visually what to expect if you still use the global axis as a guide.
  20. Your previous posts indicated that your rotor was part of a linkset, but that gif in your last post shows it's now unlinked and by itself. So I would expect calling llTargetOmega with an axis vector of <0.0, 0.1, 0.0> would make make the rotor spin about the region 's Y axis regardless of any other rotations already applied to the rotor. At least, that's what I am seeing with my own tests. (Unless I've missed something obvious) So I'm guessing it may be one of two possibilities: Either you have accidentally introduced a typo into your script and are spinning about the X axis... since the script you're currently using can't be the one you posted in the original post. Double check your axis vector: make sure the X and Z components are truly zero. Or the mesh rotor's natural orientation is somehow causing the confusion. I'm not sure about this, since as an unlinked object, it should spin about the region's Y axis (if your supplied vector is the same). But it wouldn't hurt to try different variations of the axis vector to see which one works out better: <0.1, 0.0, 0.0> <0.0, 0.1, 0.0> <0.0, 0.0, 0.1>
  21. In the case of a (presumably) non-physics enabled child prim, it would be spinning around the center of the target prim. If it's appearing to rotate around a different point, then the prim may have had some parameters altered to make it appear off-center (like path cuts or slice). Or perhaps the rotor is mesh with geometry such that its center is not where you might expect. At a glance, you can see where an individual object's center is by selecting it in the edit tool and observing where the move widgets appear (use Edit Linked to select individual child links in a linkset). If the true center of the rotor is not conducive to spinning it, then you can try to edit it if it's a prim. But if it's a mesh, you might be out of luck and may need to recreate the rotor with extra geometry to shift the origin to a position that works with the desired spin effect. Or did you mean to say it's rotating around a different axis than what you expected? As per the specification on the function's wiki page: The 2nd main bullet point would apply to your current scenario. In this case the vector axis you specify in the llTargetOmega (or SLPPF) command will not refer to the global axis, but rather the local axis relative to the root prim's orientation. Setting your entire object to be at a zeroed out rotation will be helpful while you experiment to find an appropriate value for the axis vector to supply to your llTargetOmega call. Edit: And yeah, much of the information in that video has become outdated. See the limits page for more up to date info. Best practices have also advanced. Using three scripts to modify three different prims in the same linkset is less than ideal. Everything in that demo can be easily achieved with one single script. I would recommend you give the LSL Script Efficiency page a quick view, particularly the "Efficient Design" section.
  22. The script you provided will accomplish the task of starting or stopping an object from spinning. Though in this case, the trigger for it happening is in receiving an internal message of either "start" or "stop" from the llMessageLinked command. That implies there is another script somewhere in your linkset which actually sends out the message. You should also read the specification for the llTargetOmega function as well. It explains what each of the input parameters do. In which case, yes, setting the y component of the vector would result in the omega spinning about the y axis. The specification also says that if you supply a gain (the 3rd parameter) of zero, that will also have the effect of stopping the spin. It is worth mentioning that two scripts are not needed to accomplish this task: you can achieve the same effect with a single script using the llSetLinkPrimitiveParams or llSetLinkPrimitiveParamsFast functions. These functions are excellent for letting a single script make multiple changes at once against a selection of different links in a linkset. Below is a simple example using llSetLinkPrimitiveParamsFast and a touch event to start/stop a prim's spin. In this case, simply clicking on the prim is the trigger, and it will also communicate its status to you via the llOwnerSay function. integer toggle = FALSE; integer targetLink = LINK_THIS; //change this to target other link numbers default { state_entry() { llSetLinkPrimitiveParamsFast(targetLink, [PRIM_OMEGA, <0.0,0.0,0.0>, TWO_PI, 0.0 ]); } touch_start(integer total_number) { if(toggle = !toggle) { llOwnerSay("on"); llSetLinkPrimitiveParamsFast(targetLink, [PRIM_OMEGA, <0.0,1.0,0.0>, TWO_PI, 1.0 ]); } else { llOwnerSay("off"); llSetLinkPrimitiveParamsFast(targetLink, [PRIM_OMEGA, <0.0,1.0,0.0>, TWO_PI, 0.0 ]); } } }
  23. If you just want the region name from a slurl, then you'll want to split up the slurl by "/" and then grab the list element at index 3. Also, if this is coming straight from a slurl, you won't actually have spaces in the string - instead you'll want to put the result through llUnescapeURL to convert the "%20" characters to spaces. default { state_entry() { string slurl = "https://maps.secondlife.com/secondlife/Sandbox%20Mirus/111/39/1113"; list parsedString = llParseString2List(slurl, ["/"], [""]); string unescaped = llUnescapeURL(llList2String(parsedString,3)); llSay(0,unescaped); } }
  24. Well yes, when they are given a copy of the notecard, they become the current owner of their copy. But when they drop it into your mailbox, you become the owner of that new copy. So the net result is that you are still listed as the creator/owner of the copy that ultimately gets put in your mailbox. Does last owner apply to non-rezzable inventory assets too? I thought it was only prim/mesh objects. I'm having trouble finding more info on that, how does one query last owner for inventory assets?
  25. The basic idea here is that you need to perform a loop and use it to inspect each and every object (link) in the linkset. And when you encounter a link that has the name of one of your special targets, change that link's texture accordingly. Rolig's example does this, and then goes the extra distance of constructing several lists which will ultimately be used to create a combined list for llSetLinkPrimitiveParamsFast that lets you change all of your targets in a single function call. If I may, here's another possible approach: Instead of building a combined list of targets, this one pre-defines single list to be used as a reference that pairs your target names with their corresponding textures. As before, we still loop over every link in the linkset to check the name. But here, we search the reference list for that name and if we find it, grab the next list element as the texture. My demo uses llOwnerSay to display the values, but you can easily take them and place them into a llSetLinkPrimitiveParamsFast call , targeting link number "i" (the current link being examined in the loop). list lst = [ "A","texture-for-A", "B","texture-for-B", "C","texture-for-C", "D","texture-for-D" ]; default { state_entry() { integer i = llGetNumberOfPrims(); string primName; for (; i >= 0; --i) { primName = llGetLinkName(i); integer x = llListFindList(lst,[primName]); if (x > -1) { llOwnerSay("link number "+(string)i +" has name: "+primName+", set its texture to: "+llList2String(lst,x+1)); } } } }
×
×
  • Create New...