Jump to content

Particle script target set to a prim description


Assmay
 Share

You are about to reply to a thread that has been inactive for 3583 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Hello,


I have a standard particle script here

arrows()
{
llParticleSystem([
PSYS_PART_FLAGS, 307,
PSYS_SRC_PATTERN, 8, 
PSYS_PART_START_ALPHA, 1.000000,
PSYS_PART_END_ALPHA, 1.000000,
PSYS_PART_START_COLOR, <1.000000, 1.000000, 1.000000>,
PSYS_PART_END_COLOR, <1.000000, 1.000000, 1.000000>,
PSYS_PART_START_SCALE, <0.250000, 0.250000, 0.00000>,
PSYS_PART_END_SCALE, <0.250000, 0.250000, 0.000000>,
PSYS_PART_MAX_AGE, 10.000000,
PSYS_SRC_MAX_AGE, 0.000000,
PSYS_SRC_ACCEL, <0.000000, 0.000000, 0.000000>,
PSYS_SRC_ANGLE_BEGIN, 0.000000,
PSYS_SRC_ANGLE_END, 0.000000,
PSYS_SRC_BURST_PART_COUNT, 1,
PSYS_SRC_BURST_RATE, 0.750000,
PSYS_SRC_BURST_RADIUS, 0.000000,
PSYS_SRC_BURST_SPEED_MIN, 0.500000,
PSYS_SRC_BURST_SPEED_MAX, 0.500000,
PSYS_SRC_OMEGA, <0.000000, 0.000000, 0.000000>,
PSYS_SRC_TARGET_KEY,(key)"", 
PSYS_SRC_TEXTURE, "c0ceae16-cad3-be86-ea1f-66b8c52a595a"]);
}    

default
{
    state_entry()
    {
        arrows();
    }

}

 It´s sending particles from a prim in a direction.

It is possible to set a UUID target but if I copy the set this is no help because the UUIDs change.

Has anybody an idea how I can tell the script that the particles should be sent to a prim with a certain description or name and maybe only within a certain range?

 

This would be such a great help for me - thanks in advance.

 

Kind Regards

Link to comment
Share on other sites

  1. Modify your arrow() function to allow you to pass it a key.  Example:  arrow(key id) instead of arrow(), then use "id" in your target setting in the llParticleSystem statement:  PSYS_SRC_TARGET_KEY, id,
  2. You'll need to turn on the PSYS_PART_TARGET_LINEAR_MASK or PSYS_PART_TARGET_POS_MASK in your arrow function's llParticleSystem statement, depending on if you want a direct route or a gradual route to your target.
  3. Then you need to know the target's key.  You can use a sensor to acquire nearby objects within a range, using llSensor for a single detect or llSensorRepeat for repeated detections (you can also use llSensor with a timer for more control).  You can also use the name setting in your llSensor/llSensorRepeat statement to sense a particular object's name, which allows you to pull the key for only that object.
  4. In the sensor event, use a loop to cycle through the detected objects and compare llDetectedName(x) to your desired target and point the particles to the new llDetectedKey(x) by specifying arrows(llDetectedKey(x)).

 

Below is a very simple example of how it's done.  This only runs the sensor once, searching for passive objects (non-scripted, not active or physical; doing nothing, being nothing), to detect the name "My Object" within a 10m range, 360 degrees (PI) around the object.  If not detected it lets you know with a whisper.  Note the llSensor event specifies the name we're looking for, which narrows the sensor down to that particular object name.  All other objects are ignored.

 

