Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Special Sensor Apparatus: Points and emits particles at a target.

Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
03-21-2004 00:15
Hello everyone!
In responce from popular demand in this thread, I created an apparatus to point at and emit particles at a sensed target. This is useful if you want to easily find an object via a visual cue.

This apparatus requires 17 objects, one brain object, the parent of the linked set, and 16 pointer objects.

See the attachment for an example of the setup. (The white cube is the brain, the cones are the pointers).

Scripts

The Brain Script:

CODE

// Special Particle Sensor "Brain" Script
// Written by Christopher Omega
//
// Tasks:
// Listen to the owner.
// Parse the owner's message,
// Signal individual locators to reset
// Or point at a certain object within
// 96 meters of the apparatus.

// Global Variables
// targetName Stores the name of the object that's being looked for.
string targetName = "";

// Global Constants
// LOCATOR_ALL_LOCATORS A constant defining when the message sent by this script is meant for all locators.
integer LOCATOR_ALL_LOCATORS = -1;

// SENSOR_TYPE_ALL A constant that tells the sensor to look for (ACTIVE|PASSIVE|AGENT).
// 7 is just the integer form of (ACTIVE|PASSIVE|AGENT)
integer SENSOR_TYPE_ALL = 7;

// SENSOR_MAX_RANGE A constant defining the max. range of the sensor to run. As of SL v1.2.13, it is 96.0 meters.
float SENSOR_MAX_RANGE = 96.0;

// MESSAGE_PARAMETER_SEPERATOR A constant that is used as a seperator in parsing lists sent as strings.
string MESSAGE_PARAMETER_SEPERATOR = "|~|";

// strStartsWith()
// Returns a boolean-integer that tells if the string starts with the prefix.
// @param str The string to search.
// @param prefix The prefix of str to find.
// @return TRUE or FALSE, if str starts with prefix.
integer strStartsWith(string str, string prefix) {
return (llSubStringIndex(str, prefix) == 0);
}

// contactLocator()
// Sends a message to the locators.
// @param locatorNumber The number identifyer of the locater to send the message to. LOCATOR_ALL_LOCATORS to send to all.
// @param parameters The parameters to send to the locator.
// @param command The command to send to the locator.
contactLocator(integer locatorNumber, string parameters, string command) {
integer linkNumber = locatorNumber + 2;

if(locatorNumber == LOCATOR_ALL_LOCATORS) linkNumber = LINK_ALL_OTHERS;

llMessageLinked(linkNumber, 0, parameters, command);
}

// pointLocatorAt()
// Sends a message to the locator specified by locatorNumber
// Telling it to point itself and its particle system at a
// target defined by targetId and targetPosition.
// @param locatorNumber The particle emitter to tell to point.
// @param targetId The UUID (key) of the target to point at.
// @param targetPosition The position, in region-local coordinates, of the target.
pointLocatorAt(integer locatorNumber, key targetId, vector targetPosition) {
list paramList = [targetId, targetPosition];
contactLocator(locatorNumber, llDumpList2String(paramList, MESSAGE_PARAMETER_SEPERATOR), "POINT_AT");
}

// resetLocator()
// Kills the particle system emininating from the locator defined by locatorNumber.
// @param locatorNumber The particle emitter in which to shut off. LOCATOR_ALL_LOCATERS to turn off all.
resetLocator(integer locatorNumber) {
contactLocator(locatorNumber, "", "RESET"); // Turn off the particles.
}

default {
state_entry() {
llSay(0, "Running.");
llListen(0, "", llGetOwner(), "");
resetLocator(LOCATOR_ALL_LOCATORS);
}
listen(integer chan, string name, key id, string msg) {
if (strStartsWith(msg, "#reset")) {
llSensorRemove();
resetLocator(LOCATOR_ALL_LOCATORS);
}
else if (strStartsWith(msg, "#find ")) {
resetLocator(LOCATOR_ALL_LOCATORS);

targetName = llDeleteSubString(msg, 0, 5); // Delete "#find " from msg

llSensor(targetName, NULL_KEY, SENSOR_TYPE_ALL, SENSOR_MAX_RANGE, TWO_PI);
llSay(0, "Searching for " + targetName);
}
}
no_sensor()
{
llSay(0, targetName + " not found within a distance of "
+ (string) SENSOR_MAX_RANGE + " meters.");

llSensorRemove();
}
sensor(integer numDetected) {
integer i;
for (i = 0; i < numDetected; i++) {
key targetKey = llDetectedKey(i);
vector targetPos = llDetectedPos(i);
llSay(0, targetName + " found at " + (string) targetPos
+ " with key " + (string) targetKey);
pointLocatorAt(i, targetKey, targetPos);
}
}
}


