Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

AV Detector?

Lallander Parvenu
Registered User
Join date: 21 Apr 2005
Posts: 45
11-27-2005 16:43
Hi all, I am trying to track down an open source AV detector. Not just one that says who is around but one of the ones that spawns little spheres to display in 3D there position. The one that I have, and the only one I can seem to find any reference to in game, rezzes no copy no mod objects.

If someone can hook me up that would be grand XD
Kevn Klein
God is Love!
Join date: 5 Nov 2004
Posts: 3,422
11-27-2005 16:50
From: Lallander Parvenu
Hi all, I am trying to track down an open source AV detector. Not just one that says who is around but one of the ones that spawns little spheres to display in 3D there position. The one that I have, and the only one I can seem to find any reference to in game, rezzes no copy no mod objects.

If someone can hook me up that would be grand XD


There is one for you :)

I hope that's what you want.

The avicon seems to be closed, but the main script that spawns the avicon is open.
DoctorMike Soothsayer
He's not a real doctor.
Join date: 3 Oct 2005
Posts: 113
Me too
11-28-2005 05:30
From: Kevn Klein
There is one for you :)


Where, where? Me too!
_____________________
Performance Artist and educator
"Thinking outside the Prim"
Lallander Parvenu
Registered User
Join date: 21 Apr 2005
Posts: 45
11-28-2005 06:28
From: Lallander Parvenu
The one that I have, and the only one I can seem to find any reference to in game, rezzes no copy no mod objects.



Uhm yeah, so does anyone have one that is open source?
Lallander Parvenu
Registered User
Join date: 21 Apr 2005
Posts: 45
11-29-2005 10:11
Shameless bump to keep my as of yet unanswered question on the front page.
Yumi Murakami
DoIt!AttachTheEarOfACat!
Join date: 27 Sep 2005
Posts: 6,860
11-29-2005 10:27
From: Lallander Parvenu
Shameless bump to keep my as of yet unanswered question on the front page.


Well, I thought it was such a cool idea I'm trying to write one. :)
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
11-29-2005 10:31
From: Yumi Murakami
Well, I thought it was such a cool idea I'm trying to write one. :)


lol. I was thinking the same thing. it shouldn't be all that hard. just us a sensor, and then spawn a sphere or object relative to where the "map" prim is. the code itself shouldn't be all that hard to piece together. I may construct one such thing later on today and post it.
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
11-29-2005 11:41
I have a simple version of what you're asking for, but still haven't gotten it to label the markers with names right yet, so currently it just shows distance. It's up and running at 131,137 in sandbox cordova

***Place this script in a cylinder with dimensions 3x3x.01***
CODE

list gAvs = []; //sets up our info for creating a list of avatars sensed and thier position
list gpos = [];
integer gMarker = 0;

default
{
state_entry()
{
llSensorRepeat("",NULL_KEY,AGENT,96,PI,1); //sets up the sensor. since we want it to update fairly regularly I have it set at 1 second
}

sensor(integer total_number)
{
gAvs = []; //sets the lists to null set to stop stack heap collisions
gpos = [];
llSetText((string) total_number + " Avatars Found",<1,1,1>,1); //displays how many avtars were found.
integer i;
for ( i = 0; i < total_number; i++) //loop to create our lists.
{
gAvs = gAvs + [llDetectedName(i)];
gpos = gpos + [llDetectedPos(i)];
}
for ( i = 0; i < total_number; i++) //loop to rez the marker object at the appropriate spot. note the divisor 64 in the rezpos. that is so that the 96m radius will fit on a 3m diameter (1.5m radius) disc. if you wish to use a different size "map" then you should adjust this value accordingly.
{
vector rezpos =(-llGetPos() + llList2Vector(gpos,i))/64;
vector rezat = (rezpos + llGetPos());
float dist = llVecDist(llList2Vector(gpos,i),llGetPos());
llRezObject("Marker",rezat,ZERO_VECTOR,ZERO_ROTATION,llRound(dist));
}
}

no_sensor()
{
llSetText("No Avatars Found",<1,1,1>,1);
}
}




***Place this script in a small prim named "Marker" (about .1x.1x.1) inside the main disc***
CODE