string name = "My Object";arrow(key id){    llParticleSystem([    PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_SRC_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_TARGET_LINEAR_MASK | PSYS_PART_TARGET_POS_MASK,    PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,     PSYS_PART_START_ALPHA, 1.000000,    PSYS_PART_END_ALPHA, 1.000000,    PSYS_PART_START_COLOR, <1.000000, 1.000000, 1.000000>,    PSYS_PART_END_COLOR, <1.000000, 1.000000, 1.000000>,    PSYS_PART_START_SCALE, <0.250000, 0.250000, 0.00000>,    PSYS_PART_END_SCALE, <0.250000, 0.250000, 0.000000>,    PSYS_PART_MAX_AGE, 10.000000,    PSYS_SRC_MAX_AGE, 0.000000,    PSYS_SRC_ACCEL, <0.000000, 0.000000, 0.000000>,    PSYS_SRC_ANGLE_BEGIN, 0.000000,    PSYS_SRC_ANGLE_END, 0.000000,    PSYS_SRC_BURST_PART_COUNT, 1,    PSYS_SRC_BURST_RATE, 0.750000,    PSYS_SRC_BURST_RADIUS, 0.000000,    PSYS_SRC_BURST_SPEED_MIN, 0.500000,    PSYS_SRC_BURST_SPEED_MAX, 0.500000,    PSYS_SRC_OMEGA, <0.000000, 0.000000, 0.000000>,    PSYS_SRC_TARGET_KEY, id,     PSYS_SRC_TEXTURE, "c0ceae16-cad3-be86-ea1f-66b8c52a595a"

]); }default{ state_entry() { llSensor(name,"", PASSIVE, 10.0, PI); } sensor(integer objects_found) { if (objects_found) arrow(llDetectedKey(0)); } no_sensor() { llWhisper(0,"'"+name+"' not found."); }}

 

Another example using llSensorRepeat instead and detecting all passive objects, then using a for loop in the sensor event to search for the name "My Object" in the results:

 

string name = "My Object"; // Name of object to detect

float sensor_interval = 5.0; // Sensor detects objects ever x seconds

float sensor_range = 10.0; // Range in meters

 

arrow(key id)

{

    llParticleSystem([

    PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_SRC_MASK |

PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_INTERP_COLOR_MASK |

PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_TARGET_LINEAR_MASK | PSYS_PART_TARGET_POS_MASK,

    PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,

    PSYS_PART_START_ALPHA, 1.000000,

    PSYS_PART_END_ALPHA, 1.000000,

    PSYS_PART_START_COLOR, <1.000000, 1.000000, 1.000000>,

    PSYS_PART_END_COLOR, <1.000000, 1.000000, 1.000000>,

    PSYS_PART_START_SCALE, <0.250000, 0.250000, 0.00000>,

    PSYS_PART_END_SCALE, <0.250000, 0.250000, 0.000000>,

    PSYS_PART_MAX_AGE, 10.000000,

    PSYS_SRC_MAX_AGE, 0.000000,

    PSYS_SRC_ACCEL, <0.000000, 0.000000, 0.000000>,

    PSYS_SRC_ANGLE_BEGIN, 0.000000,

    PSYS_SRC_ANGLE_END, 0.000000,

    PSYS_SRC_BURST_PART_COUNT, 1,

    PSYS_SRC_BURST_RATE, 0.750000,

    PSYS_SRC_BURST_RADIUS, 0.000000,

    PSYS_SRC_BURST_SPEED_MIN, 0.500000,

    PSYS_SRC_BURST_SPEED_MAX, 0.500000,

    PSYS_SRC_OMEGA, <0.000000, 0.000000, 0.000000>,

    PSYS_SRC_TARGET_KEY, id,

    PSYS_SRC_TEXTURE, "c0ceae16-cad3-be86-ea1f-66b8c52a595a"]);

}

 

default