The pointers' script:
(put one of these in every pointer)
CODE

//=========================Particle stuff==========================
// Particle Script 0.4
// Created by Ama Omega
// 3-7-2004

// Mask Flags - set to TRUE to enable
integer glow = FALSE; // Make the particles glow
integer bounce = FALSE; // Make particles bounce on Z plane of object
integer interpColor = TRUE; // Go from start to end color
integer interpSize = TRUE; // Go from start to end size
integer wind = FALSE; // Particles effected by wind
integer followSource = TRUE; // Particles follow the source
integer followVel = TRUE; // Particles turn to velocity direction

// Choose a pattern from the following:
// PSYS_SRC_PATTERN_EXPLODE
// PSYS_SRC_PATTERN_DROP
// PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY
// PSYS_SRC_PATTERN_ANGLE_CONE
// PSYS_SRC_PATTERN_ANGLE
integer pattern = PSYS_SRC_PATTERN_DROP;

// Select a target for particles to go towards
// "" for no target, "owner" will follow object owner
// and "self" will target this object
// or put the key of an object for particles to go to
key target = "owner";

// Particle paramaters
float age = 5; // Life of each particle
float maxSpeed = 0.1; // Max speed each particle is spit out at
float minSpeed = 0.1; // Min speed each particle is spit out at
string texture; // Texture used for particles, default used if blank
float startAlpha = 1; // Start alpha (transparency) value
float endAlpha = 1; // End alpha (transparency) value
vector startColor = <1,1,1>; // Start color of particles <R,G,B>
vector endColor = <1,1,1>; // End color of particles <R,G,B> (if interpColor == TRUE)
vector startSize = <.25,.25,.25>; // Start size of particles
vector endSize = <.25,.25,.25>; // End size of particles (if interpSize == TRUE)
vector push = <0,0,0>; // Force pushed on particles

// System paramaters
float rate = .1; // How fast (rate) to emit particles
float radius = 1; // Radius to emit particles for BURST pattern
integer count = 1; // How many particles to emit per BURST
float outerAngle = 1.54; // Outer angle for all ANGLE patterns
float innerAngle = 1.55; // Inner angle for all ANGLE patterns
vector omega = <0,0,0>; // Rotation of ANGLE patterns around the source
float life = 0; // Life in seconds for the system to make particles

// Script variables
integer pre = 2; //Adjust the precision of the generated list.

integer flags;
list sys;
integer type;
vector tempVector;
rotation tempRot;
string tempString;
integer i;

string float2String(float in)
{
return llGetSubString((string)in,0,pre - 7);
}

updateParticles()
{
flags = 0;
if (target == "owner") target = llGetOwner();
if (target == "self") target = llGetKey();
if (glow) flags = flags | PSYS_PART_EMISSIVE_MASK;
if (bounce) flags = flags | PSYS_PART_BOUNCE_MASK;
if (interpColor) flags = flags | PSYS_PART_INTERP_COLOR_MASK;
if (interpSize) flags = flags | PSYS_PART_INTERP_SCALE_MASK;
if (wind) flags = flags | PSYS_PART_WIND_MASK;
if (followSource) flags = flags | PSYS_PART_FOLLOW_SRC_MASK;
if (followVel) flags = flags | PSYS_PART_FOLLOW_VELOCITY_MASK;
if (target != "") flags = flags | PSYS_PART_TARGET_POS_MASK;
sys = [ PSYS_PART_MAX_AGE,age,
PSYS_PART_FLAGS,flags,
PSYS_PART_START_COLOR, startColor,
PSYS_PART_END_COLOR, endColor,
PSYS_PART_START_SCALE,startSize,
PSYS_PART_END_SCALE,endSize,
PSYS_SRC_PATTERN, pattern,
PSYS_SRC_BURST_RATE,rate,
PSYS_SRC_ACCEL, push,
PSYS_SRC_BURST_PART_COUNT,count,
PSYS_SRC_BURST_RADIUS,radius,
PSYS_SRC_BURST_SPEED_MIN,minSpeed,
PSYS_SRC_BURST_SPEED_MAX,maxSpeed,
PSYS_SRC_TARGET_KEY,target,
PSYS_SRC_INNERANGLE,innerAngle,
PSYS_SRC_OUTERANGLE,outerAngle,
PSYS_SRC_OMEGA, omega,
PSYS_SRC_MAX_AGE, life,
PSYS_SRC_TEXTURE, texture,
PSYS_PART_START_ALPHA, startAlpha,
PSYS_PART_END_ALPHA, endAlpha
];

llParticleSystem(sys);
}
//=========================End Particle stuff==========================