default
{
state_entry()
{
}

on_rez(integer distance)
{
distance = llGetStartParameter(); //gets the distance away from the map that is sent when this object is rezzed
llSetText((string) distance + "m",<0,1,0>,1); //sets the text on the marker to show how far away the avtar is in the world.
llSleep(7); //delay in the script before killing the marker. this number should be changing depending on the number of avatars sensed, since with less than 3 avatars a value of 3 works smoothly, but when dealing with 15-20 values around 7 or 8 appear to be smooth.
llDie();
}
}
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
11-29-2005 11:54
From: someone
***Place this script in a small prim (about .1x.1x.1) inside the main disc***


... and make sure that prim is called "Marker" :)

Your sensor repeats every second, and the markers live for 7 seconds. I think you'll build up prims over time. I'd put them both to the same timeout, maybe even kill the prims a little before the next sensor scan.

Names will be a little complex. One way to do it would be to have each marker open a listener on a known channel. Send the marker objects their ID in the on_rez parameter, the ID being a number from 1 to 16. Then the main script can rez the objects, wait a second, and llSay the ID, name and distance on that channel. Each object picks up the chat and parses the string, and if it finds the ID matching its own, it pulls the name and distance from the chat message and llSetText's that info.

Another solution - rez 16 markers at the beginning, and the markers don't die. Each marker, on rez, stores its rez location as the 'origin'. Do the same thing with listeners and chat, except this time the main script also sends out the location. Each marker picks up its message and moves to the specified offset from the origin, and sets text for name/distance. Use some special code to indicate "no one present", and the marker turns invisible (since there won't always be 16 avs in range), and then turns visible again if it picks up a valid message for its ID.
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
11-29-2005 12:34
From: Ziggy Puff
... and make sure that prim is called "Marker" :)

Your sensor repeats every second, and the markers live for 7 seconds. I think you'll build up prims over time. I'd put them both to the same timeout, maybe even kill the prims a little before the next sensor scan.

Names will be a little complex. One way to do it would be to have each marker open a listener on a known channel. Send the marker objects their ID in the on_rez parameter, the ID being a number from 1 to 16. Then the main script can rez the objects, wait a second, and llSay the ID, name and distance on that channel. Each object picks up the chat and parses the string, and if it finds the ID matching its own, it pulls the name and distance from the chat message and llSetText's that info.

Another solution - rez 16 markers at the beginning, and the markers don't die. Each marker, on rez, stores its rez location as the 'origin'. Do the same thing with listeners and chat, except this time the main script also sends out the location. Each marker picks up its message and moves to the specified offset from the origin, and sets text for name/distance. Use some special code to indicate "no one present", and the marker turns invisible (since there won't always be 16 avs in range), and then turns visible again if it picks up a valid message for its ID.


because of some kind of inherrent delay in the script when an object is rezzed, there is little to no overlap with the long delay between the die command, and the short sensor repeat. also, I have the Marker prim set as temp on rez so that if you do incorperate this into your store/homestead, the many rezed markers don't count towards your prim limit.

I was thinking of passing on a chat channel number to each marker as it's rezzed and then having it listen on that channel for the key as you, but I'm being lazy at the moment and just letting it stand as is. :P
Lallander Parvenu
Registered User
Join date: 21 Apr 2005
Posts: 45
11-29-2005 15:05
Wow, that was actually a lot faster then I thought it would be.

Works great so far from what I can tell.

Thank's a ton.

Now I can't wait to see what Yumi comes up with. n_n
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
11-30-2005 03:01
Damn - I saw the first post on this thread a while back, thought "that sounds like an interesting idea, I'll have a go at doing that" and I come back and it's going to look like I've just copied all the above.

I did similar things to all of that. I have "smart dots" (the markers) that llListen to a channel specific to them. Instead of having a die timer built in, the radar sends them a "dienow" message just before it generates a new dot on the next scan. This means you can change the scan interval without editing the marker.

The radar also sends the name and range of the av each dot represents to that dot, which displays it, as well as saying "owner" if it's the owner of the object, so that that dot can be specially coloured.

I have a "radius" parameter, which indicates the max distance from the display centre - the furthest avatar is placed at this distance, then everyone else is scaled. e.g. if av X is at 10m and av Y is at 20m, with a radius of 1m, the dot for av X will be 0.5m away from the scan centre, and the dot for av Y will be 1m away. If av Y moves out of range, Xs dot will be 1m away, as it is the furthest.