{

    state_entry()

    {

        llParticleSystem([]); // Remove particles if they exist

        

        // Depending on your object type, you may use ACTIVE and/or SCRIPTED instead of PASSIVE.

        // In this case we're detecting PASSIVE, which are non-scripted objects that are inactive

// and non-physical. PI (3.14; 360 degrees) is the arc of detection.

 

        llSensorRepeat("","", PASSIVE, sensor_range, PI, sensor_interval);

    }

 

    sensor(integer objects_found) // objects_found = number of sensed objects returned.

    {

// Sensor returns a list of detected objects from 0 to objects_found-1 (max 16; 0-15).

// We can reference information about the detected objects via llDetect functions.

// In this example we use llDetectedName(number) to reference the name of

// one of the objects.

 

        integer loop_counter; // Set up an integer to count from 0 to objects_found.

        

        // Loop through each of the detected objects in sequential order from 0 to objects_found-1.

// Use llDetectedName(loop_counter) to compare current detected object against name.

// Check to see if we've reached the end. If not, add +1 to loop_counter and continue.

 

        for(loop_counter = 0; loop_counter < objects_found; loop_counter++)

        {

 

// Does this particular object's name match our name?

// Use llToLower to negate case sensitivity with lowercase.

 

            if (llToLower(llDetectedName(loop_counter)) == llToLower(name))

            {

                llWhisper(0,"'" + name + "' found.  Target set.");

                arrow(llDetectedKey(loop_counter)); // Set our particle target; turn on particles.

                llSensorRemove(); // Stop sensor, also negates all sensor results.

                return; // Exit for loop and sensor event and go idle.

            }

        }

        

        // Not found after checking all sensed objects

// Note that this whisper repeats until object is found, for testing purposes.

 

        llWhisper(0,"'" + name + "' not found.  Continuing to search.");

        llSensorRepeat("","", PASSIVE, sensor_range, PI, sensor_interval); // Restart sensor

    }

    

    no_sensor()

    {

        // Unless you're in a place where no objects exist (per

        // your specified type), this event will never be triggered.

    }

}

 

These examples should get you started.  You can just as easily set the script to sense avatars instead using AGENTS_BY_LEGACY_NAME as the type, for instance.  See llSensor and llSensorRepeat in the wiki for more info (links to those at the top of this page).

 

NOTE:  Each prim has its own particle emitter and can only have one target.  If the object being targeted no longer exists, the particle emission stops.  Sensors only return the closest 16 objects.

Link to comment
Share on other sites

Works fine ;)

One more question if you allow...

If the target object (where the arrows point to) is attached to an avatar (worn) than the sender can´t find it´s name right?

Is there a simple solution for this problem?

Link to comment
Share on other sites

Thanks :)

 

But with (AGENT_BY_LEGACY_NAME|PASSIVE) I have to enter the avatars name so I cannot give the prim to someone by using a giver script (without editing the script).

The arrows should also hit the worn prim directly and not the pelvis of the avatar ;)

Can I place a small script in the target prim which the sender can find to send the arrows to the prim with the "target-script" in it?

Link to comment
Share on other sites

Oh.   No, if you set your sensor to scan for AGENT_BY_LEGACY_NAME it will locate the center of the avatar -- somewhere near the av's belly button.  If you want to locate an attached target, you'll have to use a completely different method.  One way, perhaps the best way, is to put a pinging script in the attachment that broadcasts a "Here I am" signal every few seconds for your particle script to hear.

Link to comment
Share on other sites

Do you think it could be possible by listening to a defined channel in the chat or would that be overkill?

The script itself could still be used I guess only the method the loop is using must change to a "listening to channel /86654" or so... I tried to find an example script but I haven´t found one yet :).

Any Ideas how a simple sender / reciever script which works with a chat channel could look like (comparable with the sensor methode)?

Any help is very very welcome :o)

Link to comment
Share on other sites

That's exactly what I was suggesting.  Send your ping message with llRegionSay (or llRegionSayTo) on a channel of your choice and simply receive it in your particle script. Handle the detected ping the same way that you are handling a sensor ping now, only with a listen event instead of a sensor event.

Link to comment
Share on other sites

An example of how to do it.

The emitter_name and object_name strings should be the unique and set in both scripts or it won't work.

The emitter object names itself "My Emitter" as per the emitter_name string.  The emitter listens for a chat message from an object named "My Object" (as set in object_name), containing the text object_name+"@".  If that test passes, anything after @ is assumed to be a key.  The key is tested first in case the message doesn't contain a valid key.  If valid, the key is used to point particles to the attached object.

 

