Jump to content

Fenix Eldritch

Resident
  • Posts

    771
  • Joined

Everything posted by Fenix Eldritch

  1. Sure, llLinkParticleSystem will let you create multiple particle emitters in a link set from a single, central script. You can even use the same base particle list, and just add the target specific stuff like [PYS_SRC_TARGET_KEY, <uuid>] for each independent call. default { state_entry() { llLinkParticleSystem(LINK_SET, []); list partList = [ PSYS_PART_MAX_AGE,1.48, PSYS_PART_FLAGS, 0 |PSYS_PART_INTERP_SCALE_MASK |PSYS_PART_FOLLOW_SRC_MASK |PSYS_PART_FOLLOW_VELOCITY_MASK |PSYS_PART_EMISSIVE_MASK |PSYS_PART_TARGET_LINEAR_MASK , PSYS_PART_START_SCALE, <0.75863, 0.75704, 0.00000>, PSYS_PART_END_SCALE, <0.75256, 0.75978, 0.00000>, PSYS_SRC_PATTERN, 1, PSYS_SRC_BURST_RATE,0.1, PSYS_SRC_BURST_PART_COUNT,1, PSYS_SRC_BURST_RADIUS,0.00, PSYS_SRC_BURST_SPEED_MIN,0.00, PSYS_SRC_BURST_SPEED_MAX,1.00, PSYS_SRC_ANGLE_BEGIN, 1.57, PSYS_SRC_ANGLE_END, 1.57, PSYS_SRC_MAX_AGE, 0.0, PSYS_SRC_TEXTURE, "8803a2bd-ea85-48e7-7d1c-baf07d2cfc45", PSYS_PART_START_ALPHA, 0.50, PSYS_PART_END_ALPHA, 0.50 ]; llLinkParticleSystem(1, partList+[PSYS_SRC_TARGET_KEY, llGetLinkKey(2)]); //update both link numbers here llLinkParticleSystem(3, partList+[PSYS_SRC_TARGET_KEY, llGetLinkKey(4)]); //update both link numbers here } } As always, it is up to you to keep track of which link number is which and update them accordingly. Edit: one other thing to be aware of is that particle systems are prim properties, which means they persist. This is important because if you take the object into inventory and re-rez it, all prims will have new uuids, and the persisting particle property will retain the old values - which means the particles won't target anything until you call the particle functions again to update the targets (or reset the script, depending on how the final script is written).
  2. Yup, it just happens to work out in our favor this time. Here's the contraption at a better angle
  3. Unfortunately no, using the ribbon flag would totally wipe out the layered 3D effect you get from staking multiple particles together normally like that. Here's a gif of what it looks like using my suggested settings. I think it's reasonably close.
  4. Normally yes, you would be correct. However we have a very specific edge case here, due to the nature of the particle texture being used. The texture is a square with multiple colored dots scattered around which gives the effect of multiple streams at once. Because of that, we can have a single emitter produce a single stream of this textured particle which gives the appearance of multiple streams. And that single stream can easily target a child prim on the same local axis to create the effect OP was looking for.
  5. There is a way to achieve the desired effect - or at least come pretty close. It won't look exactly the same, but maybe that's tolerable? It requires splitting your object into a single emitter for each side, and having each emitter target an invisible child prim off to the sides with PSYS_SRC_TARGET_KEY and PSYS_PART_TARGET_LINEAR_MASK. llParticleSystem([PSYS_PART_MAX_AGE,1.48, PSYS_PART_FLAGS, 0 |PSYS_PART_INTERP_COLOR_MASK |PSYS_PART_INTERP_SCALE_MASK |PSYS_PART_FOLLOW_SRC_MASK |PSYS_PART_FOLLOW_VELOCITY_MASK |PSYS_PART_EMISSIVE_MASK |PSYS_PART_TARGET_LINEAR_MASK //add this flag to make particles beeline to the target, even if orbiting , PSYS_SRC_TARGET_KEY, llGetLinkKey(2), //specify the key of the target prim. (assumes emitter is root and target is link #2) PSYS_PART_START_COLOR, <1.00000, 1.00000, 1.00000>, PSYS_PART_END_COLOR, <1.00000, 1.00000, 1.00000>, PSYS_PART_START_SCALE, <0.75863, 0.75704, 0.00000>, PSYS_PART_END_SCALE, <0.75256, 0.75978, 0.00000>, PSYS_SRC_PATTERN, 1, //changed to drop pettern (for use with targeting) PSYS_SRC_BURST_RATE,0.25, //dialed this back since we're emitting particles from only one side now. PSYS_SRC_BURST_PART_COUNT,1, PSYS_SRC_BURST_RADIUS,0.00, PSYS_SRC_BURST_SPEED_MIN,0.00, PSYS_SRC_BURST_SPEED_MAX,1.00, PSYS_SRC_ANGLE_BEGIN, 1.57, PSYS_SRC_ANGLE_END, 1.57, PSYS_SRC_MAX_AGE, 0.0, PSYS_SRC_TEXTURE, "8803a2bd-ea85-48e7-7d1c-baf07d2cfc45", PSYS_PART_START_ALPHA, 0.50, PSYS_PART_END_ALPHA, 0.50]); I left comments where I added or altered your original particle script. You must link an extra prim to the emitter to serve as the target (and update the PSYS_SRC_TARGET_KEY as appropriate. You can then duplicate this for the other side and link them all together, again, making sure you keep your link targets correct for each emitter. Sidenote: you have some extra stuff in there that is being unused and thus can be removed. You don't change the color, so you can remove PSYS_PART_INTERP_COLOR_MASK and the associated start/end parameters. Also, since you don't use pattern 4, you can remove the stuff relating to that as well (PSYS_SRC_ANGLE_BEGIN, PSYS_SRC_ANGLE_END, etc). Edit: removing PSYS_PART_FOLLOW_VELOCITY_MASK may look better with the above script as well.
  6. I'm not sure I fully understand the use case, but is there a specific reason why you're not just using KFM_CMD_PAUSE and resuming with KFM_CMD_PLAY? Edit: Ooof, never mind, just tried modifying the demo to use that and I'm still seeing some really noticeable drift with each click. I also tried messing around with BLOCK_GRAB to see if my clicks might accidentally be dragging, but that doesn't seem to make a difference.
  7. Scripts respond to chat commands via the listen event. And in order to get the script to listen, you must first set up a listen filter via the llListen function. That is where you specify what channel (along with other possible filters) the script will listen for. Since you are scripting the stage script and the HUD script, you alone will know what channel they communicate on. However, it would be a good idea to specify additional filters in the llListen function. This is to safeguard against any other sources that might just happen to use the channel you picked by pure luck. Since you are going to make a HUD, give it a distinct name and then use that name in the llListen filter along with the channel you want. That will make the stage script only listen to objects with the exact same name as the HUD on the channel you specified. As for the HUD itself, you have several options for having it broadcast its chat command. If both you and the stage are in the same region, consider using llRegionSay which as the name suggests, can reach anything in the same region.
  8. Configuring a particle stream to target another object needs two settings. First you need to enable the proper flags (either PSYS_PART_TARGET_LINEAR_MASK or PSYS_PART_TARGET_POS_MASK). Then you need to use the PSYS_SRC_TARGET_KEY parameter paired with the uuid of the object you want to target. Changing the stream to a ribbon similarly needs to have a special flag set, the PSYS_PART_RIBBON_MASK. PSYS_SRC_TARGET_KEY, uuid, PSYS_PART_FLAGS, 0 |PSYS_PART_RIBBON_MASK |PSYS_PART_TARGET_POS_MASK See http://wiki.secondlife.com/wiki/LlLinkParticleSystem for more details on each parameter. You can also visit the Particle Laboratory in-world for interactive demos and tutorials. Edit: bah, too slow.
  9. Expanding on what Profaitchikenz said: When you want to access a variable, you use the name you assigned when defining said variable. However in your case, you've defined several variables with the same name of "animation". Their contents are different, but the nametags are identical. If everyone has the same name, how do you tell them apart? Simply put, you can't and neither can the script - hence the error. That is why variables should each have a unique name. Side note: you can have duplicate names under certain conditions, if they are not in the same scope, such as a global variable vs a local variable. But that's not going to be very helpful in this case. Having a list of animations like Profaitchikenz suggests is going to work better than trying to use separate individual variables. It allows you to group related variables together and you can then pull them out one at a time and work with each one as needed. Also, if you are new to scripting, I would recommend looking through some of the guides and tutorials on the wiki to get the basics down. http://wiki.secondlife.com/wiki/Getting_started_with_LSL http://wiki.secondlife.com/wiki/LSL_101
  10. If you venture off the navmesh and get on an unwalkable surface, the character will throw a PU_FAILURE_INVALID_START code in the path_update event. You can use that to monitor the character's status and react accordingly. In such a situation, you could potentially call llNavigateTo and supply a coordinate for a known "good" surface along with the FORCE_DIRECT_PATH parameter to (as the name implies) force the character to go to the specified spot regardless of the navmesh. The wiki page suggests this is a way to "rescue" wayward PF characters who have fallen off the navmesh.
  11. Are you sure you've set the correct pathfinding attributes on the platform objects? Any object that a PF character is intended to walk on must have the "walkable" attribute assigned to it. You can check by going to the menu: Build > Pathfinding > Region Objects and search for the platform. Look in the "Pathfinding use" column and ensure it's set to "walkable." Additionally, any time you add, delete, alter, or move an object that affects the region's navmesh, you must rebake it for any pathfinding characters to notice. You should see an icon in the viewer's location bar indicating the region navmesh needs to be rebaked if necessary.
  12. llLoadURL is a good place to start. It is also possible to display entire web pages on a prim face via llSetPrimMediaParams.
  13. That's not how timers work. Events can't be placed inside other events, so saying you placed the timer event into the control event would be invalid. However, from what you posted, it seems you mistook the llSetTimerEvent function call for the timer event - they are two separate things. llSetTimerEvent is just a command whose only purpose is to start (or stop) a repeating internal countdown. It basically sets up the timer. When that countdown elapses, the script will trigger the timer event and run whatever code is inside it. That is where it was suggested you poll for the agent's status. In your case, I imagine you'd want to start the timer when the object is attached (and stop it when detached for completeness sake). Then in the timer event, poll the agent's info and play/stop the animation as appropriate. Additionally, I think it would be a good idea to include an extra global variable to keep track of the agent's status. That way, you can add logic to avoid unnecessarily starting the animation when it's already playing, as well as unnecessarily trying to stop an animation that's already stopped. Something to the effect of: if llGetAgentInfo says the agent is in mouselook and the global variable is FALSE, then we can assume we've just entered mouselook. So set the global variable to TRUE and start the animation. On the other hand, if llGetAgentInfo says the agent is not in mouselook and the global variable is TRUE, then we can surmise we've just exited mouselook. So in that case, set the global variable to FALSE and stop the animation. By fencing off the starting and stopping of the animation behind those explicit checks, we can have tighter control over when the commands are run and avoid doing them when it isn't necessary.
  14. You mentioned earlier that you want to do a sweeping pattern, which would require multiple rays... assuming that's still the case, are you updating the start position for each new ray? If not, that might be why you keep hitting yourself as you move forward. The origin might be correctly positioned ahead of your avatar for the first ray, but by the time you cast the next one, your avatar may have moved into range. Are you casting all the rays in the sweep at once and then processing them afterwards, or are you processing each one as they are cast? That could be the difference.
  15. It may be helpful to have a debug routine where you rez a marker prim at the coordinates the ray impacts, and perhaps also at the calculated endpoint you fed into the llCastRay function. As for sweeping a single ray, that is not possible. The llCastRay function will fire a single ray between the start and end positions and it is practically instantaneous. You would need to set up and fire multiple rays in a sweeping pattern to cover any area other than a straight line.
  16. So there are several things to consider with your current approach. If you aim to have each card be its own object that can potentially be rezzed or given to a player, you probably would want to set the next-owner-permissions on each card to no-copy. That way when the card is given to a player, the new permissions kick in and they won't be able to keep multiple copies (saves on clutter and possible cheating). Meanwhile, the deck would retain the original collection of cards in its own inventory. You mentioned that you want a very manual feel to the game - to the point where cards dealt are actually removed from the deck's inventory and must be put back in afterwards. You can do this... but I think it might be more trouble than its worth to reset the game. You'd need to code failsafes on what to do if not all cards are put back in, or stuff other than the expected cards are dropped into the deck. And again, while you probably can do this - I think it would be much more trouble than it's worth, especially for a beginner project. I think we can achieve a similar feel without necessarily messing with the deck's own inventory. Keeping that static would make things easier for you. Script-wise, you'll need to keep track of all the cards, so that you don't accidentally deal a card that has already been given out. I believe the simplest solution would be to construct a list of all card names in script memory. Assuming you have all the cards already in the deck's inventory, you can generate this list by using a loop and llGetInventoryName. There is an example on the linked wiki page on how to loop over the contents of an object's inventory. It would be good to do this in the state_entry event - i.e. when the script first starts/restarts, that was you'll always be starting with a full deck. Then whenever you need to draw a card, you will essentially generate a random number between zero and the current length of the card-name-list minus one (because lists are zero-indexed). Use this number as an index into the card-name-list and select a card name with llList2String. You can then give a copy of the card, referenced by the name we just selected using llGiveInventory. Finally, delete that item from the list in memory so we don't select it again. There is a user created function you can find on the wiki to do just that: ListItemDelete. It's okay that we delete the item from the list, because we can easily reconstruct it when we restart the script as per my mention of the state_entry event. This is much easier to recreate than say relying on players to put all the cards back manually. This is just one suggestion, there are many ways to approach solving this problem. Hopefully this will give you a starting point. In general, reading through the wiki as a whole is a good idea. There's a lot there, but it's good knowledge. You may even want to skim through some beginner tutorials to get more familiar with the basics. Good luck!
  17. The only thing special about the giant sim surround sculpts is that the sculpt map is applied to a large megaprim. Changing the type to sculpt map doesn't alter the scale of the prim, so it doesn't dispel the mega prim's size.
  18. Hmm... I had assumed the mention "off-sim" was perhaps a quirk of translation from a different language but apparently not. Very interesting effect according to the marketplace entry. I'll have to check it out in person when I can get to my PC. Wonder what happens if you stand up while out in the void...? Edit: I'm less inclined to believe this effect is using the linden vehicle functionality, so those links i posted earlier probably won't be of much help in this regard.
  19. The wiki would be a good place to start. The Linden Vehicle Tutorial goes over the basics of the various vehicle functions, parameters, theory, etc. You can also look in-world at places like the Vehicle Laboratory which has interactive demos and examples to play around with as you learn.
  20. My apologies, I was thrown by your use of the terminology a bit. Seeing "parent" and "child" in the context of SL often refers to linksets and their ordering within it. If you're talking about what happens to objects that get put into inventory, that's something else. As far as I'm aware, objects that get put into inventory are essentially dormant. Not much will change other than perhaps the current owner key and the object's permissions in cases where the object being given originated from a different user. With that in mind, you might be able to detect a change by using llGetInventoryPermMask but that assumes you can discover the permissions of the object before it gets put into another object's inventory AND that they are set to be different for the next owner... I think? I'm not entirely sure...
  21. I imagine you'd need to have a script inside the target child prim which has its own changed event logic. Additionally , when CHANGED_INVENTORY fires, you could check llGetInventoryNumber against a saved value captured when the script first inits. If the returned value is different from the baseline, then you'll know the target prim gained some inventory. Alternatively, I think you can accomplish the same thing without need of a script in the child prim by using llGetObjectDetails(llGetLinkKey(<child_prim_link_number>), [OBJECT_TOTAL_INVENTORY_COUNT]) to remotely query the child prim's inventory count from a single script in the root. Edited to add a correction: OBJECT_TOTAL_INVENTORY_COUNT, even if used targeting a chid prim will only return the total inventory count for all members of the linkset combined. So my idea for using that from the root wouldn't work. I think your best bet is to have a script in the target child prim with its own changed event logic as outlined in the first part of my post.
  22. Might be worth a feature request on the JIRA. Perhaps it could be such that setting the sky detail slider to mid/high would switch the sky-dome model to a full sphere.
  23. What if you were to cage them from a distance, and the cage would use a much lower powered push to keep the avatar suspended within itself? Since the target would be inside the object doing the push, you wouldn't have to deal with the distance falloff.
  24. If you wish to hire someone to work with you on a project, you'll get better responses by asking in Inworld Employment forum. Good luck! Edit: oops, mods already move it for you.
×
×
  • Create New...