There's also various bits of flash with voice control, on/off touch switching etc. I was having problems with reaching prim limits but I didn't know about temp prims not counting towards your limit....

It *is* a little slow when there are lots of avatars around, though. In a sandbox, it looks nice but it's not much use - also hard to read when people are clustered in groups. But it was an interesting thing to spend a few hours doing.
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
11-30-2005 03:04
actually, now I come to retest the new version, it's not too slow in a sandbox at all
Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
11-30-2005 05:34
A time of 1 second seems a little excessive, but this is definitely a cool script!
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
11-30-2005 10:33
Ordinal - is yours going to be posted?
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
11-30-2005 10:37
I'll just tidy it up a bit...
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
11-30-2005 10:49
This is the code in the radar unit...

CODE

// Visual Radar Device script v0.3
// Ordinal Malaprop
// 2005-11-29
// Free for distribution, please do not sell

float radius=2.0;
vector offset=<0,0,0.25>;
float range=96.0;
float scanInterval=1.0;
integer baseChannel=10000;
integer listenNum;
float version=0.3;
integer lastN=0;

//------------------------------------------------------------------
// Supporting functions

// Interprets heard text

interpret(string message)
{
if (llGetSubString(message, 0, 6) == "radius ") {
radius = (float)llDeleteSubString(message, 0, 6);
llOwnerSay("Radius set to " + (string)radius);
}
if (llGetSubString(message, 0, 8) == "interval ") {
scanInterval = (float)llDeleteSubString(message, 0, 8);
llOwnerSay("Scan interval set to " + (string)scanInterval
+ " - restart scan to activate");
}
}

// Gives a credits notecard when touched by non-owner

give_credits(key toucher)
{
llGiveInventory(toucher, "Visual Radar Notes");
}

// Kills n existing markers

killAll(integer n)
{
llSay(baseChannel, "dienow");
integer f;
if (n != 0) {
for (f=0; f<n; f++) {
llSay(baseChannel+f+1, "dienow");
}
}
}

//------------------------------------------------------------------
// States

default
{
on_rez(integer a)
{
llOwnerSay("Visual radar rezzed - touch me to start scan");
}

state_entry()
{
llSetAlpha(0.5, ALL_SIDES);
listenNum = llListen(0, "", llGetOwner(), "");
}

// Turn off the listen on exit
state_exit()
{
llListenRemove(listenNum);
}

// Start scan when touched
touch_start (integer n)
{
if (llDetectedKey(0) == llGetOwner()) {
state scanning;
} else {
give_credits(llDetectedKey(0));
}
}

// Deal with spoken commands
listen(integer channel, string name, key id, string message)
{
interpret(message);
}
}

// Scanning state - turned on and displaying

state scanning
{
state_entry()
{
llOwnerSay("Entering scan mode");
llSetAlpha(1.0, ALL_SIDES);
// Start scanning
llSensorRepeat("", NULL_KEY, AGENT, 96.0, PI*2, scanInterval);
llPlaySound("turn_on", 1.0);
// Start listening for commands
listenNum = llListen(0, "", llGetOwner(), "");
}

// Clean up on exit
state_exit()
{
llOwnerSay("Exiting scan mode");
llSensorRemove();
llSetText("", <1.0,0,0>, 1.0);
llPlaySound("turn_off", 1.0);
llListenRemove(listenNum);
killAll(lastN);
lastN = 0;
}

// When targets detected...
sensor(integer n)
{
integer f;
// Kill the old base marker and add a new one
llSay(baseChannel, "dienow");
llRezObject("Marker", llGetPos()+offset, ZERO_VECTOR, ZERO_ROTATION, -1);
// Determine the furthest avatar from the scanner, for scaling
float maxRange=0.0;
for (f=0; f<n; f++) {
if (llVecDist(llDetectedPos(f), llGetPos()) > maxRange) {
maxRange=llVecDist(llDetectedPos(f), llGetPos());
}
}
float scale = radius/maxRange;
// For each detected av...
for (f=0; f<n; f++) {
vector relPos = llDetectedPos(f) - llGetPos();
vector markerPos = (relPos*scale) + llGetPos()+offset;
// Kill the old marker with this number
llSay(baseChannel+f+1, "dienow");
// Create a new one
llRezObject("Marker", markerPos, ZERO_VECTOR, ZERO_ROTATION,
f+1);
// Tell marker if this is the owner
if (llDetectedKey(f) == llGetOwner()) {
llSay(baseChannel+f+1, "owner");
}
// Give marker name and distance information
llSay(baseChannel+f+1, llDetectedName(f) + "\n" +
(string)((integer)llVecDist(llDetectedPos(f), llGetPos())) +
"m");
}
// If there are fewer markers than on the last iteration,
// clean up any extras
f++;
while (f <= lastN) {
llSay(baseChannel+f+1, "dienow");
f++;
}
lastN = n;
}

// Turn off scanning if touched by owner
touch_start (integer n)
{
if (llDetectedKey(0) == llGetOwner()) {
state default;
} else {
give_credits(llDetectedKey(0));
}
}

// Deal with spoken commands
listen(integer channel, string name, key id, string message)
{
interpret(message);
}
}
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
11-30-2005 10:51
...and this is the code in the markers - bit untidy at the moment.
CODE