// This goes in your emitter object.  string emitter_name = "My Emitter"; // Name of emitter object to detect.
string object_name = "My Object"; // The name of the attached objectfloat sensor_interval = 5.0; // Sensor detects objects ever x seconds.float sensor_range = 10.0; // Range in meters.integer chat_channel = -86654; // Our script-to-script chat channel.arrow(key id){ llParticleSystem([ PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_FOLLOW_SRC_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_TARGET_LINEAR_MASK | PSYS_PART_TARGET_POS_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE, PSYS_PART_START_ALPHA, 1.000000, PSYS_PART_END_ALPHA, 1.000000, PSYS_PART_START_COLOR, <1.000000, 1.000000, 1.000000>, PSYS_PART_END_COLOR, <1.000000, 1.000000, 1.000000>, PSYS_PART_START_SCALE, <0.250000, 0.250000, 0.00000>, PSYS_PART_END_SCALE, <0.250000, 0.250000, 0.000000>, PSYS_PART_MAX_AGE, 10.000000, PSYS_SRC_MAX_AGE, 0.000000, PSYS_SRC_ACCEL, <0.000000, 0.000000, 0.000000>, PSYS_SRC_ANGLE_BEGIN, 0.000000, PSYS_SRC_ANGLE_END, 0.000000, PSYS_SRC_BURST_PART_COUNT, 1, PSYS_SRC_BURST_RATE, 0.750000, PSYS_SRC_BURST_RADIUS, 0.000000, PSYS_SRC_BURST_SPEED_MIN, 0.500000, PSYS_SRC_BURST_SPEED_MAX, 0.500000, PSYS_SRC_OMEGA, <0.000000, 0.000000, 0.000000>, PSYS_SRC_TARGET_KEY, id, PSYS_SRC_TEXTURE, "c0ceae16-cad3-be86-ea1f-66b8c52a595a"]); }default{ state_entry() {
llSetObjectName(emitter_name); // Ensure the object is named correctly. llParticleSystem([]); // Remove particles if they exist. // Start a listen for messages from "My Object. llListen(chat_channel,object_name,"",""); } listen(integer channel, string name, key id, string message) { // Look for object_name+"@" in message. If not, it's not one we want. // @ is a separator between the expected recieved phrase and the key. // (see the attachment script) if (llSubStringIndex(message,object_name+"@")>-1) { // Pull our key from the location of @ + 1 position to the end of string. string target_key = llGetSubString(message,llSubStringIndex(message,"@")+1,-1); if ((key)target_key) // Returns true if it's a good key. { arrow(target_key); // Set our particle target; turn on particles. } } }}

 

Attached object script:

Note that the sensor is hard set to look for the string emitter_name ("My Emitter").  This limits the scope of the sensor for maximum efficiency.  The sensing interval is set to every 5 seconds.  If "My Emitter" is detected within 10 meters, it sends a chat message.  The chat message is hard set to object_name+"@"+(string)llGetKey().    The object MUST BE ATTACHED TO AN AVATAR for the sensor to activate and work.

 

// This script goes in your attachment object.

string emitter_name = "My Emitter"; // Name of emitter object to detect.
string object_name = "My Object"; // The name of the attached object
float sensor_interval = 5.0; // Sensor detects objects ever x seconds.
float sensor_range = 10.0; // Range in meters.
integer chat_channel = -86654; // Chat channel for script-to-script communication.
integer toggle; // Our on/off switch for the chat message.

default
{
state_entry()
{
llSetObjectName(object_name); // Ensure our object is named correctly.
}

    attach(key avatar)
    {
        if (avatar) // Attached, start sensor
        {
llSensorRemove(); // Stop previous sensor from last detach, clear any leftovers.
            toggle = FALSE; // Flip our switch off to enable messaging again.

// Restart sensor.
            llSensorRepeat(emitter_name,"", PASSIVE | SCRIPTED, sensor_range, PI, sensor_interval);
        }
    }
    
    sensor(integer objects_found)
    {
        // If this event is triggered, we found an object named "My Emitter".
        // Send the trigger message to receive an arrow pointing to the object.
        
        if (toggle == FALSE) // Keeps from having repeated chat messages.
        {
            // Send our chat message to enable pointer arrow.
            llRegionSay(chat_channel, object_name+"@"+(string)llGetKey());
            toggle = TRUE; // Message was sent. Flip our switch on.
        }
    }
    
    no_sensor() // We've left the area; My Emitter not detected any more.
    {
        if (toggle == TRUE) toggle = FALSE; // Flip switch off, in case we find My Emitter again.
    }
}

 