// Special Particle Sensor Particle Emitter Script
// Written by Christopher Omega
//
// Tasks:
// Process commands sent by the 'brain':
// Turn off the particle system case "RESET"
// Point at, and emit particle system at target case "POINT_AT".

// Global Constants
// MESSAGE_PARAMETER_SEPERATOR A constant that is used as a seperator in parsing lists sent as strings.
string MESSAGE_PARAMETER_SEPERATOR = "|~|";

// AXIS_* constants, represent the unit vector 1 unit on the specified axis.
vector AXIS_UP = <0,0,1>;
vector AXIS_LEFT = <0,1,0>;
vector AXIS_FWD = <1,0,0>;

// SetLocalRot
// In a linked set, points a child object to the rotation.
// @param rot The rotation to rotate to.
SetLocalRot(rotation rot)
{
if(llGetLinkNumber() > 1)
{
rotation locRot = llGetLocalRot();
locRot.s = -locRot.s; // Invert local rot.

rotation parentRot = locRot * llGetRot();
parentRot.s = -parentRot.s; // Invert parent's rot.

llSetRot(rot * parentRot);
}
}

// getRotToPointAxisAt()
// Gets the rotation to point the specified axis at the specified position.
// @param axis The axis to point. Easiest to just use an AXIS_* constant.
// @param target The target, in region-local coordinates, to point the axis at.
// @return The rotation necessary to point axis at target.
rotation getRotToPointAxisAt(vector axis, vector target)
{
return llGetRot() * llRotBetween(axis * llGetRot(), target - llGetPos());
}


// pointAt
// Points up axis at targetPos, and emits a particle system at targetKey.
// @param targetKey The UUID of the target to emit particles to.
// @param targetPos The poaition of the target in region-local coordinates.
pointAt(key targetKey, vector targetPos)
{
SetLocalRot(getRotToPointAxisAt(AXIS_UP, targetPos));
target = targetKey;
startColor = llGetColor(-1);
endColor = llGetColor(-1);
updateParticles();
}


default {
state_entry() {
llParticleSystem([]);
SetLocalRot(<0,0,0,1>);
}
link_message(integer sender, integer n, string parameters, key command) {
if(command == "RESET") {
SetLocalRot(<0,0,0,1>);
llParticleSystem([]);
}
else if(command == "POINT_AT") {
list parsedParameters = llParseString2List(parameters, [MESSAGE_PARAMETER_SEPERATOR], []);
key targetKey = (key)llList2String(parsedParameters, 0);
vector targetPos = (vector)llList2String(parsedParameters, 1);

pointAt(targetKey, targetPos);
}
}
}


To activate the apparatus:

Say

#find <objectName>

Examples:
#find Object
Emits particles and points at all things within range named "Object".

#find Christopher Omega
Emits particles and points at all things within range named "Christopher Omega"

Say:
#reset
To reset the particle emitters to their default rotations, and turn off their particle systems.

Enjoy :)

==Chris
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
03-21-2004 16:32
Oops! Forgot the attachment :D
Remo Yossarian
Registered User
Join date: 15 Feb 2004
Posts: 121
Original Thread
03-23-2004 07:50
edit-/15/32/11177/1.html

=====
Back to original post
=====

I tried it just to get a better understanding of sensors and passing sensor targets.

Thanks Christopher, it works great.

Sometimes the follower pointers won't de-rez with the shout command, but I imagine that is network related, and not your code.
Drizzt Naumova
Teh Foxeh DJ
Join date: 9 Oct 2005
Posts: 116
02-04-2006 15:21
i have used this script as well, but i have a question..i am not well versed in scripting, but i do know that there is a way to search for and object or avatar by using only the first 3 letters of the object or avatar name. how would that fit into the script? That would simplify things ALOT and give this particular script much more flexibility instead of it searching for an "exact" object name or avatar name. if anyone or the creator would be willing to share their knowledge, it would be a great help, as i have a fairly large plot of land and a couple people living there, so if something went missing, and they knew at least the first name or first 3 letter of what they or I am searching for, it would help out greatly. I use this particular script for personal use only and to help others out when they lose things lol..Kinda like being a hire for free prim sleuth ;)