vector homeColor = <1.0, 0.0, 0.0>;
vector avColor = <0.0, 1.0, 0.0>;
vector ownerColor = <1.0, 1.0, 0.0>;
integer agentNum;
vector textColour = <1.0,1.0,1.0>;
float textAlpha = 0.75;
float lifespan = 30.0;
integer baseChannel = 10000;

default
{
on_rez(integer param)
{
// llOwnerSay("Rezzed at " + (string)llGetPos());
if (param != 0) {
llSetTimerEvent(lifespan);
}
if (param == -1) {
llSetColor(homeColor, ALL_SIDES);
llListen(baseChannel, "Visual Radar Display", NULL_KEY, "");
} else if (param != 0) {
llSetColor(avColor, ALL_SIDES);
agentNum = param - 1;
llListen(baseChannel+param, "Visual Radar Display", NULL_KEY, "");
}
}

listen(integer channel, string name, key id, string message)
{
if (message == "owner") {
llSetColor(ownerColor, ALL_SIDES);
} else if (message == "dienow") {
llDie();
} else {
llSetText(message, textColour, textAlpha);
}
}

timer()
{
llDie();
}
}


There are definitely a few efficiency tweaks that could be done in both.

If anyone wants to see it working there's a copy sitting in my home area.
Lallander Parvenu
Registered User
Join date: 21 Apr 2005
Posts: 45
11-30-2005 11:47
Ill post the code from the one that is half open. I think that the idea here is that each node moves itself around instead of constantly recreating icons. I think.

CODE

// test

list g_lNames;
list g_lLastReports;
float g_gLastRepReq = 0;

default
{
state_entry()
{
llListen(4242, "", NULL_KEY, "");
llListen(0, "", llGetOwner(), "");
llSensorRepeat("", NULL_KEY, AGENT, 255, PI*2, .2);
// llSensorRepeat("", llGetOwner(), AGENT, 255, PI*2, .2);
llSetTimerEvent(10);
}

touch_start(integer total_number)
{
}

listen(integer iChannel, string strName, key id, string strMsg)
{
if(iChannel == 0)
{
if(strMsg == "reset")
{
llSay(4242, "end");
}
return;
}
if(id == llGetKey())
{
return;
}
if(llGetSubString(strMsg, 0, 2) == "die")
{
string strName = llGetSubString(strMsg, 4, -1);
list l = [strName];
integer iIndex = llListFindList(g_lNames, l);
if(iIndex > -1)
{
llWhisper(0, "Killing entry for " + strName);

g_lNames = llDeleteSubList(g_lNames, iIndex, iIndex);
g_lLastReports = llDeleteSubList(g_lLastReports, iIndex, iIndex);
}
}
else // assume its a key report
{
integer iLen = llGetListLength(g_lNames);
string s = strMsg;
list l = ;
integer iIndex = llListFindList(g_lNames, l);
if(iIndex > -1)
{
list lNew;
integer iReports = 0;
for(iReports = 0; iReports < iLen; ++iReports)
{
if(iReports != iIndex)
{
lNew += llList2Float(g_lLastReports, iReports);
}
else
{
lNew += llGetTime();
}
} // end for all last reports
g_lLastReports = lNew;
}
}
} // end listen


sensor(integer iNum)
{
integer i = 0;
for(i = 0; i < iNum; ++i)
{
string s = llDetectedName(i);
list l = ;
integer iIndex = llListFindList(g_lNames, l);
if(iIndex == -1)
{
llWhisper(0, "Making icon for " + s);
llRezObject("AVIcon", llGetPos(), ZERO_VECTOR, <0,0,0,0>, 4243+i);
g_lNames += s;
g_lLastReports += llGetTime();
llSleep(.25);
llSay(4243+i, s);
llSleep(.25);
llSay(4243+i, "go";);
}
}
}

timer()
{
integer i = 0;
integer iLen = llGetListLength(g_lLastReports);
float fNow = llGetTime();
for(i=0; i < iLen; ++i)
{
float fLastReport = fNow - llList2Float(g_lLastReports, i);
if(fLastReport > 120)
{
llWhisper(0, "Killing entry for " + llList2String(g_lNames, i));
g_lNames = llDeleteSubList(g_lNames, i, i);
g_lLastReports = llDeleteSubList(g_lLastReports, i, i);
}
else if(fLastReport > 30)
{
llSay(4242, "report " + llList2String(g_lNames, i));
}
}

}
}