NOTES:  If there's no way to get around having a constant listen or sensor in a script, limit its scope as much as possible for efficiency.  In these examples we're listening for "My Object" to send a message and our sensor will only detect an object named "My Emitter".  In this way we're only getting valid messages and we're only detecting a valid object.  We further limit script run-time by making sure they're as idle as possible, using a slower detect time of 5.0 seconds and an integer as a switch to keep from having any unnecessary code to process if we don't have to.

Link to comment
Share on other sites

OMG, you are really the greatest - *blushes a bit*

Thanks for your time and work - I really appreciate that!

It works really great as long as the sender is not worn.

I will try if my Idea is also possible with the sender as a not attached prim.

I really underestimated the effort to make a script which connects two worn prims with particle arrows :)

I´m so happy that you both helped me out with this scripting... I really need to learn so much more ;)

Link to comment
Share on other sites

You're welcome.

Your description didn't specify two attached prims, so the first set was for two rezzed prims, then you said one attached, so I changed it to one attached.  lol  Had I known you wanted two scripted attachments, one the emitter and one the receiver, I would've written the scripts differently.  As it is, everything you need to achieve what you want is within these scripts.  You might have to mod them a bit, but the code is there. 

I've done most of the work.  I'm leaving it in your hands.

Link to comment
Share on other sites

Yes, I should have written a better description you are absolutely right :) Thanks for all your work.

 

I guess I will have to mod the last code so that they ping each other and not only one the other.

I will try to integrate the sender script in the reciever script and the reciever script in the sender script.

Please only warn me if I´m wrong ;D

 

Link to comment
Share on other sites

You have the right idea, although you might have to keep track of the object keys involved if you don't want them to send arrows to each other at the same time.  In other words, if one detects the other and sends out a notification, it keeps that key and knows not to send an arrow to it in return.

Link to comment
Share on other sites

llSensor/llSensorRepeat can't detect attachments.  The scripts have worked so far because one has always been in-world (not attached to an avatar).

Since you can't detect attachments with a sensor, you have to resort to other methods. 

One possible scenario:

---

Chat negotiation, where two attachements negotiate with each other for arrows.

Since you can't detect attachments using a sensor, you must spam chat to find other attachments to negotiate with.  This can be limited by using a sensor to only send out chat negotiations when avatars are detected within a certain range (AGENT_BY_LEGACY_NAME instead of PASSIVE | SCRIPTED).  You can further limit chat spam by adding in pauses between sending chat messages.

Chat negotiation would work fine between two attachments where each receives a message to send arrows to the target.  It's when you have a third attachment (third avatar) or a whole group of attachments that we run into chaos.  Attachments will fight each other.  Arrows will go from one to another based on what attachement received what message first.  Then when the chat spam continues (because it will since you're detecting avatars), arrows will change targets.  It'll be a mess.  Since all attachments are created equal, there has to be master/slave relationships, otherwise your scripts will be fighting each other.  An easy fix would be to allow the avatar to select who they want to target with the attachment via dialog menu.  You could also use script states to compartmentalize negotiation/listen/sensor/chat.  Keeping track of avatars or attachments (or both) that are negotiating/being interacted with might help keep things in check

Once negotiation happens and is locked in, all further communications would need to be shut off until there are no avatars around.  You can accomplish this by removing the listen and stopping the script from sending out chat messages.  Then, in the no_sensor() event, when no avatars are detected, drop the current target and turn chat back on for a new negotiation.

Particles can only have one target at a time.  Therefore, you can only target one attachment to another at any given time, unless your object has multiple prims, which can then be used to target multiple attachments using llLinkParticleSystem.  This opens up a whole new can of exponential worms.

---

Maybe someone else will have some input.  My brain doesn't want to work today.  I'm running on one or two cylinders. lol

Sounds like you have your work cut out for you.  Only you know what you're trying to design and what the parameters are.  I tried to help as best I could with the descriptions you gave, as you gave them, but there is no clear picture as to exactly what you're aiming for with this project.  Each of your posts has been a little more revealing, but it's not enough to form a definite direction for what you want.  I'm glad to help with the process, but I won't write the project for you, that's not what this forum is for. 

If you have further questions and need help, post your code and we'll do what we can.  Please make sure you're being completely descriptive in the functionality you're looking for.

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 3583 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...