Haravikk Mistral
Registered User
Join date: 8 Oct 2005
Posts: 2,482
12-02-2005 03:43
From: Ordinal Malaprop
This is the code in the radar unit...

CODE

// Determine the furthest avatar from the scanner, for scaling
float maxRange=0.0;
for (f=0; f<n; f++) {
if (llVecDist(llDetectedPos(f), llGetPos()) > maxRange) {
maxRange=llVecDist(llDetectedPos(f), llGetPos());
}
}


Just a note to say that my findings are that this part is uneccessary, as sensors always return their results in order of distance from the source, so:

CODE
sensor (integer x) { float maxRange = llVecDist(llDetectedPos(x - 1), llGetPos()); }


This holds true. In case you want your sensor to restrict the results it uses, you can instead back-track through the results, so you can find the furthest unrestricted item (if there is one).

Also, it is fairly easy to take into account avatar height (and this is important if you want dots on the same floor of a building to appear level. All you need to do is something like this (assume the position of the dot 'pos' has already been worked out):

CODE
vector avatarSize = llGetAgentSize(llDetectedKey(i));
pos = pos + <0,0,(avatarSize.z / 2.0)>;


These two improvements are quite handy, I don't consider my code finished yet but I may post it later.
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
12-02-2005 13:09
I'm confused. Shouldn't you be subtracting half the avatar height? Adding will put the dot at the position of their head, not level on the floor.

It might be interesting to make the icon the shape of the bounding box, actually.
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
12-02-2005 13:13
From: Haravikk Mistral
Just a note to say that my findings are that this part is uneccessary, as sensors always return their results in order of distance from the source

Thanks, didn't know that. I wasn't sure what the order was so I didn't take any chances.
Ordinal Malaprop
really very ordinary
Join date: 9 Sep 2005
Posts: 4,607
12-02-2005 13:18
From: Argent Stonecutter
I'm confused. Shouldn't you be subtracting half the avatar height? Adding will put the dot at the position of their head, not level on the floor.

It might be interesting to make the icon the shape of the bounding box, actually.

I thought so too. You'd also want to modify it on the basis of the height of the origin dot, in my example, so you'd have to add the height of the dot off the ground to the effective position (since the feet will be lower than the dot).

My implementation looks like the attached picture, which is 0.75m high IIRC.
Ziggy Puff
Registered User
Join date: 15 Jul 2005
Posts: 1,143
12-02-2005 13:45
What would be really cool is if the sensor were tracking people in a building, and then the display was shown on a small-scale semi-transparent 3D model of the building. If you lined it up right, you could show what room someone was in, and so on. A 3D holographic map. That'd be cool :)
Argent Stonecutter
Emergency Mustelid
Join date: 20 Sep 2005
Posts: 20,263
12-02-2005 23:33
You could rez a dot for each object in the building to help guide the construction of the holographic map!
1 2